diff --git a/.github/workflows/add-to-registry.yml b/.github/workflows/add-to-registry.yml deleted file mode 100644 index 8fd6a657..00000000 --- a/.github/workflows/add-to-registry.yml +++ /dev/null @@ -1,124 +0,0 @@ -name: Add compile program to registry -on: - push: - branches: - - main - paths: - - '**/*.cairo' - -jobs: - test: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Setup Scarb - uses: software-mansion/setup-scarb@v1 - - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: '3.9' - - - name: Cache Python environment - uses: actions/cache@v3 - with: - path: | - ~/.cache/pip - venv - key: ${{ runner.os }}-python-${{ hashFiles('**/requirements.txt') }}-${{ hashFiles('tools/make/setup.sh') }} - restore-keys: | - ${{ runner.os }}-python-${{ hashFiles('**/requirements.txt') }}-${{ hashFiles('tools/make/setup.sh') }} - ${{ runner.os }}-python- - - - name: Install Dependencies - run: make setup - - name: Compile Cairo program - run: | - source venv/bin/activate - mkdir -p build - - # Function to pad hash to 32 bytes - pad_hash() { - # Remove 0x prefix if present - hash=${1#0x} - # Pad to 64 characters (32 bytes) - printf "0x%064s" "$hash" | tr ' ' '0' - } - - # First program (frequently updated) - cairo-compile --cairo_path="packages/eth_essentials" "src/hdp.cairo" --output build/hdp.json - HDP_HASH=$(cairo-hash-program --program build/hdp.json) - HDP_HASH=$(pad_hash $HDP_HASH) - echo "HDP_HASH=$HDP_HASH" >> $GITHUB_ENV - - # Second program (infrequently updated) - cairo-compile --cairo_path="packages/eth_essentials" "src/contract_bootloader/contract_dry_run.cairo" --output build/contract_dry_run.json - CONTRACT_DRY_RUN_HASH=$(cairo-hash-program --program build/contract_dry_run.json) - CONTRACT_DRY_RUN_HASH=$(pad_hash $CONTRACT_DRY_RUN_HASH) - echo "CONTRACT_DRY_RUN_HASH=$CONTRACT_DRY_RUN_HASH" >> $GITHUB_ENV - - - name: Checkout compilation storage repo - uses: actions/checkout@v2 - with: - repository: petscheit/cairo-program-registry-new - token: ${{ secrets.CAIRO_PROGRAM_REGISTRY_PAT }} - path: cairo-compilations - - - name: Store compilations and update changelog - run: | - cd cairo-compilations - - # We always want to update the HDP program, as there can be changes in the hints, which are not reflected in the hash - HDP_UPDATED=true - mkdir -p ${{ env.HDP_HASH }} - cp -f ../build/hdp.json ${{ env.HDP_HASH }}/program.json - - # Store second program (only if folder doesn't exist) - CONTRACT_DRY_RUN_UPDATED=false - if [ ! -d "${{ env.CONTRACT_DRY_RUN_HASH }}" ]; then - mkdir -p ${{ env.CONTRACT_DRY_RUN_HASH }} - cp ../build/contract_dry_run.json ${{ env.CONTRACT_DRY_RUN_HASH }}/program.json - CONTRACT_DRY_RUN_UPDATED=true - fi - - # Update README with changelog only if there are updates - if [ "$HDP_UPDATED" = true ] || [ "$CONTRACT_DRY_RUN_UPDATED" = true ]; then - DATE=$(date +"%Y-%m-%d") - COMMIT_URL="https://github.com/${{ github.repository }}/commit/${{ github.sha }}" - - if [ ! -f README.md ]; then - echo "# Changelog" > README.md - echo "" >> README.md - fi - - { - echo "## Updates on $DATE" - echo "" - if [ "$HDP_UPDATED" = true ]; then - echo "### HDP Program" - echo "- **Hash:** \`${{ env.HDP_HASH }}\`" - echo "- [View commit]($COMMIT_URL)" - echo "" - fi - if [ "$CONTRACT_DRY_RUN_UPDATED" = true ]; then - echo "### Contract Dry Run" - echo "- **Hash:** \`${{ env.CONTRACT_DRY_RUN_HASH }}\`" - echo "- [View commit]($COMMIT_URL)" - echo "" - fi - echo "$(cat README.md)" - } > README.md.tmp - mv README.md.tmp README.md - - # Commit and push if there are changes - git config user.name github-actions - git config user.email github-actions@github.com - git add . - git commit -m "Add compilation(s) for hash(es) ${{ env.HDP_HASH }} and/or ${{ env.CONTRACT_DRY_RUN_HASH }} and update changelog" - git push - else - echo "No new compilations to store or changelog updates." - fi - diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml deleted file mode 100644 index fb736944..00000000 --- a/.github/workflows/merge.yml +++ /dev/null @@ -1,132 +0,0 @@ -name: Build Docker and Push Python Package - -on: - push: - branches: - - main - -jobs: - build-and-push: - runs-on: ubuntu-latest - permissions: - contents: write - id-token: write - steps: - - name: Checkout code - uses: actions/checkout@v3 # Update to v3 - with: - fetch-depth: 0 # Fetch all history and tags - - - name: Fetch all branches - run: | - git fetch --all - git fetch --tags - - - name: Set up Python - uses: actions/setup-python@v2 - with: - python-version: "3.x" - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install setuptools wheel twine bumpversion - - - name: Check for package changes - run: | - if [ "${{ github.event_name }}" = "pull_request" ]; then - # Fetch base branch to compare with PR branch - git fetch origin ${{ github.base_ref }}:${{ github.base_ref }} - CHANGED_FILES=$(git diff --name-only ${{ github.base_ref }}...HEAD) - else - # Compare current commit with the previous commit - CHANGED_FILES=$(git diff --name-only HEAD^ HEAD) - fi - echo "Changed files: $CHANGED_FILES" - if echo "$CHANGED_FILES" | grep -qE '(tools/|src/contract_bootloader/|setup.py|requirements.txt|setup.sh|environment.dockerfile)'; then - echo "CHANGES_DETECTED=true" >> $GITHUB_ENV - else - echo "CHANGES_DETECTED=false" >> $GITHUB_ENV - fi - echo "Changes detected: $CHANGES_DETECTED" - - - name: Log in to Docker Hub - if: env.CHANGES_DETECTED == 'true' && github.event_name == 'push' && github.ref == 'refs/heads/main' - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - # - name: Create remote builder certificates - # if: env.CHANGES_DETECTED == 'true' && github.event_name == 'push' && github.ref == 'refs/heads/main' - # run: | - # echo "${{ secrets.BUILDKIT_CA_PEM }}" > ${{ github.workspace }}/client-ca.pem - # echo "${{ secrets.BUILDKIT_CERT_PEM }}" > ${{ github.workspace }}/client-cert.pem - # echo "${{ secrets.BUILDKIT_KEY_PEM }}" > ${{ github.workspace }}/client-key.pem - - # - name: Set up Docker Buildx - # if: env.CHANGES_DETECTED == 'true' && github.event_name == 'push' && github.ref == 'refs/heads/main' - # uses: docker/setup-buildx-action@v3 - # with: - # driver: remote - # endpoint: "tcp://buildkit.herodotus.dev:5000" - # driver-opts: | - # cacert=${{ github.workspace }}/client-ca.pem - # cert=${{ github.workspace }}/client-cert.pem - # key=${{ github.workspace }}/client-key.pem - # cleanup: true - - - name: Set up Docker Buildx - if: env.CHANGES_DETECTED == 'true' && github.event_name == 'push' && github.ref == 'refs/heads/main' - uses: docker/setup-buildx-action@v3 - with: - version: "lab:latest" - driver: cloud - endpoint: "dataprocessor/github" - cleanup: true - - - name: Bump version - if: env.CHANGES_DETECTED == 'true' && github.event_name == 'push' && github.ref == 'refs/heads/main' - run: | - git config --local user.email "action@github.com" - git config --local user.name "GitHub Action" - bumpversion patch --allow-dirty - NEW_VERSION=$(python setup.py --version) - echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_ENV - git push origin "v${NEW_VERSION}" # Push only the new tag - git push - - - name: Build and push Docker image - if: env.CHANGES_DETECTED == 'true' && github.event_name == 'push' && github.ref == 'refs/heads/main' - uses: docker/build-push-action@v5 - with: - file: environment.dockerfile - tags: | - dataprocessor/hdp-cairo:latest - dataprocessor/hdp-cairo:v${{ env.NEW_VERSION }} - platforms: linux/amd64,linux/arm64 - push: true - context: https://github.com/HerodotusDev/hdp-cairo.git#main - - - name: Debug output - run: | - echo "Event name: ${{ github.event_name }}" - echo "GitHub ref: ${{ github.ref }}" - echo "Changes detected: ${{ env.CHANGES_DETECTED }}" - - - name: Build Python package - if: env.CHANGES_DETECTED == 'true' - run: | - python setup.py sdist bdist_wheel - - - name: Check PyPI package (dry run) - if: env.CHANGES_DETECTED == 'true' - run: | - twine check dist/* - echo "Package check completed. In a real publish, the package would be uploaded to PyPI." - - - name: Publish package to PyPI - if: env.CHANGES_DETECTED == 'true' && github.event_name == 'push' && github.ref == 'refs/heads/main' - uses: pypa/gh-action-pypi-publish@release/v1 - with: - password: ${{ secrets.PYPI_API_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml deleted file mode 100644 index 1f2ed2f2..00000000 --- a/.github/workflows/pull-request.yml +++ /dev/null @@ -1,72 +0,0 @@ -name: CI Test Workflow - -on: - pull_request: - branches: - - '**' # This pattern matches all branches -jobs: - test: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Setup Scarb - uses: software-mansion/setup-scarb@v1 - - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: '3.9' - - - name: Cache Python environment - uses: actions/cache@v3 - with: - path: | - ~/.cache/pip - venv - key: ${{ runner.os }}-python-${{ hashFiles('**/requirements.txt') }}-${{ hashFiles('tools/make/setup.sh') }} - restore-keys: | - ${{ runner.os }}-python-${{ hashFiles('**/requirements.txt') }}-${{ hashFiles('tools/make/setup.sh') }} - ${{ runner.os }}-python- - - - name: Install Dependencies - run: make setup - - - name: Check Python formatting - run: | - source venv/bin/activate - ./tools/make/python_format_check.sh - - - name: Check Python tests - env: - RPC_URL_MAINNET: ${{ secrets.RPC_URL_MAINNET }} - PROVIDER_URL_STARKNET: ${{ secrets.PROVIDER_URL_STARKNET }} - RPC_URL: ${{ secrets.RPC_URL }} - run: | - source venv/bin/activate - pytest tools/* - - - name: Check Cairo formatting - run: | - source venv/bin/activate - ./tools/make/cairo_format_check.sh - - - name: Compile Cairo files - run: | - source venv/bin/activate - make build - - - name: Run Unit Cairo tests - env: - RPC_URL_MAINNET: ${{ secrets.RPC_URL_MAINNET }} - PROVIDER_URL_STARKNET: ${{ secrets.PROVIDER_URL_STARKNET_TESTNET }} - RPC_URL: ${{ secrets.RPC_URL }} - run: | - source venv/bin/activate - ./tools/make/cairo_tests.sh - - - name: Run Full Flow tests - run: | - source venv/bin/activate - ./tools/make/full_flow_test.sh \ No newline at end of file diff --git a/.github/workflows/rust-vm.yaml b/.github/workflows/rust-vm.yaml new file mode 100644 index 00000000..932743ab --- /dev/null +++ b/.github/workflows/rust-vm.yaml @@ -0,0 +1,100 @@ +name: rust-vm-CI + +on: + push: + branches: + - "**" + +jobs: + check: + name: Format and Lint + runs-on: ubuntu-latest + + steps: + - name: Checkout Code + uses: actions/checkout@v3 + with: + submodules: true + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.9" + + - name: Set up Rust + uses: actions-rust-lang/setup-rust-toolchain@v1 + + - name: Set up Scarb + uses: software-mansion/setup-scarb@v1 + + - name: Set up Cairo + run: make setup + + - name: Cache Cargo + uses: actions/cache@v3 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + target/ + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-cargo- + + - name: Run fmt check + run: cargo fmt --all -- --check + + - name: Run clippy check + run: cargo clippy -- -D warnings + + test: + name: Run Tests + runs-on: ubuntu-latest + + steps: + - name: Checkout Code + uses: actions/checkout@v3 + with: + submodules: true + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.9" + + - name: Set up Rust + uses: actions-rust-lang/setup-rust-toolchain@v1 + + - name: Set up Scarb + uses: software-mansion/setup-scarb@v1 + + - name: Set up Cairo + run: make setup + + - name: Install Nextest + uses: taiki-e/install-action@nextest + + - name: Build Test Contracts + run: scarb build + + - name: Cache Cargo + uses: actions/cache@v3 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + target/ + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-cargo- + + - name: Run Nextest Tests + env: + ETH_RPC: ${{ secrets.RPC_URL_ETHEREUM_SEPOLIA }} + STARKNET_RPC: ${{ secrets.RPC_URL_STARKNET_SEPOLIA }} + run: cargo nextest run + diff --git a/Cargo.lock b/Cargo.lock index 657a9ae9..82b8c73e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -17,6 +17,28 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +[[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.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + [[package]] name = "ahash" version = "0.8.11" @@ -339,7 +361,7 @@ dependencies = [ "lru", "parking_lot", "pin-project", - "reqwest", + "reqwest 0.12.10", "schnellru", "serde", "serde_json", @@ -406,7 +428,7 @@ dependencies = [ "alloy-transport-ws", "futures", "pin-project", - "reqwest", + "reqwest 0.12.10", "serde", "serde_json", "tokio", @@ -619,7 +641,7 @@ checksum = "2e02ffd5d93ffc51d72786e607c97de3b60736ca3e636ead0ec1f7dce68ea3fd" dependencies = [ "alloy-json-rpc", "alloy-transport", - "reqwest", + "reqwest 0.12.10", "serde_json", "tower", "tracing", @@ -654,8 +676,8 @@ dependencies = [ "alloy-pubsub", "alloy-transport", "futures", - "http", - "rustls", + "http 1.2.0", + "rustls 0.23.20", "serde_json", "tokio", "tokio-tungstenite", @@ -976,7 +998,7 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -1039,6 +1061,12 @@ 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.6.0" @@ -1659,6 +1687,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "chrono" version = "0.4.39" @@ -1669,7 +1703,17 @@ dependencies = [ "iana-time-zone", "num-traits", "serde", - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", ] [[package]] @@ -1805,6 +1849,16 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -1882,6 +1936,15 @@ dependencies = [ "typenum", ] +[[package]] +name = "ctr" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +dependencies = [ + "cipher", +] + [[package]] name = "darling" version = "0.20.10" @@ -1989,6 +2052,12 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "deunicode" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "339544cc9e2c4dc3fc7149fd630c5f22263a4fdf18a98afd0075784968b5cf00" + [[package]] name = "diff" version = "0.1.13" @@ -2072,7 +2141,9 @@ dependencies = [ "cairo-lang-starknet-classes", "cairo-vm", "hints", + "reqwest 0.12.10", "serde", + "starknet", "starknet-types-core", "strum_macros", "syscall_handler", @@ -2097,6 +2168,18 @@ dependencies = [ "types", ] +[[package]] +name = "dummy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac124e13ae9aa56acc4241f8c8207501d93afdd8d8e62f0c1f2e12f6508c65" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.91", +] + [[package]] name = "dunce" version = "1.0.5" @@ -2188,6 +2271,28 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "eth-keystore" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fda3bf123be441da5260717e0661c25a2fd9cb2b2c1d20bf2e05580047158ab" +dependencies = [ + "aes", + "ctr", + "digest 0.10.7", + "hex", + "hmac", + "pbkdf2", + "rand", + "scrypt", + "serde", + "serde_json", + "sha2", + "sha3", + "thiserror 1.0.69", + "uuid", +] + [[package]] name = "eth_essentials_cairo_vm_hints" version = "0.1.0" @@ -2200,12 +2305,51 @@ dependencies = [ "num-traits", "rand", "sha3", - "starknet-crypto 0.7.3", + "starknet-crypto 0.7.4", "starknet-types-core", "thiserror 1.0.69", "tiny-keccak", ] +[[package]] +name = "ethbloom" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" +dependencies = [ + "crunchy", + "fixed-hash", + "impl-rlp", + "impl-serde", + "tiny-keccak", +] + +[[package]] +name = "ethereum-types" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" +dependencies = [ + "ethbloom", + "fixed-hash", + "impl-rlp", + "impl-serde", + "primitive-types", + "uint", +] + +[[package]] +name = "fake" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d391ba4af7f1d93f01fcf7b2f29e2bc9348e109dfdbf4dcbdc51dfa38dab0b6" +dependencies = [ + "deunicode", + "dummy", + "rand", + "serde_json", +] + [[package]] name = "fastrand" version = "2.3.0" @@ -2401,6 +2545,12 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" + [[package]] name = "futures-util" version = "0.3.31" @@ -2517,6 +2667,25 @@ dependencies = [ "subtle", ] +[[package]] +name = "h2" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.12", + "indexmap 2.7.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "h2" version = "0.4.7" @@ -2528,7 +2697,7 @@ dependencies = [ "fnv", "futures-core", "futures-sink", - "http", + "http 1.2.0", "indexmap 2.7.0", "slab", "tokio", @@ -2554,7 +2723,7 @@ version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ - "ahash", + "ahash 0.8.11", "allocator-api2", "serde", ] @@ -2620,12 +2789,12 @@ dependencies = [ "num-bigint", "num-traits", "rand", - "reqwest", + "reqwest 0.12.10", "serde", "serde_json", "serde_with 3.12.0", - "starknet-core", - "starknet-crypto 0.7.3", + "starknet-core 0.11.1", + "starknet-crypto 0.7.4", "starknet-types-core", "strum_macros", "thiserror 1.0.69", @@ -2643,6 +2812,17 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + [[package]] name = "http" version = "1.2.0" @@ -2654,6 +2834,17 @@ dependencies = [ "itoa", ] +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http 0.2.12", + "pin-project-lite", +] + [[package]] name = "http-body" version = "1.0.1" @@ -2661,7 +2852,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http", + "http 1.2.0", ] [[package]] @@ -2672,8 +2863,8 @@ checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", "futures-util", - "http", - "http-body", + "http 1.2.0", + "http-body 1.0.1", "pin-project-lite", ] @@ -2683,6 +2874,36 @@ version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "0.14.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + [[package]] name = "hyper" version = "1.5.2" @@ -2692,9 +2913,9 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "h2", - "http", - "http-body", + "h2 0.4.7", + "http 1.2.0", + "http-body 1.0.1", "httparse", "itoa", "pin-project-lite", @@ -2703,6 +2924,20 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-rustls" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +dependencies = [ + "futures-util", + "http 0.2.12", + "hyper 0.14.32", + "rustls 0.21.12", + "tokio", + "tokio-rustls 0.24.1", +] + [[package]] name = "hyper-rustls" version = "0.27.5" @@ -2710,13 +2945,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" dependencies = [ "futures-util", - "http", - "hyper", + "http 1.2.0", + "hyper 1.5.2", "hyper-util", - "rustls", + "rustls 0.23.20", + "rustls-native-certs", "rustls-pki-types", "tokio", - "tokio-rustls", + "tokio-rustls 0.26.1", "tower-service", ] @@ -2728,7 +2964,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper", + "hyper 1.5.2", "hyper-util", "native-tls", "tokio", @@ -2745,9 +2981,9 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "http", - "http-body", - "hyper", + "http 1.2.0", + "http-body 1.0.1", + "hyper 1.5.2", "pin-project-lite", "socket2", "tokio", @@ -2954,6 +3190,24 @@ dependencies = [ "parity-scale-codec", ] +[[package]] +name = "impl-rlp" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" +dependencies = [ + "rlp", +] + +[[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.3" @@ -2976,7 +3230,7 @@ name = "indexer" version = "0.1.0" dependencies = [ "alloy", - "reqwest", + "reqwest 0.12.10", "serde", "serde_json", "serde_with 3.12.0", @@ -3014,7 +3268,7 @@ checksum = "cbf675b85ed934d3c67b5c5469701eec7db22689d0a2139d856e0925fa28b281" dependencies = [ "console", "number_prefix", - "portable-atomic", + "portable-atomic 1.10.0", "unicode-width", "web-time", ] @@ -3025,6 +3279,15 @@ 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 = "interprocess" version = "2.2.2" @@ -3215,7 +3478,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags", + "bitflags 2.6.0", "libc", ] @@ -3272,6 +3535,28 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "metrics" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b9b8653cec6897f73b519a43fba5ee3d50f62fe9af80b428accdcc093b4a849" +dependencies = [ + "ahash 0.7.8", + "metrics-macros", + "portable-atomic 0.3.20", +] + +[[package]] +name = "metrics-macros" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "731f8ecebd9f3a4aa847dfe75455e4757a45da40a7793d2f0b1f9b6ed18b23f3" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "microlp" version = "0.2.7" @@ -3326,7 +3611,7 @@ dependencies = [ "openssl-probe", "openssl-sys", "schannel", - "security-framework", + "security-framework 2.11.1", "security-framework-sys", "tempfile", ] @@ -3341,7 +3626,7 @@ dependencies = [ "num-complex", "num-integer", "num-traits", - "portable-atomic", + "portable-atomic 1.10.0", "portable-atomic-util", "rawpointer", ] @@ -3475,6 +3760,15 @@ dependencies = [ "syn 2.0.91", ] +[[package]] +name = "num_threads" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + [[package]] name = "number_prefix" version = "0.4.0" @@ -3521,7 +3815,7 @@ version = "0.10.68" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" dependencies = [ - "bitflags", + "bitflags 2.6.0", "cfg-if", "foreign-types", "libc", @@ -3611,7 +3905,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -3626,6 +3920,66 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17359afc20d7ab31fdb42bb844c8b3bb1dabd7dcf7e68428492da7f16966fcef" +[[package]] +name = "pathfinder-common" +version = "0.15.3" +source = "git+https://github.com/eqlabs/pathfinder#98aa80659fc8efc5463993c03ebddebf6c9d4d9c" +dependencies = [ + "anyhow", + "bitvec", + "fake", + "metrics", + "num-bigint", + "num-traits", + "paste", + "pathfinder-crypto", + "primitive-types", + "rand", + "serde", + "serde_json", + "serde_with 3.12.0", + "sha3", + "tagged", + "tagged-debug-derive", + "thiserror 1.0.69", + "vergen", +] + +[[package]] +name = "pathfinder-crypto" +version = "0.15.3" +source = "git+https://github.com/eqlabs/pathfinder#98aa80659fc8efc5463993c03ebddebf6c9d4d9c" +dependencies = [ + "bitvec", + "fake", + "rand", + "serde", +] + +[[package]] +name = "pathfinder-serde" +version = "0.15.3" +source = "git+https://github.com/eqlabs/pathfinder#98aa80659fc8efc5463993c03ebddebf6c9d4d9c" +dependencies = [ + "anyhow", + "num-bigint", + "pathfinder-common", + "pathfinder-crypto", + "primitive-types", + "serde", + "serde_json", + "serde_with 3.12.0", +] + +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest 0.10.7", +] + [[package]] name = "percent-encoding" version = "2.3.1" @@ -3726,6 +4080,15 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" +[[package]] +name = "portable-atomic" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e30165d31df606f5726b090ec7592c308a0eaf61721ff64c9a3018e344a8753e" +dependencies = [ + "portable-atomic 1.10.0", +] + [[package]] name = "portable-atomic" version = "1.10.0" @@ -3738,7 +4101,7 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" dependencies = [ - "portable-atomic", + "portable-atomic 1.10.0", ] [[package]] @@ -3780,6 +4143,8 @@ checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" dependencies = [ "fixed-hash", "impl-codec", + "impl-rlp", + "impl-serde", "uint", ] @@ -3831,7 +4196,7 @@ checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" dependencies = [ "bit-set", "bit-vec", - "bitflags", + "bitflags 2.6.0", "lazy_static", "num-traits", "rand", @@ -3850,7 +4215,59 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] -name = "quote" +name = "quinn" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62e96808277ec6f97351a2380e6c25114bc9e67037775464979f3037c92d05ef" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash 2.1.0", + "rustls 0.23.20", + "socket2", + "thiserror 2.0.9", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d" +dependencies = [ + "bytes", + "getrandom", + "rand", + "ring", + "rustc-hash 2.1.0", + "rustls 0.23.20", + "rustls-pki-types", + "slab", + "thiserror 2.0.9", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c40286217b4ba3a71d644d752e6a0b71f13f1b6a2c5311acfcbe0c2418ed904" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] +name = "quote" version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" @@ -3942,7 +4359,7 @@ version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ - "bitflags", + "bitflags 2.6.0", ] [[package]] @@ -3991,6 +4408,47 @@ version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" +[[package]] +name = "reqwest" +version = "0.11.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" +dependencies = [ + "base64 0.21.7", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.32", + "hyper-rustls 0.24.2", + "ipnet", + "js-sys", + "log", + "mime", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls 0.21.12", + "rustls-pemfile 1.0.4", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper 0.1.2", + "system-configuration 0.5.1", + "tokio", + "tokio-rustls 0.24.1", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots 0.25.4", + "winreg", +] + [[package]] name = "reqwest" version = "0.12.10" @@ -4002,12 +4460,12 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "h2", - "http", - "http-body", + "h2 0.4.7", + "http 1.2.0", + "http-body 1.0.1", "http-body-util", - "hyper", - "hyper-rustls", + "hyper 1.5.2", + "hyper-rustls 0.27.5", "hyper-tls", "hyper-util", "ipnet", @@ -4018,14 +4476,19 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls-pemfile", + "quinn", + "rustls 0.23.20", + "rustls-native-certs", + "rustls-pemfile 2.2.0", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", - "sync_wrapper", - "system-configuration", + "sync_wrapper 1.0.2", + "system-configuration 0.6.1", "tokio", "tokio-native-tls", + "tokio-rustls 0.26.1", "tower", "tower-service", "url", @@ -4070,6 +4533,35 @@ dependencies = [ "rustc-hex", ] +[[package]] +name = "rstest" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97eeab2f3c0a199bc4be135c36c924b6590b88c377d416494288c14f2db30199" +dependencies = [ + "futures", + "futures-timer", + "rstest_macros", + "rustc_version 0.4.1", +] + +[[package]] +name = "rstest_macros" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d428f8247852f894ee1be110b375111b586d4fa431f6c46e64ba5a0dcccbe605" +dependencies = [ + "cfg-if", + "glob", + "proc-macro2", + "quote", + "regex", + "relative-path", + "rustc_version 0.4.1", + "syn 2.0.91", + "unicode-ident", +] + [[package]] name = "ruint" version = "1.12.4" @@ -4189,13 +4681,25 @@ version = "0.38.42" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" dependencies = [ - "bitflags", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", "windows-sys 0.59.0", ] +[[package]] +name = "rustls" +version = "0.21.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +dependencies = [ + "log", + "ring", + "rustls-webpki 0.101.7", + "sct", +] + [[package]] name = "rustls" version = "0.23.20" @@ -4205,11 +4709,32 @@ dependencies = [ "once_cell", "ring", "rustls-pki-types", - "rustls-webpki", + "rustls-webpki 0.102.8", "subtle", "zeroize", ] +[[package]] +name = "rustls-native-certs" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework 3.2.0", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64 0.21.7", +] + [[package]] name = "rustls-pemfile" version = "2.2.0" @@ -4224,6 +4749,19 @@ name = "rustls-pki-types" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" +dependencies = [ + "web-time", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] [[package]] name = "rustls-webpki" @@ -4260,6 +4798,15 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +[[package]] +name = "salsa20" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" +dependencies = [ + "cipher", +] + [[package]] name = "same-file" version = "1.0.6" @@ -4309,7 +4856,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9a8ef13a93c54d20580de1e5c413e624e53121d42fc7e2c11d10ef7f8b02367" dependencies = [ - "ahash", + "ahash 0.8.11", "cfg-if", "hashbrown 0.13.2", ] @@ -4320,6 +4867,28 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "scrypt" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f9e24d2b632954ded8ab2ef9fea0a0c769ea56ea98bddbafbad22caeeadf45d" +dependencies = [ + "hmac", + "pbkdf2", + "salsa20", + "sha2", +] + +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "sec1" version = "0.7.3" @@ -4340,8 +4909,21 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags", - "core-foundation", + "bitflags 2.6.0", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" +dependencies = [ + "bitflags 2.6.0", + "core-foundation 0.10.0", "core-foundation-sys", "libc", "security-framework-sys", @@ -4349,9 +4931,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.13.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1863fd3768cd83c56a7f60faa4dc0d403f1b6df0a38c3c25f44b7894e45370d5" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" dependencies = [ "core-foundation-sys", "libc", @@ -4708,6 +5290,52 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "starknet" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc9b221c99a1ea1d65fb130e5b0dbaa6d362698430232902ebeb2a898a1ab531" +dependencies = [ + "starknet-accounts", + "starknet-contract", + "starknet-core 0.12.1", + "starknet-core-derive", + "starknet-crypto 0.7.4", + "starknet-macros", + "starknet-providers", + "starknet-signers", +] + +[[package]] +name = "starknet-accounts" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3fc4364f5684e4a5dcb100847a9ea023deae3815f45526721a6fa94ab595651" +dependencies = [ + "async-trait", + "auto_impl", + "starknet-core 0.12.1", + "starknet-crypto 0.7.4", + "starknet-providers", + "starknet-signers", + "thiserror 1.0.69", +] + +[[package]] +name = "starknet-contract" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f2102b8f763477a1bdece683da51514bc73829d5dcc3bbe75ff1b6aca6d4e02" +dependencies = [ + "serde", + "serde_json", + "serde_with 3.12.0", + "starknet-accounts", + "starknet-core 0.12.1", + "starknet-providers", + "thiserror 1.0.69", +] + [[package]] name = "starknet-core" version = "0.11.1" @@ -4722,10 +5350,44 @@ dependencies = [ "serde_json_pythonic", "serde_with 2.3.3", "sha3", - "starknet-crypto 0.7.3", + "starknet-crypto 0.7.4", "starknet-types-core", ] +[[package]] +name = "starknet-core" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37abf0af45a3b866dd108880ace9949ae7830f6830adb8963024302ae9e82c24" +dependencies = [ + "base64 0.21.7", + "crypto-bigint", + "flate2", + "foldhash", + "hex", + "indexmap 2.7.0", + "num-traits", + "serde", + "serde_json", + "serde_json_pythonic", + "serde_with 3.12.0", + "sha3", + "starknet-core-derive", + "starknet-crypto 0.7.4", + "starknet-types-core", +] + +[[package]] +name = "starknet-core-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b08520b7d80eda7bf1a223e8db4f9bb5779a12846f15ebf8f8d76667eca7f5ad" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.91", +] + [[package]] name = "starknet-crypto" version = "0.6.2" @@ -4748,9 +5410,9 @@ dependencies = [ [[package]] name = "starknet-crypto" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded22ccf4cb9e572ce3f77de6066af53560cd2520d508876c83bb1e6b29d5cbc" +checksum = "039a3bad70806b494c9e6b21c5238a6c8a373d66a26071859deb0ccca6f93634" dependencies = [ "crypto-bigint", "hex", @@ -4806,6 +5468,76 @@ dependencies = [ "hex", ] +[[package]] +name = "starknet-gateway-types" +version = "0.15.3" +source = "git+https://github.com/eqlabs/pathfinder#98aa80659fc8efc5463993c03ebddebf6c9d4d9c" +dependencies = [ + "anyhow", + "fake", + "pathfinder-common", + "pathfinder-crypto", + "pathfinder-serde", + "primitive-types", + "rand", + "reqwest 0.12.10", + "rstest", + "serde", + "serde_json", + "serde_with 3.12.0", + "sha3", + "thiserror 1.0.69", + "tokio", +] + +[[package]] +name = "starknet-macros" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8986a940af916fc0a034f4e42c6ba76d94f1e97216d75447693dfd7aefaf3ef2" +dependencies = [ + "starknet-core 0.12.1", + "syn 2.0.91", +] + +[[package]] +name = "starknet-providers" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9256247f718564b3e4c73cc941735012691c14903fbc25cea306745bcbfa384" +dependencies = [ + "async-trait", + "auto_impl", + "ethereum-types", + "flate2", + "getrandom", + "log", + "reqwest 0.11.27", + "serde", + "serde_json", + "serde_with 3.12.0", + "starknet-core 0.12.1", + "thiserror 1.0.69", + "url", +] + +[[package]] +name = "starknet-signers" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79b9cbae629e277fba372b5f22f52aa5dd1dd40c61924bb18bf901d4d830edd1" +dependencies = [ + "async-trait", + "auto_impl", + "crypto-bigint", + "eth-keystore", + "getrandom", + "rand", + "starknet-core 0.12.1", + "starknet-crypto 0.7.4", + "thiserror 1.0.69", +] + [[package]] name = "starknet-types-core" version = "0.1.7" @@ -4908,6 +5640,12 @@ dependencies = [ "syn 2.0.91", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "sync_wrapper" version = "1.0.2" @@ -4937,15 +5675,36 @@ dependencies = [ "types", ] +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation 0.9.4", + "system-configuration-sys 0.5.0", +] + [[package]] name = "system-configuration" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "bitflags", - "core-foundation", - "system-configuration-sys", + "bitflags 2.6.0", + "core-foundation 0.9.4", + "system-configuration-sys 0.6.0", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", ] [[package]] @@ -4958,6 +5717,24 @@ dependencies = [ "libc", ] +[[package]] +name = "tagged" +version = "0.15.3" +source = "git+https://github.com/eqlabs/pathfinder#98aa80659fc8efc5463993c03ebddebf6c9d4d9c" +dependencies = [ + "fake", +] + +[[package]] +name = "tagged-debug-derive" +version = "0.15.3" +source = "git+https://github.com/eqlabs/pathfinder#98aa80659fc8efc5463993c03ebddebf6c9d4d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "tap" version = "1.0.1" @@ -5091,7 +5868,9 @@ checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" dependencies = [ "deranged", "itoa", + "libc", "num-conv", + "num_threads", "powerfmt", "serde", "time-core", @@ -5133,6 +5912,21 @@ dependencies = [ "zerovec", ] +[[package]] +name = "tinyvec" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8" +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.42.0" @@ -5172,13 +5966,23 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls 0.21.12", + "tokio", +] + [[package]] name = "tokio-rustls" version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" dependencies = [ - "rustls", + "rustls 0.23.20", "tokio", ] @@ -5202,12 +6006,12 @@ checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9" dependencies = [ "futures-util", "log", - "rustls", + "rustls 0.23.20", "rustls-pki-types", "tokio", - "tokio-rustls", + "tokio-rustls 0.26.1", "tungstenite", - "webpki-roots", + "webpki-roots 0.26.7", ] [[package]] @@ -5266,7 +6070,7 @@ dependencies = [ "futures-core", "futures-util", "pin-project-lite", - "sync_wrapper", + "sync_wrapper 1.0.2", "tokio", "tower-layer", "tower-service", @@ -5366,11 +6170,11 @@ dependencies = [ "byteorder", "bytes", "data-encoding", - "http", + "http 1.2.0", "httparse", "log", "rand", - "rustls", + "rustls 0.23.20", "rustls-pki-types", "sha1", "thiserror 1.0.69", @@ -5395,7 +6199,9 @@ dependencies = [ "serde", "serde_json", "serde_with 3.12.0", - "starknet-crypto 0.7.3", + "starknet-crypto 0.7.4", + "starknet-gateway-types", + "starknet-types-core", "strum_macros", "thiserror 1.0.69", ] @@ -5498,6 +6304,16 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "uuid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +dependencies = [ + "getrandom", + "serde", +] + [[package]] name = "valuable" version = "0.1.0" @@ -5510,6 +6326,18 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "vergen" +version = "8.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2990d9ea5967266ea0ccf413a4aa5c42a93dbcfda9cb49a97de6931726b12566" +dependencies = [ + "anyhow", + "cfg-if", + "rustversion", + "time", +] + [[package]] name = "version_check" version = "0.9.5" @@ -5650,6 +6478,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-roots" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" + [[package]] name = "webpki-roots" version = "0.26.7" @@ -5702,7 +6536,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -5713,7 +6547,7 @@ checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" dependencies = [ "windows-result", "windows-strings", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -5722,7 +6556,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -5732,7 +6566,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" dependencies = [ "windows-result", - "windows-targets", + "windows-targets 0.52.6", +] + +[[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]] @@ -5741,7 +6584,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -5750,7 +6593,22 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", +] + +[[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]] @@ -5759,28 +6617,46 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] +[[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.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[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.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[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.6" @@ -5793,24 +6669,48 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[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.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[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.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[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.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[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.6" @@ -5826,6 +6726,16 @@ dependencies = [ "memchr", ] +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + [[package]] name = "write16" version = "1.0.0" diff --git a/Cargo.toml b/Cargo.toml index 02d4f9a0..774c0997 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ members = [ alloy = { version = "0.7.2", features = ["full"] } alloy-rlp = { version = "0.3.5", features = ["derive"] } bincode = { version = "2.0.0-rc.3", default-features = false, features = ["serde"] } -cairo-lang-casm = { version = "2.9.0-dev.0", default-features = false } +cairo-lang-casm = { version = "2.9.2", default-features = false } cairo-lang-starknet-classes = "2.9.2" cairo-type-derive = { git = "https://github.com/keep-starknet-strange/snos.git", rev = "35a300a10d2107482ada440b5025ee2f651afbd4" } cairo-vm = { git = "https://github.com/lambdaclass/cairo-vm", rev = "388a4e51001377717b7e4c902c35f8e271c92ad7", features = ["extensive_hints", "clap", "cairo-1-hints"] } @@ -34,9 +34,10 @@ serde = "1.0.215" serde_json = "1.0.132" serde_with = { version = "3.11.0", features = ["hex"] } sha3 = "0.10.8" +starknet = "0.13.0" starknet-core = { version = "0.11.1", default-features = false } starknet-crypto = { version = "0.7.1", default-features = false } -starknet-types-core = { version = "0.1.5", default-features = false } +starknet-types-core = { version = "0.1.6", default-features = false } strum_macros = "0.26.4" thiserror = "1.0.64" tiny-keccak = { version = "2.0.2", features = ["keccak"] } @@ -51,4 +52,5 @@ hints = { path = "crates/hints" } indexer = { path = "crates/indexer" } sound_hint_processor = { path = "crates/sound_hint_processor" } syscall_handler = { path = "crates/syscall_handler" } -types = { path = "crates/types" } \ No newline at end of file +types = { path = "crates/types" } +pathfinder_gateway_types = { git = "https://github.com/eqlabs/pathfinder", package = "starknet-gateway-types" } \ No newline at end of file diff --git a/README.md b/README.md index a222d1a3..ecaf703a 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ The overall program is split into two main parts: ## Testing -Some tests require Ethereum Sepolia RPC calls. Ensure an environment variable named `RPC` is set. +Some tests require chain nodes RPC calls. Ensure an environment variable named `ETH_RPC` and `STARKNET_RPC` is set. 1. **Build Cairo1 Modules:** ```bash diff --git a/crates/dry_hint_processor/Cargo.toml b/crates/dry_hint_processor/Cargo.toml index 0ef7b927..f75ad9cb 100644 --- a/crates/dry_hint_processor/Cargo.toml +++ b/crates/dry_hint_processor/Cargo.toml @@ -9,9 +9,11 @@ cairo-lang-casm.workspace = true cairo-lang-starknet-classes.workspace = true cairo-vm.workspace = true serde.workspace = true +starknet.workspace = true starknet-types-core.workspace = true strum_macros.workspace = true tokio.workspace = true +reqwest.workspace = true hints.workspace = true syscall_handler.workspace = true diff --git a/crates/dry_hint_processor/src/syscall_handler/evm/account.rs b/crates/dry_hint_processor/src/syscall_handler/evm/account.rs index a2b5bdd1..2415df6b 100644 --- a/crates/dry_hint_processor/src/syscall_handler/evm/account.rs +++ b/crates/dry_hint_processor/src/syscall_handler/evm/account.rs @@ -7,8 +7,8 @@ use syscall_handler::traits::CallHandler; use syscall_handler::{SyscallExecutionError, SyscallResult}; use types::{ cairo::{evm::account::FunctionId, structs::Uint256, traits::CairoType}, - keys::account::{CairoKey, Key}, - RPC, + keys::evm::account::{CairoKey, Key}, + ETH_RPC, }; #[derive(Debug, Default)] @@ -38,7 +38,7 @@ impl CallHandler for AccountCallHandler { } async fn handle(&mut self, key: Self::Key, function_id: Self::Id, _vm: &VirtualMachine) -> SyscallResult { - let provider = RootProvider::>::new_http(Url::parse(&env::var(RPC).unwrap()).unwrap()); + let provider = RootProvider::>::new_http(Url::parse(&env::var(ETH_RPC).unwrap()).unwrap()); let value = match function_id { FunctionId::Balance => provider .get_balance(key.address) diff --git a/crates/dry_hint_processor/src/syscall_handler/evm/header.rs b/crates/dry_hint_processor/src/syscall_handler/evm/header.rs index edbd05a2..33da1001 100644 --- a/crates/dry_hint_processor/src/syscall_handler/evm/header.rs +++ b/crates/dry_hint_processor/src/syscall_handler/evm/header.rs @@ -12,8 +12,8 @@ use types::{ structs::Uint256, traits::CairoType, }, - keys::header::{CairoKey, Key}, - RPC, + keys::evm::header::{CairoKey, Key}, + ETH_RPC, }; #[derive(Debug, Default)] @@ -43,7 +43,7 @@ impl CallHandler for HeaderCallHandler { } async fn handle(&mut self, key: Self::Key, function_id: Self::Id, _vm: &VirtualMachine) -> SyscallResult { - let provider = RootProvider::>::new_http(Url::parse(&env::var(RPC).unwrap()).unwrap()); + let provider = RootProvider::>::new_http(Url::parse(&env::var(ETH_RPC).unwrap()).unwrap()); let value = provider .get_block_by_number(key.block_number.into(), BlockTransactionsKind::Hashes) .await diff --git a/crates/dry_hint_processor/src/syscall_handler/evm/mod.rs b/crates/dry_hint_processor/src/syscall_handler/evm/mod.rs index 7439f243..225d1d93 100644 --- a/crates/dry_hint_processor/src/syscall_handler/evm/mod.rs +++ b/crates/dry_hint_processor/src/syscall_handler/evm/mod.rs @@ -109,9 +109,9 @@ impl TryFrom for CallHandlerId { #[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Hash, Clone)] #[serde(rename_all = "lowercase")] pub enum DryRunKey { - Account(keys::account::Key), - Header(keys::header::Key), - Storage(keys::storage::Key), + Account(keys::evm::account::Key), + Header(keys::evm::header::Key), + Storage(keys::evm::storage::Key), } impl DryRunKey { diff --git a/crates/dry_hint_processor/src/syscall_handler/evm/storage.rs b/crates/dry_hint_processor/src/syscall_handler/evm/storage.rs index c1ffbf73..85e70880 100644 --- a/crates/dry_hint_processor/src/syscall_handler/evm/storage.rs +++ b/crates/dry_hint_processor/src/syscall_handler/evm/storage.rs @@ -7,8 +7,8 @@ use syscall_handler::traits::CallHandler; use syscall_handler::{SyscallExecutionError, SyscallResult}; use types::{ cairo::{evm::storage::FunctionId, structs::Uint256, traits::CairoType}, - keys::storage::{CairoKey, Key}, - RPC, + keys::evm::storage::{CairoKey, Key}, + ETH_RPC, }; #[derive(Debug, Default)] @@ -38,7 +38,7 @@ impl CallHandler for StorageCallHandler { } async fn handle(&mut self, key: Self::Key, function_id: Self::Id, _vm: &VirtualMachine) -> SyscallResult { - let provider = RootProvider::>::new_http(Url::parse(&env::var(RPC).unwrap()).unwrap()); + let provider = RootProvider::>::new_http(Url::parse(&env::var(ETH_RPC).unwrap()).unwrap()); let value = match function_id { FunctionId::Storage => provider .get_storage_at(key.address, key.storage_slot.into()) diff --git a/crates/dry_hint_processor/src/syscall_handler/mod.rs b/crates/dry_hint_processor/src/syscall_handler/mod.rs index 69e68af8..b24a6d68 100644 --- a/crates/dry_hint_processor/src/syscall_handler/mod.rs +++ b/crates/dry_hint_processor/src/syscall_handler/mod.rs @@ -18,7 +18,7 @@ use types::cairo::new_syscalls::{CallContractRequest, CallContractResponse}; use types::cairo::traits::CairoType; pub const ETHEREUM_MAINNET_CHAIN_ID: u128 = 0x1; -pub const ETHEREUM_TESTNET_CHAIN_ID: u128 = 0x11155111; +pub const ETHEREUM_TESTNET_CHAIN_ID: u128 = 0xaa36a7; pub const STARKNET_MAINNET_CHAIN_ID: u128 = 0x534e5f4d41494e; pub const STARKNET_TESTNET_CHAIN_ID: u128 = 0x534e5f5345504f4c4941; @@ -87,8 +87,9 @@ impl traits::SyscallHandler for CallContractHandlerRelay { } async fn execute(&mut self, request: Self::Request, vm: &mut VirtualMachine) -> SyscallResult { - let chain_id = >::try_into(*vm.get_integer((request.calldata_start + 0)?)?) + let chain_id = >::try_into(*vm.get_integer((request.calldata_start + 2)?)?) .map_err(|e| SyscallExecutionError::InternalError(e.to_string().into()))?; + match chain_id { ETHEREUM_MAINNET_CHAIN_ID | ETHEREUM_TESTNET_CHAIN_ID => self.evm_call_contract_handler.execute(request, vm).await, STARKNET_MAINNET_CHAIN_ID | STARKNET_TESTNET_CHAIN_ID => self.starknet_call_contract_handler.execute(request, vm).await, diff --git a/crates/dry_hint_processor/src/syscall_handler/starknet/header.rs b/crates/dry_hint_processor/src/syscall_handler/starknet/header.rs new file mode 100644 index 00000000..f8f547da --- /dev/null +++ b/crates/dry_hint_processor/src/syscall_handler/starknet/header.rs @@ -0,0 +1,79 @@ +use cairo_vm::{types::relocatable::Relocatable, vm::vm_core::VirtualMachine, Felt252}; +use syscall_handler::traits::CallHandler; +use syscall_handler::{SyscallExecutionError, SyscallResult}; + +use std::env; +use types::{ + cairo::{ + starknet::header::{CairoHeader, FunctionId}, + structs::Felt, + traits::CairoType, + }, + keys::starknet::header::{CairoKey, Key}, + FEEDER_GATEWAY, +}; + +use crate::syscall_handler::{STARKNET_MAINNET_CHAIN_ID, STARKNET_TESTNET_CHAIN_ID}; + +#[derive(Debug, Default)] +pub struct HeaderCallHandler; + +#[allow(refining_impl_trait)] +impl CallHandler for HeaderCallHandler { + type Key = Key; + type Id = FunctionId; + type CallHandlerResult = Felt; + + fn derive_key(vm: &VirtualMachine, ptr: &mut Relocatable) -> SyscallResult { + let ret = CairoKey::from_memory(vm, *ptr)?; + *ptr = (*ptr + CairoKey::n_fields())?; + ret.try_into().map_err(|e| SyscallExecutionError::InternalError(format!("{}", e).into())) + } + + fn derive_id(selector: Felt252) -> SyscallResult { + Self::Id::from_repr(selector.try_into().map_err(|e| SyscallExecutionError::InvalidSyscallInput { + input: selector, + info: format!("{}", e), + })?) + .ok_or(SyscallExecutionError::InvalidSyscallInput { + input: selector, + info: "Invalid function identifier".to_string(), + }) + } + + async fn handle(&mut self, key: Self::Key, function_id: Self::Id, _vm: &VirtualMachine) -> SyscallResult { + let base_url = + env::var(FEEDER_GATEWAY).map_err(|e| SyscallExecutionError::InternalError(format!("Missing FEEDER_GATEWAY env var: {}", e).into()))?; + + // Feeder Gateway rejects the requests if this header is not set + let host_header = match key.chain_id { + STARKNET_MAINNET_CHAIN_ID => "alpha-mainnet.starknet.io", + STARKNET_TESTNET_CHAIN_ID => "alpha-sepolia.starknet.io", + _ => return Err(SyscallExecutionError::InternalError(format!("Unknown chain id: {}", key.chain_id).into())), + }; + + let request = reqwest::Client::new() + .get(format!("{}get_block", base_url)) + .header("Host", host_header) + .query(&[("blockNumber", key.block_number.to_string())]); + + let response = request + .send() + .await + .map_err(|e| SyscallExecutionError::InternalError(format!("Network request failed: {}", e).into()))?; + + let block_data = match response.status().is_success() { + true => response.json().await, + false => { + let status = response.status(); + let error_body = response.text().await.unwrap_or_default(); + return Err(SyscallExecutionError::InternalError( + format!("Request failed ({}): {}", status, error_body).into(), + )); + } + } + .map_err(|e| SyscallExecutionError::InternalError(format!("Failed to parse block data: {}", e).into()))?; + + Ok(CairoHeader::new(block_data).handle(function_id)) + } +} diff --git a/crates/dry_hint_processor/src/syscall_handler/starknet/mod.rs b/crates/dry_hint_processor/src/syscall_handler/starknet/mod.rs index d3229213..4eb74a0e 100644 --- a/crates/dry_hint_processor/src/syscall_handler/starknet/mod.rs +++ b/crates/dry_hint_processor/src/syscall_handler/starknet/mod.rs @@ -1,15 +1,21 @@ use cairo_vm::{types::relocatable::Relocatable, vm::vm_core::VirtualMachine, Felt252}; +use header::HeaderCallHandler; use serde::{Deserialize, Serialize}; use std::{collections::HashSet, hash::Hash}; +use storage::StorageCallHandler; use strum_macros::FromRepr; -use syscall_handler::traits::SyscallHandler; -use syscall_handler::{SyscallExecutionError, SyscallResult, WriteResponseResult}; +use syscall_handler::traits::{CallHandler, SyscallHandler}; +use syscall_handler::{felt_from_ptr, SyscallExecutionError, SyscallResult, WriteResponseResult}; use types::cairo::new_syscalls::{CallContractRequest, CallContractResponse}; -use types::keys; +use types::cairo::traits::CairoType; +use types::keys::starknet; +pub mod header; +pub mod storage; #[derive(FromRepr)] pub enum CallHandlerId { - Storage = 0, + Header = 0, + Storage = 1, } #[derive(Debug, Default, Serialize, Deserialize, Clone)] @@ -25,8 +31,45 @@ impl SyscallHandler for CallContractHandler { unreachable!() } - async fn execute(&mut self, _request: Self::Request, _vm: &mut VirtualMachine) -> SyscallResult { - unimplemented!() + async fn execute(&mut self, request: Self::Request, vm: &mut VirtualMachine) -> SyscallResult { + let mut calldata = request.calldata_start; + + let call_handler_id = CallHandlerId::try_from(request.contract_address)?; + let segment_index = felt_from_ptr(vm, &mut calldata)?; + let offset = felt_from_ptr(vm, &mut calldata)?; + + let _memorizer = Relocatable::from(( + segment_index + .try_into() + .map_err(|e| SyscallExecutionError::InternalError(format!("{}", e).into()))?, + offset + .try_into() + .map_err(|e| SyscallExecutionError::InternalError(format!("{}", e).into()))?, + )); + + let retdata_start = vm.add_temporary_segment(); + let mut retdata_end = retdata_start; + + match call_handler_id { + CallHandlerId::Header => { + let key = HeaderCallHandler::derive_key(vm, &mut calldata)?; + let function_id = HeaderCallHandler::derive_id(request.selector)?; + let result = HeaderCallHandler.handle(key.clone(), function_id, vm).await?; + self.key_set.insert(DryRunKey::Header(key)); + result.to_memory(vm, retdata_end)?; + retdata_end += ::CallHandlerResult::n_fields(); + } + CallHandlerId::Storage => { + let key = StorageCallHandler::derive_key(vm, &mut calldata)?; + let function_id = StorageCallHandler::derive_id(request.selector)?; + let result = StorageCallHandler.handle(key.clone(), function_id, vm).await?; + self.key_set.insert(DryRunKey::Storage(key)); + result.to_memory(vm, retdata_end)?; + retdata_end += ::CallHandlerResult::n_fields(); + } + } + + Ok(Self::Response { retdata_start, retdata_end }) } fn write_response(&mut self, _response: Self::Response, _vm: &mut VirtualMachine, _ptr: &mut Relocatable) -> WriteResponseResult { @@ -51,7 +94,8 @@ impl TryFrom for CallHandlerId { #[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Hash, Clone)] #[serde(rename_all = "lowercase")] pub enum DryRunKey { - Storage(keys::storage::Key), + Header(starknet::header::Key), + Storage(starknet::storage::Key), } impl DryRunKey { diff --git a/crates/dry_hint_processor/src/syscall_handler/starknet/storage.rs b/crates/dry_hint_processor/src/syscall_handler/starknet/storage.rs new file mode 100644 index 00000000..6326fd8d --- /dev/null +++ b/crates/dry_hint_processor/src/syscall_handler/starknet/storage.rs @@ -0,0 +1,58 @@ +use std::env; + +use cairo_vm::{types::relocatable::Relocatable, vm::vm_core::VirtualMachine, Felt252}; +use starknet::{ + core::types::BlockId, + providers::{ + jsonrpc::{HttpTransport, JsonRpcClient}, + Provider, Url, + }, +}; +use syscall_handler::traits::CallHandler; +use syscall_handler::{SyscallExecutionError, SyscallResult}; +use types::{ + cairo::{evm::storage::FunctionId, structs::Felt, traits::CairoType}, + keys::starknet::storage::{CairoKey, Key}, + STARKNET_RPC, +}; + +#[derive(Debug, Default)] +pub struct StorageCallHandler; + +#[allow(refining_impl_trait)] +impl CallHandler for StorageCallHandler { + type Key = Key; + type Id = FunctionId; + type CallHandlerResult = Felt; + + fn derive_key(vm: &VirtualMachine, ptr: &mut Relocatable) -> SyscallResult { + let ret = CairoKey::from_memory(vm, *ptr)?; + *ptr = (*ptr + CairoKey::n_fields())?; + ret.try_into().map_err(|e| SyscallExecutionError::InternalError(format!("{}", e).into())) + } + + fn derive_id(selector: Felt252) -> SyscallResult { + Self::Id::from_repr(selector.try_into().map_err(|e| SyscallExecutionError::InvalidSyscallInput { + input: selector, + info: format!("{}", e), + })?) + .ok_or(SyscallExecutionError::InvalidSyscallInput { + input: selector, + info: "Invalid function identifier".to_string(), + }) + } + + async fn handle(&mut self, key: Self::Key, function_id: Self::Id, _vm: &VirtualMachine) -> SyscallResult { + let provider = JsonRpcClient::new(HttpTransport::new(Url::parse(&env::var(STARKNET_RPC).unwrap()).unwrap())); + let block_id = BlockId::Number(key.block_number); + let value = match function_id { + FunctionId::Storage => provider + .get_storage_at::(key.address, key.storage_slot, block_id) + .await + .map(Felt::from), + } + .map_err(|e| SyscallExecutionError::InternalError(e.to_string().into()))?; + + Ok(value) + } +} diff --git a/crates/fetcher/src/main.rs b/crates/fetcher/src/main.rs index a7544ede..f56666d4 100644 --- a/crates/fetcher/src/main.rs +++ b/crates/fetcher/src/main.rs @@ -12,7 +12,11 @@ use proof_keys::ProofKeys; use std::{collections::HashSet, fs, path::PathBuf}; use thiserror as _; use types::{ - proofs::{account::Account, storage::Storage, HeaderMmrMeta, Proofs}, + proofs::{ + self, + evm::{account::Account, storage::Storage, Proofs}, + header::HeaderMmrMeta, + }, ChainProofs, }; @@ -66,7 +70,7 @@ async fn main() -> Result<(), FetcherError> { pb_storage_keys.set_style(progress_style); pb_storage_keys.set_message("storage_keys"); - let mut headers_with_mmr: HashSet = HashSet::default(); + let mut headers_with_mmr: HashSet> = HashSet::default(); let mut headers_with_mmr_fut = futures::stream::iter(proof_keys.header_keys.iter().map(ProofKeys::fetch_header_proof).map(|f| f.boxed_local())) .buffer_unordered(BUFFER_UNORDERED); diff --git a/crates/fetcher/src/proof_keys.rs b/crates/fetcher/src/proof_keys.rs index 895f2910..d84b4f3e 100644 --- a/crates/fetcher/src/proof_keys.rs +++ b/crates/fetcher/src/proof_keys.rs @@ -12,23 +12,21 @@ use std::{collections::HashSet, env}; use types::{ keys, proofs::{ - account::Account, - header::{Header, HeaderProof}, + evm, + header::{HeaderMmrMeta, HeaderProof}, mmr::MmrMeta, mpt::MPTProof, - storage::Storage, - HeaderMmrMeta, }, - RPC, + ETH_RPC, }; use crate::FetcherError; #[derive(Debug, Default)] pub struct ProofKeys { - pub header_keys: HashSet, - pub account_keys: HashSet, - pub storage_keys: HashSet, + pub header_keys: HashSet, + pub account_keys: HashSet, + pub storage_keys: HashSet, } impl ProofKeys { @@ -37,7 +35,7 @@ impl ProofKeys { format!("{:0>width$}", hex_str, width = (hex_str.len() + 1) / 2 * 2) } - pub async fn fetch_header_proof(key: &keys::header::Key) -> Result { + pub async fn fetch_header_proof(key: &keys::evm::header::Key) -> Result, FetcherError> { let provider = Indexer::default(); // Fetch proof response @@ -78,7 +76,7 @@ impl ProofKeys { }; // Construct Header - let header = Header { + let header = evm::header::Header { rlp, proof: HeaderProof { leaf_idx: mmr_proof.element_index, @@ -96,8 +94,10 @@ impl ProofKeys { }) } - pub async fn fetch_account_proof(key: &keys::account::Key) -> Result<(HeaderMmrMeta, Account), FetcherError> { - let provider = RootProvider::>::new_http(Url::parse(&env::var(RPC).unwrap()).unwrap()); + pub async fn fetch_account_proof( + key: &keys::evm::account::Key, + ) -> Result<(HeaderMmrMeta, evm::account::Account), FetcherError> { + let provider = RootProvider::>::new_http(Url::parse(&env::var(ETH_RPC).unwrap()).unwrap()); let value = provider .get_proof(key.address, vec![]) .block_id(key.block_number.into()) @@ -105,12 +105,14 @@ impl ProofKeys { .map_err(|e| FetcherError::InternalError(e.to_string()))?; Ok(( Self::fetch_header_proof(&key.to_owned().into()).await?, - Account::new(value.address, vec![MPTProof::new(key.block_number, value.account_proof)]), + evm::account::Account::new(value.address, vec![MPTProof::new(key.block_number, value.account_proof)]), )) } - pub async fn fetch_storage_proof(key: &keys::storage::Key) -> Result<(HeaderMmrMeta, Account, Storage), FetcherError> { - let provider = RootProvider::>::new_http(Url::parse(&env::var(RPC).unwrap()).unwrap()); + pub async fn fetch_storage_proof( + key: &keys::evm::storage::Key, + ) -> Result<(HeaderMmrMeta, evm::account::Account, evm::storage::Storage), FetcherError> { + let provider = RootProvider::>::new_http(Url::parse(&env::var(ETH_RPC).unwrap()).unwrap()); let value = provider .get_proof(key.address, vec![key.storage_slot]) .block_id(key.block_number.into()) @@ -118,8 +120,8 @@ impl ProofKeys { .map_err(|e| FetcherError::InternalError(e.to_string()))?; Ok(( Self::fetch_header_proof(&key.to_owned().into()).await?, - Account::new(value.address, vec![MPTProof::new(key.block_number, value.account_proof)]), - Storage::new( + evm::account::Account::new(value.address, vec![MPTProof::new(key.block_number, value.account_proof)]), + evm::storage::Storage::new( value.address, key.storage_slot, vec![MPTProof::new( diff --git a/crates/hints/src/lib.rs b/crates/hints/src/lib.rs index 0c7f3a45..07292797 100644 --- a/crates/hints/src/lib.rs +++ b/crates/hints/src/lib.rs @@ -71,7 +71,7 @@ pub fn hints() -> HashMap { hints.insert(verifiers::evm::header_verifier::HINT_RLP_LEN.into(), verifiers::evm::header_verifier::hint_rlp_len); hints.insert(verifiers::evm::header_verifier::HINT_SET_HEADER.into(), verifiers::evm::header_verifier::hint_set_header); hints.insert(verifiers::evm::header_verifier::HINT_VM_ENTER_SCOPE.into(), verifiers::evm::header_verifier::hint_vm_enter_scope); - hints.insert(verifiers::evm::HINT_HEADERS_WITH_MMR_LEN.into(), verifiers::evm::hint_headers_with_mmr_headers_len); + hints.insert(verifiers::evm::header_verifier::HINT_HEADERS_WITH_MMR_LEN.into(), verifiers::evm::header_verifier::hint_headers_with_mmr_len); hints.insert(verifiers::evm::receipt_verifier::HINT_BATCH_RECEIPTS_LEN.into(), verifiers::evm::receipt_verifier::hint_batch_receipts_len); hints.insert(verifiers::evm::receipt_verifier::HINT_RECEIPT_BLOCK_NUMBER.into(), verifiers::evm::receipt_verifier::hint_receipt_block_number); hints.insert(verifiers::evm::receipt_verifier::HINT_RECEIPT_KEY_LEADING_ZEROS.into(), verifiers::evm::receipt_verifier::hint_receipt_key_leading_zeros); @@ -95,14 +95,22 @@ pub fn hints() -> HashMap { hints.insert(verifiers::evm::transaction_verifier::HINT_SET_TX_KEY.into(), verifiers::evm::transaction_verifier::hint_set_tx_key); hints.insert(verifiers::evm::transaction_verifier::HINT_SET_TX_PROOF_LEN.into(), verifiers::evm::transaction_verifier::hint_set_tx_proof_len); hints.insert(verifiers::evm::transaction_verifier::HINT_SET_TX.into(), verifiers::evm::transaction_verifier::hint_set_tx); - hints.insert(verifiers::mmr_verifier::HINT_HEADERS_WITH_MMR_META_ID.into(), verifiers::mmr_verifier::hint_headers_with_mmr_meta_id); - hints.insert(verifiers::mmr_verifier::HINT_HEADERS_WITH_MMR_META_PEAKS_LEN.into(), verifiers::mmr_verifier::hint_headers_with_mmr_meta_peaks_len); - hints.insert(verifiers::mmr_verifier::HINT_HEADERS_WITH_MMR_META_ROOT.into(), verifiers::mmr_verifier::hint_headers_with_mmr_meta_root); - hints.insert(verifiers::mmr_verifier::HINT_HEADERS_WITH_MMR_META_SIZE.into(), verifiers::mmr_verifier::hint_headers_with_mmr_meta_size); - hints.insert(verifiers::mmr_verifier::HINT_HEADERS_WITH_MMR_PEAKS.into(), verifiers::mmr_verifier::hint_headers_with_mmr_peaks); + hints.insert(verifiers::evm::mmr_verifier::HINT_HEADERS_WITH_MMR_META_ID.into(), verifiers::evm::mmr_verifier::hint_headers_with_mmr_meta_id); + hints.insert(verifiers::evm::mmr_verifier::HINT_HEADERS_WITH_MMR_META_PEAKS_LEN.into(), verifiers::evm::mmr_verifier::hint_headers_with_mmr_meta_peaks_len); + hints.insert(verifiers::evm::mmr_verifier::HINT_HEADERS_WITH_MMR_META_ROOT.into(), verifiers::evm::mmr_verifier::hint_headers_with_mmr_meta_root); + hints.insert(verifiers::evm::mmr_verifier::HINT_HEADERS_WITH_MMR_META_SIZE.into(), verifiers::evm::mmr_verifier::hint_headers_with_mmr_meta_size); + hints.insert(verifiers::evm::mmr_verifier::HINT_HEADERS_WITH_MMR_PEAKS.into(), verifiers::evm::mmr_verifier::hint_headers_with_mmr_peaks); + hints.insert(verifiers::starknet::mmr_verifier::HINT_HEADERS_WITH_MMR_META_ID.into(), verifiers::starknet::mmr_verifier::hint_headers_with_mmr_meta_id); + hints.insert(verifiers::starknet::mmr_verifier::HINT_HEADERS_WITH_MMR_META_PEAKS_LEN.into(), verifiers::starknet::mmr_verifier::hint_headers_with_mmr_meta_peaks_len); + hints.insert(verifiers::starknet::mmr_verifier::HINT_HEADERS_WITH_MMR_META_ROOT.into(), verifiers::starknet::mmr_verifier::hint_headers_with_mmr_meta_root); + hints.insert(verifiers::starknet::mmr_verifier::HINT_HEADERS_WITH_MMR_META_SIZE.into(), verifiers::starknet::mmr_verifier::hint_headers_with_mmr_meta_size); + hints.insert(verifiers::starknet::mmr_verifier::HINT_HEADERS_WITH_MMR_PEAKS.into(), verifiers::starknet::mmr_verifier::hint_headers_with_mmr_peaks); hints.insert(verifiers::verify::HINT_CHAIN_PROOFS_LEN.into(), verifiers::verify::hint_chain_proofs_len); hints.insert(verifiers::verify::HINT_CHAIN_PROOFS_CHAIN_ID.into(), verifiers::verify::hint_chain_proofs_chain_id); - hints.insert(verifiers::verify::HINT_VM_ENTER_SCOPE.into(), verifiers::verify::hint_vm_enter_scope); + hints.insert(verifiers::evm::HINT_VM_ENTER_SCOPE.into(), verifiers::evm::hint_vm_enter_scope); + hints.insert(verifiers::evm::HINT_HEADERS_WITH_MMR_LEN.into(), verifiers::evm::hint_headers_with_mmr_len); + hints.insert(verifiers::starknet::HINT_VM_ENTER_SCOPE.into(), verifiers::starknet::hint_vm_enter_scope); + hints.insert(verifiers::starknet::HINT_HEADERS_WITH_MMR_LEN.into(), verifiers::starknet::hint_headers_with_mmr_len); hints.insert(eth_essentials_cairo_vm_hints::hints::lib::bit_length::HINT_BIT_LENGTH.into(), eth_essentials_cairo_vm_hints::hints::lib::bit_length::hint_bit_length); hints.insert(eth_essentials_cairo_vm_hints::hints::lib::mmr::bit_length::MMR_BIT_LENGTH.into(), eth_essentials_cairo_vm_hints::hints::lib::mmr::bit_length::mmr_bit_length); diff --git a/crates/hints/src/vars.rs b/crates/hints/src/vars.rs index f4fc0352..7c1035ea 100644 --- a/crates/hints/src/vars.rs +++ b/crates/hints/src/vars.rs @@ -1,22 +1,34 @@ pub mod scopes { - pub const ACCOUNT: &str = "account"; - pub const BATCH: &str = "batch"; + pub const ACCOUNT_EVM: &str = "account_evm"; + pub const BATCH_EVM: &str = "batch_evm"; + pub const BATCH_STARKNET: &str = "batch_starknet"; pub const COMPILED_CLASS: &str = "compiled_class"; pub const DICT_MANAGER: &str = "dict_manager"; - pub const HEADER: &str = "header"; + pub const HEADER_EVM: &str = "header_evm"; + pub const HEADER_STARKNET: &str = "header_starknet"; pub const N_SELECTED_BUILTINS: &str = "n_selected_builtins"; pub const PARAMS: &str = "params"; pub const PROOF: &str = "proof"; pub const PROOFS: &str = "proofs"; pub const CHAIN_PROOFS: &str = "chain_proofs"; pub const RECEIPT: &str = "receipt"; - pub const STORAGE: &str = "storage"; + pub const STORAGE_EVM: &str = "storage_evm"; + pub const STORAGE_STARKNET: &str = "storage_starknet"; pub const SYSCALL_HANDLER: &str = "syscall_handler"; pub const TRANSACTION: &str = "transaction"; - pub const HEADER_WITH_MMR: &str = "header_with_mmr"; + pub const HEADER_WITH_MMR_EVM: &str = "header_with_mmr"; + pub const HEADER_WITH_MMR_STARKNET: &str = "header_with_mmr_starknet"; } pub mod ids { + pub const NODES: &str = "nodes"; + pub const NODE: &str = "node"; + pub const N_NODES: &str = "n_nodes"; + pub const LEAF: &str = "leaf"; + pub const CONTRACT_STATE_NODES: &str = "contract_state_nodes"; + pub const CONTRACT_NODES: &str = "contract_nodes"; + pub const STORAGE_ADDRESSES: &str = "storage_addresses"; + pub const FIELDS: &str = "fields"; pub const PEAKS: &str = "peaks"; pub const CHAIN_PROOFS_LEN: &str = "chain_proofs_len"; pub const RLP_LEN: &str = "rlp_len"; diff --git a/crates/hints/src/verifiers/evm/account_verifier.rs b/crates/hints/src/verifiers/evm/account_verifier.rs index ff3a2b99..4dd842be 100644 --- a/crates/hints/src/verifiers/evm/account_verifier.rs +++ b/crates/hints/src/verifiers/evm/account_verifier.rs @@ -16,9 +16,9 @@ use cairo_vm::{ }; use num_bigint::BigUint; use std::collections::HashMap; -use types::proofs::{account::Account, mpt::MPTProof, Proofs}; +use types::proofs::{evm::account::Account, evm::Proofs, mpt::MPTProof}; -pub const HINT_BATCH_ACCOUNTS_LEN: &str = "memory[ap] = to_felt_or_relocatable(len(batch.accounts))"; +pub const HINT_BATCH_ACCOUNTS_LEN: &str = "memory[ap] = to_felt_or_relocatable(len(batch_evm.accounts))"; pub fn hint_batch_accounts_len( vm: &mut VirtualMachine, @@ -26,13 +26,13 @@ pub fn hint_batch_accounts_len( _hint_data: &HintProcessorData, _constants: &HashMap, ) -> Result<(), HintError> { - let batch = exec_scopes.get::(vars::scopes::BATCH)?; + let batch = exec_scopes.get::(vars::scopes::BATCH_EVM)?; insert_value_into_ap(vm, Felt252::from(batch.accounts.len())) } pub const HINT_GET_ACCOUNT_ADDRESS: &str = - "account = batch.accounts[ids.idx]\nsegments.write_arg(ids.address, [int(x, 16) for x in account.address]))"; + "account_evm = batch_evm.accounts[ids.idx]\nsegments.write_arg(ids.address, [int(x, 16) for x in account_evm.address]))"; pub fn hint_get_account_address( vm: &mut VirtualMachine, @@ -40,7 +40,7 @@ pub fn hint_get_account_address( hint_data: &HintProcessorData, _constants: &HashMap, ) -> Result<(), HintError> { - let batch = exec_scopes.get::(vars::scopes::BATCH)?; + let batch = exec_scopes.get::(vars::scopes::BATCH_EVM)?; let idx: usize = get_integer_from_var_name(vars::ids::IDX, vm, &hint_data.ids_data, &hint_data.ap_tracking)? .try_into() .unwrap(); @@ -51,7 +51,7 @@ pub fn hint_get_account_address( .map(|chunk| MaybeRelocatable::from(Felt252::from_bytes_be_slice(&chunk.iter().rev().copied().collect::>()))) .collect(); - exec_scopes.insert_value::(vars::scopes::ACCOUNT, account); + exec_scopes.insert_value::(vars::scopes::ACCOUNT_EVM, account); let address_ptr = get_ptr_from_var_name(vars::ids::ADDRESS, vm, &hint_data.ids_data, &hint_data.ap_tracking)?; @@ -60,7 +60,7 @@ pub fn hint_get_account_address( Ok(()) } -pub const HINT_ACCOUNT_KEY: &str = "from tools.py.utils import split_128\n(ids.key.low, ids.key.high) = split_128(int(account.account_key, 16))"; +pub const HINT_ACCOUNT_KEY: &str = "from tools.py.utils import split_128\n(ids.key.low, ids.key.high) = split_128(int(account_evm.account_key, 16))"; pub fn hint_account_key( vm: &mut VirtualMachine, @@ -68,7 +68,7 @@ pub fn hint_account_key( hint_data: &HintProcessorData, _constants: &HashMap, ) -> Result<(), HintError> { - let account = exec_scopes.get::(vars::scopes::ACCOUNT)?; + let account = exec_scopes.get::(vars::scopes::ACCOUNT_EVM)?; let (key_low, key_high) = split_128(&BigUint::from_bytes_be(account.account_key.as_slice())); @@ -80,7 +80,7 @@ pub fn hint_account_key( } pub const HINT_ACCOUNT_KEY_LEADING_ZEROS: &str = - "ids.key_leading_zeros = len(account.account_key.lstrip(\"0x\")) - len(account.account_key.lstrip(\"0x\").lstrip(\"0\"))"; + "ids.key_leading_zeros = len(account_evm.account_key.lstrip(\"0x\")) - len(account_evm.account_key.lstrip(\"0x\").lstrip(\"0\"))"; pub fn hint_account_key_leading_zeros( vm: &mut VirtualMachine, @@ -88,7 +88,7 @@ pub fn hint_account_key_leading_zeros( hint_data: &HintProcessorData, _constants: &HashMap, ) -> Result<(), HintError> { - let account = exec_scopes.get::(vars::scopes::ACCOUNT)?; + let account = exec_scopes.get::(vars::scopes::ACCOUNT_EVM)?; let key_leading_zeros = count_leading_zero_nibbles_from_hex(&account.account_key.to_string()); insert_value_from_var_name( @@ -100,7 +100,7 @@ pub fn hint_account_key_leading_zeros( ) } -pub const HINT_ACCOUNT_PROOFS_LEN: &str = "memory[ap] = to_felt_or_relocatable(len(account.proofs))"; +pub const HINT_ACCOUNT_PROOFS_LEN: &str = "memory[ap] = to_felt_or_relocatable(len(account_evm.proofs))"; pub fn hint_account_proofs_len( vm: &mut VirtualMachine, @@ -108,12 +108,12 @@ pub fn hint_account_proofs_len( _hint_data: &HintProcessorData, _constants: &HashMap, ) -> Result<(), HintError> { - let account = exec_scopes.get::(vars::scopes::ACCOUNT)?; + let account = exec_scopes.get::(vars::scopes::ACCOUNT_EVM)?; insert_value_into_ap(vm, Felt252::from(account.proofs.len())) } -pub const HINT_ACCOUNT_PROOF_AT: &str = "proof = account.proofs[ids.idx]"; +pub const HINT_ACCOUNT_PROOF_AT: &str = "proof = account_evm.proofs[ids.idx]"; pub fn hint_account_proof_at( vm: &mut VirtualMachine, @@ -121,7 +121,7 @@ pub fn hint_account_proof_at( hint_data: &HintProcessorData, _constants: &HashMap, ) -> Result<(), HintError> { - let account = exec_scopes.get::(vars::scopes::ACCOUNT)?; + let account = exec_scopes.get::(vars::scopes::ACCOUNT_EVM)?; let idx: usize = get_integer_from_var_name(vars::ids::IDX, vm, &hint_data.ids_data, &hint_data.ap_tracking)? .try_into() .unwrap(); diff --git a/crates/hints/src/verifiers/evm/header_verifier.rs b/crates/hints/src/verifiers/evm/header_verifier.rs index 6afd813f..1c1629b1 100644 --- a/crates/hints/src/verifiers/evm/header_verifier.rs +++ b/crates/hints/src/verifiers/evm/header_verifier.rs @@ -10,9 +10,23 @@ use cairo_vm::{ Felt252, }; use std::{any::Any, cell::RefCell, collections::HashMap, rc::Rc}; -use types::proofs::{header::Header, HeaderMmrMeta, Proofs}; +use types::proofs::{evm, header::HeaderMmrMeta}; -pub const HINT_VM_ENTER_SCOPE: &str = "vm_enter_scope({'header_with_mmr': batch.headers_with_mmr[ids.idx - 1], '__dict_manager': __dict_manager})"; +pub const HINT_HEADERS_WITH_MMR_LEN: &str = "memory[ap] = to_felt_or_relocatable(len(batch_evm.headers_with_mmr))"; + +pub fn hint_headers_with_mmr_len( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + _hint_data: &HintProcessorData, + _constants: &HashMap, +) -> Result<(), HintError> { + let proofs = exec_scopes.get::(vars::scopes::BATCH_EVM)?; + + insert_value_into_ap(vm, Felt252::from(proofs.headers_with_mmr.len())) +} + +pub const HINT_VM_ENTER_SCOPE: &str = + "vm_enter_scope({'header_with_mmr_evm': batch_evm.headers_with_mmr[ids.idx - 1], '__dict_manager': __dict_manager})"; pub fn hint_vm_enter_scope( vm: &mut VirtualMachine, @@ -20,7 +34,7 @@ pub fn hint_vm_enter_scope( hint_data: &HintProcessorData, _constants: &HashMap, ) -> Result<(), HintError> { - let proofs = exec_scopes.get::(vars::scopes::BATCH)?; + let proofs = exec_scopes.get::(vars::scopes::BATCH_EVM)?; let idx: usize = get_integer_from_var_name(vars::ids::IDX, vm, &hint_data.ids_data, &hint_data.ap_tracking)? .try_into() .unwrap(); @@ -28,14 +42,14 @@ pub fn hint_vm_enter_scope( let headers_with_mmr: Box = Box::new(proofs.headers_with_mmr[idx - 1].clone()); let dict_manager: Box = Box::new(exec_scopes.get::>>(vars::scopes::DICT_MANAGER)?); exec_scopes.enter_scope(HashMap::from([ - (String::from(vars::scopes::HEADER_WITH_MMR), headers_with_mmr), + (String::from(vars::scopes::HEADER_WITH_MMR_EVM), headers_with_mmr), (String::from(vars::scopes::DICT_MANAGER), dict_manager), ])); Ok(()) } -pub const HINT_HEADERS_WITH_MMR_HEADERS_LEN: &str = "memory[ap] = to_felt_or_relocatable(len(header_with_mmr.headers))"; +pub const HINT_HEADERS_WITH_MMR_HEADERS_LEN: &str = "memory[ap] = to_felt_or_relocatable(len(header_with_mmr_evm.headers))"; pub fn hint_headers_with_mmr_headers_len( vm: &mut VirtualMachine, @@ -43,12 +57,13 @@ pub fn hint_headers_with_mmr_headers_len( _hint_data: &HintProcessorData, _constants: &HashMap, ) -> Result<(), HintError> { - let header_with_mmr = exec_scopes.get::(vars::scopes::HEADER_WITH_MMR)?; + let header_with_mmr = exec_scopes.get::>(vars::scopes::HEADER_WITH_MMR_EVM)?; insert_value_into_ap(vm, Felt252::from(header_with_mmr.headers.len())) } -pub const HINT_SET_HEADER: &str = "header = header_with_mmr.headers[ids.idx - 1]\nsegments.write_arg(ids.rlp, [int(x, 16) for x in header.rlp])"; +pub const HINT_SET_HEADER: &str = + "header_evm = header_with_mmr_evm.headers[ids.idx - 1]\nsegments.write_arg(ids.rlp, [int(x, 16) for x in header_evm.rlp])"; pub fn hint_set_header( vm: &mut VirtualMachine, @@ -56,7 +71,7 @@ pub fn hint_set_header( hint_data: &HintProcessorData, _constants: &HashMap, ) -> Result<(), HintError> { - let headers_with_mmr = exec_scopes.get::(vars::scopes::HEADER_WITH_MMR)?; + let headers_with_mmr = exec_scopes.get::>(vars::scopes::HEADER_WITH_MMR_EVM)?; let idx: usize = get_integer_from_var_name(vars::ids::IDX, vm, &hint_data.ids_data, &hint_data.ap_tracking)? .try_into() .unwrap(); @@ -68,7 +83,7 @@ pub fn hint_set_header( .map(|chunk| MaybeRelocatable::from(Felt252::from_bytes_be_slice(&chunk.iter().rev().copied().collect::>()))) .collect(); - exec_scopes.insert_value::
(vars::scopes::HEADER, header); + exec_scopes.insert_value::(vars::scopes::HEADER_EVM, header); let rlp_ptr = get_ptr_from_var_name(vars::ids::RLP, vm, &hint_data.ids_data, &hint_data.ap_tracking)?; @@ -77,7 +92,7 @@ pub fn hint_set_header( Ok(()) } -pub const HINT_RLP_LEN: &str = "memory[ap] = to_felt_or_relocatable(len(header.rlp))"; +pub const HINT_RLP_LEN: &str = "memory[ap] = to_felt_or_relocatable(len(header_evm.rlp))"; pub fn hint_rlp_len( vm: &mut VirtualMachine, @@ -85,12 +100,12 @@ pub fn hint_rlp_len( _hint_data: &HintProcessorData, _constants: &HashMap, ) -> Result<(), HintError> { - let header = exec_scopes.get::
(vars::scopes::HEADER)?; + let header = exec_scopes.get::(vars::scopes::HEADER_EVM)?; insert_value_into_ap(vm, Felt252::from(header.rlp.chunks(8).count())) } -pub const HINT_LEAF_IDX: &str = "memory[ap] = to_felt_or_relocatable(len(header.proof.leaf_idx))"; +pub const HINT_LEAF_IDX: &str = "memory[ap] = to_felt_or_relocatable(len(header_evm.proof.leaf_idx))"; pub fn hint_leaf_idx( vm: &mut VirtualMachine, @@ -98,12 +113,12 @@ pub fn hint_leaf_idx( _hint_data: &HintProcessorData, _constants: &HashMap, ) -> Result<(), HintError> { - let header = exec_scopes.get::
(vars::scopes::HEADER)?; + let header = exec_scopes.get::(vars::scopes::HEADER_EVM)?; insert_value_into_ap(vm, Felt252::from(header.proof.leaf_idx)) } -pub const HINT_MMR_PATH_LEN: &str = "memory[ap] = to_felt_or_relocatable(len(header.proof.mmr_path))"; +pub const HINT_MMR_PATH_LEN: &str = "memory[ap] = to_felt_or_relocatable(len(header_evm.proof.mmr_path))"; pub fn hint_mmr_path_len( vm: &mut VirtualMachine, @@ -111,12 +126,12 @@ pub fn hint_mmr_path_len( _hint_data: &HintProcessorData, _constants: &HashMap, ) -> Result<(), HintError> { - let header = exec_scopes.get::
(vars::scopes::HEADER)?; + let header = exec_scopes.get::(vars::scopes::HEADER_EVM)?; insert_value_into_ap(vm, Felt252::from(header.proof.mmr_path.len())) } -pub const HINT_MMR_PATH: &str = "segments.write_arg(ids.mmr_path, [int(x, 16) for x in header.proof.mmr_path])"; +pub const HINT_MMR_PATH: &str = "segments.write_arg(ids.mmr_path, [int(x, 16) for x in header_evm.proof.mmr_path])"; pub fn hint_mmr_path( vm: &mut VirtualMachine, @@ -124,7 +139,7 @@ pub fn hint_mmr_path( hint_data: &HintProcessorData, _constants: &HashMap, ) -> Result<(), HintError> { - let header = exec_scopes.get::
(vars::scopes::HEADER)?; + let header = exec_scopes.get::(vars::scopes::HEADER_EVM)?; let mmr_path_ptr = get_ptr_from_var_name(vars::ids::MMR_PATH, vm, &hint_data.ids_data, &hint_data.ap_tracking)?; let mmr_path: Vec = header .proof diff --git a/crates/hints/src/verifiers/mmr_verifier.rs b/crates/hints/src/verifiers/evm/mmr_verifier.rs similarity index 73% rename from crates/hints/src/verifiers/mmr_verifier.rs rename to crates/hints/src/verifiers/evm/mmr_verifier.rs index 811769df..39907c20 100644 --- a/crates/hints/src/verifiers/mmr_verifier.rs +++ b/crates/hints/src/verifiers/evm/mmr_verifier.rs @@ -8,9 +8,10 @@ use cairo_vm::{ Felt252, }; use std::collections::HashMap; -use types::proofs::HeaderMmrMeta; +use types::proofs::evm; +use types::proofs::header::HeaderMmrMeta; -pub const HINT_HEADERS_WITH_MMR_META_PEAKS_LEN: &str = "memory[ap] = to_felt_or_relocatable(len(header_with_mmr.mmr_meta.peaks))"; +pub const HINT_HEADERS_WITH_MMR_META_PEAKS_LEN: &str = "memory[ap] = to_felt_or_relocatable(len(header_with_mmr_evm.mmr_meta.peaks))"; pub fn hint_headers_with_mmr_meta_peaks_len( vm: &mut VirtualMachine, @@ -18,12 +19,12 @@ pub fn hint_headers_with_mmr_meta_peaks_len( _hint_data: &HintProcessorData, _constants: &HashMap, ) -> Result<(), HintError> { - let header_with_mmr = exec_scopes.get::(vars::scopes::HEADER_WITH_MMR)?; + let header_with_mmr = exec_scopes.get::>(vars::scopes::HEADER_WITH_MMR_EVM)?; insert_value_into_ap(vm, Felt252::from(header_with_mmr.mmr_meta.peaks.len())) } -pub const HINT_HEADERS_WITH_MMR_META_ID: &str = "memory[ap] = to_felt_or_relocatable(header_with_mmr.mmr_meta.id)"; +pub const HINT_HEADERS_WITH_MMR_META_ID: &str = "memory[ap] = to_felt_or_relocatable(header_with_mmr_evm.mmr_meta.id)"; pub fn hint_headers_with_mmr_meta_id( vm: &mut VirtualMachine, @@ -31,12 +32,12 @@ pub fn hint_headers_with_mmr_meta_id( _hint_data: &HintProcessorData, _constants: &HashMap, ) -> Result<(), HintError> { - let header_with_mmr = exec_scopes.get::(vars::scopes::HEADER_WITH_MMR)?; + let header_with_mmr = exec_scopes.get::>(vars::scopes::HEADER_WITH_MMR_EVM)?; insert_value_into_ap(vm, Felt252::from(header_with_mmr.mmr_meta.id)) } -pub const HINT_HEADERS_WITH_MMR_META_ROOT: &str = "memory[ap] = to_felt_or_relocatable(header_with_mmr.mmr_meta.root)"; +pub const HINT_HEADERS_WITH_MMR_META_ROOT: &str = "memory[ap] = to_felt_or_relocatable(header_with_mmr_evm.mmr_meta.root)"; pub fn hint_headers_with_mmr_meta_root( vm: &mut VirtualMachine, @@ -44,12 +45,12 @@ pub fn hint_headers_with_mmr_meta_root( _hint_data: &HintProcessorData, _constants: &HashMap, ) -> Result<(), HintError> { - let header_with_mmr = exec_scopes.get::(vars::scopes::HEADER_WITH_MMR)?; + let header_with_mmr = exec_scopes.get::>(vars::scopes::HEADER_WITH_MMR_EVM)?; insert_value_into_ap(vm, Felt252::from_bytes_be_slice(&header_with_mmr.mmr_meta.root)) } -pub const HINT_HEADERS_WITH_MMR_META_SIZE: &str = "memory[ap] = to_felt_or_relocatable(header_with_mmr.mmr_meta.size)"; +pub const HINT_HEADERS_WITH_MMR_META_SIZE: &str = "memory[ap] = to_felt_or_relocatable(header_with_mmr_evm.mmr_meta.size)"; pub fn hint_headers_with_mmr_meta_size( vm: &mut VirtualMachine, @@ -57,12 +58,12 @@ pub fn hint_headers_with_mmr_meta_size( _hint_data: &HintProcessorData, _constants: &HashMap, ) -> Result<(), HintError> { - let header_with_mmr = exec_scopes.get::(vars::scopes::HEADER_WITH_MMR)?; + let header_with_mmr = exec_scopes.get::>(vars::scopes::HEADER_WITH_MMR_EVM)?; insert_value_into_ap(vm, Felt252::from(header_with_mmr.mmr_meta.size)) } -pub const HINT_HEADERS_WITH_MMR_PEAKS: &str = "segments.write_arg(ids.peaks, header_with_mmr.mmr_meta.peaks)"; +pub const HINT_HEADERS_WITH_MMR_PEAKS: &str = "segments.write_arg(ids.peaks, header_with_mmr_evm.mmr_meta.peaks)"; pub fn hint_headers_with_mmr_peaks( vm: &mut VirtualMachine, @@ -70,7 +71,7 @@ pub fn hint_headers_with_mmr_peaks( hint_data: &HintProcessorData, _constants: &HashMap, ) -> Result<(), HintError> { - let header_with_mmr = exec_scopes.get::(vars::scopes::HEADER_WITH_MMR)?; + let header_with_mmr = exec_scopes.get::>(vars::scopes::HEADER_WITH_MMR_EVM)?; let peaks_ptr = get_ptr_from_var_name(vars::ids::PEAKS, vm, &hint_data.ids_data, &hint_data.ap_tracking)?; vm.load_data( diff --git a/crates/hints/src/verifiers/evm/mod.rs b/crates/hints/src/verifiers/evm/mod.rs index 99d2963a..4e06a175 100644 --- a/crates/hints/src/verifiers/evm/mod.rs +++ b/crates/hints/src/verifiers/evm/mod.rs @@ -1,28 +1,60 @@ +pub mod account_verifier; +pub mod header_verifier; +pub mod mmr_verifier; +pub mod receipt_verifier; +pub mod storage_item_verifier; +pub mod transaction_verifier; + use crate::vars; +use cairo_vm::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::HintProcessorData; +use cairo_vm::hint_processor::builtin_hint_processor::hint_utils::{get_integer_from_var_name, insert_value_into_ap}; use cairo_vm::{ - hint_processor::builtin_hint_processor::{builtin_hint_processor_definition::HintProcessorData, hint_utils::insert_value_into_ap}, types::exec_scope::ExecutionScopes, vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, Felt252, }; -use std::collections::HashMap; -use types::proofs::Proofs; - -pub mod account_verifier; -pub mod header_verifier; -pub mod receipt_verifier; -pub mod storage_item_verifier; -pub mod transaction_verifier; +use std::{any::Any, collections::HashMap}; +use types::proofs::evm; +use types::ChainProofs; -pub const HINT_HEADERS_WITH_MMR_LEN: &str = "memory[ap] = to_felt_or_relocatable(len(batch.headers_with_mmr))"; +pub const HINT_HEADERS_WITH_MMR_LEN: &str = "memory[ap] = to_felt_or_relocatable(len(batch_evm.headers_with_mmr_evm))"; -pub fn hint_headers_with_mmr_headers_len( +pub fn hint_headers_with_mmr_len( vm: &mut VirtualMachine, exec_scopes: &mut ExecutionScopes, _hint_data: &HintProcessorData, _constants: &HashMap, ) -> Result<(), HintError> { - let proofs = exec_scopes.get::(vars::scopes::BATCH)?; + let proofs = exec_scopes.get::(vars::scopes::BATCH_EVM)?; insert_value_into_ap(vm, Felt252::from(proofs.headers_with_mmr.len())) } + +pub const HINT_VM_ENTER_SCOPE: &str = "vm_enter_scope({'batch_evm': chain_proofs[ids.idx - 1].value, '__dict_manager': __dict_manager})"; + +pub fn hint_vm_enter_scope( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + hint_data: &HintProcessorData, + _constants: &HashMap, +) -> Result<(), HintError> { + let chain_proofs = exec_scopes.get::>(vars::scopes::CHAIN_PROOFS)?; + let idx: usize = get_integer_from_var_name(vars::ids::IDX, vm, &hint_data.ids_data, &hint_data.ap_tracking)? + .try_into() + .unwrap(); + + let batch: Box = match chain_proofs[idx - 1].clone() { + ChainProofs::EthereumMainnet(proofs) => Box::new(proofs), + ChainProofs::EthereumSepolia(proofs) => Box::new(proofs), + ChainProofs::StarknetMainnet(proofs) => Box::new(proofs), + ChainProofs::StarknetSepolia(proofs) => Box::new(proofs), + }; + let dict_manager: Box = Box::new(exec_scopes.get_dict_manager()?); + + exec_scopes.enter_scope(HashMap::from([ + (String::from(vars::scopes::BATCH_EVM), batch), + (String::from(vars::scopes::DICT_MANAGER), dict_manager), + ])); + + Ok(()) +} diff --git a/crates/hints/src/verifiers/evm/receipt_verifier.rs b/crates/hints/src/verifiers/evm/receipt_verifier.rs index 4950110c..627172c7 100644 --- a/crates/hints/src/verifiers/evm/receipt_verifier.rs +++ b/crates/hints/src/verifiers/evm/receipt_verifier.rs @@ -13,9 +13,9 @@ use cairo_vm::{ }; use num_bigint::BigUint; use std::collections::HashMap; -use types::proofs::{receipt::Receipt, Proofs}; +use types::proofs::{evm::receipt::Receipt, evm::Proofs}; -pub const HINT_BATCH_RECEIPTS_LEN: &str = "memory[ap] = to_felt_or_relocatable(len(batch.receipts))"; +pub const HINT_BATCH_RECEIPTS_LEN: &str = "memory[ap] = to_felt_or_relocatable(len(batch_evm.receipts))"; pub fn hint_batch_receipts_len( vm: &mut VirtualMachine, @@ -23,7 +23,7 @@ pub fn hint_batch_receipts_len( _hint_data: &HintProcessorData, _constants: &HashMap, ) -> Result<(), HintError> { - let batch = exec_scopes.get::(vars::scopes::BATCH)?; + let batch = exec_scopes.get::(vars::scopes::BATCH_EVM)?; insert_value_into_ap(vm, Felt252::from(batch.transaction_receipts.len())) } @@ -36,7 +36,7 @@ pub fn hint_set_receipt( hint_data: &HintProcessorData, _constants: &HashMap, ) -> Result<(), HintError> { - let batch = exec_scopes.get::(vars::scopes::BATCH)?; + let batch = exec_scopes.get::(vars::scopes::BATCH_EVM)?; let idx: usize = get_integer_from_var_name(vars::ids::IDX, vm, &hint_data.ids_data, &hint_data.ap_tracking)? .try_into() .unwrap(); diff --git a/crates/hints/src/verifiers/evm/storage_item_verifier.rs b/crates/hints/src/verifiers/evm/storage_item_verifier.rs index 134fd871..77efa049 100644 --- a/crates/hints/src/verifiers/evm/storage_item_verifier.rs +++ b/crates/hints/src/verifiers/evm/storage_item_verifier.rs @@ -13,9 +13,9 @@ use cairo_vm::{ }; use num_bigint::BigUint; use std::collections::HashMap; -use types::proofs::{mpt::MPTProof, storage::Storage, Proofs}; +use types::proofs::{evm::storage::Storage, evm::Proofs, mpt::MPTProof}; -pub const HINT_BATCH_STORAGES_LEN: &str = "memory[ap] = to_felt_or_relocatable(len(batch.storages))"; +pub const HINT_BATCH_STORAGES_LEN: &str = "memory[ap] = to_felt_or_relocatable(len(batch_evm.storages))"; pub fn hint_batch_storages_len( vm: &mut VirtualMachine, @@ -23,13 +23,13 @@ pub fn hint_batch_storages_len( _hint_data: &HintProcessorData, _constants: &HashMap, ) -> Result<(), HintError> { - let batch = exec_scopes.get::(vars::scopes::BATCH)?; + let batch = exec_scopes.get::(vars::scopes::BATCH_EVM)?; insert_value_into_ap(vm, Felt252::from(batch.storages.len())) } pub const HINT_SET_BATCH_STORAGES: &str = - "storage = batch.storages[ids.idx]\nsegments.write_arg(ids.address, [int(x, 16) for x in storage.address]))"; + "storage_evm = batch_evm.storages[ids.idx]\nsegments.write_arg(ids.address, [int(x, 16) for x in storage_evm.address]))"; pub fn hint_set_batch_storages( vm: &mut VirtualMachine, @@ -37,7 +37,7 @@ pub fn hint_set_batch_storages( hint_data: &HintProcessorData, _constants: &HashMap, ) -> Result<(), HintError> { - let batch = exec_scopes.get::(vars::scopes::BATCH)?; + let batch = exec_scopes.get::(vars::scopes::BATCH_EVM)?; let idx: usize = get_integer_from_var_name(vars::ids::IDX, vm, &hint_data.ids_data, &hint_data.ap_tracking)? .try_into() .unwrap(); @@ -48,7 +48,7 @@ pub fn hint_set_batch_storages( .map(|chunk| MaybeRelocatable::from(Felt252::from_bytes_be_slice(&chunk.iter().rev().copied().collect::>()))) .collect(); - exec_scopes.insert_value::(vars::scopes::STORAGE, storage); + exec_scopes.insert_value::(vars::scopes::STORAGE_EVM, storage); let address_ptr = get_ptr_from_var_name(vars::ids::ADDRESS, vm, &hint_data.ids_data, &hint_data.ap_tracking)?; @@ -57,7 +57,7 @@ pub fn hint_set_batch_storages( Ok(()) } -pub const HINT_SET_STORAGE_SLOT: &str = "segments.write_arg(ids.slot, [int(x, 16) for x in storage.slot]))"; +pub const HINT_SET_STORAGE_SLOT: &str = "segments.write_arg(ids.slot, [int(x, 16) for x in storage_evm.slot]))"; pub fn hint_set_storage_slot( vm: &mut VirtualMachine, @@ -65,7 +65,7 @@ pub fn hint_set_storage_slot( hint_data: &HintProcessorData, _constants: &HashMap, ) -> Result<(), HintError> { - let storage = exec_scopes.get::(vars::scopes::STORAGE)?; + let storage = exec_scopes.get::(vars::scopes::STORAGE_EVM)?; let slot_le_chunks: Vec = storage .slot .chunks(8) @@ -79,7 +79,8 @@ pub fn hint_set_storage_slot( Ok(()) } -pub const HINT_SET_STORAGE_KEY: &str = "from tools.py.utils import split_128\n(ids.key.low, ids.key.high) = split_128(int(storage.storage_key, 16))"; +pub const HINT_SET_STORAGE_KEY: &str = + "from tools.py.utils import split_128\n(ids.key.low, ids.key.high) = split_128(int(storage_evm.storage_key, 16))"; pub fn hint_set_storage_key( vm: &mut VirtualMachine, @@ -87,7 +88,7 @@ pub fn hint_set_storage_key( hint_data: &HintProcessorData, _constants: &HashMap, ) -> Result<(), HintError> { - let storage = exec_scopes.get::(vars::scopes::STORAGE)?; + let storage = exec_scopes.get::(vars::scopes::STORAGE_EVM)?; let (key_low, key_high) = split_128(&BigUint::from_bytes_be(storage.storage_key.as_slice())); @@ -99,7 +100,7 @@ pub fn hint_set_storage_key( } pub const HINT_SET_STORAGE_KEY_LEADING_ZEROS: &str = - "ids.key_leading_zeros = len(storage.storage_key.lstrip(\"0x\")) - len(storage.storage_key.lstrip(\"0x\").lstrip(\"0\"))"; + "ids.key_leading_zeros = len(storage_evm.storage_key.lstrip(\"0x\")) - len(storage_evm.storage_key.lstrip(\"0x\").lstrip(\"0\"))"; pub fn hint_set_storage_key_leading_zeros( vm: &mut VirtualMachine, @@ -107,7 +108,7 @@ pub fn hint_set_storage_key_leading_zeros( hint_data: &HintProcessorData, _constants: &HashMap, ) -> Result<(), HintError> { - let storage = exec_scopes.get::(vars::scopes::STORAGE)?; + let storage = exec_scopes.get::(vars::scopes::STORAGE_EVM)?; let key_leading_zeros = count_leading_zero_nibbles_from_hex(&storage.storage_key.to_string()); insert_value_from_var_name( @@ -121,7 +122,7 @@ pub fn hint_set_storage_key_leading_zeros( Ok(()) } -pub const HINT_SET_STORAGE_PROOFS_LEN: &str = "memory[ap] = to_felt_or_relocatable(len(storage.proofs))"; +pub const HINT_SET_STORAGE_PROOFS_LEN: &str = "memory[ap] = to_felt_or_relocatable(len(storage_evm.proofs))"; pub fn hint_set_storage_proofs_len( vm: &mut VirtualMachine, @@ -129,12 +130,12 @@ pub fn hint_set_storage_proofs_len( _hint_data: &HintProcessorData, _constants: &HashMap, ) -> Result<(), HintError> { - let storage = exec_scopes.get::(vars::scopes::STORAGE)?; + let storage = exec_scopes.get::(vars::scopes::STORAGE_EVM)?; insert_value_into_ap(vm, Felt252::from(storage.proofs.len())) } -pub const HINT_SET_STORAGE_PROOF_AT: &str = "proof = storage.proofs[ids.idx]"; +pub const HINT_SET_STORAGE_PROOF_AT: &str = "proof = storage_evm.proofs[ids.idx]"; pub fn hint_set_storage_proof_at( vm: &mut VirtualMachine, @@ -142,7 +143,7 @@ pub fn hint_set_storage_proof_at( hint_data: &HintProcessorData, _constants: &HashMap, ) -> Result<(), HintError> { - let storage = exec_scopes.get::(vars::scopes::STORAGE)?; + let storage = exec_scopes.get::(vars::scopes::STORAGE_EVM)?; let idx: usize = get_integer_from_var_name(vars::ids::IDX, vm, &hint_data.ids_data, &hint_data.ap_tracking)? .try_into() .unwrap(); diff --git a/crates/hints/src/verifiers/evm/transaction_verifier.rs b/crates/hints/src/verifiers/evm/transaction_verifier.rs index cc3aa73e..18ffefca 100644 --- a/crates/hints/src/verifiers/evm/transaction_verifier.rs +++ b/crates/hints/src/verifiers/evm/transaction_verifier.rs @@ -13,9 +13,9 @@ use cairo_vm::{ }; use num_bigint::BigUint; use std::collections::HashMap; -use types::proofs::{transaction::Transaction, Proofs}; +use types::proofs::{evm::transaction::Transaction, evm::Proofs}; -pub const HINT_BATCH_TRANSACTIONS_LEN: &str = "memory[ap] = to_felt_or_relocatable(len(batch.transactions))"; +pub const HINT_BATCH_TRANSACTIONS_LEN: &str = "memory[ap] = to_felt_or_relocatable(len(batch_evm.transactions))"; pub fn hint_batch_transactions_len( vm: &mut VirtualMachine, @@ -23,7 +23,7 @@ pub fn hint_batch_transactions_len( _hint_data: &HintProcessorData, _constants: &HashMap, ) -> Result<(), HintError> { - let batch = exec_scopes.get::(vars::scopes::BATCH)?; + let batch = exec_scopes.get::(vars::scopes::BATCH_EVM)?; insert_value_into_ap(vm, Felt252::from(batch.transactions.len())) } @@ -36,7 +36,7 @@ pub fn hint_set_tx( hint_data: &HintProcessorData, _constants: &HashMap, ) -> Result<(), HintError> { - let batch = exec_scopes.get::(vars::scopes::BATCH)?; + let batch = exec_scopes.get::(vars::scopes::BATCH_EVM)?; let idx: usize = get_integer_from_var_name(vars::ids::IDX, vm, &hint_data.ids_data, &hint_data.ap_tracking)? .try_into() .unwrap(); diff --git a/crates/hints/src/verifiers/mod.rs b/crates/hints/src/verifiers/mod.rs index 51c61700..ccf1e4cb 100644 --- a/crates/hints/src/verifiers/mod.rs +++ b/crates/hints/src/verifiers/mod.rs @@ -1,3 +1,3 @@ pub mod evm; -pub mod mmr_verifier; +pub mod starknet; pub mod verify; diff --git a/crates/hints/src/verifiers/starknet/header_verifier.rs b/crates/hints/src/verifiers/starknet/header_verifier.rs new file mode 100644 index 00000000..b1186da7 --- /dev/null +++ b/crates/hints/src/verifiers/starknet/header_verifier.rs @@ -0,0 +1,153 @@ +use crate::vars; +use cairo_vm::{ + hint_processor::builtin_hint_processor::{ + builtin_hint_processor_definition::HintProcessorData, + dict_manager::DictManager, + hint_utils::{get_integer_from_var_name, get_ptr_from_var_name, insert_value_into_ap}, + }, + types::{exec_scope::ExecutionScopes, relocatable::MaybeRelocatable}, + vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, + Felt252, +}; +use std::{any::Any, cell::RefCell, collections::HashMap, rc::Rc}; +use types::proofs::{header::HeaderMmrMeta, starknet}; + +pub const HINT_HEADERS_WITH_MMR_LEN: &str = "memory[ap] = to_felt_or_relocatable(len(batch_starknet.headers_with_mmr))"; + +pub fn hint_headers_with_mmr_len( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + _hint_data: &HintProcessorData, + _constants: &HashMap, +) -> Result<(), HintError> { + let proofs = exec_scopes.get::(vars::scopes::BATCH_STARKNET)?; + + insert_value_into_ap(vm, Felt252::from(proofs.headers_with_mmr.len())) +} + +pub const HINT_VM_ENTER_SCOPE: &str = + "vm_enter_scope({'header_with_mmr_starknet': batch_starknet.headers_with_mmr[ids.idx - 1], '__dict_manager': __dict_manager})"; + +pub fn hint_vm_enter_scope( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + hint_data: &HintProcessorData, + _constants: &HashMap, +) -> Result<(), HintError> { + let proofs = exec_scopes.get::(vars::scopes::BATCH_STARKNET)?; + let idx: usize = get_integer_from_var_name(vars::ids::IDX, vm, &hint_data.ids_data, &hint_data.ap_tracking)? + .try_into() + .unwrap(); + + let headers_with_mmr: Box = Box::new(proofs.headers_with_mmr[idx - 1].clone()); + let dict_manager: Box = Box::new(exec_scopes.get::>>(vars::scopes::DICT_MANAGER)?); + exec_scopes.enter_scope(HashMap::from([ + (String::from(vars::scopes::HEADER_WITH_MMR_STARKNET), headers_with_mmr), + (String::from(vars::scopes::DICT_MANAGER), dict_manager), + ])); + + Ok(()) +} + +pub const HINT_HEADERS_WITH_MMR_HEADERS_LEN: &str = "memory[ap] = to_felt_or_relocatable(len(header_with_mmr_starknet.headers))"; + +pub fn hint_headers_with_mmr_headers_len( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + _hint_data: &HintProcessorData, + _constants: &HashMap, +) -> Result<(), HintError> { + let header_with_mmr = exec_scopes.get::>(vars::scopes::HEADER_WITH_MMR_STARKNET)?; + + insert_value_into_ap(vm, Felt252::from(header_with_mmr.headers.len())) +} + +pub const HINT_SET_HEADER: &str = + "header_starknet = header_with_mmr_starknet.headers[ids.idx - 1]\nsegments.write_arg(ids.fields, [int(x, 16) for x in header_starknet.fields])"; + +pub fn hint_set_header( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + hint_data: &HintProcessorData, + _constants: &HashMap, +) -> Result<(), HintError> { + let headers_with_mmr = exec_scopes.get::>(vars::scopes::HEADER_WITH_MMR_STARKNET)?; + let idx: usize = get_integer_from_var_name(vars::ids::IDX, vm, &hint_data.ids_data, &hint_data.ap_tracking)? + .try_into() + .unwrap(); + + let header = headers_with_mmr.headers[idx - 1].clone(); + + exec_scopes.insert_value::(vars::scopes::HEADER_STARKNET, header.clone()); + + let fields_ptr = get_ptr_from_var_name(vars::ids::FIELDS, vm, &hint_data.ids_data, &hint_data.ap_tracking)?; + + vm.load_data( + fields_ptr, + &header.fields.into_iter().map(MaybeRelocatable::from).collect::>(), + )?; + + Ok(()) +} + +pub const HINT_FIELDS_LEN: &str = "memory[ap] = to_felt_or_relocatable(len(header_starknet.fields))"; + +pub fn hint_rlp_len( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + _hint_data: &HintProcessorData, + _constants: &HashMap, +) -> Result<(), HintError> { + let header = exec_scopes.get::(vars::scopes::HEADER_STARKNET)?; + + insert_value_into_ap(vm, Felt252::from(header.fields.len())) +} + +pub const HINT_LEAF_IDX: &str = "memory[ap] = to_felt_or_relocatable(len(header_starknet.proof.leaf_idx))"; + +pub fn hint_leaf_idx( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + _hint_data: &HintProcessorData, + _constants: &HashMap, +) -> Result<(), HintError> { + let header = exec_scopes.get::(vars::scopes::HEADER_STARKNET)?; + + insert_value_into_ap(vm, Felt252::from(header.proof.leaf_idx)) +} + +pub const HINT_MMR_PATH_LEN: &str = "memory[ap] = to_felt_or_relocatable(len(header_starknet.proof.mmr_path))"; + +pub fn hint_mmr_path_len( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + _hint_data: &HintProcessorData, + _constants: &HashMap, +) -> Result<(), HintError> { + let header = exec_scopes.get::(vars::scopes::HEADER_STARKNET)?; + + insert_value_into_ap(vm, Felt252::from(header.proof.mmr_path.len())) +} + +pub const HINT_MMR_PATH: &str = "segments.write_arg(ids.mmr_path, [int(x, 16) for x in header_starknet.proof.mmr_path])"; + +pub fn hint_mmr_path( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + hint_data: &HintProcessorData, + _constants: &HashMap, +) -> Result<(), HintError> { + let header = exec_scopes.get::(vars::scopes::HEADER_STARKNET)?; + let mmr_path_ptr = get_ptr_from_var_name(vars::ids::MMR_PATH, vm, &hint_data.ids_data, &hint_data.ap_tracking)?; + let mmr_path: Vec = header + .proof + .mmr_path + .into_iter() + .map(|f| Felt252::from_bytes_be_slice(&f)) + .map(MaybeRelocatable::from) + .collect(); + + vm.load_data(mmr_path_ptr, &mmr_path)?; + + Ok(()) +} diff --git a/crates/hints/src/verifiers/starknet/mmr_verifier.rs b/crates/hints/src/verifiers/starknet/mmr_verifier.rs new file mode 100644 index 00000000..c79bc96e --- /dev/null +++ b/crates/hints/src/verifiers/starknet/mmr_verifier.rs @@ -0,0 +1,88 @@ +use crate::vars; +use cairo_vm::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::HintProcessorData; +use cairo_vm::hint_processor::builtin_hint_processor::hint_utils::{get_ptr_from_var_name, insert_value_into_ap}; +use cairo_vm::types::relocatable::MaybeRelocatable; +use cairo_vm::{ + types::exec_scope::ExecutionScopes, + vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, + Felt252, +}; +use std::collections::HashMap; +use types::proofs::evm; +use types::proofs::header::HeaderMmrMeta; + +pub const HINT_HEADERS_WITH_MMR_META_PEAKS_LEN: &str = "memory[ap] = to_felt_or_relocatable(len(header_with_mmr_starknet.mmr_meta.peaks))"; + +pub fn hint_headers_with_mmr_meta_peaks_len( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + _hint_data: &HintProcessorData, + _constants: &HashMap, +) -> Result<(), HintError> { + let header_with_mmr = exec_scopes.get::>(vars::scopes::HEADER_WITH_MMR_STARKNET)?; + + insert_value_into_ap(vm, Felt252::from(header_with_mmr.mmr_meta.peaks.len())) +} + +pub const HINT_HEADERS_WITH_MMR_META_ID: &str = "memory[ap] = to_felt_or_relocatable(header_with_mmr_starknet.mmr_meta.id)"; + +pub fn hint_headers_with_mmr_meta_id( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + _hint_data: &HintProcessorData, + _constants: &HashMap, +) -> Result<(), HintError> { + let header_with_mmr = exec_scopes.get::>(vars::scopes::HEADER_WITH_MMR_STARKNET)?; + + insert_value_into_ap(vm, Felt252::from(header_with_mmr.mmr_meta.id)) +} + +pub const HINT_HEADERS_WITH_MMR_META_ROOT: &str = "memory[ap] = to_felt_or_relocatable(header_with_mmr_starknet.mmr_meta.root)"; + +pub fn hint_headers_with_mmr_meta_root( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + _hint_data: &HintProcessorData, + _constants: &HashMap, +) -> Result<(), HintError> { + let header_with_mmr = exec_scopes.get::>(vars::scopes::HEADER_WITH_MMR_STARKNET)?; + + insert_value_into_ap(vm, Felt252::from_bytes_be_slice(&header_with_mmr.mmr_meta.root)) +} + +pub const HINT_HEADERS_WITH_MMR_META_SIZE: &str = "memory[ap] = to_felt_or_relocatable(header_with_mmr_starknet.mmr_meta.size)"; + +pub fn hint_headers_with_mmr_meta_size( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + _hint_data: &HintProcessorData, + _constants: &HashMap, +) -> Result<(), HintError> { + let header_with_mmr = exec_scopes.get::>(vars::scopes::HEADER_WITH_MMR_STARKNET)?; + + insert_value_into_ap(vm, Felt252::from(header_with_mmr.mmr_meta.size)) +} + +pub const HINT_HEADERS_WITH_MMR_PEAKS: &str = "segments.write_arg(ids.peaks, header_with_mmr_starknet.mmr_meta.peaks)"; + +pub fn hint_headers_with_mmr_peaks( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + hint_data: &HintProcessorData, + _constants: &HashMap, +) -> Result<(), HintError> { + let header_with_mmr = exec_scopes.get::>(vars::scopes::HEADER_WITH_MMR_STARKNET)?; + let peaks_ptr = get_ptr_from_var_name(vars::ids::PEAKS, vm, &hint_data.ids_data, &hint_data.ap_tracking)?; + + vm.load_data( + peaks_ptr, + &header_with_mmr + .mmr_meta + .peaks + .into_iter() + .map(|f| MaybeRelocatable::from(Felt252::from_bytes_be_slice(&f))) + .collect::>(), + )?; + + Ok(()) +} diff --git a/crates/hints/src/verifiers/starknet/mod.rs b/crates/hints/src/verifiers/starknet/mod.rs new file mode 100644 index 00000000..4eb59b15 --- /dev/null +++ b/crates/hints/src/verifiers/starknet/mod.rs @@ -0,0 +1,57 @@ +pub mod header_verifier; +pub mod mmr_verifier; +pub mod storage_verifier; + +use crate::vars; +use cairo_vm::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::HintProcessorData; +use cairo_vm::hint_processor::builtin_hint_processor::hint_utils::{get_integer_from_var_name, insert_value_into_ap}; +use cairo_vm::{ + types::exec_scope::ExecutionScopes, + vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, + Felt252, +}; +use std::{any::Any, collections::HashMap}; +use types::proofs::starknet; +use types::ChainProofs; + +pub const HINT_HEADERS_WITH_MMR_LEN: &str = "memory[ap] = to_felt_or_relocatable(len(batch_starknet.headers_with_mmr_starknet))"; + +pub fn hint_headers_with_mmr_len( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + _hint_data: &HintProcessorData, + _constants: &HashMap, +) -> Result<(), HintError> { + let proofs = exec_scopes.get::(vars::scopes::BATCH_STARKNET)?; + + insert_value_into_ap(vm, Felt252::from(proofs.headers_with_mmr.len())) +} + +pub const HINT_VM_ENTER_SCOPE: &str = "vm_enter_scope({'batch_starknet': chain_proofs[ids.idx - 1].value, '__dict_manager': __dict_manager})"; + +pub fn hint_vm_enter_scope( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + hint_data: &HintProcessorData, + _constants: &HashMap, +) -> Result<(), HintError> { + let chain_proofs = exec_scopes.get::>(vars::scopes::CHAIN_PROOFS)?; + let idx: usize = get_integer_from_var_name(vars::ids::IDX, vm, &hint_data.ids_data, &hint_data.ap_tracking)? + .try_into() + .unwrap(); + + let batch: Box = match chain_proofs[idx - 1].clone() { + ChainProofs::EthereumMainnet(proofs) => Box::new(proofs), + ChainProofs::EthereumSepolia(proofs) => Box::new(proofs), + ChainProofs::StarknetMainnet(proofs) => Box::new(proofs), + ChainProofs::StarknetSepolia(proofs) => Box::new(proofs), + }; + let dict_manager: Box = Box::new(exec_scopes.get_dict_manager()?); + + exec_scopes.enter_scope(HashMap::from([ + (String::from(vars::scopes::BATCH_STARKNET), batch), + (String::from(vars::scopes::DICT_MANAGER), dict_manager), + ])); + + Ok(()) +} diff --git a/crates/hints/src/verifiers/starknet/storage_verifier.rs b/crates/hints/src/verifiers/starknet/storage_verifier.rs new file mode 100644 index 00000000..daeb6111 --- /dev/null +++ b/crates/hints/src/verifiers/starknet/storage_verifier.rs @@ -0,0 +1,284 @@ +use crate::vars; +use cairo_vm::{ + hint_processor::builtin_hint_processor::{ + builtin_hint_processor_definition::HintProcessorData, + hint_utils::{get_integer_from_var_name, get_ptr_from_var_name, insert_value_into_ap}, + }, + types::{exec_scope::ExecutionScopes, relocatable::MaybeRelocatable}, + vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, + Felt252, +}; +use std::collections::HashMap; +use types::{ + cairo::{starknet::storage::CairoTrieNode, traits::CairoType}, + proofs::starknet::{ + storage::{Storage, TrieNode}, + Proofs, + }, +}; + +pub const HINT_BATCH_STORAGES_LEN: &str = "memory[ap] = to_felt_or_relocatable(len(batch_starknet.storages))"; + +pub fn hint_batch_storages_len( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + _hint_data: &HintProcessorData, + _constants: &HashMap, +) -> Result<(), HintError> { + let batch = exec_scopes.get::(vars::scopes::BATCH_STARKNET)?; + + insert_value_into_ap(vm, Felt252::from(batch.storages.len())) +} + +pub const HINT_SET_BATCH_STORAGES: &str = "storage_starknet = batch_starknet.storages[ids.idx]"; + +pub fn hint_set_batch_storages( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + hint_data: &HintProcessorData, + _constants: &HashMap, +) -> Result<(), HintError> { + let batch = exec_scopes.get::(vars::scopes::BATCH_STARKNET)?; + let idx: usize = get_integer_from_var_name(vars::ids::IDX, vm, &hint_data.ids_data, &hint_data.ap_tracking)? + .try_into() + .unwrap(); + let storage = batch.storages[idx].clone(); + + exec_scopes.insert_value::(vars::scopes::STORAGE_STARKNET, storage); + + Ok(()) +} + +pub const HINT_SET_STORAGE_ADDRESSES_LEN: &str = "memory[ap] = to_felt_or_relocatable(len(storage_starknet.storage_addresses))"; + +pub fn hint_set_storage_addresses_len( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + _hint_data: &HintProcessorData, + _constants: &HashMap, +) -> Result<(), HintError> { + let storage = exec_scopes.get::(vars::scopes::STORAGE_STARKNET)?; + + insert_value_into_ap(vm, Felt252::from(storage.storage_addresses.len())) +} + +pub const HINT_SET_CONTRACT_ADDRESS: &str = "memory[ap] = to_felt_or_relocatable(storage_starknet.contract_address)"; + +pub fn hint_set_contract_address( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + _hint_data: &HintProcessorData, + _constants: &HashMap, +) -> Result<(), HintError> { + let storage = exec_scopes.get::(vars::scopes::STORAGE_STARKNET)?; + + insert_value_into_ap(vm, Felt252::from(storage.storage_addresses.len())) +} + +pub const HINT_SET_STORAGE_ADDRESSES: &str = "segments.write_arg(ids.storage_addresses, [int(x, 16) for x in storage_starknet.storage_addresses]))"; + +pub fn hint_set_storage_addresses( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + hint_data: &HintProcessorData, + _constants: &HashMap, +) -> Result<(), HintError> { + let storage = exec_scopes.get::(vars::scopes::STORAGE_STARKNET)?; + + let address_ptr = get_ptr_from_var_name(vars::ids::STORAGE_ADDRESSES, vm, &hint_data.ids_data, &hint_data.ap_tracking)?; + + vm.load_data( + address_ptr, + &storage + .storage_addresses + .into_iter() + .map(MaybeRelocatable::from) + .collect::>(), + )?; + + Ok(()) +} + +pub const HINT_SET_STORAGE_STARKNET_PROOF_CONTRACT_DATA_CLASS_HASH: &str = + "memory[ap] = to_felt_or_relocatable(storage_starknet.proof.contract_data.class_hash)"; + +pub fn hint_set_storage_starknet_proof_contract_data_class_hash( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + _hint_data: &HintProcessorData, + _constants: &HashMap, +) -> Result<(), HintError> { + let storage = exec_scopes.get::(vars::scopes::STORAGE_STARKNET)?; + + insert_value_into_ap(vm, storage.proof.contract_data.ok_or(HintError::WrongHintData)?.class_hash) +} + +pub const HINT_SET_STORAGE_STARKNET_PROOF_CONTRACT_DATA_NONCE: &str = + "memory[ap] = to_felt_or_relocatable(storage_starknet.proof.contract_data.nonce)"; + +pub fn hint_set_storage_starknet_proof_contract_data_nonce( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + _hint_data: &HintProcessorData, + _constants: &HashMap, +) -> Result<(), HintError> { + let storage = exec_scopes.get::(vars::scopes::STORAGE_STARKNET)?; + + insert_value_into_ap(vm, storage.proof.contract_data.ok_or(HintError::WrongHintData)?.nonce) +} + +pub const HINT_SET_STORAGE_STARKNET_PROOF_CONTRACT_DATA_CONTRACT_STATE_HASH_VERSION: &str = + "memory[ap] = to_felt_or_relocatable(storage_starknet.proof.contract_data.contract_state_hash_version)"; + +pub fn hint_set_storage_starknet_proof_contract_data_contract_state_hash_version( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + _hint_data: &HintProcessorData, + _constants: &HashMap, +) -> Result<(), HintError> { + let storage = exec_scopes.get::(vars::scopes::STORAGE_STARKNET)?; + + insert_value_into_ap( + vm, + storage.proof.contract_data.ok_or(HintError::WrongHintData)?.contract_state_hash_version, + ) +} + +pub const HINT_SET_STORAGE_STARKNET_PROOF_CONTRACT_PROOF_LEN: &str = + "memory[ap] = to_felt_or_relocatable(len(storage_starknet.proof.contract_proof))"; + +pub fn hint_set_storage_starknet_proof_contract_proof_len( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + _hint_data: &HintProcessorData, + _constants: &HashMap, +) -> Result<(), HintError> { + let storage = exec_scopes.get::(vars::scopes::STORAGE_STARKNET)?; + + insert_value_into_ap(vm, Felt252::from(storage.proof.contract_proof.len())) +} + +pub const HINT_SET_CONTRACT_NODES: &str = "segments.write_arg(ids.contract_nodes, storage_starknet.proof.contract_proof)"; + +pub fn hint_set_contract_nodes( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + hint_data: &HintProcessorData, + _constants: &HashMap, +) -> Result<(), HintError> { + let storage = exec_scopes.get::(vars::scopes::STORAGE_STARKNET)?; + let contract_nodes_ptr = get_ptr_from_var_name(vars::ids::CONTRACT_NODES, vm, &hint_data.ids_data, &hint_data.ap_tracking)?; + + vm.load_data( + contract_nodes_ptr, + &storage + .proof + .contract_proof + .into_iter() + .flat_map(|node| CairoTrieNode(node).into_iter()) + .map(MaybeRelocatable::from) + .collect::>(), + )?; + + Ok(()) +} + +pub const HINT_SET_STORAGE_STARKNET_PROOF_CLASS_COMMITMENT: &str = "memory[ap] = to_felt_or_relocatable(storage_starknet.proof.class_commitment)"; + +pub fn hint_set_storage_starknet_proof_class_commitment( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + _hint_data: &HintProcessorData, + _constants: &HashMap, +) -> Result<(), HintError> { + let storage = exec_scopes.get::(vars::scopes::STORAGE_STARKNET)?; + + insert_value_into_ap(vm, storage.proof.class_commitment.ok_or(HintError::WrongHintData)?) +} + +pub const HINT_SET_STORAGE_STARKNET_PROOF_CONTRACT_DATA_STORAGE_PROOFS_LEN: &str = + "memory[ap] = to_felt_or_relocatable(len(storage_starknet.proof.contract_data.storage_proofs[ids.idx]))"; + +pub fn hint_set_storage_starknet_proof_contract_data_storage_proofs_len( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + hint_data: &HintProcessorData, + _constants: &HashMap, +) -> Result<(), HintError> { + let storage = exec_scopes.get::(vars::scopes::STORAGE_STARKNET)?; + let idx: usize = get_integer_from_var_name(vars::ids::IDX, vm, &hint_data.ids_data, &hint_data.ap_tracking)? + .try_into() + .unwrap(); + + insert_value_into_ap(vm, storage.proof.contract_data.ok_or(HintError::WrongHintData)?.storage_proofs[idx].len()) +} + +pub const HINT_SET_STORAGE_STARKNET_PROOF_CONTRACT_DATA_STORAGE_PROOF: &str = + "segments.write_arg(ids.contract_state_nodes, storage_starknet.proof.contract_data.storage_proofs[ids.idx])"; + +pub fn hint_set_storage_starknet_proof_contract_data_storage_proof( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + hint_data: &HintProcessorData, + _constants: &HashMap, +) -> Result<(), HintError> { + let storage = exec_scopes.get::(vars::scopes::STORAGE_STARKNET)?; + let contract_state_nodes_ptr = get_ptr_from_var_name(vars::ids::CONTRACT_STATE_NODES, vm, &hint_data.ids_data, &hint_data.ap_tracking)?; + + vm.load_data( + contract_state_nodes_ptr, + &storage + .proof + .contract_data + .ok_or(HintError::WrongHintData)? + .storage_proofs + .into_iter() + .flat_map(|nodes| nodes.into_iter()) + .flat_map(|node| CairoTrieNode(node).into_iter()) + .map(MaybeRelocatable::from) + .collect::>(), + )?; + + Ok(()) +} + +pub const HINT_NODE_IS_EDGE: &str = "memory[ap] = CairoTrieNode(ids.node).is_edge()"; + +pub fn hint_node_is_edge( + vm: &mut VirtualMachine, + _exec_scopes: &mut ExecutionScopes, + hint_data: &HintProcessorData, + _constants: &HashMap, +) -> Result<(), HintError> { + let leaf_ptr = get_ptr_from_var_name(vars::ids::NODE, vm, &hint_data.ids_data, &hint_data.ap_tracking)?; + + insert_value_into_ap(vm, Felt252::from(CairoTrieNode::from_memory(vm, leaf_ptr)?.is_edge())) +} + +pub const HINT_SET_EVAL_DEPTH: &str = + "memory[ap] = to_felt_or_relocatable([ if CairoTrieNode(ids.nodes[i]).is_edge() CairoTrieNode(ids.nodes[i]).path_len else 1 for i in ids.n_nodes ].sum())"; + +pub fn hint_set_eval_depth( + vm: &mut VirtualMachine, + _exec_scopes: &mut ExecutionScopes, + hint_data: &HintProcessorData, + _constants: &HashMap, +) -> Result<(), HintError> { + let nodes_ptr = get_ptr_from_var_name(vars::ids::NODES, vm, &hint_data.ids_data, &hint_data.ap_tracking)?; + let n_nodes: usize = get_integer_from_var_name(vars::ids::N_NODES, vm, &hint_data.ids_data, &hint_data.ap_tracking)? + .try_into() + .unwrap(); + + insert_value_into_ap( + vm, + Felt252::from( + (0..n_nodes) + .map(|idx| CairoTrieNode::from_memory(vm, (nodes_ptr + CairoTrieNode::n_fields() * idx).unwrap()).unwrap()) + .map(|node| match node.0 { + TrieNode::Binary { left: _, right: _ } => 1_u64, + TrieNode::Edge { child: _, path } => path.len, + }) + .sum::(), + ), + ) +} diff --git a/crates/hints/src/verifiers/verify.rs b/crates/hints/src/verifiers/verify.rs index fa86a32a..67d83299 100644 --- a/crates/hints/src/verifiers/verify.rs +++ b/crates/hints/src/verifiers/verify.rs @@ -6,7 +6,7 @@ use cairo_vm::{ vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, Felt252, }; -use std::{any::Any, collections::HashMap}; +use std::collections::HashMap; use types::ChainProofs; pub const HINT_CHAIN_PROOFS_LEN: &str = "memory[ap] = to_felt_or_relocatable(len(chain_proofs))"; @@ -35,30 +35,3 @@ pub fn hint_chain_proofs_chain_id( .unwrap(); insert_value_into_ap(vm, Felt252::from(chain_proofs[idx - 1].chain_id())) } - -pub const HINT_VM_ENTER_SCOPE: &str = "vm_enter_scope({'batch': chain_proofs[ids.idx - 1].value, '__dict_manager': __dict_manager})"; - -pub fn hint_vm_enter_scope( - vm: &mut VirtualMachine, - exec_scopes: &mut ExecutionScopes, - hint_data: &HintProcessorData, - _constants: &HashMap, -) -> Result<(), HintError> { - let chain_proofs = exec_scopes.get::>(vars::scopes::CHAIN_PROOFS)?; - let idx: usize = get_integer_from_var_name(vars::ids::IDX, vm, &hint_data.ids_data, &hint_data.ap_tracking)? - .try_into() - .unwrap(); - - let batch: Box = match chain_proofs[idx - 1].clone() { - ChainProofs::EthereumMainnet(proofs) => Box::new(proofs), - ChainProofs::EthereumSepolia(proofs) => Box::new(proofs), - }; - let dict_manager: Box = Box::new(exec_scopes.get_dict_manager()?); - - exec_scopes.enter_scope(HashMap::from([ - (String::from(vars::scopes::BATCH), batch), - (String::from(vars::scopes::DICT_MANAGER), dict_manager), - ])); - - Ok(()) -} diff --git a/crates/sound_hint_processor/src/syscall_handler/evm/account.rs b/crates/sound_hint_processor/src/syscall_handler/evm/account.rs index e9a0bf07..5bb693ae 100644 --- a/crates/sound_hint_processor/src/syscall_handler/evm/account.rs +++ b/crates/sound_hint_processor/src/syscall_handler/evm/account.rs @@ -8,7 +8,7 @@ use syscall_handler::{SyscallExecutionError, SyscallResult}; use types::cairo::evm::account::CairoAccount; use types::{ cairo::{evm::account::FunctionId, structs::Uint256, traits::CairoType}, - keys::account::CairoKey, + keys::evm::account::CairoKey, }; #[derive(Debug)] diff --git a/crates/sound_hint_processor/src/syscall_handler/evm/header.rs b/crates/sound_hint_processor/src/syscall_handler/evm/header.rs index 9242066f..0398d573 100644 --- a/crates/sound_hint_processor/src/syscall_handler/evm/header.rs +++ b/crates/sound_hint_processor/src/syscall_handler/evm/header.rs @@ -8,7 +8,7 @@ use syscall_handler::{SyscallExecutionError, SyscallResult}; use types::cairo::evm::header::CairoHeader; use types::{ cairo::{evm::header::FunctionId, structs::Uint256, traits::CairoType}, - keys::header::CairoKey, + keys::evm::header::CairoKey, }; #[derive(Debug)] diff --git a/crates/sound_hint_processor/src/syscall_handler/evm/mod.rs b/crates/sound_hint_processor/src/syscall_handler/evm/mod.rs index 1b23da2c..94e38431 100644 --- a/crates/sound_hint_processor/src/syscall_handler/evm/mod.rs +++ b/crates/sound_hint_processor/src/syscall_handler/evm/mod.rs @@ -194,9 +194,9 @@ impl TryFrom for CallHandlerId { #[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Hash)] #[serde(rename_all = "lowercase")] pub enum DryRunKey { - Account(keys::account::Key), - Header(keys::header::Key), - Storage(keys::storage::Key), + Account(keys::evm::account::Key), + Header(keys::evm::header::Key), + Storage(keys::evm::storage::Key), } impl DryRunKey { diff --git a/crates/sound_hint_processor/src/syscall_handler/evm/storage.rs b/crates/sound_hint_processor/src/syscall_handler/evm/storage.rs index 3b075234..a58f90ee 100644 --- a/crates/sound_hint_processor/src/syscall_handler/evm/storage.rs +++ b/crates/sound_hint_processor/src/syscall_handler/evm/storage.rs @@ -8,7 +8,7 @@ use syscall_handler::{SyscallExecutionError, SyscallResult}; use types::cairo::evm::storage::CairoStorage; use types::{ cairo::{evm::storage::FunctionId, structs::Uint256, traits::CairoType}, - keys::storage::CairoKey, + keys::evm::storage::CairoKey, }; #[derive(Debug)] diff --git a/crates/types/Cargo.toml b/crates/types/Cargo.toml index 5fe87fcf..b244312a 100644 --- a/crates/types/Cargo.toml +++ b/crates/types/Cargo.toml @@ -14,4 +14,6 @@ serde_with.workspace = true serde.workspace = true starknet-crypto.workspace = true strum_macros.workspace = true -thiserror.workspace = true \ No newline at end of file +thiserror.workspace = true +pathfinder_gateway_types.workspace = true +starknet-types-core.workspace = true \ No newline at end of file diff --git a/crates/types/src/cairo/starknet/header.rs b/crates/types/src/cairo/starknet/header.rs new file mode 100644 index 00000000..9cbaf4ef --- /dev/null +++ b/crates/types/src/cairo/starknet/header.rs @@ -0,0 +1,137 @@ +use cairo_vm::Felt252; +pub use pathfinder_gateway_types::reply::Block; +use strum_macros::FromRepr; + +use crate::cairo::structs::Felt; + +#[derive(FromRepr, Debug)] +pub enum FunctionId { + Parent = 0, + BlockNumber = 1, + StateRoot = 2, + SequencerAddress = 3, + BlockTimestamp = 4, + TransactionCount = 5, + TransactionCommitment = 6, + EventCount = 7, + EventCommitment = 8, + StateDiffCommitment = 9, + StateDiffLength = 10, + ReceiptCommitment = 11, + L1GasPriceWei = 12, + L1GasPriceFri = 13, + L1DataGasPriceWei = 14, + L1DataGasPriceFri = 15, + Version = 16, +} + +pub struct CairoHeader(Block); + +impl CairoHeader { + pub fn new(value: Block) -> Self { + Self(value) + } + + pub fn parent_block_hash(&self) -> Felt { + Felt252::from_bytes_be(&self.0.parent_block_hash.as_inner().to_be_bytes()).into() + } + + pub fn block_number(&self) -> Felt { + Felt252::from(self.0.block_number.get()).into() + } + + pub fn state_root(&self) -> Felt { + Felt252::from_bytes_be(&self.0.state_commitment.as_inner().to_be_bytes()).into() + } + + pub fn sequencer_address(&self) -> Felt { + Felt252::from_bytes_be(&self.0.sequencer_address.ok_or(Felt252::ZERO).unwrap().as_inner().to_be_bytes()).into() + } + + pub fn block_timestamp(&self) -> Felt { + Felt252::from(self.0.timestamp.get()).into() + } + + pub fn transaction_count(&self) -> Felt { + Felt252::from(self.0.transactions.len()).into() + } + + pub fn transaction_commitment(&self) -> Felt { + Felt252::from_bytes_be(&self.0.transaction_commitment.as_inner().to_be_bytes()).into() + } + + pub fn event_count(&self) -> Felt { + let total_events: usize = self.0.transaction_receipts.iter().map(|(_, events)| events.len()).sum(); + + Felt252::from(total_events).into() + } + + pub fn event_commitment(&self) -> Felt { + Felt252::from_bytes_be(&self.0.event_commitment.as_inner().to_be_bytes()).into() + } + + // v0.13.2+ specific fields + pub fn state_diff_commitment(&self) -> Option { + self.0 + .state_diff_commitment + .map(|f| Felt252::from_bytes_be(&f.as_inner().to_be_bytes()).into()) + } + + pub fn state_diff_length(&self) -> Option { + self.0.state_diff_length.map(|f| Felt252::from(f).into()) + } + + pub fn receipt_commitment(&self) -> Option { + self.0 + .receipt_commitment + .map(|f| Felt252::from_bytes_be(&f.as_inner().to_be_bytes()).into()) + } + + pub fn l1_gas_price_wei(&self) -> Felt { + Felt252::from(self.0.l1_gas_price.price_in_wei.0).into() + } + + pub fn l1_gas_price_fri(&self) -> Felt { + Felt252::from(self.0.l1_gas_price.price_in_fri.0).into() + } + + pub fn l1_data_gas_price_wei(&self) -> Felt { + Felt252::from(self.0.l1_data_gas_price.price_in_wei.0).into() + } + + pub fn l1_data_gas_price_fri(&self) -> Felt { + Felt252::from(self.0.l1_data_gas_price.price_in_fri.0).into() + } + + pub fn version(&self) -> Felt { + Felt252::from(self.0.starknet_version.as_u32()).into() + } + + pub fn handle(&self, function_id: FunctionId) -> Felt { + match function_id { + FunctionId::Parent => self.parent_block_hash(), + FunctionId::BlockNumber => self.block_number(), + FunctionId::StateRoot => self.state_root(), + FunctionId::SequencerAddress => self.sequencer_address(), + FunctionId::BlockTimestamp => self.block_timestamp(), + FunctionId::TransactionCount => self.transaction_count(), + FunctionId::TransactionCommitment => self.transaction_commitment(), + FunctionId::EventCount => self.event_count(), + FunctionId::EventCommitment => self.event_commitment(), + FunctionId::StateDiffCommitment => self.state_diff_commitment().unwrap_or_else(|| Felt252::ZERO.into()), + FunctionId::StateDiffLength => self.state_diff_length().unwrap_or_else(|| Felt252::ZERO.into()), + FunctionId::ReceiptCommitment => self.receipt_commitment().unwrap_or_else(|| Felt252::ZERO.into()), + FunctionId::L1GasPriceWei => self.l1_gas_price_wei(), + FunctionId::L1GasPriceFri => self.l1_gas_price_fri(), + FunctionId::L1DataGasPriceWei => self.l1_data_gas_price_wei(), + FunctionId::L1DataGasPriceFri => self.l1_data_gas_price_fri(), + FunctionId::Version => self.version(), + } + } +} + +impl From for CairoHeader { + fn from(value: Block) -> Self { + Self(value) + } +} diff --git a/crates/types/src/cairo/starknet/mod.rs b/crates/types/src/cairo/starknet/mod.rs index 8b137891..2724315c 100644 --- a/crates/types/src/cairo/starknet/mod.rs +++ b/crates/types/src/cairo/starknet/mod.rs @@ -1 +1,2 @@ - +pub mod header; +pub mod storage; diff --git a/crates/types/src/cairo/starknet/storage.rs b/crates/types/src/cairo/starknet/storage.rs new file mode 100644 index 00000000..5fe117cc --- /dev/null +++ b/crates/types/src/cairo/starknet/storage.rs @@ -0,0 +1,105 @@ +use cairo_vm::{vm::errors::memory_errors::MemoryError, Felt252}; +use strum_macros::FromRepr; + +use crate::{ + cairo::{structs::Felt, traits::CairoType, FELT_0, FELT_1}, + proofs::starknet::storage::{Path, TrieNode}, +}; + +#[derive(FromRepr, Debug)] +pub enum FunctionId { + Storage = 0, +} + +pub struct CairoStorage(Felt); + +impl CairoStorage { + pub fn new(value: Felt) -> Self { + Self(value) + } + + pub fn storage(&self) -> Felt { + self.0.clone() + } + + pub fn handler(&self, function_id: FunctionId) -> Felt { + match function_id { + FunctionId::Storage => self.storage(), + } + } +} + +impl From for CairoStorage { + fn from(value: Felt) -> Self { + Self(value) + } +} + +pub struct CairoTrieNode(pub TrieNode); + +impl CairoTrieNode { + pub fn is_edge(&self) -> bool { + match &self.0 { + TrieNode::Binary { left: _, right: _ } => false, + TrieNode::Edge { child: _, path: _ } => true, + } + } +} + +use std::vec::IntoIter; + +impl IntoIterator for CairoTrieNode { + type Item = Felt252; + type IntoIter = IntoIter; + + fn into_iter(self) -> Self::IntoIter { + match self.0 { + TrieNode::Binary { left, right } => vec![FELT_0, left, right, FELT_0].into_iter(), + TrieNode::Edge { child, path } => vec![FELT_1, child, Felt252::from_hex(&path.value).unwrap(), Felt252::from(path.len)].into_iter(), + } + } +} + +impl CairoType for CairoTrieNode { + fn from_memory(vm: &cairo_vm::vm::vm_core::VirtualMachine, address: cairo_vm::types::relocatable::Relocatable) -> Result { + let node_type: u8 = (*vm.get_integer((address + 0)?)?).try_into().unwrap(); + match node_type { + 0 => Ok(Self(TrieNode::Binary { + left: *vm.get_integer((address + 1)?)?, + right: *vm.get_integer((address + 2)?)?, + })), + 1 => Ok(Self(TrieNode::Edge { + child: *vm.get_integer((address + 1)?)?, + path: Path { + value: (*vm.get_integer((address + 2)?)?).to_string(), + len: (*vm.get_integer((address + 3)?)?).try_into().unwrap(), + }, + })), + _ => Err(MemoryError::ErrorRetrievingMessage("node type can be either 0 or 1".into())), + } + } + fn to_memory( + &self, + vm: &mut cairo_vm::vm::vm_core::VirtualMachine, + address: cairo_vm::types::relocatable::Relocatable, + ) -> Result<(), MemoryError> { + match &self.0 { + TrieNode::Binary { left, right } => { + vm.insert_value((address + 0)?, FELT_0)?; + vm.insert_value((address + 1)?, left)?; + vm.insert_value((address + 2)?, right)?; + vm.insert_value((address + 3)?, FELT_0)?; + } + TrieNode::Edge { child, path } => { + vm.insert_value((address + 0)?, FELT_1)?; + vm.insert_value((address + 1)?, child)?; + vm.insert_value((address + 2)?, Felt252::from_hex(&path.value).unwrap())?; + vm.insert_value((address + 3)?, Felt252::from(path.len))?; + } + }; + Ok(()) + } + fn n_fields() -> usize { + 4 + } +} diff --git a/crates/types/src/cairo/structs.rs b/crates/types/src/cairo/structs.rs index fdeea4bd..8f1dd826 100644 --- a/crates/types/src/cairo/structs.rs +++ b/crates/types/src/cairo/structs.rs @@ -82,3 +82,26 @@ pub struct BuiltinParams { builtin_encodings: Felt252, builtin_instance_sizes: Felt252, } + +#[derive(FieldOffsetGetters, CairoType, Default, Debug, Clone)] +pub struct Felt { + value: Felt252, +} + +impl From for Felt { + fn from(value: Felt252) -> Self { + Self { value } + } +} + +impl From for Felt { + fn from(value: u64) -> Self { + Self { value: Felt252::from(value) } + } +} + +impl From for Felt252 { + fn from(felt: Felt) -> Self { + felt.value + } +} diff --git a/crates/types/src/keys/account.rs b/crates/types/src/keys/evm/account.rs similarity index 100% rename from crates/types/src/keys/account.rs rename to crates/types/src/keys/evm/account.rs diff --git a/crates/types/src/keys/header.rs b/crates/types/src/keys/evm/header.rs similarity index 100% rename from crates/types/src/keys/header.rs rename to crates/types/src/keys/evm/header.rs diff --git a/crates/types/src/keys/evm/mod.rs b/crates/types/src/keys/evm/mod.rs new file mode 100644 index 00000000..50239120 --- /dev/null +++ b/crates/types/src/keys/evm/mod.rs @@ -0,0 +1,13 @@ +pub mod account; +pub mod header; +pub mod receipt; +pub mod storage; +pub mod transaction; + +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum KeyError { + #[error("Conversion Error: {0}")] + ConversionError(String), +} diff --git a/crates/types/src/keys/receipt.rs b/crates/types/src/keys/evm/receipt.rs similarity index 100% rename from crates/types/src/keys/receipt.rs rename to crates/types/src/keys/evm/receipt.rs diff --git a/crates/types/src/keys/storage.rs b/crates/types/src/keys/evm/storage.rs similarity index 100% rename from crates/types/src/keys/storage.rs rename to crates/types/src/keys/evm/storage.rs diff --git a/crates/types/src/keys/transaction.rs b/crates/types/src/keys/evm/transaction.rs similarity index 100% rename from crates/types/src/keys/transaction.rs rename to crates/types/src/keys/evm/transaction.rs diff --git a/crates/types/src/keys/mod.rs b/crates/types/src/keys/mod.rs index 50239120..9f3dd66d 100644 --- a/crates/types/src/keys/mod.rs +++ b/crates/types/src/keys/mod.rs @@ -1,13 +1,2 @@ -pub mod account; -pub mod header; -pub mod receipt; -pub mod storage; -pub mod transaction; - -use thiserror::Error; - -#[derive(Error, Debug)] -pub enum KeyError { - #[error("Conversion Error: {0}")] - ConversionError(String), -} +pub mod evm; +pub mod starknet; diff --git a/crates/types/src/keys/starknet/header.rs b/crates/types/src/keys/starknet/header.rs new file mode 100644 index 00000000..74eb50ae --- /dev/null +++ b/crates/types/src/keys/starknet/header.rs @@ -0,0 +1,54 @@ +use super::KeyError; +use crate::cairo::traits::CairoType; +use cairo_vm::{ + types::relocatable::Relocatable, + vm::{errors::memory_errors::MemoryError, vm_core::VirtualMachine}, + Felt252, +}; +use serde::{Deserialize, Serialize}; +use starknet_crypto::poseidon_hash_many; + +#[derive(Debug, Clone)] +pub struct CairoKey { + chain_id: Felt252, + block_number: Felt252, +} + +impl CairoKey { + pub fn hash(&self) -> Felt252 { + poseidon_hash_many(&[self.chain_id, self.block_number]) + } +} + +impl CairoType for CairoKey { + fn from_memory(vm: &VirtualMachine, address: Relocatable) -> Result { + Ok(Self { + chain_id: *vm.get_integer((address + 0)?)?, + block_number: *vm.get_integer((address + 1)?)?, + }) + } + fn to_memory(&self, vm: &mut VirtualMachine, address: Relocatable) -> Result<(), MemoryError> { + vm.insert_value((address + 0)?, self.chain_id)?; + vm.insert_value((address + 1)?, self.block_number)?; + Ok(()) + } + fn n_fields() -> usize { + 2 + } +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +pub struct Key { + pub chain_id: u128, + pub block_number: u64, +} + +impl TryFrom for Key { + type Error = KeyError; + fn try_from(value: CairoKey) -> Result { + Ok(Self { + chain_id: value.chain_id.try_into().map_err(|e| KeyError::ConversionError(format!("{}", e)))?, + block_number: value.block_number.try_into().map_err(|e| KeyError::ConversionError(format!("{}", e)))?, + }) + } +} diff --git a/crates/types/src/keys/starknet/mod.rs b/crates/types/src/keys/starknet/mod.rs new file mode 100644 index 00000000..47a2c991 --- /dev/null +++ b/crates/types/src/keys/starknet/mod.rs @@ -0,0 +1,10 @@ +pub mod header; +pub mod storage; + +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum KeyError { + #[error("Conversion Error: {0}")] + ConversionError(String), +} diff --git a/crates/types/src/keys/starknet/storage.rs b/crates/types/src/keys/starknet/storage.rs new file mode 100644 index 00000000..c07352bf --- /dev/null +++ b/crates/types/src/keys/starknet/storage.rs @@ -0,0 +1,66 @@ +use super::KeyError; +use crate::cairo::traits::CairoType; +use cairo_vm::{ + types::relocatable::Relocatable, + vm::{errors::memory_errors::MemoryError, vm_core::VirtualMachine}, + Felt252, +}; +use serde::{Deserialize, Serialize}; +use starknet_crypto::poseidon_hash_many; + +#[derive(Debug, Clone)] +pub struct CairoKey { + chain_id: Felt252, + block_number: Felt252, + address: Felt252, + storage_slot: Felt252, +} + +impl CairoKey { + pub fn hash(&self) -> Felt252 { + poseidon_hash_many(&[self.chain_id, self.block_number, self.address, self.storage_slot]) + } +} + +impl CairoType for CairoKey { + fn from_memory(vm: &VirtualMachine, address: Relocatable) -> Result { + Ok(Self { + chain_id: *vm.get_integer((address + 0)?)?, + block_number: *vm.get_integer((address + 1)?)?, + address: *vm.get_integer((address + 2)?)?, + storage_slot: *vm.get_integer((address + 3)?)?, + }) + } + fn to_memory(&self, vm: &mut VirtualMachine, address: Relocatable) -> Result<(), MemoryError> { + vm.insert_value((address + 0)?, self.chain_id)?; + vm.insert_value((address + 1)?, self.block_number)?; + vm.insert_value((address + 2)?, self.address)?; + vm.insert_value((address + 3)?, self.storage_slot)?; + Ok(()) + } + fn n_fields() -> usize { + 4 + } +} + +pub type StorageKey = Felt252; + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +pub struct Key { + pub chain_id: u128, + pub block_number: u64, + pub address: Felt252, + pub storage_slot: Felt252, +} + +impl TryFrom for Key { + type Error = KeyError; + fn try_from(value: CairoKey) -> Result { + Ok(Self { + chain_id: value.chain_id.try_into().map_err(|e| KeyError::ConversionError(format!("{}", e)))?, + block_number: value.block_number.try_into().map_err(|e| KeyError::ConversionError(format!("{}", e)))?, + address: value.address, + storage_slot: value.storage_slot, + }) + } +} diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index 45bcf1d2..c88f9062 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -8,13 +8,14 @@ pub mod keys; pub mod param; pub mod proofs; -use alloy::primitives::ChainId; use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; use param::Param; -use proofs::Proofs; +use proofs::{evm, starknet}; use serde::{Deserialize, Serialize}; -pub const RPC: &str = "RPC"; +pub const ETH_RPC: &str = "ETH_RPC"; +pub const STARKNET_RPC: &str = "STARKNET_RPC"; +pub const FEEDER_GATEWAY: &str = "FEEDER_GATEWAY"; #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct HDPDryRunInput { @@ -31,15 +32,19 @@ pub struct HDPInput { #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub enum ChainProofs { - EthereumMainnet(Proofs), - EthereumSepolia(Proofs), + EthereumMainnet(evm::Proofs), + EthereumSepolia(evm::Proofs), + StarknetMainnet(starknet::Proofs), + StarknetSepolia(starknet::Proofs), } impl ChainProofs { - pub fn chain_id(&self) -> ChainId { + pub fn chain_id(&self) -> u128 { match self { - ChainProofs::EthereumMainnet(_) => 1, - ChainProofs::EthereumSepolia(_) => 11155111, + ChainProofs::EthereumMainnet(_) => 0x1, + ChainProofs::EthereumSepolia(_) => 0xaa36a7, + ChainProofs::StarknetMainnet(_) => 0x534e5f4d41494e, + ChainProofs::StarknetSepolia(_) => 0x534e5f5345504f4c4941, } } } diff --git a/crates/types/src/proofs/account.rs b/crates/types/src/proofs/evm/account.rs similarity index 94% rename from crates/types/src/proofs/account.rs rename to crates/types/src/proofs/evm/account.rs index 0d1cca3c..facd13c4 100644 --- a/crates/types/src/proofs/account.rs +++ b/crates/types/src/proofs/evm/account.rs @@ -1,4 +1,4 @@ -use super::mpt::MPTProof; +use crate::proofs::mpt::MPTProof; use alloy::primitives::{keccak256, Address, B256}; use serde::{Deserialize, Serialize}; diff --git a/crates/types/src/proofs/evm/header.rs b/crates/types/src/proofs/evm/header.rs new file mode 100644 index 00000000..dbfc1779 --- /dev/null +++ b/crates/types/src/proofs/evm/header.rs @@ -0,0 +1,9 @@ +use crate::proofs::header::HeaderProof; +use alloy::primitives::Bytes; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Eq, Hash, Default)] +pub struct Header { + pub rlp: Bytes, + pub proof: HeaderProof, +} diff --git a/crates/types/src/proofs/evm/mod.rs b/crates/types/src/proofs/evm/mod.rs new file mode 100644 index 00000000..f08127de --- /dev/null +++ b/crates/types/src/proofs/evm/mod.rs @@ -0,0 +1,22 @@ +use super::header::HeaderMmrMeta; +use account::Account; +use header::Header; +use receipt::Receipt; +use serde::{Deserialize, Serialize}; +use storage::Storage; +use transaction::Transaction; + +pub mod account; +pub mod header; +pub mod receipt; +pub mod storage; +pub mod transaction; + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Default)] +pub struct Proofs { + pub headers_with_mmr: Vec>, + pub accounts: Vec, + pub storages: Vec, + pub transactions: Vec, + pub transaction_receipts: Vec, +} diff --git a/crates/types/src/proofs/receipt.rs b/crates/types/src/proofs/evm/receipt.rs similarity index 90% rename from crates/types/src/proofs/receipt.rs rename to crates/types/src/proofs/evm/receipt.rs index 69d70c89..387158d4 100644 --- a/crates/types/src/proofs/receipt.rs +++ b/crates/types/src/proofs/evm/receipt.rs @@ -1,4 +1,4 @@ -use super::mpt::MPTProof; +use crate::proofs::mpt::MPTProof; use alloy::primitives::U256; use serde::{Deserialize, Serialize}; diff --git a/crates/types/src/proofs/storage.rs b/crates/types/src/proofs/evm/storage.rs similarity index 95% rename from crates/types/src/proofs/storage.rs rename to crates/types/src/proofs/evm/storage.rs index 2137b0fa..787136b1 100644 --- a/crates/types/src/proofs/storage.rs +++ b/crates/types/src/proofs/evm/storage.rs @@ -1,4 +1,4 @@ -use super::mpt::MPTProof; +use crate::proofs::mpt::MPTProof; use alloy::primitives::{keccak256, Address, StorageKey, B256}; use serde::{Deserialize, Serialize}; diff --git a/crates/types/src/proofs/transaction.rs b/crates/types/src/proofs/evm/transaction.rs similarity index 90% rename from crates/types/src/proofs/transaction.rs rename to crates/types/src/proofs/evm/transaction.rs index 8c7b522b..c60898fc 100644 --- a/crates/types/src/proofs/transaction.rs +++ b/crates/types/src/proofs/evm/transaction.rs @@ -1,4 +1,4 @@ -use super::mpt::MPTProof; +use crate::proofs::mpt::MPTProof; use alloy::primitives::U256; use serde::{Deserialize, Serialize}; diff --git a/crates/types/src/proofs/header.rs b/crates/types/src/proofs/header.rs index 54d65e38..a01a2c08 100644 --- a/crates/types/src/proofs/header.rs +++ b/crates/types/src/proofs/header.rs @@ -1,16 +1,17 @@ +use super::mmr::MmrMeta; use alloy::primitives::Bytes; use serde::{Deserialize, Serialize}; use serde_with::serde_as; +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Default, Hash)] +pub struct HeaderMmrMeta { + pub headers: Vec, + pub mmr_meta: MmrMeta, +} + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Eq, Hash, Default)] #[serde_as] pub struct HeaderProof { pub leaf_idx: u64, pub mmr_path: Vec, } - -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Eq, Hash, Default)] -pub struct Header { - pub rlp: Bytes, - pub proof: HeaderProof, -} diff --git a/crates/types/src/proofs/mod.rs b/crates/types/src/proofs/mod.rs index 410c82d4..3493064a 100644 --- a/crates/types/src/proofs/mod.rs +++ b/crates/types/src/proofs/mod.rs @@ -1,30 +1,5 @@ -pub mod account; +pub mod evm; pub mod header; pub mod mmr; pub mod mpt; -pub mod receipt; -pub mod storage; -pub mod transaction; - -use account::Account; -use header::Header; -use mmr::MmrMeta; -use receipt::Receipt; -use serde::{Deserialize, Serialize}; -use storage::Storage; -use transaction::Transaction; - -#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Default, Hash)] -pub struct HeaderMmrMeta { - pub headers: Vec
, - pub mmr_meta: MmrMeta, -} - -#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Default)] -pub struct Proofs { - pub headers_with_mmr: Vec, - pub accounts: Vec, - pub storages: Vec, - pub transactions: Vec, - pub transaction_receipts: Vec, -} +pub mod starknet; diff --git a/crates/types/src/proofs/starknet/header.rs b/crates/types/src/proofs/starknet/header.rs new file mode 100644 index 00000000..555c259d --- /dev/null +++ b/crates/types/src/proofs/starknet/header.rs @@ -0,0 +1,9 @@ +use crate::proofs::header::HeaderProof; +use cairo_vm::Felt252; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Eq, Hash, Default)] +pub struct Header { + pub fields: Vec, + pub proof: HeaderProof, +} diff --git a/crates/types/src/proofs/starknet/mod.rs b/crates/types/src/proofs/starknet/mod.rs new file mode 100644 index 00000000..281281e2 --- /dev/null +++ b/crates/types/src/proofs/starknet/mod.rs @@ -0,0 +1,13 @@ +use super::header::HeaderMmrMeta; +use header::Header; +use serde::{Deserialize, Serialize}; +use storage::Storage; + +pub mod header; +pub mod storage; + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Default)] +pub struct Proofs { + pub headers_with_mmr: Vec>, + pub storages: Vec, +} diff --git a/crates/types/src/proofs/starknet/storage.rs b/crates/types/src/proofs/starknet/storage.rs new file mode 100644 index 00000000..a00e7399 --- /dev/null +++ b/crates/types/src/proofs/starknet/storage.rs @@ -0,0 +1,110 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Eq, Hash)] +pub struct Storage { + pub block_number: u64, + pub contract_address: Felt252, + pub storage_addresses: Vec, + pub proof: GetProofOutput, +} + +impl Storage { + pub fn new(block_number: u64, contract_address: Felt252, storage_addresses: Vec, proof: GetProofOutput) -> Self { + Self { + block_number, + contract_address, + storage_addresses, + proof, + } + } +} + +// Diclaimers: +// Currently, there is no good way of importing this type from an external crate. We have found the following implementations: +// - https://github.com/keep-starknet-strange/snos/tree/main/crates/rpc-client/src/pathfinder +// - https://github.com/eqlabs/pathfinder/blob/main/crates/rpc/src/pathfinder/methods/get_proof.rs +// Both fo these implementations essentially force us to follow the cairo-vm versions that are used, which is a bad idea for us to do. +// We should aim for finding an implementation that we can simply update instead of manageing it ourself. +// This is a temporary solution that we should aim to replace. + +use cairo_vm::Felt252; +use serde_with::skip_serializing_none; +use starknet_types_core::hash::StarkHash; + +/// Codebase is from +/// Holds the membership/non-membership of a contract and its associated +/// contract contract if the contract exists. +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Eq, Hash)] +#[skip_serializing_none] +pub struct GetProofOutput { + /// The global state commitment for Starknet 0.11.0 blocks onwards, if + /// absent the hash of the first node in the + /// [contract_proof](GetProofOutput#contract_proof) is the global state + /// commitment. + pub state_commitment: Option, + /// Required to verify that the hash of the class commitment and the root of + /// the [contract_proof](GetProofOutput::contract_proof) matches the + /// [state_commitment](Self#state_commitment). Present only for Starknet + /// blocks 0.11.0 onwards. + pub class_commitment: Option, + + /// Membership / Non-membership proof for the queried contract + pub contract_proof: Vec, + + /// Additional contract data if it exists. + pub contract_data: Option, +} + +/// A node in a Starknet patricia-merkle trie. +/// +/// See pathfinders merkle-tree crate for more information. +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Eq, Hash)] +pub enum TrieNode { + #[serde(rename = "binary")] + Binary { left: Felt252, right: Felt252 }, + #[serde(rename = "edge")] + Edge { child: Felt252, path: Path }, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Eq, Hash)] +pub struct Path { + pub len: u64, + pub value: String, +} + +impl TrieNode { + pub fn hash(&self) -> Felt252 { + match self { + TrieNode::Binary { left, right } => H::hash(left, right), + TrieNode::Edge { child, path } => { + let bytes: [u8; 32] = path.value.as_bytes().try_into().unwrap(); + let mut length = [0; 32]; + // Safe as len() is guaranteed to be <= 251 + length[31] = bytes.len() as u8; + + let length = Felt252::from_bytes_be(&length); + let path = Felt252::from_bytes_be(&bytes); + H::hash(child, &path) + length + } + } + } +} + +/// Holds the data and proofs for a specific contract. +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Eq, Hash)] +pub struct ContractData { + /// Required to verify the contract state hash to contract root calculation. + pub class_hash: Felt252, + /// Required to verify the contract state hash to contract root calculation. + pub nonce: Felt252, + + /// Root of the Contract state tree + pub root: Felt252, + + /// This is currently just a constant = 0, however it might change in the + /// future. + pub contract_state_hash_version: Felt252, + + /// The proofs associated with the queried storage values + pub storage_proofs: Vec>, +} diff --git a/src/hdp.cairo b/src/hdp.cairo index 52739fb2..aeee0148 100644 --- a/src/hdp.cairo +++ b/src/hdp.cairo @@ -88,6 +88,7 @@ func run{ let (mmr_metas_len) = run_state_verification{ range_check_ptr=range_check_ptr, + pedersen_ptr=pedersen_ptr, poseidon_ptr=poseidon_ptr, keccak_ptr=keccak_ptr, bitwise_ptr=bitwise_ptr, diff --git a/src/types.cairo b/src/types.cairo index baef9a28..e9217191 100644 --- a/src/types.cairo +++ b/src/types.cairo @@ -18,3 +18,23 @@ struct ModuleTask { module_inputs_len: felt, module_inputs: felt*, } + +// Enum TrieNode +struct TrieNode { + type: felt, + field1: felt, + field2: felt, + field3: felt, +} +struct TrieNodeBinary { + type: felt, + left: felt, + right: felt, + _unused: felt, +} +struct TrieNodeEdge { + type: felt, + child: felt, + value: felt, + len: felt, +} diff --git a/src/verifiers/evm/account_verifier.cairo b/src/verifiers/evm/account_verifier.cairo index 7a50cd47..7068d5c3 100644 --- a/src/verifiers/evm/account_verifier.cairo +++ b/src/verifiers/evm/account_verifier.cairo @@ -22,7 +22,7 @@ func verify_accounts{ }() { alloc_locals; - tempvar n_accounts: felt = nondet %{ len(batch.accounts) %}; + tempvar n_accounts: felt = nondet %{ len(batch_evm.accounts) %}; verify_accounts_inner(n_accounts, 0); return (); @@ -44,18 +44,18 @@ func verify_accounts_inner{ let (address: felt*) = alloc(); %{ - account = batch.accounts[ids.idx] - segments.write_arg(ids.address, [int(x, 16) for x in account.address])) + account_evm = batch_evm.accounts[ids.idx] + segments.write_arg(ids.address, [int(x, 16) for x in account_evm.address])) %} local key: Uint256; %{ from tools.py.utils import split_128 - (ids.key.low, ids.key.high) = split_128(int(account.account_key, 16)) + (ids.key.low, ids.key.high) = split_128(int(account_evm.account_key, 16)) %} local key_leading_zeros: felt; - %{ ids.key_leading_zeros = len(account.account_key.lstrip("0x")) - len(account.account_key.lstrip("0x").lstrip("0")) %} + %{ ids.key_leading_zeros = len(account_evm.account_key.lstrip("0x")) - len(account_evm.account_key.lstrip("0x").lstrip("0")) %} // Validate MPT key matches address let (hash: Uint256) = keccak_bigend(address, 20); @@ -64,7 +64,7 @@ func verify_accounts_inner{ let (felt_address) = le_address_chunks_to_felt(address); - tempvar n_proofs: felt = nondet %{ len(account.proofs) %}; + tempvar n_proofs: felt = nondet %{ len(account_evm.proofs) %}; verify_account( address=felt_address, key=key, key_leading_zeros=key_leading_zeros, n_proofs=n_proofs, idx=0 ); @@ -86,7 +86,7 @@ func verify_account{ return (); } - %{ proof = account.proofs[ids.idx] %} + %{ proof = account_evm.proofs[ids.idx] %} tempvar proof_len: felt = nondet %{ len(proof.proof) %}; tempvar block_number: felt = nondet %{ proof.block_number %}; diff --git a/src/verifiers/evm/block_tx_verifier.cairo b/src/verifiers/evm/block_tx_verifier.cairo index 00d7dbdf..dc92bf4f 100644 --- a/src/verifiers/evm/block_tx_verifier.cairo +++ b/src/verifiers/evm/block_tx_verifier.cairo @@ -29,7 +29,7 @@ func verify_block_tx_proofs{ }() { alloc_locals; - tempvar n_tx_proofs: felt = nondet %{ len(batch.transactions) %}; + tempvar n_tx_proofs: felt = nondet %{ len(batch_evm.transactions) %}; verify_block_tx_proofs_inner(n_tx_proofs, 0); return (); diff --git a/src/verifiers/evm/header_verifier.cairo b/src/verifiers/evm/header_verifier.cairo index 9f1a5162..ef9c320c 100644 --- a/src/verifiers/evm/header_verifier.cairo +++ b/src/verifiers/evm/header_verifier.cairo @@ -9,7 +9,7 @@ from packages.eth_essentials.lib.mmr import hash_subtree_path from src.types import MMRMeta, ChainInfo from src.memorizers.evm.memorizer import EvmMemorizer, EvmHashParams from src.decoders.evm.header_decoder import HeaderDecoder -from src.verifiers.mmr_verifier import validate_mmr_meta +from src.verifiers.mmr_verifier import validate_mmr_meta_evm func verify_mmr_batches{ range_check_ptr, @@ -26,12 +26,12 @@ func verify_mmr_batches{ return (mmr_meta_idx=mmr_meta_idx); } - %{ vm_enter_scope({'header_with_mmr': batch.headers_with_mmr[ids.idx - 1], '__dict_manager': __dict_manager}) %} + %{ vm_enter_scope({'header_with_mmr_evm': batch_evm.headers_with_mmr[ids.idx - 1], '__dict_manager': __dict_manager}) %} - let (mmr_meta, peaks_dict, peaks_dict_start) = validate_mmr_meta(); + let (mmr_meta, peaks_dict, peaks_dict_start) = validate_mmr_meta_evm(); assert mmr_metas[mmr_meta_idx] = mmr_meta; - tempvar n_header_proofs: felt = nondet %{ len(header_with_mmr.headers) %}; + tempvar n_header_proofs: felt = nondet %{ len(header_with_mmr_evm.headers) %}; with mmr_meta, peaks_dict { verify_headers_with_mmr_peaks(n_header_proofs); } @@ -67,12 +67,12 @@ func verify_headers_with_mmr_peaks{ let (rlp) = alloc(); %{ - header = header_with_mmr.headers[ids.idx - 1] - segments.write_arg(ids.rlp, [int(x, 16) for x in header.rlp]) + header_evm = header_with_mmr_evm.headers[ids.idx - 1] + segments.write_arg(ids.rlp, [int(x, 16) for x in header_evm.rlp]) %} - tempvar rlp_len: felt = nondet %{ len(header.rlp) %}; - tempvar leaf_idx: felt = nondet %{ len(header.proof.leaf_idx) %}; + tempvar rlp_len: felt = nondet %{ len(header_evm.rlp) %}; + tempvar leaf_idx: felt = nondet %{ len(header_evm.proof.leaf_idx) %}; // compute the hash of the header let (poseidon_hash) = poseidon_hash_many(n=rlp_len, elements=rlp); @@ -92,8 +92,8 @@ func verify_headers_with_mmr_peaks{ } let (mmr_path) = alloc(); - tempvar mmr_path_len: felt = nondet %{ len(header.proof.mmr_path) %}; - %{ segments.write_arg(ids.mmr_path, [int(x, 16) for x in header.proof.mmr_path]) %} + tempvar mmr_path_len: felt = nondet %{ len(header_evm.proof.mmr_path) %}; + %{ segments.write_arg(ids.mmr_path, [int(x, 16) for x in header_evm.proof.mmr_path]) %} // compute the peak of the header let (computed_peak) = hash_subtree_path( diff --git a/src/verifiers/evm/receipt_verifier.cairo b/src/verifiers/evm/receipt_verifier.cairo index 4b133936..d73e439b 100644 --- a/src/verifiers/evm/receipt_verifier.cairo +++ b/src/verifiers/evm/receipt_verifier.cairo @@ -28,7 +28,7 @@ func verify_block_receipt_proofs{ }() { alloc_locals; - tempvar n_receipts: felt = nondet %{ len(batch.receipts) %}; + tempvar n_receipts: felt = nondet %{ len(batch_evm.receipts) %}; verify_block_receipt_proofs_inner(n_receipts, 0); return (); diff --git a/src/verifiers/evm/storage_item_verifier.cairo b/src/verifiers/evm/storage_item_verifier.cairo index ddb2d0e8..ed482058 100644 --- a/src/verifiers/evm/storage_item_verifier.cairo +++ b/src/verifiers/evm/storage_item_verifier.cairo @@ -28,7 +28,7 @@ func verify_storage_items{ }() { alloc_locals; - tempvar n_storage_items: felt = nondet %{ len(batch.storages) %}; + tempvar n_storage_items: felt = nondet %{ len(batch_evm.storages) %}; verify_storage_items_inner(n_storage_items, 0); return (); @@ -51,21 +51,21 @@ func verify_storage_items_inner{ let (address: felt*) = alloc(); %{ - storage = batch.storages[ids.idx] - segments.write_arg(ids.address, [int(x, 16) for x in storage.address])) + storage_evm = batch_evm.storages[ids.idx] + segments.write_arg(ids.address, [int(x, 16) for x in storage_evm.address])) %} let (slot: felt*) = alloc(); - %{ segments.write_arg(ids.slot, [int(x, 16) for x in storage.slot])) %} + %{ segments.write_arg(ids.slot, [int(x, 16) for x in storage_evm.slot])) %} local key: Uint256; %{ from tools.py.utils import split_128 - (ids.key.low, ids.key.high) = split_128(int(storage.storage_key, 16)) + (ids.key.low, ids.key.high) = split_128(int(storage_evm.storage_key, 16)) %} local key_leading_zeros: felt; - %{ ids.key_leading_zeros = len(storage.storage_key.lstrip("0x")) - len(storage.storage_key.lstrip("0x").lstrip("0")) %} + %{ ids.key_leading_zeros = len(storage_evm.storage_key.lstrip("0x")) - len(storage_evm.storage_key.lstrip("0x").lstrip("0")) %} // ensure that slot matches the key let (hash: Uint256) = keccak_bigend(slot, 32); @@ -78,7 +78,7 @@ func verify_storage_items_inner{ let (felt_address) = le_address_chunks_to_felt(address); - tempvar n_proofs: felt = nondet %{ len(storage.proofs) %}; + tempvar n_proofs: felt = nondet %{ len(storage_evm.proofs) %}; verify_storage_item( address=felt_address, slot=slot_be, @@ -106,7 +106,7 @@ func verify_storage_item{ return (); } - %{ proof = storage.proofs[ids.idx] %} + %{ proof = storage_evm.proofs[ids.idx] %} tempvar proof_len: felt = nondet %{ len(proof.proof) %}; tempvar block_number: felt = nondet %{ proof.block_number %}; diff --git a/src/verifiers/evm/verify.cairo b/src/verifiers/evm/verify.cairo index 6609873b..ae04de22 100644 --- a/src/verifiers/evm/verify.cairo +++ b/src/verifiers/evm/verify.cairo @@ -4,24 +4,31 @@ from src.verifiers.evm.header_verifier import verify_mmr_batches from src.verifiers.evm.block_tx_verifier import verify_block_tx_proofs from src.verifiers.evm.receipt_verifier import verify_block_receipt_proofs from starkware.cairo.common.dict_access import DictAccess -from starkware.cairo.common.cairo_builtins import PoseidonBuiltin, BitwiseBuiltin, KeccakBuiltin +from starkware.cairo.common.cairo_builtins import ( + PoseidonBuiltin, + BitwiseBuiltin, + KeccakBuiltin, + HashBuiltin, +) from src.types import MMRMeta, ChainInfo from src.utils.chain_info import fetch_chain_info func run_state_verification{ range_check_ptr, + pedersen_ptr: HashBuiltin*, poseidon_ptr: PoseidonBuiltin*, keccak_ptr: KeccakBuiltin*, bitwise_ptr: BitwiseBuiltin*, pow2_array: felt*, evm_memorizer: DictAccess*, + starknet_memorizer: DictAccess*, mmr_metas: MMRMeta*, chain_info: ChainInfo, }(mmr_meta_idx: felt) -> (mmr_meta_idx: felt) { alloc_locals; // Step 1: Verify MMR and headers inclusion - tempvar n_proofs: felt = nondet %{ len(batch.headers_with_mmr) %}; + tempvar n_proofs: felt = nondet %{ len(batch_evm.headers_with_mmr_evm) %}; let (mmr_meta_idx) = verify_mmr_batches(n_proofs, mmr_meta_idx); // Step 2: Verify the accounts verify_accounts(); diff --git a/src/verifiers/mmr_verifier.cairo b/src/verifiers/mmr_verifier.cairo index b861aa5d..86b8fde2 100644 --- a/src/verifiers/mmr_verifier.cairo +++ b/src/verifiers/mmr_verifier.cairo @@ -4,7 +4,6 @@ from packages.eth_essentials.lib.utils import write_felt_array_to_dict_keys from starkware.cairo.common.dict_access import DictAccess from starkware.cairo.common.default_dict import default_dict_new from starkware.cairo.common.alloc import alloc - from packages.eth_essentials.lib.mmr import ( mmr_root_poseidon, assert_mmr_size_is_valid, @@ -16,24 +15,61 @@ from packages.eth_essentials.lib.mmr import ( // 2. mmr_peaks_len matches the expected value based on mmr_size // 3. mmr_peaks, mmr_size recreate the mmr_root // It writes the peaks to the dict and returns the mmr_meta. -func validate_mmr_meta{range_check_ptr, poseidon_ptr: PoseidonBuiltin*, pow2_array: felt*}() -> ( - mmr_meta: MMRMeta, dict: DictAccess*, dict_start: DictAccess* -) { +func validate_mmr_meta_evm{range_check_ptr, poseidon_ptr: PoseidonBuiltin*, pow2_array: felt*}( + ) -> (mmr_meta: MMRMeta, dict: DictAccess*, dict_start: DictAccess*) { + alloc_locals; + + let (local dict: DictAccess*) = default_dict_new(default_value=-1); + tempvar dict_start = dict; + + local mmr_meta: MMRMeta = MMRMeta( + id=nondet %{ header_with_mmr_evm.mmr_meta.id %}, + root=nondet %{ header_with_mmr_evm.mmr_meta.root %}, + size=nondet %{ header_with_mmr_evm.mmr_meta.size %}, + ); + + tempvar peaks_len: felt = nondet %{ len(header_with_mmr_evm.mmr_meta.peaks) %}; + + let (peaks: felt*) = alloc(); + %{ segments.write_arg(ids.peaks, header_with_mmr_evm.mmr_meta.peaks) %} + + assert_mmr_size_is_valid(mmr_meta.size); + + // ensure the mmr_peaks_len is valid + let (_, expected_peaks_len) = compute_peaks_positions(mmr_meta.size); + assert 0 = peaks_len - expected_peaks_len; + + // ensure the mmr_peaks recreate the passed mmr_root + let (mmr_root) = mmr_root_poseidon(peaks, mmr_meta.size, peaks_len); + assert 0 = mmr_meta.root - mmr_root; + + write_felt_array_to_dict_keys{dict_end=dict}(array=peaks, index=peaks_len - 1); + + return (mmr_meta=mmr_meta, dict=dict, dict_start=dict_start); +} + +// Validates the MMR meta, ensuring the peaks are valid and the root is correct. +// 1. mmr_size is valid +// 2. mmr_peaks_len matches the expected value based on mmr_size +// 3. mmr_peaks, mmr_size recreate the mmr_root +// It writes the peaks to the dict and returns the mmr_meta. +func validate_mmr_meta_starknet{range_check_ptr, poseidon_ptr: PoseidonBuiltin*, pow2_array: felt*}( + ) -> (mmr_meta: MMRMeta, dict: DictAccess*, dict_start: DictAccess*) { alloc_locals; let (local dict: DictAccess*) = default_dict_new(default_value=-1); tempvar dict_start = dict; local mmr_meta: MMRMeta = MMRMeta( - id=nondet %{ header_with_mmr.mmr_meta.id %}, - root=nondet %{ header_with_mmr.mmr_meta.root %}, - size=nondet %{ header_with_mmr.mmr_meta.size %}, + id=nondet %{ header_with_mmr_starknet.mmr_meta.id %}, + root=nondet %{ header_with_mmr_starknet.mmr_meta.root %}, + size=nondet %{ header_with_mmr_starknet.mmr_meta.size %}, ); - tempvar peaks_len: felt = nondet %{ len(header_with_mmr.mmr_meta.peaks) %}; + tempvar peaks_len: felt = nondet %{ len(header_with_mmr_starknet.mmr_meta.peaks) %}; let (peaks: felt*) = alloc(); - %{ segments.write_arg(ids.peaks, header_with_mmr.mmr_meta.peaks) %} + %{ segments.write_arg(ids.peaks, header_with_mmr_starknet.mmr_meta.peaks) %} assert_mmr_size_is_valid(mmr_meta.size); diff --git a/src/verifiers/starknet/header_verifier.cairo b/src/verifiers/starknet/header_verifier.cairo index 650199c9..04bb9cf4 100644 --- a/src/verifiers/starknet/header_verifier.cairo +++ b/src/verifiers/starknet/header_verifier.cairo @@ -1,4 +1,4 @@ -from starkware.cairo.common.cairo_builtins import PoseidonBuiltin +from starkware.cairo.common.cairo_builtins import PoseidonBuiltin, BitwiseBuiltin from starkware.cairo.common.dict_access import DictAccess from starkware.cairo.common.dict import dict_read from starkware.cairo.common.alloc import alloc @@ -9,22 +9,29 @@ from packages.eth_essentials.lib.mmr import hash_subtree_path from src.types import MMRMeta, ChainInfo from src.memorizers.starknet.memorizer import StarknetMemorizer, StarknetHashParams from src.decoders.starknet.header_decoder import StarknetHeaderDecoder, StarknetHeaderFields -from src.verifiers.mmr_verifier import validate_mmr_meta +from src.verifiers.mmr_verifier import validate_mmr_meta_starknet func verify_mmr_batches{ range_check_ptr, poseidon_ptr: PoseidonBuiltin*, + bitwise_ptr: BitwiseBuiltin*, pow2_array: felt*, starknet_memorizer: DictAccess*, mmr_metas: MMRMeta*, chain_info: ChainInfo, -}(mmr_meta_idx: felt) -> (mmr_meta_idx: felt) { +}(idx: felt, mmr_meta_idx: felt) -> (mmr_meta_idx: felt) { alloc_locals; - let (mmr_meta, peaks_dict, peaks_dict_start) = validate_mmr_meta(); + if (0 == idx) { + return (mmr_meta_idx=mmr_meta_idx); + } + + %{ vm_enter_scope({'header_with_mmr_starknet': batch_starknet.headers_with_mmr[ids.idx - 1], '__dict_manager': __dict_manager}) %} + + let (mmr_meta, peaks_dict, peaks_dict_start) = validate_mmr_meta_starknet(); assert mmr_metas[mmr_meta_idx] = mmr_meta; - tempvar n_header_proofs: felt = nondet %{ len(header_with_mmr.headers) %}; + tempvar n_header_proofs: felt = nondet %{ len(header_with_mmr_starknet.headers) %}; with mmr_meta, peaks_dict { verify_headers_with_mmr_peaks(n_header_proofs); } @@ -32,7 +39,9 @@ func verify_mmr_batches{ // Ensure the peaks dict for this batch is finalized default_dict_finalize(peaks_dict_start, peaks_dict, -1); - return (mmr_meta_idx=mmr_meta_idx + 1); + %{ vm_exit_scope() %} + + return verify_mmr_batches(idx=idx - 1, mmr_meta_idx=mmr_meta_idx + 1); } // Guard function that verifies the inclusion of headers in the MMR. @@ -44,10 +53,11 @@ func verify_mmr_batches{ func verify_headers_with_mmr_peaks{ range_check_ptr, poseidon_ptr: PoseidonBuiltin*, + bitwise_ptr: BitwiseBuiltin*, pow2_array: felt*, + starknet_memorizer: DictAccess*, chain_info: ChainInfo, mmr_meta: MMRMeta, - starknet_memorizer: DictAccess*, peaks_dict: DictAccess*, }(idx: felt) { alloc_locals; @@ -57,37 +67,46 @@ func verify_headers_with_mmr_peaks{ let (fields) = alloc(); %{ - header = header_with_mmr.headers[ids.idx - 1] - segments.write_arg(ids.fields, [int(x, 16) for x in header.fields]) + header_starknet = header_with_mmr_starknet.headers[ids.idx - 1] + segments.write_arg(ids.fields, [int(x, 16) for x in header_starknet.fields]) %} - tempvar fields_len: felt = nondet %{ len(header.fields) %}; - tempvar leaf_idx: felt = nondet %{ len(header.proof.leaf_idx) %}; + tempvar fields_len: felt = nondet %{ len(header_starknet.fields) %}; + tempvar leaf_idx: felt = nondet %{ len(header_starknet.proof.leaf_idx) %}; // compute the hash of the header - let (header_hash) = poseidon_hash_many(n=fields_len, elements=fields); + let (poseidon_hash) = poseidon_hash_many(n=fields_len, elements=fields); // a header can be the right-most peak if (leaf_idx == mmr_meta.size) { // instead of running an inclusion proof, we ensure its a known peak - let (contains_peak) = dict_read{dict_ptr=peaks_dict}(header_hash); + let (contains_peak) = dict_read{dict_ptr=peaks_dict}(poseidon_hash); assert contains_peak = 1; // add to memorizer - let block_number = [fields + 1]; - let memorizer_key = StarknetHashParams.header(chain_info.id, block_number); - StarknetMemorizer.add(key=memorizer_key, data=fields); + // we prefix the fields with its length to make it retrievable from the memorizer + let (length_and_fields: felt*) = alloc(); + assert length_and_fields[0] = fields_len; + memcpy(length_and_fields + 1, fields, fields_len); + + let (block_number) = StarknetHeaderDecoder.get_field( + length_and_fields, StarknetHeaderFields.BLOCK_NUMBER + ); + let memorizer_key = StarknetHashParams.header( + chain_id=chain_info.id, block_number=block_number + ); + StarknetMemorizer.add(key=memorizer_key, data=length_and_fields); return verify_headers_with_mmr_peaks(idx=idx - 1); } let (mmr_path) = alloc(); - tempvar mmr_path_len: felt = nondet %{ len(header.proof.mmr_path) %}; - %{ segments.write_arg(ids.mmr_path, [int(x, 16) for x in header.proof.mmr_path]) %} + tempvar mmr_path_len: felt = nondet %{ len(header_starknet.proof.mmr_path) %}; + %{ segments.write_arg(ids.mmr_path, [int(x, 16) for x in header_starknet.proof.mmr_path]) %} // compute the peak of the header let (computed_peak) = hash_subtree_path( - element=header_hash, + element=poseidon_hash, height=0, position=leaf_idx, inclusion_proof=mmr_path, @@ -98,6 +117,7 @@ func verify_headers_with_mmr_peaks{ let (contains_peak) = dict_read{dict_ptr=peaks_dict}(computed_peak); assert contains_peak = 1; + // add to memorizer // we prefix the fields with its length to make it retrievable from the memorizer let (length_and_fields: felt*) = alloc(); assert length_and_fields[0] = fields_len; @@ -106,7 +126,9 @@ func verify_headers_with_mmr_peaks{ let (block_number) = StarknetHeaderDecoder.get_field( length_and_fields, StarknetHeaderFields.BLOCK_NUMBER ); - let memorizer_key = StarknetHashParams.header(chain_info.id, block_number); + let memorizer_key = StarknetHashParams.header( + chain_id=chain_info.id, block_number=block_number + ); StarknetMemorizer.add(key=memorizer_key, data=length_and_fields); return verify_headers_with_mmr_peaks(idx=idx - 1); diff --git a/src/verifiers/starknet/storage_verifier.cairo b/src/verifiers/starknet/storage_verifier.cairo index 7f208ddf..4234ad9b 100644 --- a/src/verifiers/starknet/storage_verifier.cairo +++ b/src/verifiers/starknet/storage_verifier.cairo @@ -16,7 +16,9 @@ from starkware.cairo.common.builtin_poseidon.poseidon import ( from packages.eth_essentials.lib.utils import bitwise_divmod from src.memorizers.starknet.memorizer import StarknetMemorizer, StarknetHashParams from src.decoders.starknet.header_decoder import StarknetHeaderDecoder, StarknetHeaderFields -from src.types import ChainInfo +from src.types import ChainInfo, TrieNode, TrieNodeBinary, TrieNodeEdge + +const STARKNET_STATE_V0 = 28355430774503553497671514844211693180464; func verify_proofs{ range_check_ptr, @@ -29,7 +31,7 @@ func verify_proofs{ }() { alloc_locals; - tempvar n_storage_items: felt = nondet %{ len(batch.storages) %}; + tempvar n_storage_items: felt = nondet %{ len(batch_starknet.storages) %}; verify_proofs_loop(n_storage_items, 0); return (); @@ -44,14 +46,16 @@ func verify_proofs_loop{ starknet_memorizer: DictAccess*, chain_info: ChainInfo, pow2_array: felt*, -}(n_storage_items: felt, index: felt) { +}(n_storage_items: felt, idx: felt) { alloc_locals; - if (n_storage_items == index) { + if (n_storage_items == idx) { return (); } - local block_number: felt; - %{ ids.block_number = batch["storages"][ids.index]["block_number"] %} + + %{ storage_starknet = batch_starknet.storages[ids.idx] %} + + tempvar block_number: felt = nondet %{ storage_starknet.block_number %}; let memorizer_key = StarknetHashParams.header( chain_id=chain_info.id, block_number=block_number @@ -61,9 +65,9 @@ func verify_proofs_loop{ header_data, StarknetHeaderFields.STATE_ROOT ); - verify_proofs_inner(state_root, block_number, index); + verify_proofs_inner(state_root, block_number, idx); - return verify_proofs_loop(n_storage_items, index + 1); + return verify_proofs_loop(n_storage_items, idx + 1); } func verify_proofs_inner{ @@ -77,16 +81,11 @@ func verify_proofs_inner{ }(state_root: felt, block_number: felt, index: felt) { alloc_locals; - let storage_addresses: felt* = alloc(); - local state_root: felt; - local storage_count: felt; - local contract_address: felt; - %{ - storage_proof = batch["storages"][ids.index] - segments.write_arg(ids.storage_addresses, [int(key, 16) for key in storage_proof["storage_addresses"]]) - ids.storage_count = len(storage_proof["storage_addresses"]) - ids.contract_address = int(storage_proof["contract_address"], 16) - %} + tempvar storage_count: felt = nondet %{ len(storage_starknet.storage_addresses) %}; + tempvar contract_address: felt = nondet %{ storage_starknet.contract_address %}; + + let (storage_addresses: felt*) = alloc(); + %{ segments.write_arg(ids.storage_addresses, [int(x, 16) for x in storage_starknet.storage_addresses])) %} // Compute contract_root and write values to memorizer with contract_address, storage_addresses, block_number { @@ -94,14 +93,9 @@ func verify_proofs_inner{ } // Compute contract_state_hash - local class_hash: felt; - local nonce: felt; - local contract_state_hash_version: felt; - %{ - ids.class_hash = int(storage_proof["proof"]["contract_data"]["class_hash"], 16) - ids.nonce = int(storage_proof["proof"]["contract_data"]["nonce"], 16) - ids.contract_state_hash_version = int(storage_proof["proof"]["contract_data"]["contract_state_hash_version"], 16) - %} + tempvar class_hash: felt = nondet %{ storage_starknet.proof.contract_data.class_hash %}; + tempvar nonce: felt = nondet %{ storage_starknet.proof.contract_data.nonce %}; + tempvar contract_state_hash_version: felt = nondet %{ storage_starknet.proof.contract_data.contract_state_hash_version %}; let (hash_value) = hash2{hash_ptr=pedersen_ptr}(class_hash, contract_root); let (hash_value) = hash2{hash_ptr=pedersen_ptr}(hash_value, nonce); @@ -110,23 +104,21 @@ func verify_proofs_inner{ ); // Compute contract_state_hash - %{ vm_enter_scope(dict(nodes=storage_proof["proof"]["contract_proof"])) %} - let (contract_nodes, contract_nodes_len) = load_nodes(); + tempvar contract_nodes_len: felt = nondet %{ len(storage_starknet.proof.contract_proof) %}; + let (contract_nodes: felt**) = alloc(); + %{ segments.write_arg(ids.contract_nodes, storage_starknet.proof.contract_proof) %} + let (contract_tree_root, expected_contract_state_hash) = traverse( - contract_nodes, contract_nodes_len, contract_address + cast(contract_nodes, TrieNode**), contract_nodes_len, contract_address ); - %{ vm_exit_scope() %} // Assert Validity assert contract_state_hash = expected_contract_state_hash; - local class_commitment: felt; - %{ ids.class_commitment = int(storage_proof["proof"]["class_commitment"], 16) %} - let (hash_chain: felt*) = alloc(); - assert hash_chain[0] = 28355430774503553497671514844211693180464; // STARKNET_STATE_V0 + assert hash_chain[0] = STARKNET_STATE_V0; assert hash_chain[1] = contract_tree_root; - assert hash_chain[2] = class_commitment; + assert hash_chain[2] = nondet %{ storage_starknet.proof.class_commitment %}; let (computed_state_root) = poseidon_hash_many(3, hash_chain); assert state_root = computed_state_root; @@ -147,55 +139,53 @@ func validate_storage_proofs{ contract_address: felt, storage_addresses: felt*, block_number: felt, -}(contract_root: felt, storage_count: felt, index: felt) -> (root: felt) { +}(contract_root: felt, storage_count: felt, idx: felt) -> (root: felt) { alloc_locals; - if (index == storage_count) { + + if (storage_count == idx) { return (root=contract_root); } // Compute contract_root - %{ - vm_enter_scope({ - 'nodes': storage_proof["proof"]["contract_data"]["storage_proofs"][ids.index], - }) - %} - let (contract_state_nodes, contract_state_nodes_len) = load_nodes(); + tempvar contract_state_nodes_len: felt = nondet %{ len(storage_starknet.proof.contract_data.storage_proofs[ids.idx]) %}; + let (contract_state_nodes: felt**) = alloc(); + %{ segments.write_arg(ids.contract_state_nodes, storage_starknet.proof.contract_data.storage_proofs[ids.idx]) %} + let (new_contract_root, value) = traverse( - contract_state_nodes, contract_state_nodes_len, storage_addresses[index] + cast(contract_state_nodes, TrieNode**), contract_state_nodes_len, storage_addresses[idx] ); - %{ vm_exit_scope() %} // Assert that the contract root is consistent between storage slots - if (index != 0) { + if (idx != 0) { with_attr error_message("Contract Root Mismatch!") { assert contract_root = new_contract_root; } } + let memorizer_key = StarknetHashParams.storage( chain_id=chain_info.id, block_number=block_number, contract_address=contract_address, - storage_address=storage_addresses[index], + storage_address=storage_addresses[idx], ); - // ideally we could cast this somehow, but this is a quick fix - let (data) = alloc(); + local data: felt*; assert [data] = value; - - // We need to cast the value to a felt* to match the expected input type. StarknetMemorizer.add(key=memorizer_key, data=data); - return validate_storage_proofs(new_contract_root, storage_count, index + 1); + + return validate_storage_proofs(new_contract_root, storage_count, idx + 1); } // Function used to traverse the passed nodes. The nodes are hashed from the leaf to the root. // This function can be used for inclusion or non-inclusion proofs. In case of non-inclusion, // the function will return the root and a zero value. func traverse{pedersen_ptr: HashBuiltin*, bitwise_ptr: BitwiseBuiltin*, pow2_array: felt*}( - nodes: felt**, n_nodes: felt, expected_path: felt + nodes: TrieNode**, n_nodes: felt, expected_path: felt ) -> (root: felt, value: felt) { alloc_locals; - %{ memory[ap] = nodes_types[ids.n_nodes - 1] %} + let node = nodes[n_nodes - 1]; + %{ memory[ap] = CairoTrieNode(ids.node).is_edge() %} jmp edge_leaf if [ap] != 0, ap++; return traverse_binary_leaf(nodes, n_nodes, expected_path); @@ -207,25 +197,17 @@ func traverse{pedersen_ptr: HashBuiltin*, bitwise_ptr: BitwiseBuiltin*, pow2_arr // This could be an inclusion or non-inclusion proof. func traverse_edge_leaf{ pedersen_ptr: HashBuiltin*, bitwise_ptr: BitwiseBuiltin*, pow2_array: felt* -}(nodes: felt**, n_nodes: felt, expected_path: felt) -> (root: felt, value: felt) { +}(nodes: TrieNode**, n_nodes: felt, expected_path: felt) -> (root: felt, value: felt) { alloc_locals; - let leaf = nodes[n_nodes - 1]; + let leaf: TrieNodeEdge* = cast(nodes[n_nodes - 1], TrieNodeEdge*); let leaf_hash = hash_edge_node(leaf); - let node_path = leaf[1]; + let node_path = leaf.value; + // First we precompute the eval depth of the proof via hint. // In case of non-inclusion, we dont nececcary need to traverse the entire depth of the tree. // The eval depth is how many bits we went down the binary tree from the root for the proof. - local eval_depth: felt; - %{ - eval_depth = 0 - for i, node in enumerate(nodes_types): - if node == 0: - eval_depth += 1 - else: - eval_depth += nodes[i][2] - ids.eval_depth = eval_depth - %} + tempvar eval_depth: felt = nondet %{ [ if CairoTrieNode(ids.nodes[i]).is_edge() CairoTrieNode(ids.nodes[i]).path_len else 1 for i in ids.n_nodes ].sum() %}; // If the eval_depth is not 251, we no we are dealing with a non-inclusion proof. (we can also have non-inclusion proofs with eval depth 251 though) // To verify these proofs correctly, we need to shift the traversed path, so it matches the length of the expected path (251 bits). @@ -241,7 +223,8 @@ func traverse_edge_leaf{ // _____| |_____ // | | // eval_depth - leaf_len eval_depth - local edge_node_shift = 251 - (eval_depth - leaf[2]); + local edge_node_shift = 251 - (eval_depth - leaf.len); + // Since devisions are impractical in Cairo, we traverse the proof from the bottom up. // To track where we are in the tree, we use this variable: path_length_pow2 // We initializer it with the shifted index we computed above (pow of 2) @@ -250,17 +233,17 @@ func traverse_edge_leaf{ with nodes { let (root, traversed_path, traversed_eval_depth) = traverse_inner( - n_nodes - 1, expected_path, leaf_hash, node_path, edge_node_start_position, leaf[2] + n_nodes - 1, expected_path, leaf_hash, node_path, edge_node_start_position, leaf.len ); } // As we precomputed the eval depth, we need to validate the hint here. assert traversed_eval_depth = eval_depth; - let (proof_mode) = derive_proof_mode(leaf[1], edge_node_start_position, expected_path); + let (proof_mode) = derive_proof_mode(leaf.value, edge_node_start_position, expected_path); if (proof_mode == 1) { assert traversed_path = expected_path; - return (root=root, value=leaf[0]); + return (root=root, value=leaf.child); } else { // If we have a valid non-inclusion proof, we return 0 as value. assert_subpath(traversed_path, expected_path, edge_node_start_position); @@ -272,10 +255,10 @@ func traverse_edge_leaf{ // This is always an inclusion proof. func traverse_binary_leaf{ pedersen_ptr: HashBuiltin*, bitwise_ptr: BitwiseBuiltin*, pow2_array: felt* -}(nodes: felt**, n_nodes: felt, expected_path: felt) -> (root: felt, value: felt) { +}(nodes: TrieNode**, n_nodes: felt, expected_path: felt) -> (root: felt, value: felt) { alloc_locals; - let leaf = nodes[n_nodes - 1]; + let leaf: TrieNodeBinary* = cast(nodes[n_nodes - 1], TrieNodeBinary*); let leaf_hash = hash_binary_node(leaf); // In this case, the initial path is the least signficant bit of the expected path. @@ -291,13 +274,24 @@ func traverse_binary_leaf{ // If the leaf node is a binary node, we always have inclusion. assert traversed_path = expected_path; - return (root=root, value=leaf[node_path]); + + if (node_path == 0) { + return (root=root, value=leaf.left); + } + + if (node_path == 1) { + return (root=root, value=leaf.right); + } + + assert 0 = 1; + + return (root=0, value=0); } // Inner traverse function used to traverse the nodes. // This function will return the path is took through the tree, along with the computed root. func traverse_inner{ - pedersen_ptr: HashBuiltin*, bitwise_ptr: BitwiseBuiltin*, pow2_array: felt*, nodes: felt** + pedersen_ptr: HashBuiltin*, bitwise_ptr: BitwiseBuiltin*, pow2_array: felt*, nodes: TrieNode** }( n_nodes: felt, expected_path: felt, @@ -307,6 +301,7 @@ func traverse_inner{ traversed_eval_depth: felt, ) -> (root: felt, traversed_path: felt, traversed_eval_depth: felt) { alloc_locals; + if (n_nodes == 0) { return ( root=hash_value, @@ -315,22 +310,23 @@ func traverse_inner{ ); } - let node = nodes[n_nodes - 1]; - %{ memory[ap] = nodes_types[ids.n_nodes - 1] %} + let node: TrieNode* = nodes[n_nodes - 1]; + %{ memory[ap] = CairoTrieNode(ids.node).is_edge() %} jmp edge_node if [ap] != 0, ap++; // binary_node: + let node_binary = cast(node, TrieNodeBinary*); let (result) = bitwise_and(expected_path, path_length_pow2); local new_path: felt; if (result == 0) { - assert hash_value = node[0]; + assert hash_value = node_binary.left; new_path = traversed_path; } else { - assert hash_value = node[1]; + assert hash_value = node_binary.right; new_path = traversed_path + path_length_pow2; } let next_path_length_pow2 = path_length_pow2 * 2; - let next_hash = hash_binary_node(node); + let next_hash = hash_binary_node(node_binary); return traverse_inner( n_nodes - 1, @@ -342,10 +338,11 @@ func traverse_inner{ ); edge_node: - assert hash_value = node[0]; - let next_path = traversed_path + node[1] * path_length_pow2; - let next_path_length_pow2 = path_length_pow2 * pow2_array[node[2]]; - let next_hash = hash_edge_node(node); + let node_edge = cast(node, TrieNodeEdge*); + assert hash_value = node_edge.child; + let next_path = traversed_path + node_edge.value * path_length_pow2; + let next_path_length_pow2 = path_length_pow2 * pow2_array[node_edge.len]; + let next_hash = hash_edge_node(node_edge); return traverse_inner( n_nodes - 1, @@ -353,20 +350,20 @@ func traverse_inner{ next_hash, next_path, next_path_length_pow2, - traversed_eval_depth + node[2], + traversed_eval_depth + node_edge.len, ); } // Hash function for binary nodes. -func hash_binary_node{pedersen_ptr: HashBuiltin*}(node: felt*) -> felt { - let (node_hash) = hash2{hash_ptr=pedersen_ptr}(node[0], node[1]); +func hash_binary_node{pedersen_ptr: HashBuiltin*}(node: TrieNodeBinary*) -> felt { + let (node_hash) = hash2{hash_ptr=pedersen_ptr}(node.left, node.right); return node_hash; } // Hash function for edge nodes. -func hash_edge_node{pedersen_ptr: HashBuiltin*}(node: felt*) -> felt { - let (node_hash) = hash2{hash_ptr=pedersen_ptr}(node[0], node[1]); - return node_hash + node[2]; +func hash_edge_node{pedersen_ptr: HashBuiltin*}(node: TrieNodeEdge*) -> felt { + let (node_hash) = hash2{hash_ptr=pedersen_ptr}(node.child, node.value); + return node_hash + node.len; } // If the leaf node is an edge node, there are two cases: @@ -417,25 +414,3 @@ func assert_subpath{bitwise_ptr: BitwiseBuiltin*, pow2_array: felt*}( return (); } - -// Loads the proof nodes into memory. -func load_nodes() -> (nodes: felt**, len: felt) { - alloc_locals; - let (nodes: felt**) = alloc(); - local len: felt; - %{ - nodes_types = [] - parsed_nodes = [] - for node in nodes: - if "binary" in node: - nodes_types.append(0) - parsed_nodes.append([int(node["binary"]["left"], 16), int(node["binary"]["right"], 16)]) - else: - nodes_types.append(1) - parsed_nodes.append([int(node["edge"]["child"], 16), int(node["edge"]["path"]["value"], 16), node["edge"]["path"]["len"]]) - ids.len = len(parsed_nodes) - nodes = parsed_nodes - segments.write_arg(ids.nodes, parsed_nodes) - %} - return (nodes=nodes, len=len); -} diff --git a/src/verifiers/starknet/verify.cairo b/src/verifiers/starknet/verify.cairo index 10efc05d..590eae04 100644 --- a/src/verifiers/starknet/verify.cairo +++ b/src/verifiers/starknet/verify.cairo @@ -14,8 +14,10 @@ func run_state_verification{ range_check_ptr, pedersen_ptr: HashBuiltin*, poseidon_ptr: PoseidonBuiltin*, + keccak_ptr: KeccakBuiltin*, bitwise_ptr: BitwiseBuiltin*, pow2_array: felt*, + evm_memorizer: DictAccess*, starknet_memorizer: DictAccess*, mmr_metas: MMRMeta*, chain_info: ChainInfo, @@ -23,22 +25,10 @@ func run_state_verification{ alloc_locals; // Step 1: Verify MMR and headers inclusion - let chain_id = chain_info.id; - with chain_id { - let (mmr_meta_idx) = verify_mmr_batches(mmr_meta_idx); - } - - // Step 2: Storage Slots + tempvar n_proofs: felt = nondet %{ len(batch_starknet.headers_with_mmr_starknet) %}; + let (mmr_meta_idx) = verify_mmr_batches(n_proofs, mmr_meta_idx); + // Step 2: Verify storage slots verify_proofs(); - // // Step 3: Verify the storage items - // verify_storage_items(); - - // // Step 4: Verify the block tx proofs - // verify_block_tx_proofs(); - - // // Step 5: Verify the block receipt proofs - // verify_block_receipt_proofs(); - return (mmr_meta_idx=mmr_meta_idx); } diff --git a/src/verifiers/verify.cairo b/src/verifiers/verify.cairo index 3f379445..a2b47d09 100644 --- a/src/verifiers/verify.cairo +++ b/src/verifiers/verify.cairo @@ -11,7 +11,7 @@ from starkware.cairo.common.cairo_builtins import ( ) from src.types import MMRMeta, ChainInfo -from src.utils.chain_info import fetch_chain_info +from src.utils.chain_info import fetch_chain_info, Layout func run_state_verification{ range_check_ptr, @@ -40,18 +40,35 @@ func run_state_verification_inner{ starknet_memorizer: DictAccess*, mmr_metas: MMRMeta*, }(mmr_meta_idx: felt, idx: felt) -> (mmr_meta_idx: felt, idx: felt) { + alloc_locals; + if (idx == 0) { return (mmr_meta_idx=mmr_meta_idx, idx=idx); } tempvar chain_id: felt = nondet %{ chain_proofs[ids.idx - 1].chain_id %}; - let (chain_info) = fetch_chain_info(chain_id); + let (local chain_info) = fetch_chain_info(chain_id); + + if (chain_info.layout == Layout.EVM) { + with chain_info { + %{ vm_enter_scope({'batch_evm': chain_proofs[ids.idx - 1].value, '__dict_manager': __dict_manager}) %} + let (mmr_meta_idx) = evm_run_state_verification(mmr_meta_idx); + %{ vm_exit_scope() %} + + return run_state_verification_inner(mmr_meta_idx=mmr_meta_idx, idx=idx - 1); + } + } + + if (chain_info.layout == Layout.STARKNET) { + with chain_info { + %{ vm_enter_scope({'batch_starknet': chain_proofs[ids.idx - 1].value, '__dict_manager': __dict_manager}) %} + let (mmr_meta_idx) = starknet_run_state_verification(mmr_meta_idx); + %{ vm_exit_scope() %} - %{ vm_enter_scope({'batch': chain_proofs[ids.idx - 1].value, '__dict_manager': __dict_manager}) %} - with chain_info { - let (mmr_meta_idx) = evm_run_state_verification(mmr_meta_idx); + return run_state_verification_inner(mmr_meta_idx=mmr_meta_idx, idx=idx - 1); + } } - %{ vm_exit_scope() %} - return run_state_verification_inner(mmr_meta_idx=mmr_meta_idx, idx=idx - 1); + assert 0 = 1; + return (mmr_meta_idx=0, idx=0); } diff --git a/tests/modules/src/tests/mod.rs b/tests/modules/src/tests/mod.rs index e9cd1bd8..d2a0f248 100644 --- a/tests/modules/src/tests/mod.rs +++ b/tests/modules/src/tests/mod.rs @@ -4,13 +4,13 @@ use cairo_vm::{ types::{layout_name::LayoutName, program::Program}, vm::runners::cairo_runner::{CairoRunner, RunnerMode}, }; -use dry_hint_processor::syscall_handler::evm::{self, SyscallHandler, SyscallHandlerWrapper}; +use dry_hint_processor::syscall_handler::{evm, SyscallHandler, SyscallHandlerWrapper}; use fetcher::proof_keys::ProofKeys; use futures::{FutureExt, StreamExt}; use hints::vars; use std::{collections::HashSet, env, path::PathBuf}; use types::{ - proofs::{account::Account, storage::Storage, HeaderMmrMeta, Proofs}, + proofs::{self, header::HeaderMmrMeta}, ChainProofs, HDPDryRunInput, HDPInput, }; @@ -77,7 +77,7 @@ async fn run(compiled_class: CasmContractClass) { .clone(); let mut proof_keys = ProofKeys::default(); - for key in syscall_handler.call_contract_handler.key_set { + for key in syscall_handler.call_contract_handler.evm_call_contract_handler.key_set { match key { evm::DryRunKey::Account(value) => { proof_keys.account_keys.insert(value); @@ -91,7 +91,7 @@ async fn run(compiled_class: CasmContractClass) { } } - let mut headers_with_mmr: HashSet = HashSet::default(); + let mut headers_with_mmr: HashSet> = HashSet::default(); let mut headers_with_mmr_fut = futures::stream::iter(proof_keys.header_keys.iter().map(ProofKeys::fetch_header_proof).map(|f| f.boxed_local())) .buffer_unordered(BUFFER_UNORDERED); @@ -100,7 +100,7 @@ async fn run(compiled_class: CasmContractClass) { headers_with_mmr.insert(item); } - let mut accounts: HashSet = HashSet::default(); + let mut accounts: HashSet = HashSet::default(); let mut accounts_fut = futures::stream::iter( proof_keys @@ -116,7 +116,7 @@ async fn run(compiled_class: CasmContractClass) { accounts.insert(account); } - let mut storages: HashSet = HashSet::default(); + let mut storages: HashSet = HashSet::default(); let mut storages_fut = futures::stream::iter( proof_keys @@ -133,7 +133,7 @@ async fn run(compiled_class: CasmContractClass) { storages.insert(storage); } - let proofs = Proofs { + let proofs = proofs::evm::Proofs { headers_with_mmr: headers_with_mmr.into_iter().collect(), accounts: accounts.into_iter().collect(), storages: storages.into_iter().collect(),