diff --git a/.github/ISSUE_TEMPLATE/daily_failure.md b/.github/ISSUE_TEMPLATE/daily_failure.md index c130abdec..e607cfc4a 100644 --- a/.github/ISSUE_TEMPLATE/daily_failure.md +++ b/.github/ISSUE_TEMPLATE/daily_failure.md @@ -1,18 +1,16 @@ --- -title: "Daily Workflow Failure: Block Range {{ env.BLOCK_START }}-{{ env.BLOCK_END }}" +title: "Daily Workflow Failure" labels: bug --- -Comparing VM execution against Native in the given block range produced diffs: +Comparing VM execution against Native produced diffs: - Commit: {{ env.COMMIT_SHA }} -- Block Start: {{ env.BLOCK_START }} -- Block End: {{ env.BLOCK_END }} - Workflow URL: {{ env.WORKFLOW_URL }} ## Compare Output -The transaction were not compared in order. You should rerun the whole block to find the error root +The transaction were not compared in order. You should rerun the whole failing block to find the error root ``` {{ env.OUTPUT }} diff --git a/.github/workflows/bench-hyperfine.yml b/.github/workflows/bench-hyperfine.yml index 727e58226..f6b79ebb5 100644 --- a/.github/workflows/bench-hyperfine.yml +++ b/.github/workflows/bench-hyperfine.yml @@ -43,7 +43,7 @@ jobs: sudo rm -rf /usr/share/dotnet/ sudo rm -rf /usr/local/lib/android df -h - - uses: dtolnay/rust-toolchain@1.83.0 + - uses: dtolnay/rust-toolchain@1.84.0 with: components: clippy - uses: Swatinem/rust-cache@v2 @@ -131,7 +131,7 @@ jobs: df -h - name: Install Rust if: ${{ steps.cache-binary.outputs.cache-hit != 'true' || steps.cache-library.outputs.cache-hit != 'true' }} - uses: dtolnay/rust-toolchain@1.83.0 + uses: dtolnay/rust-toolchain@1.84.0 - name: add llvm deb repository if: ${{ steps.cache-binary.outputs.cache-hit != 'true' || steps.cache-library.outputs.cache-hit != 'true' }} uses: myci-actions/add-deb-repo@11 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0bc962e69..eb2d0c09d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: TABLEGEN_190_PREFIX: /usr/lib/llvm-19/ steps: - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@1.83.0 + - uses: dtolnay/rust-toolchain@1.84.0 with: components: clippy, rustfmt - uses: Swatinem/rust-cache@v2 @@ -41,7 +41,7 @@ jobs: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@1.83.0 + - uses: dtolnay/rust-toolchain@1.84.0 with: components: rustfmt - run: cargo fmt --all -- --check @@ -134,7 +134,7 @@ jobs: sudo rm -rf /usr/local/lib/android df -h - name: Setup rust env - uses: dtolnay/rust-toolchain@1.83.0 + uses: dtolnay/rust-toolchain@1.84.0 - name: Retreive cached dependecies uses: Swatinem/rust-cache@v2 - name: add llvm deb repository @@ -166,7 +166,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Rustup toolchain install - uses: dtolnay/rust-toolchain@1.83.0 + uses: dtolnay/rust-toolchain@1.84.0 with: components: clippy - name: Rust `$PATH` workaround. @@ -225,7 +225,7 @@ jobs: sudo rm -rf /usr/local/lib/android df -h - name: Setup rust env - uses: dtolnay/rust-toolchain@1.83.0 + uses: dtolnay/rust-toolchain@1.84.0 - name: Retreive cached dependecies uses: Swatinem/rust-cache@v2 - name: add llvm deb repository @@ -278,7 +278,7 @@ jobs: needs: [coverage] steps: - name: Setup rust env - uses: dtolnay/rust-toolchain@1.83.0 + uses: dtolnay/rust-toolchain@1.84.0 - name: Retreive cached dependencies uses: Swatinem/rust-cache@v2 - name: Install testing tools diff --git a/.github/workflows/daily.yml b/.github/workflows/daily.yml index 5129b8ffd..8adac740f 100644 --- a/.github/workflows/daily.yml +++ b/.github/workflows/daily.yml @@ -18,7 +18,7 @@ jobs: RPC_ENDPOINT_TESTNET: ${{ secrets.RPC_ENDPOINT_TESTNET }} RPC_ENDPOINT_MAINNET: ${{ secrets.RPC_ENDPOINT_MAINNET }} strategy: - max-parallel: 15 + max-parallel: 30 matrix: block: - 740000 @@ -41,16 +41,6 @@ jobs: - 800350 - 800400 - 800450 - - 800500 - - 801550 - - 801600 - - 800650 - - 800700 - - 800750 - - 800800 - - 800850 - - 800900 - - 800950 - 900000 - 900100 - 900200 @@ -61,6 +51,16 @@ jobs: - 900700 - 900800 - 900900 + - 1000400 + - 1000500 + - 1002000 + - 1003000 + - 1004000 + - 1005000 + - 1006000 + - 1007000 + - 1008000 + - 1009000 runner: - native - vm @@ -71,24 +71,42 @@ jobs: working-directory: ./starknet-replay steps: - # We checkout replay first, as it's the main repository for this workflow + # We checkout replay as it's the main repository for this workflow - name: Checkout Replay uses: actions/checkout@v4 with: repository: lambdaclass/starknet-replay path: starknet-replay - # We need native for building the runtime + # We need native if we want to run with cairo native main - name: Checkout Native uses: actions/checkout@v4 with: path: cairo_native + # We need sequencer if we want to run with cairo native main + - name: Checkout Native + uses: actions/checkout@v4 + with: + repository: lambdaclass/sequencer + path: sequencer + ref: replay + + - name: Cache RPC Calls + uses: actions/cache@v4 + with: + path: starknet-replay/rpc_cache + key: cache-${{matrix.block}} # Install dependencies - uses: ./cairo_native/.github/actions/install-linux-deps - name: Setup rust env - uses: dtolnay/rust-toolchain@1.83.0 + uses: dtolnay/rust-toolchain@1.84.0 - name: Retreive cached dependecies uses: Swatinem/rust-cache@v2 + with: + workspaces: | + starknet-replay + cairo_native + - name: Build Cairo Native Runtime Library shell: bash run: | @@ -96,10 +114,30 @@ jobs: make runtime echo "CAIRO_NATIVE_RUNTIME_LIBRARY=$(pwd)/libcairo_native_runtime.a" > $GITHUB_ENV - - name: Patch dependencies + - name: Patch replay dependencies run: | - # Patches native dependency to local path, to use current cairo native version - echo -e "\n[patch.crates-io]\ncairo-native = { path = \"../cairo_native\" }" >> Cargo.toml + # Updates sequencer dependency to local path + name='[[:alnum:]_-]+' + sequencer_url='"https:\/\/github.com\/lambdaclass\/sequencer\.git"' + rev='"[[:alnum:]]+"' + new_path='"..\/sequencer\/crates\/\1"' + sed -i'' -r "s/^($name) = \{ git = $sequencer_url, rev = $rev/\1 = { path = $new_path/" Cargo.toml + + # Updates native dependency to local path + new_path='"..\/cairo_native"' + sed -i'' -r "s/^cairo-native = .*/cairo-native.path = $new_path/" Cargo.toml + + git diff + + - name: Patch sequencer dependencies + run: | + cd ../sequencer + + # Updates native dependency to local path + new_path='"..\/cairo_native"' + sed -i'' -r "s/^cairo-native = .*/cairo-native.path = $new_path/" Cargo.toml + + git diff - name: Run with Native if: ${{ matrix.runner == 'native' }} @@ -128,50 +166,6 @@ jobs: # We always run the compare job, to ensure that a single run job failing # would not cancel the whole comparison. if: ${{ always() }} - strategy: - matrix: - block: - - 740000 - - 741000 - - 742000 - - 743000 - - 744000 - - 745000 - - 746000 - - 747000 - - 748000 - - 749000 - - 800000 - - 800050 - - 800100 - - 800150 - - 800200 - - 800250 - - 800300 - - 800350 - - 800400 - - 800450 - - 800500 - - 800550 - - 800600 - - 800650 - - 800700 - - 800750 - - 800800 - - 800850 - - 800900 - - 800950 - - 900000 - - 900100 - - 900200 - - 900300 - - 900400 - - 900500 - - 900600 - - 900700 - - 900800 - - 900900 - fail-fast: false defaults: run: shell: bash @@ -181,14 +175,16 @@ jobs: - name: Fetch Native dumps uses: actions/download-artifact@v4 with: - name: dump-${{matrix.block}}-native + pattern: dump-*-native path: state_dumps/native + merge-multiple: true continue-on-error: true - name: Fetch VM dumps uses: actions/download-artifact@v4 with: - name: dump-${{matrix.block}}-vm + pattern: dump-*-vm path: state_dumps/vm + merge-multiple: true continue-on-error: true - name: Compare states @@ -198,12 +194,6 @@ jobs: - name: Prepare env vars if: ${{ always() }} run: | - # Save blocks to env var - BLOCK_START=${{ matrix.block }} - BLOCK_END=$(($BLOCK_START + $RANGE_SIZE - 1)) - echo "BLOCK_END=$BLOCK_END" | tee -a $GITHUB_ENV - echo "BLOCK_START=$BLOCK_START" | tee -a $GITHUB_ENV - # Save workflow url REPO_URL="${{ github.server_url }}/${{ github.repository }}" echo "WORKFLOW_URL=$REPO_URL/actions/runs/${{ github.run_id }}" | tee -a $GITHUB_ENV diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 3b374c054..3f4c59463 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -26,7 +26,7 @@ jobs: sudo rm -rf /usr/share/dotnet/ sudo rm -rf /usr/local/lib/android - name: Setup rust env - uses: dtolnay/rust-toolchain@1.83.0 + uses: dtolnay/rust-toolchain@1.84.0 - name: Retreive cached dependecies uses: Swatinem/rust-cache@v2 - name: add llvm deb repository diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2d44b06d4..c099b7ff8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -25,7 +25,7 @@ jobs: sudo rm -rf /usr/share/dotnet/ sudo rm -rf /usr/local/lib/android - name: Setup rust env - uses: dtolnay/rust-toolchain@1.83.0 + uses: dtolnay/rust-toolchain@1.84.0 - name: Retreive cached dependecies uses: Swatinem/rust-cache@v2 - name: add llvm deb repository @@ -60,7 +60,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Rustup toolchain install - uses: dtolnay/rust-toolchain@1.83.0 + uses: dtolnay/rust-toolchain@1.84.0 with: components: clippy - name: Rust `$PATH` workaround. diff --git a/.github/workflows/rustdoc.yml b/.github/workflows/rustdoc.yml index 359953d64..b61346384 100644 --- a/.github/workflows/rustdoc.yml +++ b/.github/workflows/rustdoc.yml @@ -18,7 +18,7 @@ jobs: TABLEGEN_190_PREFIX: /usr/lib/llvm-19/ steps: - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@1.83.0 + - uses: dtolnay/rust-toolchain@1.84.0 - uses: Swatinem/rust-cache@v2 - name: add llvm deb repository uses: myci-actions/add-deb-repo@11 diff --git a/.github/workflows/starknet-blocks.yml b/.github/workflows/starknet-blocks.yml index 4ecc2e4d6..d43ebc449 100644 --- a/.github/workflows/starknet-blocks.yml +++ b/.github/workflows/starknet-blocks.yml @@ -1,4 +1,4 @@ -name: Execute blocks +name: Starknet Blocks on: pull_request: @@ -20,130 +20,118 @@ jobs: matrix: runner: [native, vm] block: [742001, 769597, 779328, 801008, 803072] + fail-fast: false + defaults: + run: + shell: bash + working-directory: ./starknet-replay steps: - - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@1.83.0 + # We checkout replay as it's the main repository for this workflow + - name: Checkout Replay + uses: actions/checkout@v4 + with: + repository: lambdaclass/starknet-replay + path: starknet-replay + ref: 6738a2ba8786118d38eb94b209949bcb8285cce0 + # We need native to build the runtime + - name: Checkout Native + uses: actions/checkout@v4 with: - components: clippy - - uses: Swatinem/rust-cache@v2 + path: cairo_native + - name: Checkout Sequencer + uses: actions/checkout@v4 with: - key: "ref-955512a96ab317c61d0b12ae230f33176b6005e4" + repository: lambdaclass/sequencer + path: sequencer + ref: ee977cc338f63f7bc34c01c21363b3a318bcac65 - - name: Check and free hdd space left - if: ${{ matrix.runner == 'native' }} - run: | - echo "Listing 20 largest packages" - dpkg-query -Wf '${Installed-Size}\t${Package}\n' | sort -n | tail -n 20 - df -h - sudo apt-get update - sudo apt-get remove -y '^llvm-.*' - sudo apt-get remove -y 'php.*' - sudo apt-get remove -y '^dotnet-.*' - sudo apt-get remove -y '^temurin-.*' - sudo apt-get remove -y azure-cli microsoft-edge-stable google-chrome-stable firefox mono-devel - sudo apt-get autoremove -y - sudo apt-get clean - df -h - echo "Removing large directories" - # deleting 15GB - sudo rm -rf /usr/share/dotnet/ - sudo rm -rf /usr/local/lib/android - df -h - - - name: add llvm deb repository - uses: myci-actions/add-deb-repo@11 + - name: Cache RPC Calls + uses: actions/cache@v4 + with: + path: starknet-replay/rpc_cache + key: cache-${{matrix.block}}-${{matrix.runner}} + + # Install dependencies + - uses: ./cairo_native/.github/actions/install-linux-deps + - name: Setup rust env + uses: dtolnay/rust-toolchain@1.84.0 + - name: Retreive cached dependecies + uses: Swatinem/rust-cache@v2 with: - repo: deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-19 main - repo-name: llvm-repo - keys-asc: https://apt.llvm.org/llvm-snapshot.gpg.key - - name: Install LLVM - run: sudo apt-get install llvm-19 llvm-19-dev llvm-19-runtime clang-19 clang-tools-19 lld-19 libpolly-19-dev libmlir-19-dev mlir-19-tools + workspaces: | + starknet-replay + cairo_native - - name: Install Cairo Native deps - if: ${{ matrix.runner == 'native' }} - run: make deps - - name: Build Cairo Native project - if: ${{ matrix.runner == 'native' }} - run: cargo b --release - - name: Build runtime + - name: Build Cairo Native Runtime Library + shell: bash run: | + cd ../cairo_native make runtime - cargo update echo "CAIRO_NATIVE_RUNTIME_LIBRARY=$(pwd)/libcairo_native_runtime.a" > $GITHUB_ENV - - name: Checkout Starknet Replay - uses: actions/checkout@v4 - with: - repository: lambdaclass/starknet-replay - ref: 955512a96ab317c61d0b12ae230f33176b6005e4 - path: replay + - name: Patch replay dependencies + run: | + # Updates sequencer dependency to local path + name='[[:alnum:]_-]+' + sequencer_url='"https:\/\/github.com\/lambdaclass\/sequencer\.git"' + rev='"[[:alnum:]]+"' + new_path='"..\/sequencer\/crates\/\1"' + sed -i'' -r "s/^($name) = \{ git = $sequencer_url, rev = $rev/\1 = { path = $new_path/" Cargo.toml - - name: Install Starknet Replay deps - run: make deps + # Updates native dependency to local path + new_path='"..\/cairo_native"' + sed -i'' -r "s/^cairo-native = .*/cairo-native.path = $new_path/" Cargo.toml - - name: Patch Cairo Native's version - if: ${{ matrix.runner == 'native' }} + git diff + + - name: Patch sequencer dependencies run: | - cd replay - echo -e '[patch.crates-io]\ncairo-native = { path = ".." }' >> Cargo.toml + cd ../sequencer + + # Updates native dependency to local path + new_path='"..\/cairo_native"' + sed -i'' -r "s/^cairo-native = .*/cairo-native.path = $new_path/" Cargo.toml - - name: Run Blocks Native + git diff + + - name: Run with Native if: ${{ matrix.runner == 'native' }} run: | - cd replay - cargo build --release --bin replay - cargo run --release --features state_dump block mainnet ${{ matrix.block }} + cargo run --features state_dump block mainnet ${{ matrix.block }} - - name: Run Blocks VM + - name: Run with VM if: ${{ matrix.runner == 'vm' }} run: | - cd replay - cargo build --release --bin replay - cargo run --release --features "state_dump,only_cairo_vm" block mainnet ${{ matrix.block }} + cargo run --features "state_dump,only_cairo_vm" block mainnet ${{ matrix.block }} - name: Upload dumps uses: actions/upload-artifact@v4 with: name: dump-${{matrix.block}}-${{matrix.runner}} - path: replay/state_dumps/${{matrix.runner}} + path: starknet-replay/state_dumps/${{matrix.runner}} compare-dumps: + name: Compare Dumps needs: [run-blocks] runs-on: ubuntu-latest - strategy: - matrix: - block: [742001, 769597, 779328, 801008, 803072] - fail-fast: false steps: - uses: actions/checkout@v4 - - name: Check and free hdd space left - if: ${{ matrix.runner == 'native' }} - run: | - sudo apt-get update - sudo apt-get remove -y '^llvm-.*' - sudo apt-get remove -y 'php.*' - sudo apt-get remove -y '^dotnet-.*' - sudo apt-get remove -y '^temurin-.*' - sudo apt-get remove -y azure-cli microsoft-edge-stable google-chrome-stable firefox mono-devel - sudo apt-get autoremove -y - sudo apt-get clean - echo "Removing large directories" - # deleting 15GB - sudo rm -rf /usr/share/dotnet/ - sudo rm -rf /usr/local/lib/android - - name: Fetch Native dumps uses: actions/download-artifact@v4 with: - name: dump-${{matrix.block}}-native + pattern: dump-*-native path: state_dumps/native - + merge-multiple: true + continue-on-error: true - name: Fetch VM dumps uses: actions/download-artifact@v4 with: - name: dump-${{matrix.block}}-vm + pattern: dump-*-vm path: state_dumps/vm + merge-multiple: true + continue-on-error: true - - name: Check Diffs - run: ./scripts/diff-check.sh + - name: Compare states + run: | + ./scripts/cmp_state_dumps.sh diff --git a/Cargo.lock b/Cargo.lock index 9a777b84c..6dcc61583 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -103,19 +103,19 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.93" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" [[package]] name = "aquamarine" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21cc1548309245035eb18aa7f0967da6bc65587005170c56e6ef2788a4cf3f4e" +checksum = "0f50776554130342de4836ba542aa85a4ddb361690d7e8df13774d7284c3d5c2" dependencies = [ "include_dir", "itertools 0.10.5", - "proc-macro-error", + "proc-macro-error2", "proc-macro2", "quote", "syn 2.0.89", @@ -151,7 +151,7 @@ dependencies = [ "ark-std 0.5.0", "educe 0.6.0", "fnv", - "hashbrown 0.15.1", + "hashbrown 0.15.2", "itertools 0.13.0", "num-bigint", "num-integer", @@ -270,7 +270,7 @@ dependencies = [ "ark-std 0.5.0", "educe 0.6.0", "fnv", - "hashbrown 0.15.1", + "hashbrown 0.15.2", ] [[package]] @@ -432,29 +432,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bindgen" -version = "0.69.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" -dependencies = [ - "bitflags", - "cexpr", - "clang-sys", - "itertools 0.12.1", - "lazy_static", - "lazycell", - "log", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash 1.1.0", - "shlex", - "syn 2.0.89", - "which", -] - [[package]] name = "bindgen" version = "0.71.1" @@ -517,31 +494,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "bon" -version = "3.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61030e4aaccae9727cc388843dcc7ad1fb9e1ccdef5571e3e8393976b49b74ce" -dependencies = [ - "bon-macros", - "rustversion", -] - -[[package]] -name = "bon-macros" -version = "3.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67d5d25cc9bd33120702000acc60836db15f06eabc4466230bf79dc80bd0a6ee" -dependencies = [ - "darling", - "ident_case", - "prettyplease", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.89", -] - [[package]] name = "bstr" version = "1.11.0" @@ -593,9 +545,9 @@ dependencies = [ [[package]] name = "cairo-lang-casm" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3929a38c1d586e35e19dbdf7798b146fba3627b308417a6d373fea8939535b6b" +checksum = "31a9a437bd4015a0f888d0de9876fd4786eb24b4e17b25c86c53980865980f9d" dependencies = [ "cairo-lang-utils", "indoc", @@ -607,9 +559,9 @@ dependencies = [ [[package]] name = "cairo-lang-compiler" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bed098f0c3666b3ad3a93aef6293f91fc1119bef660ce994105f6d1bc2802cf" +checksum = "4608693f366e8e86061c824adaca33b56bf0bd7e1cd5edc8592be7a380950322" dependencies = [ "anyhow", "cairo-lang-defs", @@ -633,18 +585,18 @@ dependencies = [ [[package]] name = "cairo-lang-debug" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7763505dcfe15f36899074c27185bf7e3494875f63fd06350c6e3ed8d1f91d5" +checksum = "4217fd373449a74efde259f8a4df501a7664f6f9c73b547c3aff632ad14feabf" dependencies = [ "cairo-lang-utils", ] [[package]] name = "cairo-lang-defs" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4d29dc5a3cafe94ea4397d41b00cd54a9dffbe9bc3a3092a9ea617ea737bc6e" +checksum = "dadf2d1002c9851ea17d37b83a26bbe6f0f53d5f94ba2e477a7a6e9d498f805b" dependencies = [ "cairo-lang-debug", "cairo-lang-diagnostics", @@ -659,9 +611,9 @@ dependencies = [ [[package]] name = "cairo-lang-diagnostics" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "761d20ca9c3a3eb7025b2488aa6e0e5dc23c5d551dd95e83a989b5e87687f523" +checksum = "4c4ac1831e7c14e5308a66254bcc57a8d4790f18567ef8d4d6768b39ffb955a0" dependencies = [ "cairo-lang-debug", "cairo-lang-filesystem", @@ -671,9 +623,9 @@ dependencies = [ [[package]] name = "cairo-lang-eq-solver" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d778ec864e92c82293370a512195715b12775b05981e14065d85eb5dd3dd96b6" +checksum = "33c5f879bca42caef7e06f1de022d6961d36c5567db600faed8a947e2b705eaa" dependencies = [ "cairo-lang-utils", "good_lp", @@ -681,9 +633,9 @@ dependencies = [ [[package]] name = "cairo-lang-filesystem" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9dc486c554e2df3be8e84c47e30fe55b59d2349b680fbe992bfba801ef93ff5" +checksum = "c632b6d3ee5f1684f757f86e04ba9cf1daa8e4e74c6a5d6c0b7773cc4465a6c6" dependencies = [ "cairo-lang-debug", "cairo-lang-utils", @@ -697,9 +649,9 @@ dependencies = [ [[package]] name = "cairo-lang-formatter" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "675d281a3c9aa365055ce6e201d5dd91534dfccfd2929a41b7397f665c80293c" +checksum = "8295a3ddc62d8d92d942292f103de0434d622f47e936a3aea25eccc3eed88c58" dependencies = [ "anyhow", "cairo-lang-diagnostics", @@ -717,9 +669,9 @@ dependencies = [ [[package]] name = "cairo-lang-lowering" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d880470c94f94fac08c2150bc0ce4af930b6760956a56966e47612de376d57ec" +checksum = "b2a93c2644c64cfdbbe64b1bd6e13d9c6ed511950cfae2e738d228bc89dc5605" dependencies = [ "cairo-lang-debug", "cairo-lang-defs", @@ -742,9 +694,9 @@ dependencies = [ [[package]] name = "cairo-lang-parser" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e2b488f659432c8b866bf540e54ab3696a24ac0f366faac33b860c5313e78c" +checksum = "d884d9418895fef5b8ffd7458211523ab5abf4357845938b354adfbae1089fe2" dependencies = [ "cairo-lang-diagnostics", "cairo-lang-filesystem", @@ -762,9 +714,9 @@ dependencies = [ [[package]] name = "cairo-lang-plugins" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13cf34fd39a1efb997455fa38dbdb6bef489a125a2d17d77ebfea1ee580559f3" +checksum = "b224afdc76d9890edf9009fa8ffff9a91ac15614a41049d48c77c192e8c966e3" dependencies = [ "cairo-lang-defs", "cairo-lang-diagnostics", @@ -787,9 +739,9 @@ checksum = "123ac0ecadf31bacae77436d72b88fa9caef2b8e92c89ce63a125ae911a12fae" [[package]] name = "cairo-lang-proc-macros" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3c4a161868276ce022c44ac500afbfa0d7d8371106feb40dfca34ea7be97503" +checksum = "0ae35a282e5f2d15f47ba6fffae5a32e8aa2f254366865339cf326e2e015b8f8" dependencies = [ "cairo-lang-debug", "quote", @@ -798,9 +750,9 @@ dependencies = [ [[package]] name = "cairo-lang-project" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fde3cc9777fff4daacbfd839a6fcefa29abd660068de47f72ac6d5883fa93ccd" +checksum = "4da40ba380208db0b861d8b1e6e558adaa98dd0b382177b25bdb1abf8fd8d766" dependencies = [ "cairo-lang-filesystem", "cairo-lang-utils", @@ -811,9 +763,9 @@ dependencies = [ [[package]] name = "cairo-lang-runnable-utils" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "872d846834c8fdc886a7dc591c1f6ddd969d25d2c88dd65452931c63dfca7acc" +checksum = "951b72522c8a76e177119699bdcd3c4288bdc0bc784ac22dd7c0f80b2a7444d0" dependencies = [ "cairo-lang-casm", "cairo-lang-sierra", @@ -829,9 +781,9 @@ dependencies = [ [[package]] name = "cairo-lang-runner" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9121164a61b0a8fcadefc8b21240e372bf04e6648ea31d09f9e85701e60877a" +checksum = "35b1d5b0e9103bea4e39ac1099ad47893a25f334c3ca2596d07b1a8920be22cb" dependencies = [ "ark-ff 0.4.2", "ark-secp256k1 0.4.0", @@ -859,9 +811,9 @@ dependencies = [ [[package]] name = "cairo-lang-semantic" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8af1f92ba601fd61a994c44d0c80d711fbb3d64b2b5a1e72905fc6f581b1fadd" +checksum = "babdf14729236dfb455519d35e7e399ba73f0eaa4f1e929474d4c37dc9ef7a29" dependencies = [ "cairo-lang-debug", "cairo-lang-defs", @@ -886,14 +838,14 @@ dependencies = [ [[package]] name = "cairo-lang-sierra" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "075c6457642ada82b32cf657d871a8545ae7a9d61c78dd5588a794c8c905abdc" +checksum = "74c0e4951ecd88023856e0faa9fd444647d9f1ec69ca09dfa8e3aebf9d2afdef" dependencies = [ "anyhow", "cairo-lang-utils", "const-fnv1a-hash", - "convert_case", + "convert_case 0.6.0", "derivative", "itertools 0.12.1", "lalrpop", @@ -913,9 +865,9 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-ap-change" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b69172fe8354b1dd564bba318ccb5233aa78f70d57145b8c92a0b1cf009fa0fc" +checksum = "9ea9c51356e603fa38fcbd4524d19e391ac25e89e64889c3a4ef849de3d1e911" dependencies = [ "cairo-lang-eq-solver", "cairo-lang-sierra", @@ -929,9 +881,9 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-gas" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42b571b73d9b02103f780aeee05dbf9a71d68d8a16341a04aa1dd581d0db3ad6" +checksum = "1af17244a222fd2398caaf09e909f0b584abe14c77e1b5dc8f479ef35d1e8d50" dependencies = [ "cairo-lang-eq-solver", "cairo-lang-sierra", @@ -945,9 +897,9 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-generator" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d3857cd98a0cb35b32cc962e70c04e6ddfcd8bf61106ac37b6cf453ec76b878" +checksum = "2368d57175b18976222f844e4dda52d0025d70ce8b2dda35e0cc96efaa9bb4a5" dependencies = [ "cairo-lang-debug", "cairo-lang-defs", @@ -969,9 +921,9 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-to-casm" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add264b156dfb01f18292282a6037070c078acca3bccde05787da1e1c997b78c" +checksum = "866e6cbba9e81bae1c2f6b8f8e718f702fee69980c3f22bdea1e4657f09a540c" dependencies = [ "assert_matches", "cairo-lang-casm", @@ -990,9 +942,9 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-type-size" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bda5388ef862bc26388e999ac7ad62dd8ab3064720c3483b81fd761b051e627" +checksum = "f8e797aa2f4023e984d13c5adf7068688da665328da6b055842f50fb673fb48b" dependencies = [ "cairo-lang-sierra", "cairo-lang-utils", @@ -1000,9 +952,9 @@ dependencies = [ [[package]] name = "cairo-lang-starknet" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32d5ed4aa48fe739f643a8c503c14aec0858c31dc73ba4e6a335b77ca7438807" +checksum = "85c16967be9b0befaa0e21f65c9c803f8354d0db09de7adf28cdf0dc54b2c90d" dependencies = [ "anyhow", "cairo-lang-compiler", @@ -1030,15 +982,15 @@ dependencies = [ [[package]] name = "cairo-lang-starknet-classes" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe691200b431e51e3d6cfa84f256a3dd2e8405f44d182843fbe124f803d085ff" +checksum = "b0f7b0c28430c9ad477c38dba089ac5a148443bbeaa77cc3f14980de255a220e" dependencies = [ "cairo-lang-casm", "cairo-lang-sierra", "cairo-lang-sierra-to-casm", "cairo-lang-utils", - "convert_case", + "convert_case 0.6.0", "itertools 0.12.1", "num-bigint", "num-integer", @@ -1053,9 +1005,9 @@ dependencies = [ [[package]] name = "cairo-lang-syntax" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a38f1431f22a9487b9b0dd7aef098c9605fe6b8677e0f620547aa69195f7fb5" +checksum = "f5adf933d378225e031200bd41c82e09cb0fde1042f5fe3f3c82d1ccd559a6f2" dependencies = [ "cairo-lang-debug", "cairo-lang-filesystem", @@ -1070,9 +1022,9 @@ dependencies = [ [[package]] name = "cairo-lang-syntax-codegen" -version = "2.9.2" +version = "2.10.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd7990586c9bb37eaa875ffeb218bdecf96f87881d03263ebf84fcd46514ca9f" +checksum = "cd79262096fbbd618c52d01964f5ed36e693f9dc1113a0d217e1b3825bd85822" dependencies = [ "genco", "xshell", @@ -1080,9 +1032,9 @@ dependencies = [ [[package]] name = "cairo-lang-test-plugin" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5432fb1e290bed1c961a6bd778b3b553480b364524e7dbc343495b79b452131b" +checksum = "2a9c6f1976c28de3e502589f53b97bdc5f8566724d20ff68de83d8f382f5fc99" dependencies = [ "anyhow", "cairo-lang-compiler", @@ -1107,9 +1059,9 @@ dependencies = [ [[package]] name = "cairo-lang-test-utils" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b76c55a742da177540d2a0eb39fa50d011998d0ccfdeae8b48ea0e2d7f077f" +checksum = "aa7c6930beb6f221c1bc274460fca091e93c377570994b612682da30795ed74e" dependencies = [ "cairo-lang-formatter", "cairo-lang-utils", @@ -1120,9 +1072,9 @@ dependencies = [ [[package]] name = "cairo-lang-utils" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff5d7609abc99c15de7d7f90b8441b27e2bd52e930a3014c95a9b620e5d3211a" +checksum = "91b6546d9f285c7d4a2700c084f745c35e1884a1dc2e4fa54a71034cea5606aa" dependencies = [ "hashbrown 0.14.5", "indexmap 2.6.0", @@ -1135,7 +1087,7 @@ dependencies = [ [[package]] name = "cairo-native" -version = "0.2.5" +version = "0.2.8" dependencies = [ "anyhow", "aquamarine", @@ -1158,7 +1110,7 @@ dependencies = [ "cairo-lang-test-plugin", "cairo-lang-utils", "cairo-native-runtime", - "cairo-vm 2.0.0-rc1", + "cairo-vm 2.0.0-rc3", "cc", "clap", "colored", @@ -1189,7 +1141,7 @@ dependencies = [ "stats_alloc", "tempfile", "test-case", - "thiserror 2.0.9", + "thiserror 2.0.11", "tracing", "tracing-subscriber", "utf8_iter", @@ -1198,12 +1150,12 @@ dependencies = [ [[package]] name = "cairo-native-runtime" -version = "0.2.5" +version = "0.2.8" dependencies = [ "cairo-lang-sierra", "cairo-lang-sierra-gas", "cairo-lang-utils", - "itertools 0.13.0", + "itertools 0.14.0", "lazy_static", "num-bigint", "num-traits", @@ -1246,9 +1198,9 @@ dependencies = [ [[package]] name = "cairo-vm" -version = "2.0.0-rc1" +version = "2.0.0-rc3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "094da2b352a8a0c8400a26f7db6a75c35279f39cc401e08900a714393f110957" +checksum = "88898d02699b294573d2954d42900c8f0d1fa2c6de0514a36e86be8c8fb3165c" dependencies = [ "anyhow", "ark-ff 0.4.2", @@ -1259,7 +1211,7 @@ dependencies = [ "cairo-lang-starknet", "cairo-lang-starknet-classes", "generic-array", - "hashbrown 0.14.5", + "hashbrown 0.15.2", "hex", "keccak", "lazy_static", @@ -1274,7 +1226,7 @@ dependencies = [ "serde_json", "sha2", "sha3", - "starknet-crypto 0.6.2", + "starknet-crypto 0.7.3", "starknet-types-core", "thiserror-no-std", "wasm-bindgen", @@ -1308,9 +1260,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.5" +version = "1.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31a0499c1dc64f458ad13872de75c0eb7e3fdb0e67964610c914b034fc5956e" +checksum = "13208fcbb66eaeffe09b99fffbe1af420f00a7b35aa99ad683dfc1aa76145229" dependencies = [ "jobserver", "libc", @@ -1438,16 +1390,13 @@ dependencies = [ [[package]] name = "comrak" -version = "0.31.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453dcb42e33f7b474d7e0db12e0b8d82802c88f35cf5a1d8c297d0dfcecb154f" +checksum = "39bff2cbb80102771ca62bd2375bc6f6611dc1493373440b23aa08a155538708" dependencies = [ - "bon", "caseless", "entities", "memchr", - "once_cell", - "regex", "slug", "typed-arena", "unicode_categories", @@ -1513,6 +1462,15 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "convert_case" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb402b8d4c85569410425650ce3eddc7d698ed96d39a73f941b08fb63082f1e7" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "cpufeatures" version = "0.2.15" @@ -1620,41 +1578,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "darling" -version = "0.20.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.20.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 2.0.89", -] - -[[package]] -name = "darling_macro" -version = "0.20.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" -dependencies = [ - "darling_core", - "quote", - "syn 2.0.89", -] - [[package]] name = "darrentsung_debug_parser" version = "0.3.1" @@ -1929,54 +1852,12 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" -[[package]] -name = "futures" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" -dependencies = [ - "futures-core", - "futures-sink", -] - [[package]] name = "futures-core" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" -[[package]] -name = "futures-executor" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" - [[package]] name = "futures-macro" version = "0.3.31" @@ -1988,12 +1869,6 @@ dependencies = [ "syn 2.0.89", ] -[[package]] -name = "futures-sink" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" - [[package]] name = "futures-task" version = "0.3.31" @@ -2012,13 +1887,9 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ - "futures-channel", "futures-core", - "futures-io", "futures-macro", - "futures-sink", "futures-task", - "memchr", "pin-project-lite", "pin-utils", "slab", @@ -2148,13 +2019,14 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.1" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" dependencies = [ "allocator-api2", "equivalent", "foldhash", + "serde", ] [[package]] @@ -2190,15 +2062,6 @@ dependencies = [ "digest", ] -[[package]] -name = "home" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" -dependencies = [ - "windows-sys 0.52.0", -] - [[package]] name = "html-escape" version = "0.2.13" @@ -2214,12 +2077,6 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - [[package]] name = "ignore" version = "0.4.23" @@ -2290,7 +2147,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.15.1", + "hashbrown 0.15.2", "serde", ] @@ -2375,6 +2232,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.13" @@ -2495,12 +2361,6 @@ dependencies = [ "spin", ] -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - [[package]] name = "libc" version = "0.2.164" @@ -2575,7 +2435,7 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.15.1", + "hashbrown 0.15.2", ] [[package]] @@ -2599,9 +2459,9 @@ dependencies = [ [[package]] name = "melior" -version = "0.20.1" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6359eb3167955f03dd9664feeb042cb31fbb3509e2118ccb044cfd450e7dcf57" +checksum = "1cfcb398e6571361b6f54fd0057066d9b47a822bcb797bf5867e5412e9e6f387" dependencies = [ "melior-macro", "mlir-sys", @@ -2609,17 +2469,17 @@ dependencies = [ [[package]] name = "melior-macro" -version = "0.13.1" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e14d65328cdb958e2b9fa66f440b84d8e410d9e16742cad4237f2458ab8c17e" +checksum = "53793223a7d821e2f69ac9cb4054d885074013f5a5a7f0accbaba74b454769be" dependencies = [ "comrak", - "convert_case", + "convert_case 0.7.1", "proc-macro2", "quote", "regex", "syn 2.0.89", - "tblgen-alt", + "tblgen", "unindent", ] @@ -2660,7 +2520,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21b598f9c0fa7a453eeaa9fe419ae93759c94a66eb6f8a496d195ba596ae3c4d" dependencies = [ - "bindgen 0.71.1", + "bindgen", ] [[package]] @@ -3082,27 +2942,24 @@ dependencies = [ ] [[package]] -name = "proc-macro-error" -version = "1.0.4" +name = "proc-macro-error-attr2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" dependencies = [ - "proc-macro-error-attr", "proc-macro2", "quote", - "syn 1.0.109", - "version_check", ] [[package]] -name = "proc-macro-error-attr" -version = "1.0.4" +name = "proc-macro-error2" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" dependencies = [ + "proc-macro-error-attr2", "proc-macro2", "quote", - "version_check", ] [[package]] @@ -3308,21 +3165,21 @@ dependencies = [ [[package]] name = "rstest" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a2c585be59b6b5dd66a9d2084aa1d8bd52fbdb806eafdeffb52791147862035" +checksum = "03e905296805ab93e13c1ec3a03f4b6c4f35e9498a3d5fa96dc626d22c03cd89" dependencies = [ - "futures", "futures-timer", + "futures-util", "rstest_macros", "rustc_version", ] [[package]] name = "rstest_macros" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "825ea780781b15345a146be27eaefb05085e337e869bff01b4306a4fd4a9ad5a" +checksum = "ef0053bbffce09062bee4bcc499b0fbe7a57b879f1efe088d6d8d4c7adcdef9b" dependencies = [ "cfg-if", "glob", @@ -3628,13 +3485,14 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "sierra-emu" version = "0.1.0" -source = "git+https://github.com/lambdaclass/sierra-emu#73706c141b77073afc0403167ef11645c96fd183" dependencies = [ "cairo-lang-compiler", "cairo-lang-filesystem", + "cairo-lang-runner", "cairo-lang-sierra", "cairo-lang-sierra-ap-change", "cairo-lang-sierra-gas", + "cairo-lang-starknet-classes", "cairo-lang-utils", "clap", "k256", @@ -3652,7 +3510,7 @@ dependencies = [ "starknet-curve 0.5.1", "starknet-types-core", "tempfile", - "thiserror 2.0.9", + "thiserror 2.0.11", "tracing", "tracing-subscriber", ] @@ -3896,25 +3754,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] -name = "tblgen-alt" -version = "0.4.0" +name = "tblgen" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ecbc9175dd38627cd01d546e7b41c9a115e5773f4c98f64e2185c81ec5f45ab" +checksum = "c155c9310c9e11e6f642b4c8a30ae572ea0cad013d5c9e28bb264b52fa8163bb" dependencies = [ - "bindgen 0.69.5", + "bindgen", "cc", "paste", - "thiserror 1.0.69", + "thiserror 2.0.11", ] [[package]] name = "tempfile" -version = "3.14.0" +version = "3.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" +checksum = "9a8a559c81686f576e8cd0290cd2a24a2a9ad80c98b3478856500fcbd7acd704" dependencies = [ "cfg-if", "fastrand", + "getrandom", "once_cell", "rustix", "windows-sys 0.59.0", @@ -3975,11 +3834,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.9" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f072643fd0190df67a8bab670c20ef5d8737177d6ac6b2e9a236cb096206b2cc" +checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" dependencies = [ - "thiserror-impl 2.0.9", + "thiserror-impl 2.0.11", ] [[package]] @@ -3995,9 +3854,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.9" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b50fa271071aae2e6ee85f842e2e28ba8cd2c5fb67f11fcb1fd70b276f9e7d4" +checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" dependencies = [ "proc-macro2", "quote", @@ -4412,18 +4271,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "which" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix", -] - [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index 0261af376..321a74093 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cairo-native" -version = "0.2.5" +version = "0.2.8" edition = "2021" license = "Apache-2.0" description = "A compiler to convert Cairo's intermediate representation Sierra code to MLIR." @@ -57,21 +57,21 @@ with-trace-dump = ["cairo-native-runtime/with-trace-dump"] normal = ["aquamarine"] [dependencies] -aquamarine = "0.5.0" +aquamarine = "0.6.0" bumpalo = "3.16.0" -cairo-lang-compiler = "2.9.2" -cairo-lang-defs = "2.9.2" -cairo-lang-filesystem = "2.9.2" -cairo-lang-runner = "2.9.2" -cairo-lang-semantic = "2.9.2" -cairo-lang-sierra = "2.9.2" -cairo-lang-sierra-generator = "2.9.2" +cairo-lang-compiler = "=2.10.0-rc.0" +cairo-lang-defs = "=2.10.0-rc.0" +cairo-lang-filesystem = "=2.10.0-rc.0" +cairo-lang-runner = "=2.10.0-rc.0" +cairo-lang-semantic = "=2.10.0-rc.0" +cairo-lang-sierra = "=2.10.0-rc.0" +cairo-lang-sierra-generator = "=2.10.0-rc.0" educe = "0.5.11" # can't update until https://github.com/magiclen/educe/issues/27 itertools = "0.13.0" lazy_static = "1.5" libc = "0.2" llvm-sys = "191.0.0" -melior = { version = "0.20.0", features = ["ods-dialects", "helpers"] } +melior = { version = "0.20.2", features = ["ods-dialects", "helpers"] } mlir-sys = { version = "0.4.1" } num-bigint = "0.4.6" num-traits = "0.2" @@ -80,19 +80,19 @@ starknet-types-core = { version = "0.1.7", default-features = false, features = "serde", "num-traits", ] } -tempfile = "3.13" -thiserror = "2.0.8" +tempfile = "3.15.0" +thiserror = "2.0.9" tracing = "0.1" utf8_iter = "1.0.4" # CLI dependencies -cairo-lang-sierra-ap-change = "2.9.2" -cairo-lang-sierra-gas = "2.9.2" -cairo-lang-starknet = "2.9.2" -cairo-lang-utils = "2.9.2" -cairo-lang-starknet-classes = "2.9.2" -cairo-native-runtime = { version = "0.2.5", path = "runtime", optional = true } +cairo-lang-sierra-ap-change = "=2.10.0-rc.0" +cairo-lang-sierra-gas = "=2.10.0-rc.0" +cairo-lang-starknet = "=2.10.0-rc.0" +cairo-lang-utils = "=2.10.0-rc.0" +cairo-lang-starknet-classes = "=2.10.0-rc.0" +cairo-native-runtime = { version = "0.2.8", path = "runtime", optional = true } clap = { version = "4.5.23", features = ["derive"], optional = true } libloading = "0.8.6" tracing-subscriber = { version = "0.3.19", features = [ @@ -102,7 +102,7 @@ tracing-subscriber = { version = "0.3.19", features = [ ], optional = true } serde = { version = "1.0", features = ["derive"] } anyhow = { version = "1.0", optional = true } -cairo-lang-test-plugin = { version = "2.9.2", optional = true } +cairo-lang-test-plugin = { version = "=2.10.0-rc.0", optional = true } colored = { version = "2.1.0", optional = true } # needed to interface with cairo-lang-* keccak = "0.1.5" @@ -120,20 +120,20 @@ ark-ff = "0.5.0" num-integer = "0.1.46" [dev-dependencies] -cairo-vm = { version = "2.0.0-rc0", features = ["cairo-1-hints"] } -cairo-lang-semantic = { version = "2.9.2", features = ["testing"] } +cairo-vm = { version = "2.0.0-rc3", features = ["cairo-1-hints"] } +cairo-lang-semantic = { version = "=2.10.0-rc.0", features = ["testing"] } criterion = { version = "0.5.1", features = ["html_reports"] } lambdaworks-math = "0.11.0" pretty_assertions_sorted = "1.2.3" proptest = "1.5.0" -rstest = "0.23.0" +rstest = "0.24.0" test-case = "3.3" walkdir = "2.5.0" serde_json = { version = "1.0.128" } rayon = "1.10.0" [build-dependencies] -cc = "1.2.3" +cc = "1.2.7" [profile.optimized-dev] inherits = "dev" diff --git a/Makefile b/Makefile index 1779443d4..6e5178f17 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # Environment detection. UNAME := $(shell uname) -CAIRO_2_VERSION = 2.9.2 +CAIRO_2_VERSION = 2.10.0-rc.0 SCARB_VERSION = 2.9.2 # Usage is the default target for newcomers running `make`. diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 2a673b8eb..6972ba422 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cairo-native-runtime" -version = "0.2.5" +version = "0.2.8" description = "The runtime for cairo-native." edition = "2021" license = "Apache-2.0" @@ -23,14 +23,13 @@ starknet-types-core = { version = "0.1.7", default-features = false, features = "serde", "hash", ] } -cairo-lang-sierra-gas = "2.9.2" -itertools = "0.13.0" +cairo-lang-sierra-gas = "=2.10.0-rc.0" +starknet-curve = "0.5.1" lazy_static = "1.5.0" rand = "0.8.5" -starknet-curve = "0.5.1" - num-bigint = { version = "0.4.4", optional = true } -num-traits = { version = "0.2" } -cairo-lang-sierra = { version = "2.9.0-dev.0", optional = true } -cairo-lang-utils = { version = "2.9.0-dev.0", optional = true } -sierra-emu = { git = "https://github.com/lambdaclass/sierra-emu", optional = true } +cairo-lang-sierra = { version = "=2.10.0-rc.0", optional = true } +cairo-lang-utils = { version = "=2.10.0-rc.0", optional = true } +sierra-emu = { git = "https://github.com/lambdaclass/sierra-emu.git", rev = "70b392fd816cd6c4a55410f9936fe62eaba85713", optional = true } +itertools = "0.14.0" +num-traits = "0.2" diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index bc8ccf1c6..a3671924b 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -20,9 +20,11 @@ use std::{ ffi::{c_int, c_void}, fs::File, io::Write, - mem::ManuallyDrop, + mem::{forget, ManuallyDrop}, os::fd::FromRawFd, ptr::{self, null, null_mut}, + rc::Rc, + slice, }; use std::{ops::Mul, vec::IntoIter}; @@ -35,6 +37,20 @@ lazy_static! { (DICT_SQUASH_UNIQUE_KEY_COST.cost() - DICT_SQUASH_REPEATED_ACCESS_COST.cost()) as u64; } +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn cairo_native__get_version(target: *mut u8, length: usize) -> usize { + let version = env!("CARGO_PKG_VERSION"); + assert!(length > version.len(), "version buffer not big enough"); + + let target = slice::from_raw_parts_mut(target, length); + + target[..version.len()].copy_from_slice(version.as_bytes()); + target[version.len()] = b'\0'; + + version.len() +} + /// Based on `cairo-lang-runner`'s implementation. /// /// Source: @@ -151,9 +167,96 @@ pub struct FeltDict { pub layout: Layout, pub elements: *mut (), + pub dup_fn: Option, + pub drop_fn: Option, + pub count: u64, } +impl Clone for FeltDict { + fn clone(&self) -> Self { + let mut new_dict = FeltDict { + mappings: HashMap::with_capacity(self.mappings.len()), + + layout: self.layout, + elements: if self.mappings.is_empty() { + null_mut() + } else { + unsafe { + alloc(Layout::from_size_align_unchecked( + self.layout.pad_to_align().size() * self.mappings.len(), + self.layout.align(), + )) + .cast() + } + }, + + dup_fn: self.dup_fn, + drop_fn: self.drop_fn, + + // TODO: Check if `0` is fine or otherwise we should copy the value from `old_dict` too. + count: 0, + }; + + for (&key, &old_index) in self.mappings.iter() { + let old_value_ptr = unsafe { + self.elements + .byte_add(self.layout.pad_to_align().size() * old_index) + }; + + let new_index = new_dict.mappings.len(); + let new_value_ptr = unsafe { + new_dict + .elements + .byte_add(new_dict.layout.pad_to_align().size() * new_index) + }; + + new_dict.mappings.insert(key, new_index); + match self.dup_fn { + Some(dup_fn) => dup_fn(old_value_ptr.cast(), new_value_ptr.cast()), + None => unsafe { + ptr::copy_nonoverlapping::( + old_value_ptr.cast(), + new_value_ptr.cast(), + self.layout.size(), + ) + }, + } + } + + new_dict + } +} + +impl Drop for FeltDict { + fn drop(&mut self) { + // Free the entries manually. + if let Some(drop_fn) = self.drop_fn { + for (_, &index) in self.mappings.iter() { + let value_ptr = unsafe { + self.elements + .byte_add(self.layout.pad_to_align().size() * index) + }; + + drop_fn(value_ptr.cast()); + } + } + + // Free the value data. + if !self.elements.is_null() { + unsafe { + dealloc( + self.elements.cast(), + Layout::from_size_align_unchecked( + self.layout.pad_to_align().size() * self.mappings.capacity(), + self.layout.align(), + ), + ) + }; + } + } +} + /// Allocate a new dictionary. /// /// # Safety @@ -161,21 +264,27 @@ pub struct FeltDict { /// This function is intended to be called from MLIR, deals with pointers, and is therefore /// definitely unsafe to use manually. #[no_mangle] -pub unsafe extern "C" fn cairo_native__dict_new(size: u64, align: u64) -> *mut FeltDict { - Box::into_raw(Box::new(FeltDict { +pub unsafe extern "C" fn cairo_native__dict_new( + size: u64, + align: u64, + dup_fn: Option, + drop_fn: Option, +) -> *const FeltDict { + Rc::into_raw(Rc::new(FeltDict { mappings: HashMap::default(), layout: Layout::from_size_align_unchecked(size as usize, align as usize), elements: null_mut(), + dup_fn, + drop_fn, + count: 0, })) } /// Free a dictionary using an optional callback to drop each element. /// -/// The `drop_fn` callback is present when the value implements `Drop`. -/// /// # Safety /// /// This function is intended to be called from MLIR, deals with pointers, and is therefore @@ -184,88 +293,23 @@ pub unsafe extern "C" fn cairo_native__dict_new(size: u64, align: u64) -> *mut F // pointer optimization. Check out // https://doc.rust-lang.org/nomicon/ffi.html#the-nullable-pointer-optimization for more info. #[no_mangle] -pub unsafe extern "C" fn cairo_native__dict_drop( - ptr: *mut FeltDict, - drop_fn: Option, -) { - let dict = Box::from_raw(ptr); - - // Free the entries manually. - if let Some(drop_fn) = drop_fn { - for (_, &index) in dict.mappings.iter() { - let value_ptr = dict - .elements - .byte_add(dict.layout.pad_to_align().size() * index); - - drop_fn(value_ptr.cast()); - } - } - - // Free the value data. - if !dict.elements.is_null() { - dealloc( - dict.elements.cast(), - Layout::from_size_align_unchecked( - dict.layout.pad_to_align().size() * dict.mappings.capacity(), - dict.layout.align(), - ), - ); - } +pub unsafe extern "C" fn cairo_native__dict_drop(ptr: *const FeltDict) { + drop(Rc::from_raw(ptr)); } /// Duplicate a dictionary using a provided callback to clone each element. /// -/// The `dup_fn` callback is present when the value is not `Copy`, but `Clone`. The first argument -/// is the original value while the second is the target pointer. -/// /// # Safety /// /// This function is intended to be called from MLIR, deals with pointers, and is therefore /// definitely unsafe to use manually. #[no_mangle] -pub unsafe extern "C" fn cairo_native__dict_dup( - old_dict: &FeltDict, - dup_fn: Option, -) -> *mut FeltDict { - let mut new_dict = Box::new(FeltDict { - mappings: HashMap::with_capacity(old_dict.mappings.len()), - - layout: old_dict.layout, - elements: if old_dict.mappings.is_empty() { - null_mut() - } else { - alloc(Layout::from_size_align_unchecked( - old_dict.layout.pad_to_align().size() * old_dict.mappings.len(), - old_dict.layout.align(), - )) - .cast() - }, - - // TODO: Check if `0` is fine or otherwise we should copy the value from `old_dict` too. - count: 0, - }); - - for (new_index, (&key, &old_index)) in old_dict.mappings.iter().enumerate() { - let old_value_ptr = old_dict - .elements - .byte_add(old_dict.layout.pad_to_align().size() * old_index); - - let new_value_ptr = new_dict - .elements - .byte_add(new_dict.layout.pad_to_align().size() * new_index); - - new_dict.mappings.insert(key, new_index); - match dup_fn { - Some(dup_fn) => dup_fn(old_value_ptr.cast(), new_value_ptr.cast()), - None => ptr::copy_nonoverlapping::( - old_value_ptr.cast(), - new_value_ptr.cast(), - old_dict.layout.size(), - ), - } - } +pub unsafe extern "C" fn cairo_native__dict_dup(dict_ptr: *const FeltDict) -> *const FeltDict { + let old_dict = Rc::from_raw(dict_ptr); + let new_dict = Rc::clone(&old_dict); - Box::into_raw(new_dict) + forget(old_dict); + Rc::into_raw(new_dict) } /// Return a pointer to the entry's value pointer for a given key, inserting a null pointer if not @@ -280,45 +324,46 @@ pub unsafe extern "C" fn cairo_native__dict_dup( /// definitely unsafe to use manually. #[no_mangle] pub unsafe extern "C" fn cairo_native__dict_get( - dict: &mut FeltDict, + dict: *const FeltDict, key: &[u8; 32], value_ptr: *mut *mut c_void, ) -> c_int { - let mut key = *key; - key[31] &= 0x0F; // Filter out first 4 bits (they're outside an i252). - - let old_capacity = dict.mappings.capacity(); - let index = dict.mappings.len(); - let (index, is_present) = match dict.mappings.entry(key) { - Entry::Occupied(entry) => (*entry.get(), 1), - Entry::Vacant(entry) => { - entry.insert(index); + let mut dict_rc = Rc::from_raw(dict); + let dict = Rc::make_mut(&mut dict_rc); - // Reallocate `mem_data` to match the slab's capacity. - if old_capacity != dict.mappings.capacity() { - dict.elements = realloc( - dict.elements.cast(), - Layout::from_size_align_unchecked( - dict.layout.pad_to_align().size() * old_capacity, - dict.layout.align(), - ), - dict.layout.pad_to_align().size() * dict.mappings.capacity(), - ) - .cast(); - } + let num_mappings = dict.mappings.len(); + let has_capacity = num_mappings != dict.mappings.capacity(); - (index, 0) + let (is_present, index) = match dict.mappings.entry(*key) { + Entry::Occupied(entry) => (true, *entry.get()), + Entry::Vacant(entry) => { + entry.insert(num_mappings); + (false, num_mappings) } }; - value_ptr.write( - dict.elements - .byte_add(dict.layout.pad_to_align().size() * index) - .cast(), - ); + // Maybe realloc (conditions: !has_capacity && !is_present). + if !has_capacity && !is_present { + dict.elements = realloc( + dict.elements.cast(), + Layout::from_size_align_unchecked( + dict.layout.pad_to_align().size() * dict.mappings.len(), + dict.layout.align(), + ), + dict.layout.pad_to_align().size() * dict.mappings.capacity(), + ) + .cast(); + } + + *value_ptr = dict + .elements + .byte_add(dict.layout.pad_to_align().size() * index) + .cast(); + dict.count += 1; + forget(dict_rc); - is_present + is_present as c_int } /// Compute the total gas refund for the dictionary at squash time. @@ -329,8 +374,12 @@ pub unsafe extern "C" fn cairo_native__dict_get( /// definitely unsafe to use manually. #[no_mangle] pub unsafe extern "C" fn cairo_native__dict_gas_refund(ptr: *const FeltDict) -> u64 { - let dict = &*ptr; - (dict.count.saturating_sub(dict.mappings.len() as u64)) * *DICT_GAS_REFUND_PER_ACCESS + let dict = Rc::from_raw(ptr); + let amount = + (dict.count.saturating_sub(dict.mappings.len() as u64)) * *DICT_GAS_REFUND_PER_ACCESS; + + forget(dict); + amount } /// Compute `ec_point_from_x_nz(x)` and store it. @@ -1320,21 +1369,27 @@ mod tests { #[test] fn test_dict() { - let dict = - unsafe { cairo_native__dict_new(size_of::() as u64, align_of::() as u64) }; + let dict = unsafe { + cairo_native__dict_new( + size_of::() as u64, + align_of::() as u64, + None, + None, + ) + }; let key = Felt::ONE.to_bytes_le(); let mut ptr = null_mut::(); assert_eq!( - unsafe { cairo_native__dict_get(&mut *dict, &key, (&raw mut ptr).cast()) }, + unsafe { cairo_native__dict_get(dict, &key, (&raw mut ptr).cast()) }, 0, ); assert!(!ptr.is_null()); unsafe { *ptr = 24 }; assert_eq!( - unsafe { cairo_native__dict_get(&mut *dict, &key, (&raw mut ptr).cast()) }, + unsafe { cairo_native__dict_get(dict, &key, (&raw mut ptr).cast()) }, 1, ); assert!(!ptr.is_null()); @@ -1344,17 +1399,17 @@ mod tests { let refund = unsafe { cairo_native__dict_gas_refund(dict) }; assert_eq!(refund, 4050); - let cloned_dict = unsafe { cairo_native__dict_dup(&*dict, None) }; - unsafe { cairo_native__dict_drop(dict, None) }; + let cloned_dict = unsafe { cairo_native__dict_dup(&*dict) }; + unsafe { cairo_native__dict_drop(dict) }; assert_eq!( - unsafe { cairo_native__dict_get(&mut *cloned_dict, &key, (&raw mut ptr).cast()) }, + unsafe { cairo_native__dict_get(cloned_dict, &key, (&raw mut ptr).cast()) }, 1, ); assert!(!ptr.is_null()); assert_eq!(unsafe { *ptr }, 42); - unsafe { cairo_native__dict_drop(cloned_dict, None) }; + unsafe { cairo_native__dict_drop(cloned_dict) }; } #[test] diff --git a/rust-toolchain.toml b/rust-toolchain.toml index dcea74bc7..3651b37c1 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "1.83.0" +channel = "1.84.0" components = ["rustfmt", "clippy"] profile = "minimal" diff --git a/src/arch.rs b/src/arch.rs index ceaca4cdb..0316034e9 100644 --- a/src/arch.rs +++ b/src/arch.rs @@ -15,7 +15,10 @@ use cairo_lang_sierra::{ ids::ConcreteTypeId, program_registry::ProgramRegistry, }; -use std::ptr::{null, NonNull}; +use std::{ + ffi::c_void, + ptr::{null, NonNull}, +}; mod aarch64; mod x86_64; @@ -24,7 +27,17 @@ mod x86_64; pub trait AbiArgument { /// Serialize the argument into the buffer. This method should keep track of arch-dependent /// stuff like register vs stack allocation. - fn to_bytes(&self, buffer: &mut Vec) -> Result<()>; + fn to_bytes( + &self, + buffer: &mut Vec, + find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), + ) -> Result<()>; } /// A wrapper that implements `AbiArgument` for `Value`s. It contains all the required stuff to @@ -58,10 +71,21 @@ impl<'a> ValueWithInfoWrapper<'a> { } impl AbiArgument for ValueWithInfoWrapper<'_> { - fn to_bytes(&self, buffer: &mut Vec) -> Result<()> { + fn to_bytes( + &self, + buffer: &mut Vec, + find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), + ) -> Result<()> { match (self.value, self.info) { (value, CoreTypeConcrete::Box(info)) => { - let ptr = value.to_ptr(self.arena, self.registry, self.type_id)?; + let ptr = + value.to_ptr(self.arena, self.registry, self.type_id, find_dict_overrides)?; let layout = self.registry.get_type(&info.ty)?.layout(self.registry)?; let heap_ptr = unsafe { @@ -70,13 +94,18 @@ impl AbiArgument for ValueWithInfoWrapper<'_> { heap_ptr }; - heap_ptr.to_bytes(buffer)?; + heap_ptr.to_bytes(buffer, find_dict_overrides)?; } (value, CoreTypeConcrete::Nullable(info)) => { if matches!(value, Value::Null) { - null::<()>().to_bytes(buffer)?; + null::<()>().to_bytes(buffer, find_dict_overrides)?; } else { - let ptr = value.to_ptr(self.arena, self.registry, self.type_id)?; + let ptr = value.to_ptr( + self.arena, + self.registry, + self.type_id, + find_dict_overrides, + )?; let layout = self.registry.get_type(&info.ty)?.layout(self.registry)?; let heap_ptr = unsafe { @@ -85,51 +114,64 @@ impl AbiArgument for ValueWithInfoWrapper<'_> { heap_ptr }; - heap_ptr.to_bytes(buffer)?; + heap_ptr.to_bytes(buffer, find_dict_overrides)?; } } - (value, CoreTypeConcrete::NonZero(info) | CoreTypeConcrete::Snapshot(info)) => { - self.map(value, &info.ty)?.to_bytes(buffer)? - } + (value, CoreTypeConcrete::NonZero(info) | CoreTypeConcrete::Snapshot(info)) => self + .map(value, &info.ty)? + .to_bytes(buffer, find_dict_overrides)?, (Value::Array(_), CoreTypeConcrete::Array(_)) => { // TODO: Assert that `info.ty` matches all the values' types. - let abi_ptr = self.value.to_ptr(self.arena, self.registry, self.type_id)?; + let abi_ptr = self.value.to_ptr( + self.arena, + self.registry, + self.type_id, + find_dict_overrides, + )?; let abi = unsafe { abi_ptr.cast::>().as_ref() }; - abi.ptr.to_bytes(buffer)?; - abi.since.to_bytes(buffer)?; - abi.until.to_bytes(buffer)?; - abi.capacity.to_bytes(buffer)?; + abi.ptr.to_bytes(buffer, find_dict_overrides)?; + abi.since.to_bytes(buffer, find_dict_overrides)?; + abi.until.to_bytes(buffer, find_dict_overrides)?; + abi.capacity.to_bytes(buffer, find_dict_overrides)?; } (Value::BoundedInt { .. }, CoreTypeConcrete::BoundedInt(_)) => { native_panic!("todo: implement AbiArgument for Value::BoundedInt case") } - (Value::Bytes31(value), CoreTypeConcrete::Bytes31(_)) => value.to_bytes(buffer)?, + (Value::Bytes31(value), CoreTypeConcrete::Bytes31(_)) => { + value.to_bytes(buffer, find_dict_overrides)? + } (Value::EcPoint(x, y), CoreTypeConcrete::EcPoint(_)) => { - x.to_bytes(buffer)?; - y.to_bytes(buffer)?; + x.to_bytes(buffer, find_dict_overrides)?; + y.to_bytes(buffer, find_dict_overrides)?; } (Value::EcState(x, y, x0, y0), CoreTypeConcrete::EcState(_)) => { - x.to_bytes(buffer)?; - y.to_bytes(buffer)?; - x0.to_bytes(buffer)?; - y0.to_bytes(buffer)?; + x.to_bytes(buffer, find_dict_overrides)?; + y.to_bytes(buffer, find_dict_overrides)?; + x0.to_bytes(buffer, find_dict_overrides)?; + y0.to_bytes(buffer, find_dict_overrides)?; } (Value::Enum { tag, value, .. }, CoreTypeConcrete::Enum(info)) => { if self.info.is_memory_allocated(self.registry)? { - let abi_ptr = self.value.to_ptr(self.arena, self.registry, self.type_id)?; + let abi_ptr = self.value.to_ptr( + self.arena, + self.registry, + self.type_id, + find_dict_overrides, + )?; let abi_ptr = unsafe { *abi_ptr.cast::>().as_ref() }; - abi_ptr.as_ptr().to_bytes(buffer)?; + abi_ptr.as_ptr().to_bytes(buffer, find_dict_overrides)?; } else { match (info.variants.len().next_power_of_two().trailing_zeros() + 7) / 8 { 0 => {} - _ => (*tag as u64).to_bytes(buffer)?, + _ => (*tag as u64).to_bytes(buffer, find_dict_overrides)?, } - self.map(value, &info.variants[*tag])?.to_bytes(buffer)?; + self.map(value, &info.variants[*tag])? + .to_bytes(buffer, find_dict_overrides)?; } } ( @@ -141,7 +183,7 @@ impl AbiArgument for ValueWithInfoWrapper<'_> { | StarkNetTypeConcrete::StorageAddress(_) | StarkNetTypeConcrete::StorageBaseAddress(_), ), - ) => value.to_bytes(buffer)?, + ) => value.to_bytes(buffer, find_dict_overrides)?, (Value::Felt252Dict { .. }, CoreTypeConcrete::Felt252Dict(_)) => { #[cfg(not(feature = "with-runtime"))] native_panic!("enable the `with-runtime` feature to use felt252 dicts"); @@ -151,9 +193,9 @@ impl AbiArgument for ValueWithInfoWrapper<'_> { // TODO: Assert that `info.ty` matches all the values' types. self.value - .to_ptr(self.arena, self.registry, self.type_id)? + .to_ptr(self.arena, self.registry, self.type_id, find_dict_overrides)? .as_ptr() - .to_bytes(buffer)? + .to_bytes(buffer, find_dict_overrides)? } } ( @@ -168,27 +210,47 @@ impl AbiArgument for ValueWithInfoWrapper<'_> { Secp256PointTypeConcrete::R1(_), )), ) => { - x.to_bytes(buffer)?; - y.to_bytes(buffer)?; - is_infinity.to_bytes(buffer)?; - } - (Value::Sint128(value), CoreTypeConcrete::Sint128(_)) => value.to_bytes(buffer)?, - (Value::Sint16(value), CoreTypeConcrete::Sint16(_)) => value.to_bytes(buffer)?, - (Value::Sint32(value), CoreTypeConcrete::Sint32(_)) => value.to_bytes(buffer)?, - (Value::Sint64(value), CoreTypeConcrete::Sint64(_)) => value.to_bytes(buffer)?, - (Value::Sint8(value), CoreTypeConcrete::Sint8(_)) => value.to_bytes(buffer)?, + x.to_bytes(buffer, find_dict_overrides)?; + y.to_bytes(buffer, find_dict_overrides)?; + is_infinity.to_bytes(buffer, find_dict_overrides)?; + } + (Value::Sint128(value), CoreTypeConcrete::Sint128(_)) => { + value.to_bytes(buffer, find_dict_overrides)? + } + (Value::Sint16(value), CoreTypeConcrete::Sint16(_)) => { + value.to_bytes(buffer, find_dict_overrides)? + } + (Value::Sint32(value), CoreTypeConcrete::Sint32(_)) => { + value.to_bytes(buffer, find_dict_overrides)? + } + (Value::Sint64(value), CoreTypeConcrete::Sint64(_)) => { + value.to_bytes(buffer, find_dict_overrides)? + } + (Value::Sint8(value), CoreTypeConcrete::Sint8(_)) => { + value.to_bytes(buffer, find_dict_overrides)? + } (Value::Struct { fields, .. }, CoreTypeConcrete::Struct(info)) => { fields .iter() .zip(&info.members) .map(|(value, type_id)| self.map(value, type_id)) - .try_for_each(|wrapper| wrapper?.to_bytes(buffer))?; + .try_for_each(|wrapper| wrapper?.to_bytes(buffer, find_dict_overrides))?; + } + (Value::Uint128(value), CoreTypeConcrete::Uint128(_)) => { + value.to_bytes(buffer, find_dict_overrides)? + } + (Value::Uint16(value), CoreTypeConcrete::Uint16(_)) => { + value.to_bytes(buffer, find_dict_overrides)? + } + (Value::Uint32(value), CoreTypeConcrete::Uint32(_)) => { + value.to_bytes(buffer, find_dict_overrides)? + } + (Value::Uint64(value), CoreTypeConcrete::Uint64(_)) => { + value.to_bytes(buffer, find_dict_overrides)? + } + (Value::Uint8(value), CoreTypeConcrete::Uint8(_)) => { + value.to_bytes(buffer, find_dict_overrides)? } - (Value::Uint128(value), CoreTypeConcrete::Uint128(_)) => value.to_bytes(buffer)?, - (Value::Uint16(value), CoreTypeConcrete::Uint16(_)) => value.to_bytes(buffer)?, - (Value::Uint32(value), CoreTypeConcrete::Uint32(_)) => value.to_bytes(buffer)?, - (Value::Uint64(value), CoreTypeConcrete::Uint64(_)) => value.to_bytes(buffer)?, - (Value::Uint8(value), CoreTypeConcrete::Uint8(_)) => value.to_bytes(buffer)?, _ => native_panic!( "todo: abi argument unimplemented for ({:?}, {:?})", self.value, diff --git a/src/arch/aarch64.rs b/src/arch/aarch64.rs index ad699033c..2ab529944 100644 --- a/src/arch/aarch64.rs +++ b/src/arch/aarch64.rs @@ -11,15 +11,27 @@ use super::AbiArgument; use crate::{error::Error, starknet::U256, utils::get_integer_layout}; +use cairo_lang_sierra::ids::ConcreteTypeId; use num_traits::ToBytes; use starknet_types_core::felt::Felt; +use std::ffi::c_void; fn align_to(buffer: &mut Vec, align: usize) { buffer.resize(buffer.len().next_multiple_of(align), 0); } impl AbiArgument for bool { - fn to_bytes(&self, buffer: &mut Vec) -> Result<(), Error> { + fn to_bytes( + &self, + buffer: &mut Vec, + _find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), + ) -> Result<(), Error> { if buffer.len() < 64 { buffer.extend_from_slice(&(*self as u64).to_ne_bytes()); } else { @@ -31,7 +43,17 @@ impl AbiArgument for bool { } impl AbiArgument for u8 { - fn to_bytes(&self, buffer: &mut Vec) -> Result<(), Error> { + fn to_bytes( + &self, + buffer: &mut Vec, + _find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), + ) -> Result<(), Error> { if buffer.len() < 64 { buffer.extend_from_slice(&(*self as u64).to_ne_bytes()); } else { @@ -43,7 +65,17 @@ impl AbiArgument for u8 { } impl AbiArgument for i8 { - fn to_bytes(&self, buffer: &mut Vec) -> Result<(), Error> { + fn to_bytes( + &self, + buffer: &mut Vec, + _find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), + ) -> Result<(), Error> { if buffer.len() < 64 { buffer.extend_from_slice(&(*self as u64).to_ne_bytes()); } else { @@ -55,7 +87,17 @@ impl AbiArgument for i8 { } impl AbiArgument for u16 { - fn to_bytes(&self, buffer: &mut Vec) -> Result<(), Error> { + fn to_bytes( + &self, + buffer: &mut Vec, + _find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), + ) -> Result<(), Error> { if buffer.len() < 64 { buffer.extend_from_slice(&(*self as u64).to_ne_bytes()); } else { @@ -67,7 +109,17 @@ impl AbiArgument for u16 { } impl AbiArgument for i16 { - fn to_bytes(&self, buffer: &mut Vec) -> Result<(), Error> { + fn to_bytes( + &self, + buffer: &mut Vec, + _find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), + ) -> Result<(), Error> { if buffer.len() < 64 { buffer.extend_from_slice(&(*self as u64).to_ne_bytes()); } else { @@ -79,7 +131,17 @@ impl AbiArgument for i16 { } impl AbiArgument for u32 { - fn to_bytes(&self, buffer: &mut Vec) -> Result<(), Error> { + fn to_bytes( + &self, + buffer: &mut Vec, + _find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), + ) -> Result<(), Error> { if buffer.len() < 64 { buffer.extend_from_slice(&(*self as u64).to_ne_bytes()); } else { @@ -91,7 +153,17 @@ impl AbiArgument for u32 { } impl AbiArgument for i32 { - fn to_bytes(&self, buffer: &mut Vec) -> Result<(), Error> { + fn to_bytes( + &self, + buffer: &mut Vec, + _find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), + ) -> Result<(), Error> { if buffer.len() < 64 { buffer.extend_from_slice(&(*self as u64).to_ne_bytes()); } else { @@ -103,7 +175,17 @@ impl AbiArgument for i32 { } impl AbiArgument for u64 { - fn to_bytes(&self, buffer: &mut Vec) -> Result<(), Error> { + fn to_bytes( + &self, + buffer: &mut Vec, + _find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), + ) -> Result<(), Error> { if buffer.len() >= 64 { align_to(buffer, get_integer_layout(64).align()); } @@ -113,7 +195,17 @@ impl AbiArgument for u64 { } impl AbiArgument for i64 { - fn to_bytes(&self, buffer: &mut Vec) -> Result<(), Error> { + fn to_bytes( + &self, + buffer: &mut Vec, + _find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), + ) -> Result<(), Error> { if buffer.len() >= 64 { align_to(buffer, get_integer_layout(64).align()); } @@ -123,7 +215,17 @@ impl AbiArgument for i64 { } impl AbiArgument for u128 { - fn to_bytes(&self, buffer: &mut Vec) -> Result<(), Error> { + fn to_bytes( + &self, + buffer: &mut Vec, + _find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), + ) -> Result<(), Error> { if buffer.len() >= 56 { align_to(buffer, get_integer_layout(128).align()); } @@ -133,7 +235,17 @@ impl AbiArgument for u128 { } impl AbiArgument for i128 { - fn to_bytes(&self, buffer: &mut Vec) -> Result<(), Error> { + fn to_bytes( + &self, + buffer: &mut Vec, + _find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), + ) -> Result<(), Error> { if buffer.len() >= 56 { align_to(buffer, get_integer_layout(128).align()); } @@ -143,7 +255,17 @@ impl AbiArgument for i128 { } impl AbiArgument for Felt { - fn to_bytes(&self, buffer: &mut Vec) -> Result<(), Error> { + fn to_bytes( + &self, + buffer: &mut Vec, + _find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), + ) -> Result<(), Error> { if buffer.len() >= 56 { align_to(buffer, get_integer_layout(252).align()); } @@ -153,14 +275,34 @@ impl AbiArgument for Felt { } impl AbiArgument for U256 { - fn to_bytes(&self, buffer: &mut Vec) -> Result<(), Error> { - self.lo.to_bytes(buffer)?; - self.hi.to_bytes(buffer) + fn to_bytes( + &self, + buffer: &mut Vec, + find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), + ) -> Result<(), Error> { + self.lo.to_bytes(buffer, find_dict_overrides)?; + self.hi.to_bytes(buffer, find_dict_overrides) } } impl AbiArgument for [u8; 31] { - fn to_bytes(&self, buffer: &mut Vec) -> Result<(), Error> { + fn to_bytes( + &self, + buffer: &mut Vec, + _find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), + ) -> Result<(), Error> { // The `bytes31` type is treated as a 248-bit integer, therefore it follows the same // splitting rules as them. if buffer.len() >= 56 { @@ -173,14 +315,34 @@ impl AbiArgument for [u8; 31] { } impl AbiArgument for *const T { - fn to_bytes(&self, buffer: &mut Vec) -> Result<(), Error> { - ::to_bytes(&(*self as u64), buffer) + fn to_bytes( + &self, + buffer: &mut Vec, + find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), + ) -> Result<(), Error> { + ::to_bytes(&(*self as u64), buffer, find_dict_overrides) } } impl AbiArgument for *mut T { - fn to_bytes(&self, buffer: &mut Vec) -> Result<(), Error> { - ::to_bytes(&(*self as u64), buffer) + fn to_bytes( + &self, + buffer: &mut Vec, + find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), + ) -> Result<(), Error> { + ::to_bytes(&(*self as u64), buffer, find_dict_overrides) } } @@ -192,12 +354,12 @@ mod test { fn u8_to_bytes() { // Buffer initially empty let mut buffer = vec![]; - u8::MAX.to_bytes(&mut buffer).unwrap(); + u8::MAX.to_bytes(&mut buffer, |_| unreachable!()).unwrap(); assert_eq!(buffer, [u8::MAX, 0, 0, 0, 0, 0, 0, 0]); // Buffer initially filled with 70 zeros (len > 64) let mut buffer = vec![0; 70]; - u8::MAX.to_bytes(&mut buffer).unwrap(); + u8::MAX.to_bytes(&mut buffer, |_| unreachable!()).unwrap(); assert_eq!( buffer, [0; 70].into_iter().chain([u8::MAX]).collect::>() @@ -208,17 +370,17 @@ mod test { fn i8_to_bytes() { // Buffer initially empty let mut buffer = vec![]; - i8::MAX.to_bytes(&mut buffer).unwrap(); + i8::MAX.to_bytes(&mut buffer, |_| unreachable!()).unwrap(); assert_eq!(buffer, [i8::MAX as u8, 0, 0, 0, 0, 0, 0, 0]); // Buffer initially empty with negative value let mut buffer = vec![]; - i8::MIN.to_bytes(&mut buffer).unwrap(); + i8::MIN.to_bytes(&mut buffer, |_| unreachable!()).unwrap(); assert_eq!(buffer, [128, 255, 255, 255, 255, 255, 255, 255]); // Buffer initially filled with 70 zeros (len > 64) let mut buffer = vec![0; 70]; - i8::MAX.to_bytes(&mut buffer).unwrap(); + i8::MAX.to_bytes(&mut buffer, |_| unreachable!()).unwrap(); assert_eq!( buffer, [0; 70] @@ -229,7 +391,7 @@ mod test { // Buffer initially filled with 70 zeros (len > 64) and negative value let mut buffer = vec![0; 70]; - i8::MIN.to_bytes(&mut buffer).unwrap(); + i8::MIN.to_bytes(&mut buffer, |_| unreachable!()).unwrap(); assert_eq!(buffer, [0; 70].into_iter().chain([128]).collect::>()); } @@ -237,12 +399,12 @@ mod test { fn u16_to_bytes() { // Buffer initially empty let mut buffer = vec![]; - u16::MAX.to_bytes(&mut buffer).unwrap(); + u16::MAX.to_bytes(&mut buffer, |_| unreachable!()).unwrap(); assert_eq!(buffer, vec![u8::MAX, u8::MAX, 0, 0, 0, 0, 0, 0]); // Buffer initially filled with 70 zeros (len > 64) let mut buffer = vec![0; 70]; - u16::MAX.to_bytes(&mut buffer).unwrap(); + u16::MAX.to_bytes(&mut buffer, |_| unreachable!()).unwrap(); assert_eq!( buffer, [0; 70] @@ -256,17 +418,17 @@ mod test { fn i16_to_bytes() { // Buffer initially empty let mut buffer = vec![]; - i16::MAX.to_bytes(&mut buffer).unwrap(); + i16::MAX.to_bytes(&mut buffer, |_| unreachable!()).unwrap(); assert_eq!(buffer, vec![u8::MAX, i8::MAX as u8, 0, 0, 0, 0, 0, 0]); // Buffer initially empty with negative value let mut buffer = vec![]; - i16::MIN.to_bytes(&mut buffer).unwrap(); + i16::MIN.to_bytes(&mut buffer, |_| unreachable!()).unwrap(); assert_eq!(buffer, [0, 128, 255, 255, 255, 255, 255, 255]); // Buffer initially filled with 70 zeros (len > 64) let mut buffer = vec![0; 70]; - i16::MAX.to_bytes(&mut buffer).unwrap(); + i16::MAX.to_bytes(&mut buffer, |_| unreachable!()).unwrap(); assert_eq!( buffer, [0; 70] @@ -277,7 +439,7 @@ mod test { // Buffer initially filled with 70 zeros (len > 64) and negative value let mut buffer = vec![0; 70]; - i16::MIN.to_bytes(&mut buffer).unwrap(); + i16::MIN.to_bytes(&mut buffer, |_| unreachable!()).unwrap(); assert_eq!( buffer, [0; 70].into_iter().chain([0, 128]).collect::>() @@ -288,7 +450,7 @@ mod test { fn u32_to_bytes() { // Buffer initially empty let mut buffer = vec![]; - u32::MAX.to_bytes(&mut buffer).unwrap(); + u32::MAX.to_bytes(&mut buffer, |_| unreachable!()).unwrap(); assert_eq!( buffer, vec![u8::MAX; 4] @@ -299,7 +461,7 @@ mod test { // Buffer initially filled with 70 zeros (len > 64) let mut buffer = vec![0; 70]; - u32::MAX.to_bytes(&mut buffer).unwrap(); + u32::MAX.to_bytes(&mut buffer, |_| unreachable!()).unwrap(); assert_eq!( buffer, [0; 72] @@ -313,7 +475,7 @@ mod test { fn i32_to_bytes() { // Buffer initially empty let mut buffer = vec![]; - i32::MAX.to_bytes(&mut buffer).unwrap(); + i32::MAX.to_bytes(&mut buffer, |_| unreachable!()).unwrap(); assert_eq!( buffer, vec![u8::MAX, u8::MAX, u8::MAX, i8::MAX as u8, 0, 0, 0, 0] @@ -321,12 +483,12 @@ mod test { // Buffer initially empty with negative value let mut buffer = vec![]; - i32::MIN.to_bytes(&mut buffer).unwrap(); + i32::MIN.to_bytes(&mut buffer, |_| unreachable!()).unwrap(); assert_eq!(buffer, [0, 0, 0, 128, 255, 255, 255, 255]); // Buffer initially filled with 70 zeros (len > 64) let mut buffer = vec![0; 70]; - i32::MAX.to_bytes(&mut buffer).unwrap(); + i32::MAX.to_bytes(&mut buffer, |_| unreachable!()).unwrap(); assert_eq!( buffer, [0; 72] @@ -337,7 +499,7 @@ mod test { // Buffer initially filled with 70 zeros (len > 64) and negative value let mut buffer = vec![0; 70]; - i32::MIN.to_bytes(&mut buffer).unwrap(); + i32::MIN.to_bytes(&mut buffer, |_| unreachable!()).unwrap(); assert_eq!( buffer, [0; 72] @@ -351,12 +513,12 @@ mod test { fn u64_to_bytes() { // Buffer initially empty let mut buffer = vec![]; - u64::MAX.to_bytes(&mut buffer).unwrap(); + u64::MAX.to_bytes(&mut buffer, |_| unreachable!()).unwrap(); assert_eq!(buffer, u64::MAX.to_ne_bytes().to_vec()); // Buffer initially filled with 70 zeros (len > 64) let mut buffer = vec![0; 70]; - u64::MAX.to_bytes(&mut buffer).unwrap(); + u64::MAX.to_bytes(&mut buffer, |_| unreachable!()).unwrap(); assert_eq!( buffer, [0; 72] @@ -370,17 +532,17 @@ mod test { fn i64_to_bytes() { // Buffer initially empty let mut buffer = vec![]; - i64::MAX.to_bytes(&mut buffer).unwrap(); + i64::MAX.to_bytes(&mut buffer, |_| unreachable!()).unwrap(); assert_eq!(buffer, i64::MAX.to_ne_bytes().to_vec()); // Buffer initially empty with negative value let mut buffer = vec![]; - i64::MIN.to_bytes(&mut buffer).unwrap(); + i64::MIN.to_bytes(&mut buffer, |_| unreachable!()).unwrap(); assert_eq!(buffer, i64::MIN.to_ne_bytes().to_vec()); // Buffer initially filled with 70 zeros (len > 64) let mut buffer = vec![0; 70]; - i64::MAX.to_bytes(&mut buffer).unwrap(); + i64::MAX.to_bytes(&mut buffer, |_| unreachable!()).unwrap(); assert_eq!( buffer, [0; 72] @@ -391,7 +553,7 @@ mod test { // Buffer initially filled with 70 zeros (len > 64) and negative value let mut buffer = vec![0; 70]; - i64::MIN.to_bytes(&mut buffer).unwrap(); + i64::MIN.to_bytes(&mut buffer, |_| unreachable!()).unwrap(); assert_eq!( buffer, [0; 72] @@ -404,7 +566,7 @@ mod test { #[test] fn u128_stack_split() { let mut buffer = vec![0; 56]; - u128::MAX.to_bytes(&mut buffer).unwrap(); + u128::MAX.to_bytes(&mut buffer, |_| unreachable!()).unwrap(); assert_eq!( buffer, [0; 64].into_iter().chain([0xFF; 16]).collect::>() @@ -417,7 +579,7 @@ mod test { let mut buffer = vec![0; 40]; Felt::from_hex("0x00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") .unwrap() - .to_bytes(&mut buffer) + .to_bytes(&mut buffer, |_| unreachable!()) .unwrap(); assert_eq!( buffer, @@ -432,7 +594,7 @@ mod test { let mut buffer = vec![0; 48]; Felt::from_hex("0x00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") .unwrap() - .to_bytes(&mut buffer) + .to_bytes(&mut buffer, |_| unreachable!()) .unwrap(); assert_eq!( buffer, @@ -447,7 +609,7 @@ mod test { let mut buffer = vec![0; 56]; Felt::from_hex("0x00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") .unwrap() - .to_bytes(&mut buffer) + .to_bytes(&mut buffer, |_| unreachable!()) .unwrap(); assert_eq!( buffer, diff --git a/src/arch/x86_64.rs b/src/arch/x86_64.rs index 2eea9ec65..ec82c60bf 100644 --- a/src/arch/x86_64.rs +++ b/src/arch/x86_64.rs @@ -11,78 +11,180 @@ use super::AbiArgument; use crate::{error::Error, starknet::U256, utils::get_integer_layout}; +use cairo_lang_sierra::ids::ConcreteTypeId; use num_traits::ToBytes; use starknet_types_core::felt::Felt; +use std::ffi::c_void; fn align_to(buffer: &mut Vec, align: usize) { buffer.resize(buffer.len().next_multiple_of(align), 0); } impl AbiArgument for bool { - fn to_bytes(&self, buffer: &mut Vec) -> Result<(), Error> { + fn to_bytes( + &self, + buffer: &mut Vec, + _find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), + ) -> Result<(), Error> { buffer.extend_from_slice(&(*self as u64).to_ne_bytes()); Ok(()) } } impl AbiArgument for u8 { - fn to_bytes(&self, buffer: &mut Vec) -> Result<(), Error> { + fn to_bytes( + &self, + buffer: &mut Vec, + _find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), + ) -> Result<(), Error> { buffer.extend_from_slice(&(*self as u64).to_ne_bytes()); Ok(()) } } impl AbiArgument for i8 { - fn to_bytes(&self, buffer: &mut Vec) -> Result<(), Error> { + fn to_bytes( + &self, + buffer: &mut Vec, + _find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), + ) -> Result<(), Error> { buffer.extend_from_slice(&(*self as u64).to_ne_bytes()); Ok(()) } } impl AbiArgument for u16 { - fn to_bytes(&self, buffer: &mut Vec) -> Result<(), Error> { + fn to_bytes( + &self, + buffer: &mut Vec, + _find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), + ) -> Result<(), Error> { buffer.extend_from_slice(&(*self as u64).to_ne_bytes()); Ok(()) } } impl AbiArgument for i16 { - fn to_bytes(&self, buffer: &mut Vec) -> Result<(), Error> { + fn to_bytes( + &self, + buffer: &mut Vec, + _find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), + ) -> Result<(), Error> { buffer.extend_from_slice(&(*self as u64).to_ne_bytes()); Ok(()) } } impl AbiArgument for u32 { - fn to_bytes(&self, buffer: &mut Vec) -> Result<(), Error> { + fn to_bytes( + &self, + buffer: &mut Vec, + _find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), + ) -> Result<(), Error> { buffer.extend_from_slice(&(*self as u64).to_ne_bytes()); Ok(()) } } impl AbiArgument for i32 { - fn to_bytes(&self, buffer: &mut Vec) -> Result<(), Error> { + fn to_bytes( + &self, + buffer: &mut Vec, + _find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), + ) -> Result<(), Error> { buffer.extend_from_slice(&(*self as u64).to_ne_bytes()); Ok(()) } } impl AbiArgument for u64 { - fn to_bytes(&self, buffer: &mut Vec) -> Result<(), Error> { + fn to_bytes( + &self, + buffer: &mut Vec, + _find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), + ) -> Result<(), Error> { buffer.extend_from_slice(&self.to_ne_bytes()); Ok(()) } } impl AbiArgument for i64 { - fn to_bytes(&self, buffer: &mut Vec) -> Result<(), Error> { + fn to_bytes( + &self, + buffer: &mut Vec, + _find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), + ) -> Result<(), Error> { buffer.extend_from_slice(&self.to_ne_bytes()); Ok(()) } } impl AbiArgument for u128 { - fn to_bytes(&self, buffer: &mut Vec) -> Result<(), Error> { + fn to_bytes( + &self, + buffer: &mut Vec, + _find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), + ) -> Result<(), Error> { if buffer.len() >= 40 { align_to(buffer, get_integer_layout(128).align()); } @@ -93,7 +195,17 @@ impl AbiArgument for u128 { } impl AbiArgument for i128 { - fn to_bytes(&self, buffer: &mut Vec) -> Result<(), Error> { + fn to_bytes( + &self, + buffer: &mut Vec, + _find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), + ) -> Result<(), Error> { if buffer.len() >= 40 { align_to(buffer, get_integer_layout(128).align()); } @@ -104,7 +216,17 @@ impl AbiArgument for i128 { } impl AbiArgument for Felt { - fn to_bytes(&self, buffer: &mut Vec) -> Result<(), Error> { + fn to_bytes( + &self, + buffer: &mut Vec, + _find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), + ) -> Result<(), Error> { if buffer.len() >= 40 { align_to(buffer, get_integer_layout(252).align()); } @@ -115,14 +237,34 @@ impl AbiArgument for Felt { } impl AbiArgument for U256 { - fn to_bytes(&self, buffer: &mut Vec) -> Result<(), Error> { - self.lo.to_bytes(buffer)?; - self.hi.to_bytes(buffer) + fn to_bytes( + &self, + buffer: &mut Vec, + find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), + ) -> Result<(), Error> { + self.lo.to_bytes(buffer, find_dict_overrides)?; + self.hi.to_bytes(buffer, find_dict_overrides) } } impl AbiArgument for [u8; 31] { - fn to_bytes(&self, buffer: &mut Vec) -> Result<(), Error> { + fn to_bytes( + &self, + buffer: &mut Vec, + _find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), + ) -> Result<(), Error> { // The `bytes31` type is treated as a 248-bit integer, therefore it follows the same // splitting rules as them. @@ -137,14 +279,34 @@ impl AbiArgument for [u8; 31] { } impl AbiArgument for *const T { - fn to_bytes(&self, buffer: &mut Vec) -> Result<(), Error> { - ::to_bytes(&(*self as u64), buffer) + fn to_bytes( + &self, + buffer: &mut Vec, + find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), + ) -> Result<(), Error> { + ::to_bytes(&(*self as u64), buffer, find_dict_overrides) } } impl AbiArgument for *mut T { - fn to_bytes(&self, buffer: &mut Vec) -> Result<(), Error> { - ::to_bytes(&(*self as u64), buffer) + fn to_bytes( + &self, + buffer: &mut Vec, + find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), + ) -> Result<(), Error> { + ::to_bytes(&(*self as u64), buffer, find_dict_overrides) } } @@ -155,7 +317,7 @@ mod test { #[test] fn u128_stack_split() { let mut buffer = vec![0; 40]; - u128::MAX.to_bytes(&mut buffer).unwrap(); + u128::MAX.to_bytes(&mut buffer, |_| unreachable!()).unwrap(); assert_eq!( buffer, [0; 48].into_iter().chain([0xFF; 16]).collect::>() @@ -168,7 +330,7 @@ mod test { let mut buffer = vec![0; 24]; Felt::from_hex("0x00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") .unwrap() - .to_bytes(&mut buffer) + .to_bytes(&mut buffer, |_| unreachable!()) .unwrap(); assert_eq!( buffer, @@ -183,7 +345,7 @@ mod test { let mut buffer = vec![0; 32]; Felt::from_hex("0x00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") .unwrap() - .to_bytes(&mut buffer) + .to_bytes(&mut buffer, |_| unreachable!()) .unwrap(); assert_eq!( buffer, @@ -198,7 +360,7 @@ mod test { let mut buffer = vec![0; 40]; Felt::from_hex("0x00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") .unwrap() - .to_bytes(&mut buffer) + .to_bytes(&mut buffer, |_| unreachable!()) .unwrap(); assert_eq!( buffer, diff --git a/src/bin/cairo-native-stress/main.rs b/src/bin/cairo-native-stress/main.rs index cf5471b1e..167ef1869 100644 --- a/src/bin/cairo-native-stress/main.rs +++ b/src/bin/cairo-native-stress/main.rs @@ -307,7 +307,12 @@ where } }; - let executor = AotNativeExecutor::new(shared_library, registry, metadata); + let executor = AotNativeExecutor::new( + shared_library, + registry, + metadata, + native_module.metadata().get().cloned().unwrap_or_default(), + ); let executor = Arc::new(executor); self.cache.insert(key, executor.clone()); diff --git a/src/cache/aot.rs b/src/cache/aot.rs index 28aaa6a91..f939b131f 100644 --- a/src/cache/aot.rs +++ b/src/cache/aot.rs @@ -1,7 +1,7 @@ use crate::error::{Error, Result}; use crate::{ - context::NativeContext, executor::AotNativeExecutor, metadata::gas::GasMetadata, - module::NativeModule, utils::SHARED_LIBRARY_EXT, OptLevel, + context::NativeContext, executor::AotNativeExecutor, module::NativeModule, + utils::SHARED_LIBRARY_EXT, OptLevel, }; use cairo_lang_sierra::program::Program; use libloading::Library; @@ -44,7 +44,7 @@ where let NativeModule { module, registry, - metadata, + mut metadata, } = self .context .compile(program, false, Some(Default::default()))?; @@ -64,10 +64,8 @@ where let executor = AotNativeExecutor::new( shared_library, registry, - metadata - .get::() - .cloned() - .ok_or(Error::MissingMetadata)?, + metadata.remove().ok_or(Error::MissingMetadata)?, + metadata.remove().unwrap_or_default(), ); let executor = Arc::new(executor); diff --git a/src/debug.rs b/src/debug.rs index eeefff5c8..b90ed0779 100644 --- a/src/debug.rs +++ b/src/debug.rs @@ -408,6 +408,7 @@ pub const fn libfunc_to_name(value: &CoreConcreteLibfunc) -> &'static str { BoundedIntConcreteLibfunc::Constrain(_) => "bounded_int_constrain", BoundedIntConcreteLibfunc::IsZero(_) => "bounded_int_is_zero", BoundedIntConcreteLibfunc::WrapNonZero(_) => "bounded_int_wrap_non_zero", + BoundedIntConcreteLibfunc::Trim(_) => "bounded_int_trim", }, CoreConcreteLibfunc::IntRange(selector) => match selector { IntRangeConcreteLibfunc::TryNew(_) => "int_range_try_new", diff --git a/src/executor.rs b/src/executor.rs index 26f95d761..8aaf2d9fe 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -63,6 +63,7 @@ extern "C" { /// constructs the function call in place. /// /// To pass the arguments, they are stored in a arena. +#[allow(clippy::too_many_arguments)] fn invoke_dynamic( registry: &ProgramRegistry, function_ptr: *const c_void, @@ -71,6 +72,13 @@ fn invoke_dynamic( args: &[Value], gas: u64, mut syscall_handler: Option, + find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), ) -> Result { tracing::info!("Invoking function with signature: {function_signature:?}."); let arena = Bump::new(); @@ -116,7 +124,9 @@ fn invoke_dynamic( })?; let return_ptr = arena.alloc_layout(layout).cast::<()>(); - return_ptr.as_ptr().to_bytes(&mut invoke_data)?; + return_ptr + .as_ptr() + .to_bytes(&mut invoke_data, |_| unreachable!())?; Some(return_ptr) } else { @@ -164,19 +174,23 @@ fn invoke_dynamic( // Process gas requirements and syscall handler. match type_info { - CoreTypeConcrete::GasBuiltin(_) => gas.to_bytes(&mut invoke_data)?, + CoreTypeConcrete::GasBuiltin(_) => { + gas.to_bytes(&mut invoke_data, |_| unreachable!())? + } CoreTypeConcrete::StarkNet(StarkNetTypeConcrete::System(_)) => { let syscall_handler = syscall_handler .as_mut() .to_native_assert_error("syscall handler should be available")?; (syscall_handler as *mut StarknetSyscallHandlerCallbacks<_>) - .to_bytes(&mut invoke_data)?; + .to_bytes(&mut invoke_data, |_| unreachable!())?; } CoreTypeConcrete::BuiltinCosts(_) => { - builtin_costs.to_bytes(&mut invoke_data)?; + builtin_costs.to_bytes(&mut invoke_data, |_| unreachable!())?; + } + type_info if type_info.is_builtin() => { + 0u64.to_bytes(&mut invoke_data, |_| unreachable!())? } - type_info if type_info.is_builtin() => 0u64.to_bytes(&mut invoke_data)?, type_info => ValueWithInfoWrapper { value: iter .next() @@ -187,7 +201,7 @@ fn invoke_dynamic( arena: &arena, registry, } - .to_bytes(&mut invoke_data)?, + .to_bytes(&mut invoke_data, find_dict_overrides)?, } } diff --git a/src/executor/aot.rs b/src/executor/aot.rs index 84528862a..257bb775a 100644 --- a/src/executor/aot.rs +++ b/src/executor/aot.rs @@ -1,9 +1,7 @@ -use std::io; - use crate::{ error::Error, execution_result::{ContractExecutionResult, ExecutionResult}, - metadata::gas::GasMetadata, + metadata::{felt252_dict::Felt252DictOverrides, gas::GasMetadata}, module::NativeModule, starknet::{DummySyscallHandler, StarknetSyscallHandler}, utils::generate_function_name, @@ -12,7 +10,7 @@ use crate::{ }; use cairo_lang_sierra::{ extensions::core::{CoreLibfunc, CoreType}, - ids::FunctionId, + ids::{ConcreteTypeId, FunctionId}, program::FunctionSignature, program_registry::ProgramRegistry, }; @@ -20,6 +18,7 @@ use educe::Educe; use libc::c_void; use libloading::Library; use starknet_types_core::felt::Felt; +use std::{io, mem::transmute}; use tempfile::NamedTempFile; #[derive(Educe)] @@ -31,6 +30,7 @@ pub struct AotNativeExecutor { registry: ProgramRegistry, gas_metadata: GasMetadata, + dict_overrides: Felt252DictOverrides, } unsafe impl Send for AotNativeExecutor {} @@ -41,11 +41,13 @@ impl AotNativeExecutor { library: Library, registry: ProgramRegistry, gas_metadata: GasMetadata, + dict_overrides: Felt252DictOverrides, ) -> Self { Self { library, registry, gas_metadata, + dict_overrides, } } @@ -69,6 +71,7 @@ impl AotNativeExecutor { library: unsafe { Library::new(&library_path)? }, registry, gas_metadata: metadata.remove().ok_or(Error::MissingMetadata)?, + dict_overrides: metadata.remove().unwrap_or_default(), }) } @@ -102,6 +105,7 @@ impl AotNativeExecutor { args, available_gas, Option::::None, + self.build_find_dict_overrides(), ) } @@ -136,6 +140,7 @@ impl AotNativeExecutor { args, available_gas, Some(syscall_handler), + self.build_find_dict_overrides(), ) } @@ -175,6 +180,7 @@ impl AotNativeExecutor { }], available_gas, Some(syscall_handler), + self.build_find_dict_overrides(), )?) } @@ -204,6 +210,30 @@ impl AotNativeExecutor { fn extract_signature(&self, function_id: &FunctionId) -> Result<&FunctionSignature, Error> { Ok(&self.registry.get_function(function_id)?.signature) } + + fn build_find_dict_overrides( + &self, + ) -> impl '_ + + Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ) { + |type_id| { + ( + self.dict_overrides + .get_dup_fn(type_id) + .and_then(|symbol| self.find_symbol_ptr(symbol)) + .map(|ptr| unsafe { transmute(ptr as *const ()) }), + self.dict_overrides + .get_drop_fn(type_id) + .and_then(|symbol| self.find_symbol_ptr(symbol)) + .map(|ptr| unsafe { transmute(ptr as *const ()) }), + ) + } + } } #[cfg(test)] diff --git a/src/executor/contract.rs b/src/executor/contract.rs index a4bb2351a..a7791263c 100644 --- a/src/executor/contract.rs +++ b/src/executor/contract.rs @@ -119,20 +119,7 @@ pub enum BuiltinType { impl BuiltinType { pub const fn size_in_bytes(&self) -> usize { - match self { - BuiltinType::Bitwise => 8, - BuiltinType::EcOp => 8, - BuiltinType::RangeCheck => 8, - BuiltinType::SegmentArena => 8, - BuiltinType::Poseidon => 8, - BuiltinType::Pedersen => 8, - BuiltinType::RangeCheck96 => 8, - BuiltinType::CircuitAdd => 8, - BuiltinType::CircuitMul => 8, - BuiltinType::Gas => 16, - BuiltinType::System => 8, - BuiltinType::BuiltinCosts => 8, - } + size_of::() } } @@ -279,8 +266,25 @@ impl AotContractExecutor { pub fn load(library_path: &Path) -> Result { let info_str = std::fs::read_to_string(library_path.with_extension("json"))?; let contract_info: NativeContractInfo = serde_json::from_str(&info_str)?; + + let library = Arc::new(unsafe { Library::new(library_path)? }); + unsafe { + let get_version = library + .get:: usize>(b"cairo_native__get_version")?; + + let mut version_buffer = [0u8; 16]; + let version_len = get_version(version_buffer.as_mut_ptr(), version_buffer.len()); + + let target_version = env!("CARGO_PKG_VERSION"); + assert_eq!( + &version_buffer[..version_len], + target_version.as_bytes(), + "aot-compiled contract version mismatch" + ); + }; + Ok(Self { - library: Arc::new(unsafe { Library::new(library_path)? }), + library, path: library_path.to_path_buf(), is_temp_path: false, contract_info, @@ -340,25 +344,29 @@ impl AotContractExecutor { Layout::from_size_align_unchecked(128 + builtins_size, 16) }); - return_ptr.as_ptr().to_bytes(&mut invoke_data)?; + return_ptr + .as_ptr() + .to_bytes(&mut invoke_data, |_| unreachable!())?; let mut syscall_handler = StarknetSyscallHandlerCallbacks::new(&mut syscall_handler); for b in &self.contract_info.entry_points_info[&function_id.id].builtins { match b { BuiltinType::Gas => { - gas.to_bytes(&mut invoke_data)?; + gas.to_bytes(&mut invoke_data, |_| unreachable!())?; } BuiltinType::BuiltinCosts => { // todo: check if valid - builtin_costs.as_ptr().to_bytes(&mut invoke_data)?; + builtin_costs + .as_ptr() + .to_bytes(&mut invoke_data, |_| unreachable!())?; } BuiltinType::System => { (&mut syscall_handler as *mut StarknetSyscallHandlerCallbacks<_>) - .to_bytes(&mut invoke_data)?; + .to_bytes(&mut invoke_data, |_| unreachable!())?; } _ => { - 0u64.to_bytes(&mut invoke_data)?; + 0u64.to_bytes(&mut invoke_data, |_| unreachable!())?; } } } @@ -386,15 +394,15 @@ impl AotContractExecutor { .try_into() .to_native_assert_error("number of arguments should fit into a u32")?; - ptr.to_bytes(&mut invoke_data)?; + ptr.to_bytes(&mut invoke_data, |_| unreachable!())?; if cfg!(target_arch = "aarch64") { - 0u32.to_bytes(&mut invoke_data)?; // start - len.to_bytes(&mut invoke_data)?; // end - len.to_bytes(&mut invoke_data)?; // cap + 0u32.to_bytes(&mut invoke_data, |_| unreachable!())?; // start + len.to_bytes(&mut invoke_data, |_| unreachable!())?; // end + len.to_bytes(&mut invoke_data, |_| unreachable!())?; // cap } else if cfg!(target_arch = "x86_64") { - (0u32 as u64).to_bytes(&mut invoke_data)?; // start - (len as u64).to_bytes(&mut invoke_data)?; // end - (len as u64).to_bytes(&mut invoke_data)?; // cap + (0u32 as u64).to_bytes(&mut invoke_data, |_| unreachable!())?; // start + (len as u64).to_bytes(&mut invoke_data, |_| unreachable!())?; // end + (len as u64).to_bytes(&mut invoke_data, |_| unreachable!())?; // cap } else { unreachable!("unsupported architecture"); } @@ -737,7 +745,6 @@ mod tests { &mut StubSyscallHandler::default(), ) .unwrap(); - assert_eq!(result.return_values, vec![Felt::from(n), Felt::from(n * 2)]); assert_eq!(result.remaining_gas, 18446744073709551615); }); @@ -807,9 +814,8 @@ mod tests { &mut StubSyscallHandler::default(), ) .unwrap(); - assert_eq!(result.return_values, vec![Felt::from(3628800)]); - assert_eq!(result.remaining_gas, 18446744073709538915); + assert_eq!(result.remaining_gas, 18446744073709537615); } #[rstest] diff --git a/src/executor/jit.rs b/src/executor/jit.rs index ad707d994..6697e7f5e 100644 --- a/src/executor/jit.rs +++ b/src/executor/jit.rs @@ -1,7 +1,7 @@ use crate::{ error::Error, execution_result::{ContractExecutionResult, ExecutionResult}, - metadata::gas::GasMetadata, + metadata::{felt252_dict::Felt252DictOverrides, gas::GasMetadata}, module::NativeModule, starknet::{DummySyscallHandler, StarknetSyscallHandler}, utils::{create_engine, generate_function_name}, @@ -10,13 +10,14 @@ use crate::{ }; use cairo_lang_sierra::{ extensions::core::{CoreLibfunc, CoreType}, - ids::FunctionId, + ids::{ConcreteTypeId, FunctionId}, program::FunctionSignature, program_registry::ProgramRegistry, }; use libc::c_void; use melior::{ir::Module, ExecutionEngine}; use starknet_types_core::felt::Felt; +use std::mem::transmute; /// A MLIR JIT execution engine in the context of Cairo Native. pub struct JitNativeExecutor<'m> { @@ -26,6 +27,7 @@ pub struct JitNativeExecutor<'m> { registry: ProgramRegistry, gas_metadata: GasMetadata, + dict_overrides: Felt252DictOverrides, } unsafe impl Send for JitNativeExecutor<'_> {} @@ -48,17 +50,15 @@ impl<'m> JitNativeExecutor<'m> { let NativeModule { module, registry, - metadata, + mut metadata, } = native_module; Ok(Self { engine: create_engine(&module, &metadata, opt_level), module, registry, - gas_metadata: metadata - .get::() - .cloned() - .ok_or(Error::MissingMetadata)?, + gas_metadata: metadata.remove().ok_or(Error::MissingMetadata)?, + dict_overrides: metadata.remove().unwrap_or_default(), }) } @@ -93,6 +93,7 @@ impl<'m> JitNativeExecutor<'m> { args, available_gas, Option::::None, + self.build_find_dict_overrides(), ) } @@ -120,6 +121,7 @@ impl<'m> JitNativeExecutor<'m> { args, available_gas, Some(syscall_handler), + self.build_find_dict_overrides(), ) } @@ -151,6 +153,7 @@ impl<'m> JitNativeExecutor<'m> { }], available_gas, Some(syscall_handler), + self.build_find_dict_overrides(), )?) } @@ -178,4 +181,28 @@ impl<'m> JitNativeExecutor<'m> { .get_function(function_id) .map(|func| &func.signature)?) } + + fn build_find_dict_overrides( + &self, + ) -> impl '_ + + Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ) { + |type_id| { + ( + self.dict_overrides + .get_dup_fn(type_id) + .and_then(|symbol| self.find_symbol_ptr(symbol)) + .map(|ptr| unsafe { transmute(ptr as *const ()) }), + self.dict_overrides + .get_drop_fn(type_id) + .and_then(|symbol| self.find_symbol_ptr(symbol)) + .map(|ptr| unsafe { transmute(ptr as *const ()) }), + ) + } + } } diff --git a/src/libfuncs/array.rs b/src/libfuncs/array.rs index ff788f2fa..dd09436ec 100644 --- a/src/libfuncs/array.rs +++ b/src/libfuncs/array.rs @@ -1075,6 +1075,7 @@ fn build_pop<'ctx, 'this, const CONSUME: bool, const REVERSE: bool>( block.const_int(context, location, elem_layout.pad_to_align().size(), 64)?; match metadata.get::() { Some(dup_overrides_meta) if dup_overrides_meta.is_overriden(elem_ty) => { + // TODO: If extract_len is 1 there is no need for the for loop. block.append_operation(scf::r#for( k0, value_size, @@ -1159,7 +1160,7 @@ fn build_pop<'ctx, 'this, const CONSUME: bool, const REVERSE: bool>( )?; let data_ptr = if REVERSE { - data_ptr + array_ptr } else { let offset = block.append_op_result(arith::extui( extract_len_value, diff --git a/src/libfuncs/bounded_int.rs b/src/libfuncs/bounded_int.rs index 5da4785e0..7a652d215 100644 --- a/src/libfuncs/bounded_int.rs +++ b/src/libfuncs/bounded_int.rs @@ -12,7 +12,7 @@ use cairo_lang_sierra::{ extensions::{ bounded_int::{ BoundedIntConcreteLibfunc, BoundedIntConstrainConcreteLibfunc, - BoundedIntDivRemConcreteLibfunc, + BoundedIntDivRemConcreteLibfunc, BoundedIntTrimConcreteLibfunc, }, core::{CoreLibfunc, CoreType}, lib_func::SignatureOnlyConcreteLibfunc, @@ -57,6 +57,9 @@ pub fn build<'ctx, 'this>( BoundedIntConcreteLibfunc::Constrain(info) => { build_constrain(context, registry, entry, location, helper, metadata, info) } + BoundedIntConcreteLibfunc::Trim(info) => { + build_trim(context, registry, entry, location, helper, metadata, info) + } BoundedIntConcreteLibfunc::IsZero(info) => { build_is_zero(context, registry, entry, location, helper, metadata, info) } @@ -699,6 +702,56 @@ fn build_constrain<'ctx, 'this>( Ok(()) } +/// Makes a downcast of a type `T` to `BoundedInt` +/// or `BoundedInt` where `T` can be any type of signed +/// or unsigned integer. +/// +/// ```cairo +/// extern fn bounded_int_trim>( +/// value: T, +/// ) -> core::internal::OptionRev nopanic; +/// ``` +fn build_trim<'ctx, 'this>( + context: &'ctx Context, + registry: &ProgramRegistry, + entry: &'this Block<'ctx>, + location: Location<'ctx>, + helper: &LibfuncHelper<'ctx, 'this>, + _metadata: &mut MetadataStorage, + info: &BoundedIntTrimConcreteLibfunc, +) -> Result<()> { + let value: Value = entry.arg(0)?; + let trimmed_value = entry.const_int_from_type( + context, + location, + info.trimmed_value.clone(), + value.r#type(), + )?; + let trim_type = registry.get_type(&info.param_signatures()[0].ty)?; + let is_invalid = entry.cmpi(context, CmpiPredicate::Eq, value, trimmed_value, location)?; + let int_range = trim_type.integer_range(registry)?; + + // There is no need to truncate the value type since we're only receiving power-of-two integers + // and constraining their range a single value from either the lower or upper limit. However, + // since we're returning a `BoundedInt` we need to offset its internal representation + // accordingly. + let value = if info.trimmed_value == BigInt::ZERO || int_range.lower < BigInt::ZERO { + let offset = entry.const_int_from_type( + context, + location, + &info.trimmed_value + 1, + value.r#type(), + )?; + entry.append_op_result(arith::subi(value, offset, location))? + } else { + value + }; + + entry.append_operation(helper.cond_br(context, is_invalid, [0, 1], [&[], &[value]], location)); + + Ok(()) +} + /// Generate MLIR operations for the `bounded_int_is_zero` libfunc. fn build_is_zero<'ctx, 'this>( context: &'ctx Context, @@ -761,3 +814,137 @@ fn build_wrap_non_zero<'ctx, 'this>( &info.signature.param_signatures, ) } + +#[cfg(test)] +mod test { + use cairo_vm::Felt252; + + use crate::{ + context::NativeContext, execution_result::ExecutionResult, executor::JitNativeExecutor, + utils::test::load_cairo, OptLevel, Value, + }; + + #[test] + fn test_trim_some_pos_i8() { + let (_, program) = load_cairo!( + use core::internal::{OptionRev, bounded_int::BoundedInt}; + use core::internal::bounded_int; + fn main() -> BoundedInt<-128, 126> { + let num = match bounded_int::trim::(1) { + OptionRev::Some(n) => n, + OptionRev::None => 0, + }; + + num + } + ); + let ctx = NativeContext::new(); + let module = ctx.compile(&program, false, None).unwrap(); + let executor = JitNativeExecutor::from_native_module(module, OptLevel::Default).unwrap(); + let ExecutionResult { + remaining_gas: _, + return_value, + builtin_stats: _, + } = executor + .invoke_dynamic(&program.funcs[0].id, &[], None) + .unwrap(); + + let Value::BoundedInt { value, range: _ } = return_value else { + panic!(); + }; + assert_eq!(value, Felt252::from(1_u8)); + } + + #[test] + fn test_trim_some_neg_i8() { + let (_, program) = load_cairo!( + use core::internal::{OptionRev, bounded_int::BoundedInt}; + use core::internal::bounded_int; + fn main() -> BoundedInt<-127, 127> { + let num = match bounded_int::trim::(1) { + OptionRev::Some(n) => n, + OptionRev::None => 1, + }; + + num + } + ); + let ctx = NativeContext::new(); + let module = ctx.compile(&program, false, None).unwrap(); + let executor = JitNativeExecutor::from_native_module(module, OptLevel::Default).unwrap(); + let ExecutionResult { + remaining_gas: _, + return_value, + builtin_stats: _, + } = executor + .invoke_dynamic(&program.funcs[0].id, &[], None) + .unwrap(); + + let Value::BoundedInt { value, range: _ } = return_value else { + panic!(); + }; + assert_eq!(value, Felt252::from(1_u8)); + } + + #[test] + fn test_trim_some_u32() { + let (_, program) = load_cairo!( + use core::internal::{OptionRev, bounded_int::BoundedInt}; + use core::internal::bounded_int; + fn main() -> BoundedInt<0, 4294967294> { + let num = match bounded_int::trim::(0xfffffffe) { + OptionRev::Some(n) => n, + OptionRev::None => 0, + }; + + num + } + ); + let ctx = NativeContext::new(); + let module = ctx.compile(&program, false, None).unwrap(); + let executor = JitNativeExecutor::from_native_module(module, OptLevel::Default).unwrap(); + let ExecutionResult { + remaining_gas: _, + return_value, + builtin_stats: _, + } = executor + .invoke_dynamic(&program.funcs[0].id, &[], None) + .unwrap(); + + let Value::BoundedInt { value, range: _ } = return_value else { + panic!(); + }; + assert_eq!(value, Felt252::from(0xfffffffe_u32)); + } + + #[test] + fn test_trim_none() { + let (_, program) = load_cairo!( + use core::internal::{OptionRev, bounded_int::BoundedInt}; + use core::internal::bounded_int; + fn main() -> BoundedInt<-32767, 32767> { + let num = match bounded_int::trim::(-0x8000) { + OptionRev::Some(n) => n, + OptionRev::None => 0, + }; + + num + } + ); + let ctx = NativeContext::new(); + let module = ctx.compile(&program, false, None).unwrap(); + let executor = JitNativeExecutor::from_native_module(module, OptLevel::Default).unwrap(); + let ExecutionResult { + remaining_gas: _, + return_value, + builtin_stats: _, + } = executor + .invoke_dynamic(&program.funcs[0].id, &[], None) + .unwrap(); + + let Value::BoundedInt { value, range: _ } = return_value else { + panic!(); + }; + assert_eq!(value, Felt252::from(0)); + } +} diff --git a/src/libfuncs/felt252_dict.rs b/src/libfuncs/felt252_dict.rs index f0303c2a7..09e9967db 100644 --- a/src/libfuncs/felt252_dict.rs +++ b/src/libfuncs/felt252_dict.rs @@ -3,7 +3,9 @@ use super::LibfuncHelper; use crate::{ error::Result, - metadata::{runtime_bindings::RuntimeBindingsMeta, MetadataStorage}, + metadata::{ + felt252_dict::Felt252DictOverrides, runtime_bindings::RuntimeBindingsMeta, MetadataStorage, + }, native_panic, types::TypeBuilder, utils::BlockExt, @@ -17,6 +19,7 @@ use cairo_lang_sierra::{ program_registry::ProgramRegistry, }; use melior::{ + dialect::{llvm, ods}, ir::{Block, Location}, Context, }; @@ -52,20 +55,71 @@ pub fn build_new<'ctx, 'this>( ) -> Result<()> { let segment_arena = super::increment_builtin_counter(context, entry, location, entry.arg(0)?)?; - let runtime_bindings = metadata - .get_mut::() - .expect("Runtime library not available."); - let value_type_id = match registry.get_type(&info.signature.branch_signatures[0].vars[1].ty)? { CoreTypeConcrete::Felt252Dict(info) => &info.ty, _ => native_panic!("entered unreachable code"), }; + let (dup_fn, drop_fn) = { + let mut dict_overrides = metadata + .remove::() + .unwrap_or_default(); + + let dup_fn = match dict_overrides.build_dup_fn( + context, + helper, + registry, + metadata, + value_type_id, + )? { + Some(dup_fn) => Some( + entry.append_op_result( + ods::llvm::mlir_addressof( + context, + llvm::r#type::pointer(context, 0), + dup_fn, + location, + ) + .into(), + )?, + ), + None => None, + }; + let drop_fn = match dict_overrides.build_drop_fn( + context, + helper, + registry, + metadata, + value_type_id, + )? { + Some(drop_fn_symbol) => Some( + entry.append_op_result( + ods::llvm::mlir_addressof( + context, + llvm::r#type::pointer(context, 0), + drop_fn_symbol, + location, + ) + .into(), + )?, + ), + None => None, + }; + + metadata.insert(dict_overrides); + (dup_fn, drop_fn) + }; + + let runtime_bindings = metadata + .get_mut::() + .expect("Runtime library not available."); let dict_ptr = runtime_bindings.dict_new( context, helper, entry, location, + dup_fn, + drop_fn, registry.get_type(value_type_id)?.layout(registry)?, )?; diff --git a/src/libfuncs/gas.rs b/src/libfuncs/gas.rs index db8a924f8..662544f7a 100644 --- a/src/libfuncs/gas.rs +++ b/src/libfuncs/gas.rs @@ -35,7 +35,9 @@ pub fn build<'ctx, 'this>( GasConcreteLibfunc::WithdrawGas(info) => { build_withdraw_gas(context, registry, entry, location, helper, metadata, info) } - GasConcreteLibfunc::RedepositGas(_) => todo!("implement redeposit gas libfunc"), + GasConcreteLibfunc::RedepositGas(info) => { + build_redeposit_gas(context, registry, entry, location, helper, metadata, info) + } GasConcreteLibfunc::GetAvailableGas(info) => { build_get_available_gas(context, registry, entry, location, helper, metadata, info) } @@ -80,7 +82,7 @@ pub fn build_withdraw_gas<'ctx, 'this>( let gas_cost = metadata .get::() - .expect("builtin_withdraw_gas should always have a gas cost") + .expect("withdraw_gas should always have a gas cost") .clone(); let u64_type: melior::ir::Type = IntegerType::new(context, 64).into(); @@ -153,6 +155,83 @@ pub fn build_withdraw_gas<'ctx, 'this>( Ok(()) } +/// Returns the unused gas to the remaining +/// +/// ```cairo +/// extern fn redeposit_gas() implicits(GasBuiltin) nopanic; +/// ``` +pub fn build_redeposit_gas<'ctx, 'this>( + context: &'ctx Context, + _registry: &ProgramRegistry, + entry: &'this Block<'ctx>, + location: Location<'ctx>, + helper: &LibfuncHelper<'ctx, 'this>, + metadata: &mut MetadataStorage, + _info: &SignatureOnlyConcreteLibfunc, +) -> Result<()> { + let current_gas = entry.arg(0)?; + + let gas_cost = metadata + .get::() + .expect("redeposit_gas should always have a gas cost") + .clone(); + + let u64_type: melior::ir::Type = IntegerType::new(context, 64).into(); + + let builtin_ptr = { + let runtime = metadata + .get_mut::() + .ok_or(Error::MissingMetadata)?; + runtime + .get_gas_builtin(context, helper, entry, location)? + .result(0)? + .into() + }; + + let mut total_gas_cost_value = entry.const_int_from_type(context, location, 0, u64_type)?; + + for (cost_count, token_type) in &gas_cost.0 { + if *cost_count == 0 { + continue; + } + + let builtin_costs_index = match token_type { + CostTokenType::Const => 0, + CostTokenType::Pedersen => 1, + CostTokenType::Bitwise => 2, + CostTokenType::EcOp => 3, + CostTokenType::Poseidon => 4, + CostTokenType::AddMod => 5, + CostTokenType::MulMod => 6, + _ => native_panic!("matched an unexpected CostTokenType which is not being used"), + }; + + let cost_count_value = + entry.const_int_from_type(context, location, *cost_count, u64_type)?; + let builtin_costs_index_value = + entry.const_int_from_type(context, location, builtin_costs_index, u64_type)?; + + let builtin_cost_value_ptr = entry.gep( + context, + location, + builtin_ptr, + &[GepIndex::Value(builtin_costs_index_value)], + u64_type, + )?; + let cost_value = entry.load(context, location, builtin_cost_value_ptr, u64_type)?; + let gas_cost_value = entry.muli(cost_count_value, cost_value, location)?; + total_gas_cost_value = entry.addi(total_gas_cost_value, gas_cost_value, location)?; + } + + let resulting_gas = entry.append_op_result( + ods::llvm::intr_uadd_sat(context, current_gas, total_gas_cost_value, location).into(), + )?; + + entry.append_operation(helper.br(0, &[resulting_gas], location)); + + Ok(()) +} + /// Generate MLIR operations for the `withdraw_gas_all` libfunc. pub fn build_builtin_withdraw_gas<'ctx, 'this>( context: &'ctx Context, @@ -289,6 +368,6 @@ mod test { ); let result = run_program(&program, "run_test", &[]); - assert_eq!(result.remaining_gas, Some(18446744073709545195)); + assert_eq!(result.remaining_gas, Some(18446744073709545265)); } } diff --git a/src/metadata.rs b/src/metadata.rs index 6cbb29b60..b4328d69c 100644 --- a/src/metadata.rs +++ b/src/metadata.rs @@ -19,6 +19,7 @@ pub mod debug_utils; pub mod drop_overrides; pub mod dup_overrides; pub mod enum_snapshot_variants; +pub mod felt252_dict; pub mod gas; pub mod realloc_bindings; pub mod runtime_bindings; diff --git a/src/metadata/felt252_dict.rs b/src/metadata/felt252_dict.rs new file mode 100644 index 000000000..ac9109660 --- /dev/null +++ b/src/metadata/felt252_dict.rs @@ -0,0 +1,163 @@ +use super::{drop_overrides::DropOverridesMeta, dup_overrides::DupOverridesMeta, MetadataStorage}; +use crate::{ + error::{Error, Result}, + utils::{BlockExt, ProgramRegistryExt}, +}; +use cairo_lang_sierra::{ + extensions::core::{CoreLibfunc, CoreType}, + ids::ConcreteTypeId, + program_registry::ProgramRegistry, +}; +use melior::{ + dialect::llvm, + ir::{ + attribute::{FlatSymbolRefAttribute, StringAttribute, TypeAttribute}, + Attribute, Block, Identifier, Location, Module, Region, + }, + Context, +}; +use std::collections::{hash_map::Entry, HashMap}; + +#[derive(Clone, Debug, Default)] +pub struct Felt252DictOverrides { + dup_overrides: HashMap, + drop_overrides: HashMap, +} + +impl Felt252DictOverrides { + pub fn get_dup_fn(&self, type_id: &ConcreteTypeId) -> Option<&str> { + self.dup_overrides.get(type_id).map(String::as_str) + } + + pub fn get_drop_fn(&self, type_id: &ConcreteTypeId) -> Option<&str> { + self.drop_overrides.get(type_id).map(String::as_str) + } + + pub fn build_dup_fn<'ctx>( + &mut self, + context: &'ctx Context, + module: &Module<'ctx>, + registry: &ProgramRegistry, + metadata: &mut MetadataStorage, + type_id: &ConcreteTypeId, + ) -> Result>> { + let location = Location::unknown(context); + + let inner_ty = registry.build_type(context, module, metadata, type_id)?; + Ok(match metadata.get::() { + Some(dup_overrides_meta) if dup_overrides_meta.is_overriden(type_id) => { + let dup_fn_symbol = format!("dup${}$item", type_id.id); + let flat_symbol_ref = FlatSymbolRefAttribute::new(context, &dup_fn_symbol); + + if let Entry::Vacant(entry) = self.dup_overrides.entry(type_id.clone()) { + let dup_fn_symbol = entry.insert(dup_fn_symbol); + + let region = Region::new(); + let entry = region.append_block(Block::new(&[ + (llvm::r#type::pointer(context, 0), location), + (llvm::r#type::pointer(context, 0), location), + ])); + + let source_ptr = entry.arg(0)?; + let target_ptr = entry.arg(1)?; + + let value = entry.load(context, location, source_ptr, inner_ty)?; + let values = dup_overrides_meta + .invoke_override(context, &entry, location, type_id, value)?; + entry.store(context, location, source_ptr, values.0)?; + entry.store(context, location, target_ptr, values.1)?; + + entry.append_operation(llvm::r#return(None, location)); + + module.body().append_operation(llvm::func( + context, + StringAttribute::new(context, dup_fn_symbol), + TypeAttribute::new(llvm::r#type::function( + llvm::r#type::void(context), + &[ + llvm::r#type::pointer(context, 0), + llvm::r#type::pointer(context, 0), + ], + false, + )), + region, + &[ + ( + Identifier::new(context, "sym_visibility"), + StringAttribute::new(context, "public").into(), + ), + ( + Identifier::new(context, "linkage"), + Attribute::parse(context, "#llvm.linkage") + .ok_or(Error::ParseAttributeError)?, + ), + ], + location, + )); + } + + Some(flat_symbol_ref) + } + _ => None, + }) + } + + pub fn build_drop_fn<'ctx>( + &mut self, + context: &'ctx Context, + module: &Module<'ctx>, + registry: &ProgramRegistry, + metadata: &mut MetadataStorage, + type_id: &ConcreteTypeId, + ) -> Result>> { + let location = Location::unknown(context); + + let inner_ty = registry.build_type(context, module, metadata, type_id)?; + Ok(match metadata.get::() { + Some(drop_overrides_meta) if drop_overrides_meta.is_overriden(type_id) => { + let drop_fn_symbol = format!("drop${}$item", type_id.id); + let flat_symbol_ref = FlatSymbolRefAttribute::new(context, &drop_fn_symbol); + + if let Entry::Vacant(entry) = self.drop_overrides.entry(type_id.clone()) { + let drop_fn_symbol = entry.insert(drop_fn_symbol); + + let region = Region::new(); + let entry = region + .append_block(Block::new(&[(llvm::r#type::pointer(context, 0), location)])); + + let value = entry.load(context, location, entry.arg(0)?, inner_ty)?; + drop_overrides_meta + .invoke_override(context, &entry, location, type_id, value)?; + + entry.append_operation(llvm::r#return(None, location)); + + module.body().append_operation(llvm::func( + context, + StringAttribute::new(context, drop_fn_symbol), + TypeAttribute::new(llvm::r#type::function( + llvm::r#type::void(context), + &[llvm::r#type::pointer(context, 0)], + false, + )), + region, + &[ + ( + Identifier::new(context, "sym_visibility"), + StringAttribute::new(context, "public").into(), + ), + ( + Identifier::new(context, "llvm.linkage"), + Attribute::parse(context, "#llvm.linkage") + .ok_or(Error::ParseAttributeError)?, + ), + ], + location, + )); + } + + Some(flat_symbol_ref) + } + _ => None, + }) + } +} diff --git a/src/metadata/runtime_bindings.rs b/src/metadata/runtime_bindings.rs index 0df01a628..f7e2f2b29 100644 --- a/src/metadata/runtime_bindings.rs +++ b/src/metadata/runtime_bindings.rs @@ -539,6 +539,8 @@ impl RuntimeBindingsMeta { module: &Module, block: &'a Block<'c>, location: Location<'c>, + dup_fn: Option>, + drop_fn: Option>, layout: Layout, ) -> Result> where @@ -553,7 +555,12 @@ impl RuntimeBindingsMeta { TypeAttribute::new( FunctionType::new( context, - &[i64_ty, i64_ty], + &[ + i64_ty, + i64_ty, + llvm::r#type::pointer(context, 0), + llvm::r#type::pointer(context, 0), + ], &[llvm::r#type::pointer(context, 0)], ) .into(), @@ -577,10 +584,23 @@ impl RuntimeBindingsMeta { let size = block.const_int_from_type(context, location, layout.size(), i64_ty)?; let align = block.const_int_from_type(context, location, layout.align(), i64_ty)?; + let dup_fn = match dup_fn { + Some(x) => x, + None => { + block.append_op_result(llvm::zero(llvm::r#type::pointer(context, 0), location))? + } + }; + let drop_fn = match drop_fn { + Some(x) => x, + None => { + block.append_op_result(llvm::zero(llvm::r#type::pointer(context, 0), location))? + } + }; + block.append_op_result(func::call( context, FlatSymbolRefAttribute::new(context, "cairo_native__dict_new"), - &[size, align], + &[size, align, dup_fn, drop_fn], &[llvm::r#type::pointer(context, 0)], location, )) @@ -596,7 +616,6 @@ impl RuntimeBindingsMeta { module: &Module, block: &'a Block<'c>, ptr: Value<'c, 'a>, - drop_fn: Option>, location: Location<'c>, ) -> Result> where @@ -607,15 +626,7 @@ impl RuntimeBindingsMeta { context, StringAttribute::new(context, "cairo_native__dict_drop"), TypeAttribute::new( - FunctionType::new( - context, - &[ - llvm::r#type::pointer(context, 0), - llvm::r#type::pointer(context, 0), - ], - &[], - ) - .into(), + FunctionType::new(context, &[llvm::r#type::pointer(context, 0)], &[]).into(), ), Region::new(), &[ @@ -633,17 +644,10 @@ impl RuntimeBindingsMeta { )); } - let drop_fn = match drop_fn { - Some(x) => x, - None => { - block.append_op_result(llvm::zero(llvm::r#type::pointer(context, 0), location))? - } - }; - Ok(block.append_operation(func::call( context, FlatSymbolRefAttribute::new(context, "cairo_native__dict_drop"), - &[ptr, drop_fn], + &[ptr], &[], location, ))) @@ -659,7 +663,6 @@ impl RuntimeBindingsMeta { module: &Module, block: &'a Block<'c>, ptr: Value<'c, 'a>, - dup_fn: Option>, location: Location<'c>, ) -> Result> where @@ -672,10 +675,7 @@ impl RuntimeBindingsMeta { TypeAttribute::new( FunctionType::new( context, - &[ - llvm::r#type::pointer(context, 0), - llvm::r#type::pointer(context, 0), - ], + &[llvm::r#type::pointer(context, 0)], &[llvm::r#type::pointer(context, 0)], ) .into(), @@ -696,17 +696,10 @@ impl RuntimeBindingsMeta { )); } - let dup_fn = match dup_fn { - Some(x) => x, - None => { - block.append_op_result(llvm::zero(llvm::r#type::pointer(context, 0), location))? - } - }; - block.append_op_result(func::call( context, FlatSymbolRefAttribute::new(context, "cairo_native__dict_dup"), - &[ptr, dup_fn], + &[ptr], &[llvm::r#type::pointer(context, 0)], location, )) diff --git a/src/types.rs b/src/types.rs index cc2e6e847..8c0f0a0ca 100644 --- a/src/types.rs +++ b/src/types.rs @@ -122,6 +122,7 @@ pub trait TypeBuilder { &self, registry: &ProgramRegistry, ) -> Result; + /// Return whether the type is a `felt252`, either directly or indirectly (ex. through /// `NonZero>`). fn is_felt252( diff --git a/src/types/felt252_dict.rs b/src/types/felt252_dict.rs index 3164bcbf8..dfe672bb4 100644 --- a/src/types/felt252_dict.rs +++ b/src/types/felt252_dict.rs @@ -11,10 +11,9 @@ use crate::{ error::{Error, Result}, metadata::{ drop_overrides::DropOverridesMeta, dup_overrides::DupOverridesMeta, - realloc_bindings::ReallocBindingsMeta, runtime_bindings::RuntimeBindingsMeta, - MetadataStorage, + felt252_dict::Felt252DictOverrides, realloc_bindings::ReallocBindingsMeta, + runtime_bindings::RuntimeBindingsMeta, MetadataStorage, }, - types::TypeBuilder, utils::{BlockExt, ProgramRegistryExt}, }; use cairo_lang_sierra::{ @@ -25,11 +24,8 @@ use cairo_lang_sierra::{ program_registry::ProgramRegistry, }; use melior::{ - dialect::{func, llvm, ods}, - ir::{ - attribute::{FlatSymbolRefAttribute, StringAttribute, TypeAttribute}, - Attribute, Block, Identifier, Location, Module, Region, Type, - }, + dialect::{func, llvm}, + ir::{Block, Location, Module, Region, Type}, Context, }; @@ -88,84 +84,24 @@ fn build_dup<'ctx>( } let value_ty = registry.build_type(context, module, metadata, info.self_ty())?; - let inner_ty = registry.get_type(&info.ty)?; - let inner_ty = inner_ty.build(context, module, registry, metadata, &info.ty)?; - - let dup_fn = match metadata.get::() { - Some(dup_overrides_meta) if dup_overrides_meta.is_overriden(&info.ty) => { - let region = Region::new(); - let entry = region.append_block(Block::new(&[ - (llvm::r#type::pointer(context, 0), location), - (llvm::r#type::pointer(context, 0), location), - ])); - - let source_ptr = entry.arg(0)?; - let target_ptr = entry.arg(1)?; - - let value = entry.load(context, location, source_ptr, inner_ty)?; - let values = - dup_overrides_meta.invoke_override(context, &entry, location, &info.ty, value)?; - entry.store(context, location, source_ptr, values.0)?; - entry.store(context, location, target_ptr, values.1)?; - - entry.append_operation(llvm::r#return(None, location)); - - let dup_fn_symbol = format!("dup${}$item", info.self_ty().id); - module.body().append_operation(llvm::func( - context, - StringAttribute::new(context, &dup_fn_symbol), - TypeAttribute::new(llvm::r#type::function( - llvm::r#type::void(context), - &[ - llvm::r#type::pointer(context, 0), - llvm::r#type::pointer(context, 0), - ], - false, - )), - region, - &[ - ( - Identifier::new(context, "sym_visibility"), - StringAttribute::new(context, "public").into(), - ), - ( - Identifier::new(context, "linkage"), - Attribute::parse(context, "#llvm.linkage") - .ok_or(Error::ParseAttributeError)?, - ), - ], - location, - )); - Some(dup_fn_symbol) - } - _ => None, - }; + { + let mut dict_overrides = metadata + .remove::() + .unwrap_or_default(); + dict_overrides.build_dup_fn(context, module, registry, metadata, &info.ty)?; + metadata.insert(dict_overrides); + } let region = Region::new(); let entry = region.append_block(Block::new(&[(value_ty, location)])); - let dup_fn = match dup_fn { - Some(dup_fn) => Some( - entry.append_op_result( - ods::llvm::mlir_addressof( - context, - llvm::r#type::pointer(context, 0), - FlatSymbolRefAttribute::new(context, &dup_fn), - location, - ) - .into(), - )?, - ), - None => None, - }; - // The following unwrap is unreachable because the registration logic will always insert it. let value0 = entry.arg(0)?; let value1 = metadata .get_mut::() .ok_or(Error::MissingMetadata)? - .dict_dup(context, module, &entry, value0, dup_fn, location)?; + .dict_dup(context, module, &entry, value0, location)?; entry.append_operation(func::r#return(&[value0, value1], location)); Ok(region) @@ -184,71 +120,23 @@ fn build_drop<'ctx>( } let value_ty = registry.build_type(context, module, metadata, info.self_ty())?; - let inner_ty = registry.build_type(context, module, metadata, &info.ty)?; - - let drop_fn_symbol = match metadata.get::() { - Some(drop_overrides_meta) if drop_overrides_meta.is_overriden(&info.ty) => { - let region = Region::new(); - let entry = - region.append_block(Block::new(&[(llvm::r#type::pointer(context, 0), location)])); - - let value = entry.load(context, location, entry.arg(0)?, inner_ty)?; - drop_overrides_meta.invoke_override(context, &entry, location, &info.ty, value)?; - - entry.append_operation(llvm::r#return(None, location)); - - let drop_fn_symbol = format!("drop${}$item", info.self_ty().id); - module.body().append_operation(llvm::func( - context, - StringAttribute::new(context, &drop_fn_symbol), - TypeAttribute::new(llvm::r#type::function( - llvm::r#type::void(context), - &[llvm::r#type::pointer(context, 0)], - false, - )), - region, - &[ - ( - Identifier::new(context, "sym_visibility"), - StringAttribute::new(context, "public").into(), - ), - ( - Identifier::new(context, "llvm.linkage"), - Attribute::parse(context, "#llvm.linkage") - .ok_or(Error::ParseAttributeError)?, - ), - ], - location, - )); - Some(drop_fn_symbol) - } - _ => None, - }; + { + let mut dict_overrides = metadata + .remove::() + .unwrap_or_default(); + dict_overrides.build_drop_fn(context, module, registry, metadata, &info.ty)?; + metadata.insert(dict_overrides); + } let region = Region::new(); let entry = region.append_block(Block::new(&[(value_ty, location)])); - let drop_fn = match drop_fn_symbol { - Some(drop_fn_symbol) => Some( - entry.append_op_result( - ods::llvm::mlir_addressof( - context, - llvm::r#type::pointer(context, 0), - FlatSymbolRefAttribute::new(context, &drop_fn_symbol), - location, - ) - .into(), - )?, - ), - None => None, - }; - // The following unwrap is unreachable because the registration logic will always insert it. let runtime_bindings_meta = metadata .get_mut::() .ok_or(Error::MissingMetadata)?; - runtime_bindings_meta.dict_drop(context, module, &entry, entry.arg(0)?, drop_fn, location)?; + runtime_bindings_meta.dict_drop(context, module, &entry, entry.arg(0)?, location)?; entry.append_operation(func::r#return(&[], location)); Ok(region) diff --git a/src/values.rs b/src/values.rs index 042443173..b9b5b846d 100644 --- a/src/values.rs +++ b/src/values.rs @@ -25,15 +25,17 @@ use educe::Educe; use num_bigint::{BigInt, BigUint, Sign}; use num_traits::{Euclid, One}; use starknet_types_core::felt::Felt; -use std::{alloc::Layout, collections::HashMap, ptr::NonNull, slice}; -#[cfg(feature = "with-runtime")] -use { - cairo_native_runtime::FeltDict, - std::{ - alloc::{alloc, dealloc}, - ptr::null_mut, - }, +use std::{ + alloc::Layout, + collections::HashMap, + ffi::c_void, + mem::forget, + ptr::{null_mut, NonNull}, + rc::Rc, + slice, }; +#[cfg(feature = "with-runtime")] +use {cairo_native_runtime::FeltDict, std::alloc::alloc}; /// A Value is a value that can be passed to either the JIT engine or a compiled program as an argument or received as a result. /// @@ -164,6 +166,13 @@ impl Value { arena: &Bump, registry: &ProgramRegistry, type_id: &ConcreteTypeId, + find_dict_overrides: impl Copy + + Fn( + &ConcreteTypeId, + ) -> ( + Option, + Option, + ), ) -> Result, Error> { let ty = registry.get_type(type_id)?; @@ -240,7 +249,8 @@ impl Value { // Write the data. for (idx, elem) in data.iter().enumerate() { - let elem = elem.to_ptr(arena, registry, &info.ty)?; + let elem = + elem.to_ptr(arena, registry, &info.ty, find_dict_overrides)?; std::ptr::copy_nonoverlapping( elem.cast::().as_ptr(), @@ -299,7 +309,12 @@ impl Value { }; layout = Some(new_layout); - let member_ptr = member.to_ptr(arena, registry, member_type_id)?; + let member_ptr = member.to_ptr( + arena, + registry, + member_type_id, + find_dict_overrides, + )?; data.push(( member_layout, offset, @@ -345,7 +360,8 @@ impl Value { native_assert!(*tag < info.variants.len(), "Variant index out of range."); let payload_type_id = &info.variants[*tag]; - let payload = value.to_ptr(arena, registry, payload_type_id)?; + let payload = + value.to_ptr(arena, registry, payload_type_id, find_dict_overrides)?; let (layout, tag_layout, variant_layouts) = crate::types::r#enum::get_layout_for_variants( @@ -385,7 +401,11 @@ impl Value { let elem_ty = registry.get_type(&info.ty)?; let elem_layout = elem_ty.layout(registry)?.pad_to_align(); - let mut value_map = Box::new(FeltDict { + // We need `find_dict_overrides` to obtain the function pointers of the dup and drop + // implementations (if any) for the value type. This is required to be able to clone and drop + // the dictionary automatically when their reference count drops to zero. + let (dup_fn, drop_fn) = find_dict_overrides(&info.ty); + let mut value_map = FeltDict { mappings: HashMap::with_capacity(map.len()), layout: elem_layout, @@ -399,14 +419,18 @@ impl Value { .cast() }, + dup_fn, + drop_fn, + count: 0, - }); + }; // next key must be called before next_value for (key, value) in map.iter() { let key = key.to_bytes_le(); - let value = value.to_ptr(arena, registry, &info.ty)?; + let value = + value.to_ptr(arena, registry, &info.ty, find_dict_overrides)?; let index = value_map.mappings.len(); value_map.mappings.insert(key, index); @@ -421,7 +445,7 @@ impl Value { ); } - NonNull::new_unchecked(Box::into_raw(value_map)).cast() + NonNull::new_unchecked(Rc::into_raw(Rc::new(value_map)) as *mut ()).cast() } else { Err(Error::UnexpectedValue(format!( "expected value of type {:?} but got a felt dict", @@ -533,11 +557,11 @@ impl Value { let inner = registry.get_type(&info.ty)?; let inner_layout = inner.layout(registry)?; - let x_ptr = x.to_ptr(arena, registry, &info.ty)?; + let x_ptr = x.to_ptr(arena, registry, &info.ty, find_dict_overrides)?; let (struct_layout, y_offset) = inner_layout.extend(inner_layout)?; - let y_ptr = y.to_ptr(arena, registry, &info.ty)?; + let y_ptr = y.to_ptr(arena, registry, &info.ty, find_dict_overrides)?; let ptr = arena.alloc_layout(struct_layout.pad_to_align()).as_ptr(); @@ -806,11 +830,7 @@ impl Value { #[cfg(feature = "with-runtime")] CoreTypeConcrete::Felt252Dict(info) | CoreTypeConcrete::SquashedFelt252Dict(info) => { - let dict = &ptr - .cast::>() - .as_ref() - .cast::() - .as_ref(); + let dict = Rc::from_raw(ptr.cast::<*const FeltDict>().read()); let mut output_map = HashMap::with_capacity(dict.mappings.len()); for (&key, &index) in dict.mappings.iter() { @@ -818,6 +838,8 @@ impl Value { key[31] &= 0x0F; // Filter out first 4 bits (they're outside an i252). let key = Felt::from_bytes_le(&key); + // The dictionary items are not being dropped here. They'll be dropped along + // with the dictionary (if requested using `should_drop`). output_map.insert( key, Self::from_ptr( @@ -831,28 +853,15 @@ impl Value { .cast(), &info.ty, registry, - should_drop, + false, )?, ); } if should_drop { - let dict = Box::from_raw( - ptr.cast::>() - .as_ref() - .cast::() - .as_ptr(), - ); - - dealloc( - dict.elements.cast(), - Layout::from_size_align_unchecked( - dict.layout.pad_to_align().size() * dict.mappings.capacity(), - dict.layout.align(), - ), - ); - drop(dict); + } else { + forget(dict); } Self::Felt252Dict { @@ -1142,7 +1151,12 @@ mod test { assert_eq!( unsafe { *Value::Felt252(Felt::from(42)) - .to_ptr(&Bump::new(), ®istry, &program.type_declarations[0].id) + .to_ptr( + &Bump::new(), + ®istry, + &program.type_declarations[0].id, + |_| todo!(), + ) .unwrap() .cast::<[u32; 8]>() .as_ptr() @@ -1153,7 +1167,12 @@ mod test { assert_eq!( unsafe { *Value::Felt252(Felt::MAX) - .to_ptr(&Bump::new(), ®istry, &program.type_declarations[0].id) + .to_ptr( + &Bump::new(), + ®istry, + &program.type_declarations[0].id, + |_| todo!(), + ) .unwrap() .cast::<[u32; 8]>() .as_ptr() @@ -1165,7 +1184,12 @@ mod test { assert_eq!( unsafe { *Value::Felt252(Felt::MAX + Felt::ONE) - .to_ptr(&Bump::new(), ®istry, &program.type_declarations[0].id) + .to_ptr( + &Bump::new(), + ®istry, + &program.type_declarations[0].id, + |_| todo!(), + ) .unwrap() .cast::<[u32; 8]>() .as_ptr() @@ -1183,7 +1207,12 @@ mod test { assert_eq!( unsafe { *Value::Uint8(9) - .to_ptr(&Bump::new(), ®istry, &program.type_declarations[0].id) + .to_ptr( + &Bump::new(), + ®istry, + &program.type_declarations[0].id, + |_| todo!(), + ) .unwrap() .cast::() .as_ptr() @@ -1201,7 +1230,12 @@ mod test { assert_eq!( unsafe { *Value::Uint16(17) - .to_ptr(&Bump::new(), ®istry, &program.type_declarations[0].id) + .to_ptr( + &Bump::new(), + ®istry, + &program.type_declarations[0].id, + |_| todo!(), + ) .unwrap() .cast::() .as_ptr() @@ -1219,7 +1253,12 @@ mod test { assert_eq!( unsafe { *Value::Uint32(33) - .to_ptr(&Bump::new(), ®istry, &program.type_declarations[0].id) + .to_ptr( + &Bump::new(), + ®istry, + &program.type_declarations[0].id, + |_| todo!(), + ) .unwrap() .cast::() .as_ptr() @@ -1237,7 +1276,12 @@ mod test { assert_eq!( unsafe { *Value::Uint64(65) - .to_ptr(&Bump::new(), ®istry, &program.type_declarations[0].id) + .to_ptr( + &Bump::new(), + ®istry, + &program.type_declarations[0].id, + |_| todo!(), + ) .unwrap() .cast::() .as_ptr() @@ -1255,7 +1299,12 @@ mod test { assert_eq!( unsafe { *Value::Uint128(129) - .to_ptr(&Bump::new(), ®istry, &program.type_declarations[0].id) + .to_ptr( + &Bump::new(), + ®istry, + &program.type_declarations[0].id, + |_| todo!(), + ) .unwrap() .cast::() .as_ptr() @@ -1273,7 +1322,12 @@ mod test { assert_eq!( unsafe { *Value::Sint8(-9) - .to_ptr(&Bump::new(), ®istry, &program.type_declarations[0].id) + .to_ptr( + &Bump::new(), + ®istry, + &program.type_declarations[0].id, + |_| todo!(), + ) .unwrap() .cast::() .as_ptr() @@ -1291,7 +1345,12 @@ mod test { assert_eq!( unsafe { *Value::Sint16(-17) - .to_ptr(&Bump::new(), ®istry, &program.type_declarations[0].id) + .to_ptr( + &Bump::new(), + ®istry, + &program.type_declarations[0].id, + |_| todo!(), + ) .unwrap() .cast::() .as_ptr() @@ -1309,7 +1368,12 @@ mod test { assert_eq!( unsafe { *Value::Sint32(-33) - .to_ptr(&Bump::new(), ®istry, &program.type_declarations[0].id) + .to_ptr( + &Bump::new(), + ®istry, + &program.type_declarations[0].id, + |_| todo!(), + ) .unwrap() .cast::() .as_ptr() @@ -1327,7 +1391,12 @@ mod test { assert_eq!( unsafe { *Value::Sint64(-65) - .to_ptr(&Bump::new(), ®istry, &program.type_declarations[0].id) + .to_ptr( + &Bump::new(), + ®istry, + &program.type_declarations[0].id, + |_| todo!(), + ) .unwrap() .cast::() .as_ptr() @@ -1345,7 +1414,12 @@ mod test { assert_eq!( unsafe { *Value::Sint128(-129) - .to_ptr(&Bump::new(), ®istry, &program.type_declarations[0].id) + .to_ptr( + &Bump::new(), + ®istry, + &program.type_declarations[0].id, + |_| todo!(), + ) .unwrap() .cast::() .as_ptr() @@ -1365,7 +1439,12 @@ mod test { assert_eq!( unsafe { *Value::EcPoint(Felt::from(1234), Felt::from(4321)) - .to_ptr(&Bump::new(), ®istry, &program.type_declarations[0].id) + .to_ptr( + &Bump::new(), + ®istry, + &program.type_declarations[0].id, + |_| todo!(), + ) .unwrap() .cast::<[[u32; 8]; 2]>() .as_ptr() @@ -1390,7 +1469,12 @@ mod test { Felt::from(3333), Felt::from(4444), ) - .to_ptr(&Bump::new(), ®istry, &program.type_declarations[0].id) + .to_ptr( + &Bump::new(), + ®istry, + &program.type_declarations[0].id, + |_| todo!(), + ) .unwrap() .cast::<[[u32; 8]; 4]>() .as_ptr() @@ -1423,7 +1507,12 @@ mod test { value: Box::new(Value::Uint8(10)), debug_name: None, } - .to_ptr(&Bump::new(), ®istry, &program.type_declarations[1].id); + .to_ptr( + &Bump::new(), + ®istry, + &program.type_declarations[1].id, + |_| todo!(), + ); // Assertion to verify that the value returned by to_jit is not NULL assert!(result.is_ok()); @@ -1452,7 +1541,12 @@ mod test { upper: BigInt::from(510), }, } - .to_ptr(&Bump::new(), ®istry, &program.type_declarations[1].id) + .to_ptr( + &Bump::new(), + ®istry, + &program.type_declarations[1].id, + |_| todo!(), + ) .unwrap() .cast::<[u32; 8]>() .as_ptr() @@ -1482,7 +1576,12 @@ mod test { upper: BigInt::from(10), }, } - .to_ptr(&Bump::new(), ®istry, &program.type_declarations[1].id); + .to_ptr( + &Bump::new(), + ®istry, + &program.type_declarations[1].id, + |_| todo!(), + ); assert!(matches!( result, @@ -1511,7 +1610,12 @@ mod test { upper: BigInt::from(510), }, } - .to_ptr(&Bump::new(), ®istry, &program.type_declarations[1].id); + .to_ptr( + &Bump::new(), + ®istry, + &program.type_declarations[1].id, + |_| todo!(), + ); assert!(matches!( result, @@ -1540,7 +1644,12 @@ mod test { upper: BigInt::from(510), }, } - .to_ptr(&Bump::new(), ®istry, &program.type_declarations[1].id); + .to_ptr( + &Bump::new(), + ®istry, + &program.type_declarations[1].id, + |_| todo!(), + ); assert!(matches!( result, @@ -1569,7 +1678,12 @@ mod test { upper: BigInt::from(10), }, } - .to_ptr(&Bump::new(), ®istry, &program.type_declarations[1].id); + .to_ptr( + &Bump::new(), + ®istry, + &program.type_declarations[1].id, + |_| todo!(), + ); assert!(matches!( result, @@ -1596,7 +1710,12 @@ mod test { value: Box::new(Value::Uint8(10)), debug_name: None, } - .to_ptr(&Bump::new(), ®istry, &program.type_declarations[1].id) + .to_ptr( + &Bump::new(), + ®istry, + &program.type_declarations[1].id, + |_| todo!(), + ) .unwrap_err(); let error = result.to_string().clone(); @@ -1621,7 +1740,12 @@ mod test { value: Box::new(Value::Uint8(10)), debug_name: None, } - .to_ptr(&Bump::new(), ®istry, &program.type_declarations[1].id) + .to_ptr( + &Bump::new(), + ®istry, + &program.type_declarations[1].id, + |_| todo!(), + ) .unwrap_err(); let error = result.to_string().clone(); @@ -1656,7 +1780,12 @@ mod test { }), debug_name: None, } - .to_ptr(&Bump::new(), ®istry, &program.type_declarations[0].id) + .to_ptr( + &Bump::new(), + ®istry, + &program.type_declarations[0].id, + |_| todo!(), + ) .unwrap_err(); // Unwrapping the error // Matching the error result to verify the error type and message. @@ -1694,7 +1823,12 @@ mod test { fields: vec![Value::from(2u32)], debug_name: None, } - .to_ptr(&Bump::new(), ®istry, &program.type_declarations[0].id) + .to_ptr( + &Bump::new(), + ®istry, + &program.type_declarations[0].id, + |_| todo!(), + ) .unwrap_err(); // Unwrapping the error // Matching the error result to verify the error type and message. diff --git a/tests/alexandria/Scarb.lock b/tests/alexandria/Scarb.lock index 5619e7201..732296e12 100644 --- a/tests/alexandria/Scarb.lock +++ b/tests/alexandria/Scarb.lock @@ -13,7 +13,7 @@ dependencies = [ [[package]] name = "alexandria_bytes" version = "0.1.0" -source = "git+https://github.com/ishay-starkware/alexandria?rev=e4eb87718e3a870a792ca83361860be800c90acd#e4eb87718e3a870a792ca83361860be800c90acd" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=162bed1c636d31ccaaa90ed3eb32c9eb1d5e3bd3#162bed1c636d31ccaaa90ed3eb32c9eb1d5e3bd3" dependencies = [ "alexandria_data_structures", "alexandria_math", @@ -22,7 +22,7 @@ dependencies = [ [[package]] name = "alexandria_data_structures" version = "0.2.0" -source = "git+https://github.com/ishay-starkware/alexandria?rev=e4eb87718e3a870a792ca83361860be800c90acd#e4eb87718e3a870a792ca83361860be800c90acd" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=162bed1c636d31ccaaa90ed3eb32c9eb1d5e3bd3#162bed1c636d31ccaaa90ed3eb32c9eb1d5e3bd3" dependencies = [ "alexandria_encoding", ] @@ -30,7 +30,7 @@ dependencies = [ [[package]] name = "alexandria_encoding" version = "0.1.0" -source = "git+https://github.com/ishay-starkware/alexandria?rev=e4eb87718e3a870a792ca83361860be800c90acd#e4eb87718e3a870a792ca83361860be800c90acd" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=162bed1c636d31ccaaa90ed3eb32c9eb1d5e3bd3#162bed1c636d31ccaaa90ed3eb32c9eb1d5e3bd3" dependencies = [ "alexandria_bytes", "alexandria_data_structures", @@ -41,12 +41,12 @@ dependencies = [ [[package]] name = "alexandria_math" version = "0.2.1" -source = "git+https://github.com/ishay-starkware/alexandria?rev=e4eb87718e3a870a792ca83361860be800c90acd#e4eb87718e3a870a792ca83361860be800c90acd" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=162bed1c636d31ccaaa90ed3eb32c9eb1d5e3bd3#162bed1c636d31ccaaa90ed3eb32c9eb1d5e3bd3" [[package]] name = "alexandria_numeric" version = "0.1.0" -source = "git+https://github.com/ishay-starkware/alexandria?rev=e4eb87718e3a870a792ca83361860be800c90acd#e4eb87718e3a870a792ca83361860be800c90acd" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=162bed1c636d31ccaaa90ed3eb32c9eb1d5e3bd3#162bed1c636d31ccaaa90ed3eb32c9eb1d5e3bd3" dependencies = [ "alexandria_math", "alexandria_searching", @@ -55,7 +55,7 @@ dependencies = [ [[package]] name = "alexandria_searching" version = "0.1.0" -source = "git+https://github.com/ishay-starkware/alexandria?rev=e4eb87718e3a870a792ca83361860be800c90acd#e4eb87718e3a870a792ca83361860be800c90acd" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=162bed1c636d31ccaaa90ed3eb32c9eb1d5e3bd3#162bed1c636d31ccaaa90ed3eb32c9eb1d5e3bd3" dependencies = [ "alexandria_data_structures", ] diff --git a/tests/alexandria/Scarb.toml b/tests/alexandria/Scarb.toml index ef1ce6b5e..c507a5b23 100644 --- a/tests/alexandria/Scarb.toml +++ b/tests/alexandria/Scarb.toml @@ -7,7 +7,6 @@ edition = "2024_07" # See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html [dependencies] -# todo: change to https://github.com/keep-starknet-strange/alexandria.git after pr is merged for 2.9.2 -alexandria_math = { rev = "e4eb87718e3a870a792ca83361860be800c90acd", git = "https://github.com/ishay-starkware/alexandria" } -alexandria_data_structures = { rev = "e4eb87718e3a870a792ca83361860be800c90acd", git = "https://github.com/ishay-starkware/alexandria" } -alexandria_encoding = { rev = "e4eb87718e3a870a792ca83361860be800c90acd", git = "https://github.com/ishay-starkware/alexandria" } +alexandria_math = { rev = "162bed1c636d31ccaaa90ed3eb32c9eb1d5e3bd3", git = "https://github.com/keep-starknet-strange/alexandria.git" } +alexandria_data_structures = { rev = "162bed1c636d31ccaaa90ed3eb32c9eb1d5e3bd3", git = "https://github.com/keep-starknet-strange/alexandria.git" } +alexandria_encoding = { rev = "162bed1c636d31ccaaa90ed3eb32c9eb1d5e3bd3", git = "https://github.com/keep-starknet-strange/alexandria.git" } diff --git a/tests/common.rs b/tests/common.rs index a768eec11..1d8eab078 100644 --- a/tests/common.rs +++ b/tests/common.rs @@ -750,7 +750,7 @@ pub fn compare_outputs( let mut size_cache = HashMap::new(); let ty = function.signature.ret_types.last(); - let is_builtin = ty.map_or(false, |ty| { + let is_builtin = ty.is_some_and(|ty| { matches!( registry.get_type(ty).unwrap(), CoreTypeConcrete::Bitwise(_) @@ -768,7 +768,7 @@ pub fn compare_outputs( | CoreTypeConcrete::Circuit(CircuitTypeConcrete::MulMod(_)) ) }); - let returns_panic = ty.map_or(false, |ty| { + let returns_panic = ty.is_some_and(|ty| { ty.debug_name .as_ref() .map(|x| x.starts_with("core::panics::PanicResult")) diff --git a/tests/tests/starknet/keccak.rs b/tests/tests/starknet/keccak.rs index 71babc3c7..ff4b4bc49 100644 --- a/tests/tests/starknet/keccak.rs +++ b/tests/tests/starknet/keccak.rs @@ -36,7 +36,7 @@ fn keccak_test() { ); assert!(!result.failure_flag); - assert_eq!(result.remaining_gas, 18446744073709483875); + assert_eq!(result.remaining_gas, 18446744073709484425); assert_eq!(result.return_values, vec![1.into()]); let result_aot_ct = run_native_starknet_aot_contract( diff --git a/tests/tests/starknet/u256.rs b/tests/tests/starknet/u256.rs index b87bff3ff..62295dfc6 100644 --- a/tests/tests/starknet/u256.rs +++ b/tests/tests/starknet/u256.rs @@ -41,5 +41,5 @@ fn u256_test() { result.return_values, vec![Felt::from_hex("0xf70cba9bb86caa97b086fdfa3df602ed").unwrap()] ); - assert_eq!(result.remaining_gas, 18446744073709532575); + assert_eq!(result.remaining_gas, 18446744073709532255); }