diff --git a/.github/codecov.yml b/.github/codecov.yml index 50fe74a541..07b930c0a2 100644 --- a/.github/codecov.yml +++ b/.github/codecov.yml @@ -8,4 +8,5 @@ ignore: - src/vm/errors - src/types/errors - hint_accountant + - src/hint_processor/cairo-1-hint-processor # TODO: Remove this line - ./deps diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 5c7885cad3..836dad3f85 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -15,7 +15,7 @@ jobs: strategy: matrix: # NOTE: we build cairo_proof_programs so clippy can check the benchmarks too - program-target: [ cairo_bench_programs, cairo_proof_programs, cairo_test_programs ] + program-target: [ cairo_bench_programs, cairo_proof_programs, cairo_test_programs, cairo_1_test_contracts ] name: Build Cairo programs runs-on: ubuntu-22.04 steps: @@ -28,7 +28,9 @@ jobs: uses: actions/cache@v3 id: cache-programs with: - path: cairo_programs/**/*.json + path: | + cairo_programs/**/*.casm + cairo_programs/**/*.json key: ${{ matrix.program-target }}-cache-${{ hashFiles( 'cairo_programs/**/*.cairo' ) }} restore-keys: ${{ matrix.program-target }}-cache- @@ -46,6 +48,10 @@ jobs: - name: Install cairo-lang and deps if: ${{ steps.cache-programs.outputs.cache-hit != 'true' }} run: pip install -r requirements.txt + + - name: Install cairo 1 compiler + if: ${{ steps.cache-programs.outputs.cache-hit != 'true' }} + run: make build-cairo-1-compiler - name: Build programs if: ${{ steps.cache-programs.outputs.cache-hit != 'true' }} @@ -72,18 +78,31 @@ jobs: - name: Fetch test programs uses: actions/cache/restore@v3 with: - path: cairo_programs/**/*.json + path: | + cairo_programs/**/*.casm + cairo_programs/**/*.json key: cairo_test_programs-cache-${{ hashFiles( 'cairo_programs/**/*.cairo' ) }} - name: Fetch proof programs uses: actions/cache/restore@v3 with: - path: cairo_programs/**/*.json + path: | + cairo_programs/**/*.casm + cairo_programs/**/*.json key: cairo_proof_programs-cache-${{ hashFiles( 'cairo_programs/**/*.cairo' ) }} - name: Fetch bench programs uses: actions/cache/restore@v3 with: - path: cairo_programs/**/*.json + path: | + cairo_programs/**/*.casm + cairo_programs/**/*.json key: cairo_bench_programs-cache-${{ hashFiles( 'cairo_programs/**/*.cairo' ) }} + - name: Fetch test contracts + uses: actions/cache/restore@v3 + with: + path: | + cairo_programs/**/*.casm + cairo_programs/**/*.json + key: cairo_1_test_contracts-cache-${{ hashFiles( 'cairo_programs/**/*.cairo' ) }} - name: Run clippy run: make clippy @@ -109,18 +128,31 @@ jobs: - name: Fetch test programs uses: actions/cache/restore@v3 with: - path: cairo_programs/**/*.json + path: | + cairo_programs/**/*.casm + cairo_programs/**/*.json key: cairo_test_programs-cache-${{ hashFiles( 'cairo_programs/**/*.cairo' ) }} - name: Fetch proof programs uses: actions/cache/restore@v3 with: - path: cairo_programs/**/*.json + path: | + cairo_programs/**/*.casm + cairo_programs/**/*.json key: cairo_proof_programs-cache-${{ hashFiles( 'cairo_programs/**/*.cairo' ) }} - name: Fetch bench programs uses: actions/cache/restore@v3 with: - path: cairo_programs/**/*.json + path: | + cairo_programs/**/*.casm + cairo_programs/**/*.json key: cairo_bench_programs-cache-${{ hashFiles( 'cairo_programs/**/*.cairo' ) }} + - name: Fetch test contracts + uses: actions/cache/restore@v3 + with: + path: | + cairo_programs/**/*.casm + cairo_programs/**/*.json + key: cairo_1_test_contracts-cache-${{ hashFiles( 'cairo_programs/**/*.cairo' ) }} - name: Check run: cargo check-all-features --workspace --all-targets @@ -154,13 +186,24 @@ jobs: - name: Fetch test programs uses: actions/cache/restore@v3 with: - path: cairo_programs/**/*.json + path: | + cairo_programs/**/*.casm + cairo_programs/**/*.json key: cairo_test_programs-cache-${{ hashFiles( 'cairo_programs/**/*.cairo' ) }} - name: Fetch proof programs uses: actions/cache/restore@v3 with: - path: cairo_programs/**/*.json + path: | + cairo_programs/**/*.casm + cairo_programs/**/*.json key: cairo_proof_programs-cache-${{ hashFiles( 'cairo_programs/**/*.cairo' ) }} + - name: Fetch test contracts + uses: actions/cache/restore@v3 + with: + path: | + cairo_programs/**/*.casm + cairo_programs/**/*.json + key: cairo_1_test_contracts-cache-${{ hashFiles( 'cairo_programs/**/*.cairo' ) }} - name: Install testing tools uses: taiki-e/install-action@v2 @@ -171,7 +214,7 @@ jobs: # FIXME: we need to update the Makefile to do this correctly case ${{ matrix.target }} in 'test') - cargo llvm-cov nextest --lcov --output-path lcov-${{ matrix.target }}.info --workspace --features test_utils + cargo llvm-cov nextest --lcov --output-path lcov-${{ matrix.target }}.info --workspace --features "cairo-1-hints, test_utils" ;; 'test-no_std') cargo llvm-cov nextest --lcov --output-path lcov-${{ matrix.target }}.info --workspace --features test_utils --no-default-features @@ -253,7 +296,9 @@ jobs: if: ${{ steps.trace-cache.outputs.cache-hit != 'true' }} uses: actions/cache/restore@v3 with: - path: cairo_programs/**/*.json + path: | + cairo_programs/**/*.casm + cairo_programs/**/*.json key: ${{ matrix.program-target }}-cache-${{ hashFiles( 'cairo_programs/**/*.cairo' ) }} fail-on-cache-miss: true @@ -294,7 +339,9 @@ jobs: - name: Fetch programs uses: actions/cache/restore@v3 with: - path: cairo_programs/**/*.json + path: | + cairo_programs/**/*.casm + cairo_programs/**/*.json key: ${{ matrix.program-target }}-cache-${{ hashFiles( 'cairo_programs/**/*.cairo' ) }} fail-on-cache-miss: true diff --git a/.gitignore b/.gitignore index 01c4357d9d..010070081c 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,8 @@ **/*.json !hint_accountant/whitelists/*.json !cairo_programs/manually_compiled/*.json +**/*.casm +**/*.sierra **/*.trace **/*.memory **/*.swp diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f0beb23b5..013b93364d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,18 @@ #### Upcoming Changes +* Add some small considerations regarding Cairo 1 programs [#1144](https://github.com/lambdaclass/cairo-rs/pull/1144): + + * Ignore Casm and Sierra files + * Add special flag to compile Cairo 1 programs + +* Make the VM able to run `CasmContractClass` files under `cairo-1-hints` feature [#1098](https://github.com/lambdaclass/cairo-rs/pull/1098) + + * Implement `TryFrom for Program` + * Add `Cairo1HintProcessor` + +* Add `CairoRunner::get_program method` [#1123](https://github.com/lambdaclass/cairo-rs/pull/1123): + * perf: insert elements from the tail in `load_data` so reallocation happens only once [#1117](https://github.com/lambdaclass/cairo-rs/pull/1117) * Add `CairoRunner::get_program method` [#1123](https://github.com/lambdaclass/cairo-rs/pull/1123) diff --git a/Cargo.lock b/Cargo.lock index b75cbb8ec3..88ef9618d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -24,11 +24,69 @@ dependencies = [ "version_check", ] +[[package]] +name = "aho-corasick" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is-terminal", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d" + +[[package]] +name = "anstyle-parse" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "anstyle-wincon" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" +dependencies = [ + "anstyle", + "windows-sys 0.48.0", +] + [[package]] name = "anyhow" -version = "1.0.70" +version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4" +checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" [[package]] name = "ark-ff" @@ -39,12 +97,12 @@ dependencies = [ "ark-ff-asm", "ark-ff-macros", "ark-serialize", - "ark-std", + "ark-std 0.4.0", "derivative", "digest", "itertools", "num-bigint", - "num-traits", + "num-traits 0.2.15", "paste", "rustc_version", "zeroize", @@ -67,7 +125,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" dependencies = [ "num-bigint", - "num-traits", + "num-traits 0.2.15", "proc-macro2", "quote", "syn 1.0.109", @@ -79,21 +137,40 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" dependencies = [ - "ark-std", + "ark-std 0.4.0", "digest", "num-bigint", ] +[[package]] +name = "ark-std" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" +dependencies = [ + "num-traits 0.2.15", + "rand", +] + [[package]] name = "ark-std" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" dependencies = [ - "num-traits", + "num-traits 0.2.15", "rand", ] +[[package]] +name = "ascii-canvas" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" +dependencies = [ + "term", +] + [[package]] name = "assert_matches" version = "1.5.0" @@ -178,9 +255,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.12.0" +version = "3.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" +checksum = "9b1ce199063694f33ffb7dd4e0ee620741495c32833cde5aa08f02a0bf96f0c8" [[package]] name = "byteorder" @@ -195,11 +272,401 @@ dependencies = [ "lazy_static", "num-bigint", "num-integer", - "num-traits", + "num-traits 0.2.15", "proptest", "serde", ] +[[package]] +name = "cairo-felt" +version = "0.3.0-rc1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a93dedd19b8edf685798f1f12e4e0ac21ac196ea5262c300783f69f3fa0cb28b" +dependencies = [ + "lazy_static", + "num-bigint", + "num-integer", + "num-traits 0.2.15", + "serde", +] + +[[package]] +name = "cairo-lang-casm" +version = "1.0.0-alpha.7" +source = "git+https://github.com/starkware-libs/cairo.git?rev=a08bedbf26b711e81cec8b7660698a3788e67d46#a08bedbf26b711e81cec8b7660698a3788e67d46" +dependencies = [ + "cairo-lang-utils", + "indoc", + "num-bigint", + "num-traits 0.2.15", + "serde", + "thiserror", +] + +[[package]] +name = "cairo-lang-compiler" +version = "1.0.0-alpha.7" +source = "git+https://github.com/starkware-libs/cairo.git?rev=a08bedbf26b711e81cec8b7660698a3788e67d46#a08bedbf26b711e81cec8b7660698a3788e67d46" +dependencies = [ + "anyhow", + "cairo-lang-defs", + "cairo-lang-diagnostics", + "cairo-lang-filesystem", + "cairo-lang-lowering", + "cairo-lang-parser", + "cairo-lang-plugins", + "cairo-lang-project", + "cairo-lang-semantic", + "cairo-lang-sierra", + "cairo-lang-sierra-generator", + "cairo-lang-syntax", + "cairo-lang-utils", + "clap 4.2.7", + "log", + "salsa", + "smol_str", + "thiserror", +] + +[[package]] +name = "cairo-lang-debug" +version = "1.0.0-alpha.7" +source = "git+https://github.com/starkware-libs/cairo.git?rev=a08bedbf26b711e81cec8b7660698a3788e67d46#a08bedbf26b711e81cec8b7660698a3788e67d46" + +[[package]] +name = "cairo-lang-defs" +version = "1.0.0-alpha.7" +source = "git+https://github.com/starkware-libs/cairo.git?rev=a08bedbf26b711e81cec8b7660698a3788e67d46#a08bedbf26b711e81cec8b7660698a3788e67d46" +dependencies = [ + "cairo-lang-debug", + "cairo-lang-diagnostics", + "cairo-lang-filesystem", + "cairo-lang-parser", + "cairo-lang-syntax", + "cairo-lang-utils", + "indexmap", + "itertools", + "salsa", + "smol_str", +] + +[[package]] +name = "cairo-lang-diagnostics" +version = "1.0.0-alpha.7" +source = "git+https://github.com/starkware-libs/cairo.git?rev=a08bedbf26b711e81cec8b7660698a3788e67d46#a08bedbf26b711e81cec8b7660698a3788e67d46" +dependencies = [ + "cairo-lang-filesystem", + "cairo-lang-utils", + "itertools", + "salsa", +] + +[[package]] +name = "cairo-lang-eq-solver" +version = "1.0.0-alpha.7" +source = "git+https://github.com/starkware-libs/cairo.git?rev=a08bedbf26b711e81cec8b7660698a3788e67d46#a08bedbf26b711e81cec8b7660698a3788e67d46" +dependencies = [ + "cairo-lang-utils", + "good_lp", + "indexmap", + "itertools", +] + +[[package]] +name = "cairo-lang-filesystem" +version = "1.0.0-alpha.7" +source = "git+https://github.com/starkware-libs/cairo.git?rev=a08bedbf26b711e81cec8b7660698a3788e67d46#a08bedbf26b711e81cec8b7660698a3788e67d46" +dependencies = [ + "cairo-lang-debug", + "cairo-lang-utils", + "path-clean", + "salsa", + "serde", + "smol_str", +] + +[[package]] +name = "cairo-lang-lowering" +version = "1.0.0-alpha.7" +source = "git+https://github.com/starkware-libs/cairo.git?rev=a08bedbf26b711e81cec8b7660698a3788e67d46#a08bedbf26b711e81cec8b7660698a3788e67d46" +dependencies = [ + "cairo-lang-debug", + "cairo-lang-defs", + "cairo-lang-diagnostics", + "cairo-lang-filesystem", + "cairo-lang-parser", + "cairo-lang-proc-macros", + "cairo-lang-semantic", + "cairo-lang-syntax", + "cairo-lang-utils", + "id-arena", + "indexmap", + "itertools", + "log", + "num-bigint", + "num-traits 0.2.15", + "salsa", + "smol_str", +] + +[[package]] +name = "cairo-lang-parser" +version = "1.0.0-alpha.7" +source = "git+https://github.com/starkware-libs/cairo.git?rev=a08bedbf26b711e81cec8b7660698a3788e67d46#a08bedbf26b711e81cec8b7660698a3788e67d46" +dependencies = [ + "cairo-lang-diagnostics", + "cairo-lang-filesystem", + "cairo-lang-syntax", + "cairo-lang-syntax-codegen", + "cairo-lang-utils", + "colored", + "itertools", + "log", + "num-bigint", + "num-traits 0.2.15", + "salsa", + "smol_str", + "unescaper", +] + +[[package]] +name = "cairo-lang-plugins" +version = "1.0.0-alpha.7" +source = "git+https://github.com/starkware-libs/cairo.git?rev=a08bedbf26b711e81cec8b7660698a3788e67d46#a08bedbf26b711e81cec8b7660698a3788e67d46" +dependencies = [ + "cairo-lang-defs", + "cairo-lang-diagnostics", + "cairo-lang-filesystem", + "cairo-lang-parser", + "cairo-lang-semantic", + "cairo-lang-syntax", + "cairo-lang-utils", + "indoc", + "itertools", + "salsa", + "smol_str", +] + +[[package]] +name = "cairo-lang-proc-macros" +version = "1.0.0-alpha.7" +source = "git+https://github.com/starkware-libs/cairo.git?rev=a08bedbf26b711e81cec8b7660698a3788e67d46#a08bedbf26b711e81cec8b7660698a3788e67d46" +dependencies = [ + "cairo-lang-debug", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "cairo-lang-project" +version = "1.0.0-alpha.7" +source = "git+https://github.com/starkware-libs/cairo.git?rev=a08bedbf26b711e81cec8b7660698a3788e67d46#a08bedbf26b711e81cec8b7660698a3788e67d46" +dependencies = [ + "cairo-lang-filesystem", + "serde", + "smol_str", + "thiserror", + "toml 0.4.10", +] + +[[package]] +name = "cairo-lang-semantic" +version = "1.0.0-alpha.7" +source = "git+https://github.com/starkware-libs/cairo.git?rev=a08bedbf26b711e81cec8b7660698a3788e67d46#a08bedbf26b711e81cec8b7660698a3788e67d46" +dependencies = [ + "cairo-lang-debug", + "cairo-lang-defs", + "cairo-lang-diagnostics", + "cairo-lang-filesystem", + "cairo-lang-parser", + "cairo-lang-proc-macros", + "cairo-lang-syntax", + "cairo-lang-utils", + "id-arena", + "itertools", + "log", + "num-bigint", + "num-traits 0.2.15", + "salsa", + "smol_str", +] + +[[package]] +name = "cairo-lang-sierra" +version = "1.0.0-alpha.7" +source = "git+https://github.com/starkware-libs/cairo.git?rev=a08bedbf26b711e81cec8b7660698a3788e67d46#a08bedbf26b711e81cec8b7660698a3788e67d46" +dependencies = [ + "cairo-lang-utils", + "const-fnv1a-hash", + "convert_case", + "derivative", + "itertools", + "lalrpop", + "lalrpop-util", + "num-bigint", + "num-traits 0.2.15", + "regex", + "salsa", + "serde", + "sha3", + "smol_str", + "thiserror", +] + +[[package]] +name = "cairo-lang-sierra-ap-change" +version = "1.0.0-alpha.7" +source = "git+https://github.com/starkware-libs/cairo.git?rev=a08bedbf26b711e81cec8b7660698a3788e67d46#a08bedbf26b711e81cec8b7660698a3788e67d46" +dependencies = [ + "cairo-lang-eq-solver", + "cairo-lang-sierra", + "cairo-lang-utils", + "itertools", + "thiserror", +] + +[[package]] +name = "cairo-lang-sierra-gas" +version = "1.0.0-alpha.7" +source = "git+https://github.com/starkware-libs/cairo.git?rev=a08bedbf26b711e81cec8b7660698a3788e67d46#a08bedbf26b711e81cec8b7660698a3788e67d46" +dependencies = [ + "cairo-lang-eq-solver", + "cairo-lang-sierra", + "cairo-lang-utils", + "itertools", + "thiserror", +] + +[[package]] +name = "cairo-lang-sierra-generator" +version = "1.0.0-alpha.7" +source = "git+https://github.com/starkware-libs/cairo.git?rev=a08bedbf26b711e81cec8b7660698a3788e67d46#a08bedbf26b711e81cec8b7660698a3788e67d46" +dependencies = [ + "cairo-lang-debug", + "cairo-lang-defs", + "cairo-lang-diagnostics", + "cairo-lang-filesystem", + "cairo-lang-lowering", + "cairo-lang-parser", + "cairo-lang-plugins", + "cairo-lang-proc-macros", + "cairo-lang-semantic", + "cairo-lang-sierra", + "cairo-lang-syntax", + "cairo-lang-utils", + "id-arena", + "indexmap", + "itertools", + "num-bigint", + "salsa", + "smol_str", +] + +[[package]] +name = "cairo-lang-sierra-to-casm" +version = "1.0.0-alpha.7" +source = "git+https://github.com/starkware-libs/cairo.git?rev=a08bedbf26b711e81cec8b7660698a3788e67d46#a08bedbf26b711e81cec8b7660698a3788e67d46" +dependencies = [ + "anyhow", + "assert_matches", + "cairo-felt 0.3.0-rc1 (registry+https://github.com/rust-lang/crates.io-index)", + "cairo-lang-casm", + "cairo-lang-sierra", + "cairo-lang-sierra-ap-change", + "cairo-lang-sierra-gas", + "cairo-lang-utils", + "clap 4.2.7", + "indoc", + "itertools", + "log", + "num-bigint", + "num-traits 0.2.15", + "thiserror", +] + +[[package]] +name = "cairo-lang-starknet" +version = "1.0.0-alpha.7" +source = "git+https://github.com/starkware-libs/cairo.git?rev=a08bedbf26b711e81cec8b7660698a3788e67d46#a08bedbf26b711e81cec8b7660698a3788e67d46" +dependencies = [ + "anyhow", + "cairo-felt 0.3.0-rc1 (registry+https://github.com/rust-lang/crates.io-index)", + "cairo-lang-casm", + "cairo-lang-compiler", + "cairo-lang-defs", + "cairo-lang-diagnostics", + "cairo-lang-filesystem", + "cairo-lang-lowering", + "cairo-lang-parser", + "cairo-lang-plugins", + "cairo-lang-semantic", + "cairo-lang-sierra", + "cairo-lang-sierra-ap-change", + "cairo-lang-sierra-gas", + "cairo-lang-sierra-generator", + "cairo-lang-sierra-to-casm", + "cairo-lang-syntax", + "cairo-lang-utils", + "clap 4.2.7", + "convert_case", + "genco", + "indoc", + "itertools", + "log", + "num-bigint", + "num-integer", + "num-traits 0.2.15", + "once_cell", + "serde", + "serde_json", + "sha3", + "smol_str", + "thiserror", +] + +[[package]] +name = "cairo-lang-syntax" +version = "1.0.0-alpha.7" +source = "git+https://github.com/starkware-libs/cairo.git?rev=a08bedbf26b711e81cec8b7660698a3788e67d46#a08bedbf26b711e81cec8b7660698a3788e67d46" +dependencies = [ + "cairo-lang-debug", + "cairo-lang-filesystem", + "cairo-lang-utils", + "num-bigint", + "num-traits 0.2.15", + "salsa", + "smol_str", + "thiserror", + "unescaper", +] + +[[package]] +name = "cairo-lang-syntax-codegen" +version = "1.0.0-alpha.7" +source = "git+https://github.com/starkware-libs/cairo.git?rev=a08bedbf26b711e81cec8b7660698a3788e67d46#a08bedbf26b711e81cec8b7660698a3788e67d46" +dependencies = [ + "cairo-lang-utils", + "genco", + "log", + "xshell", +] + +[[package]] +name = "cairo-lang-utils" +version = "1.0.0-alpha.7" +source = "git+https://github.com/starkware-libs/cairo.git?rev=a08bedbf26b711e81cec8b7660698a3788e67d46#a08bedbf26b711e81cec8b7660698a3788e67d46" +dependencies = [ + "env_logger", + "indexmap", + "itertools", + "log", + "num-bigint", + "num-integer", + "num-traits 0.2.15", + "serde", + "time", +] + [[package]] name = "cairo-take_until_unbalanced" version = "0.24.2-rc1" @@ -213,10 +680,14 @@ name = "cairo-vm" version = "0.3.0-rc1" dependencies = [ "anyhow", + "ark-ff", + "ark-std 0.3.0", "assert_matches", "bincode", "bitvec", - "cairo-felt", + "cairo-felt 0.3.0-rc1", + "cairo-lang-casm", + "cairo-lang-starknet", "cairo-take_until_unbalanced", "criterion", "generic-array", @@ -230,7 +701,7 @@ dependencies = [ "num-bigint", "num-integer", "num-prime", - "num-traits", + "num-traits 0.2.15", "proptest", "rand", "rand_core", @@ -254,7 +725,7 @@ dependencies = [ "assert_matches", "bincode", "cairo-vm", - "clap 3.2.23", + "clap 3.2.25", "mimalloc", "nom", "rstest", @@ -301,14 +772,14 @@ dependencies = [ [[package]] name = "clap" -version = "3.2.23" +version = "3.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" +checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" dependencies = [ "atty", "bitflags", - "clap_derive", - "clap_lex", + "clap_derive 3.2.25", + "clap_lex 0.2.4", "indexmap", "once_cell", "strsim", @@ -316,19 +787,55 @@ dependencies = [ "textwrap 0.16.0", ] +[[package]] +name = "clap" +version = "4.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34d21f9bf1b425d2968943631ec91202fe5e837264063503708b83013f8fc938" +dependencies = [ + "clap_builder", + "clap_derive 4.2.0", + "once_cell", +] + +[[package]] +name = "clap_builder" +version = "4.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "914c8c79fb560f238ef6429439a30023c862f7a28e688c58f7203f12b29970bd" +dependencies = [ + "anstream", + "anstyle", + "bitflags", + "clap_lex 0.4.1", + "strsim", +] + [[package]] name = "clap_derive" -version = "3.2.18" +version = "3.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" +checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro-error", "proc-macro2", "quote", "syn 1.0.109", ] +[[package]] +name = "clap_derive" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "syn 2.0.15", +] + [[package]] name = "clap_lex" version = "0.2.4" @@ -338,6 +845,29 @@ dependencies = [ "os_str_bytes", ] +[[package]] +name = "clap_lex" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1" + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + +[[package]] +name = "colored" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd" +dependencies = [ + "atty", + "lazy_static", + "winapi", +] + [[package]] name = "console_error_panic_hook" version = "0.1.7" @@ -348,11 +878,26 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "const-fnv1a-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b13ea120a812beba79e34316b3942a857c86ec1593cb34f27bb28272ce2cca" + +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "cpufeatures" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "280a9f2d8b3a38871a3c8a46fb80db65e5e5ed97da80c4d08bf27fb63e35e181" +checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58" dependencies = [ "libc", ] @@ -370,7 +915,7 @@ dependencies = [ "csv", "itertools", "lazy_static", - "num-traits", + "num-traits 0.2.15", "oorandom", "plotters", "rayon", @@ -436,6 +981,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "crypto-bigint" version = "0.5.2" @@ -489,6 +1040,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + [[package]] name = "digest" version = "0.10.6" @@ -500,12 +1057,55 @@ dependencies = [ "subtle", ] +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "either" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +[[package]] +name = "ena" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c533630cf40e9caa44bd91aadc88a75d75a4c3a12b4cfde353cbed41daa1e1f1" +dependencies = [ + "log", +] + +[[package]] +name = "env_logger" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + [[package]] name = "envmnt" version = "0.8.4" @@ -546,6 +1146,12 @@ dependencies = [ "instant", ] +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + [[package]] name = "fnv" version = "1.0.7" @@ -659,6 +1265,28 @@ dependencies = [ "slab", ] +[[package]] +name = "genco" +version = "0.17.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6973ce8518068a71d404f428f6a5b563088545546a6bd8f9c0a7f2608149bc8a" +dependencies = [ + "genco-macros", + "relative-path", + "smallvec", +] + +[[package]] +name = "genco-macros" +version = "0.17.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c2c778cf01917d0fbed53900259d6604a421fab4916a2e738856ead9f1d926a" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -691,6 +1319,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "good_lp" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eed4d07599e3cdb52477f1d36bef936c89ce854c452e7026b2ba327b93c86f61" +dependencies = [ + "fnv", + "minilp", +] + [[package]] name = "half" version = "1.8.2" @@ -716,6 +1354,15 @@ dependencies = [ "serde", ] +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "heck" version = "0.4.1" @@ -770,12 +1417,24 @@ dependencies = [ "digest", ] +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + [[package]] name = "iai" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71a816c97c42258aa5834d07590b718b4c9a598944cd39a52dc25b351185d678" +[[package]] +name = "id-arena" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" + [[package]] name = "indexmap" version = "1.9.3" @@ -784,8 +1443,15 @@ checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown 0.12.3", + "serde", ] +[[package]] +name = "indoc" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f2cb48b81b1dc9f39676bf99f5499babfec7cd8fe14307f7b3d747208fb5690" + [[package]] name = "instant" version = "0.1.12" @@ -806,6 +1472,18 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "is-terminal" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" +dependencies = [ + "hermit-abi 0.3.1", + "io-lifetimes", + "rustix", + "windows-sys 0.48.0", +] + [[package]] name = "itertools" version = "0.10.5" @@ -822,21 +1500,52 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" [[package]] -name = "js-sys" -version = "0.3.61" +name = "js-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "keccak" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lalrpop" +version = "0.19.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +checksum = "0a1cbf952127589f2851ab2046af368fd20645491bb4b376f04b7f94d7a9837b" dependencies = [ - "wasm-bindgen", + "ascii-canvas", + "bit-set", + "diff", + "ena", + "is-terminal", + "itertools", + "lalrpop-util", + "petgraph", + "regex", + "regex-syntax 0.6.29", + "string_cache", + "term", + "tiny-keccak", + "unicode-xid", ] [[package]] -name = "keccak" -version = "0.1.3" +name = "lalrpop-util" +version = "0.19.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3afef3b6eff9ce9d8ff9b3601125eec7f0c8cbac7abd14f355d053fa56c98768" +checksum = "d3c48237b9604c5a4702de6b824e02006c3214327564636aef27c1028a8fa0ed" dependencies = [ - "cpufeatures", + "regex", ] [[package]] @@ -850,9 +1559,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.141" +version = "0.2.142" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" +checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317" [[package]] name = "libm" @@ -862,9 +1571,9 @@ checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" [[package]] name = "libmimalloc-sys" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a558e3d911bc3c7bfc8c78bc580b404d6e51c1cefbf656e176a94b49b0df40" +checksum = "f4ac0e912c8ef1b735e92369695618dc5b1819f5a7bf3f167301a3ba1cea515e" dependencies = [ "cc", "libc", @@ -872,9 +1581,19 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.3.1" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f" +checksum = "ece97ea872ece730aed82664c424eb4c8291e1ff2480247ccf7409044bc6479f" + +[[package]] +name = "lock_api" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +dependencies = [ + "autocfg", + "scopeguard", +] [[package]] name = "log" @@ -894,6 +1613,15 @@ dependencies = [ "hashbrown 0.12.3", ] +[[package]] +name = "matrixmultiply" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "916806ba0031cd542105d916a97c8572e1fa6dd79c9c51e7eb43a09ec2dd84c1" +dependencies = [ + "rawpointer", +] + [[package]] name = "memchr" version = "2.5.0" @@ -911,19 +1639,48 @@ dependencies = [ [[package]] name = "mimalloc" -version = "0.1.36" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d88dad3f985ec267a3fcb7a1726f5cb1a7e8cad8b646e70a84f967210df23da" +checksum = "4e2894987a3459f3ffb755608bd82188f8ed00d0ae077f1edea29c068d639d98" dependencies = [ "libmimalloc-sys", ] +[[package]] +name = "minilp" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82a7750a9e5076c660b7bec5e6457b4dbff402b9863c8d112891434e18fd5385" +dependencies = [ + "log", + "sprs", +] + [[package]] name = "minimal-lexical" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +[[package]] +name = "ndarray" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac06db03ec2f46ee0ecdca1a1c34a99c0d188a0d83439b84bf0cb4b386e4ab09" +dependencies = [ + "matrixmultiply", + "num-complex", + "num-integer", + "num-traits 0.2.15", + "rawpointer", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" + [[package]] name = "nias" version = "0.5.0" @@ -948,11 +1705,21 @@ checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" dependencies = [ "autocfg", "num-integer", - "num-traits", + "num-traits 0.2.15", "rand", "serde", ] +[[package]] +name = "num-complex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" +dependencies = [ + "autocfg", + "num-traits 0.2.15", +] + [[package]] name = "num-integer" version = "0.1.45" @@ -960,7 +1727,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" dependencies = [ "autocfg", - "num-traits", + "num-traits 0.2.15", ] [[package]] @@ -971,7 +1738,7 @@ checksum = "64a5fe11d4135c3bcdf3a95b18b194afa9608a5f6ff034f5d857bc9a27fb0119" dependencies = [ "num-bigint", "num-integer", - "num-traits", + "num-traits 0.2.15", ] [[package]] @@ -986,10 +1753,19 @@ dependencies = [ "num-bigint", "num-integer", "num-modular", - "num-traits", + "num-traits 0.2.15", "rand", ] +[[package]] +name = "num-traits" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" +dependencies = [ + "num-traits 0.2.15", +] + [[package]] name = "num-traits" version = "0.2.15" @@ -1010,6 +1786,15 @@ dependencies = [ "libc", ] +[[package]] +name = "num_threads" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +dependencies = [ + "libc", +] + [[package]] name = "once_cell" version = "1.17.1" @@ -1028,12 +1813,85 @@ version = "6.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ceedf44fb00f2d1984b0bc98102627ce622e083e49a5bacdb3e514fa4238e267" +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core 0.8.6", +] + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core 0.9.7", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall 0.2.16", + "smallvec", + "winapi", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.2.16", + "smallvec", + "windows-sys 0.45.0", +] + [[package]] name = "paste" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" +[[package]] +name = "path-clean" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecba01bf2678719532c5e3059e0b5f0811273d94b397088b82e3bd0a78c78fdd" + +[[package]] +name = "petgraph" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + [[package]] name = "pin-project-lite" version = "0.2.9" @@ -1052,7 +1910,7 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97" dependencies = [ - "num-traits", + "num-traits 0.2.15", "plotters-backend", "plotters-svg", "wasm-bindgen", @@ -1080,6 +1938,12 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -1123,12 +1987,12 @@ dependencies = [ "bitflags", "byteorder", "lazy_static", - "num-traits", + "num-traits 0.2.15", "quick-error 2.0.1", "rand", "rand_chacha", "rand_xorshift", - "regex-syntax", + "regex-syntax 0.6.29", "rusty-fork", "tempfile", "unarray", @@ -1200,6 +2064,12 @@ dependencies = [ "rand_core", ] +[[package]] +name = "rawpointer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" + [[package]] name = "rayon" version = "1.7.0" @@ -1222,6 +2092,15 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + [[package]] name = "redox_syscall" version = "0.3.5" @@ -1231,13 +2110,26 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom", + "redox_syscall 0.2.16", + "thiserror", +] + [[package]] name = "regex" -version = "1.7.3" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" +checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370" dependencies = [ - "regex-syntax", + "aho-corasick", + "memchr", + "regex-syntax 0.7.1", ] [[package]] @@ -1246,6 +2138,18 @@ version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" +[[package]] +name = "regex-syntax" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c" + +[[package]] +name = "relative-path" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bf2521270932c3c7bed1a59151222bd7643c79310f2916f01925e1e16255698" + [[package]] name = "rfc6979" version = "0.4.0" @@ -1282,6 +2186,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustc_version" version = "0.4.0" @@ -1293,9 +2203,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.11" +version = "0.37.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85597d61f83914ddeba6a47b3b8ffe7365107221c2e557ed94426489fefb5f77" +checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" dependencies = [ "bitflags", "errno", @@ -1305,6 +2215,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "rustversion" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" + [[package]] name = "rusty-fork" version = "0.3.0" @@ -1326,7 +2242,7 @@ dependencies = [ "ci_info", "getopts", "nias", - "toml", + "toml 0.5.11", ] [[package]] @@ -1335,6 +2251,35 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +[[package]] +name = "salsa" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b84d9f96071f3f3be0dc818eae3327625d8ebc95b58da37d6850724f31d3403" +dependencies = [ + "crossbeam-utils", + "indexmap", + "lock_api", + "log", + "oorandom", + "parking_lot 0.11.2", + "rustc-hash", + "salsa-macros", + "smallvec", +] + +[[package]] +name = "salsa-macros" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd3904a4ba0a9d0211816177fd34b04c7095443f8cdacd11175064fe541c8fe2" +dependencies = [ + "heck 0.3.3", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "same-file" version = "1.0.6" @@ -1364,9 +2309,9 @@ checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" [[package]] name = "serde" -version = "1.0.159" +version = "1.0.160" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065" +checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" dependencies = [ "serde_derive", ] @@ -1392,9 +2337,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.159" +version = "1.0.160" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c614d17805b093df4b147b51339e7e44bf05ef59fba1e45d83500bcfb4d8585" +checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" dependencies = [ "proc-macro2", "quote", @@ -1403,9 +2348,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.95" +version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d721eca97ac802aa7777b701877c8004d950fc142651367300d21c1cc0194744" +checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" dependencies = [ "itoa", "ryu", @@ -1425,14 +2370,20 @@ dependencies = [ [[package]] name = "sha3" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdf0c33fae925bdc080598b84bc15c55e7b9a4a43b3c704da051f977469691c9" +checksum = "54c2bb1a323307527314a36bfb73f24febb08ce2b8a554bf4ffd6f51ad15198c" dependencies = [ "digest", "keccak", ] +[[package]] +name = "siphasher" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" + [[package]] name = "slab" version = "0.4.8" @@ -1442,24 +2393,50 @@ dependencies = [ "autocfg", ] +[[package]] +name = "smallvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" + +[[package]] +name = "smol_str" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74212e6bbe9a4352329b2f68ba3130c15a3f26fe88ff22dbdc6cdd58fa85e99c" +dependencies = [ + "serde", +] + [[package]] name = "spin" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "sprs" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec63571489873d4506683915840eeb1bb16b3198ee4894cc6f2fe3013d505e56" +dependencies = [ + "ndarray", + "num-complex", + "num-traits 0.1.43", +] + [[package]] name = "starknet-crypto" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0fd67d10f0b0e7398a62138eaa2b2d500d60fdfc9bb50a4d84ad8be65ead337" +checksum = "693e6362f150f9276e429a910481fb7f3bcb8d6aa643743f587cfece0b374874" dependencies = [ "crypto-bigint", "hex", "hmac", "num-bigint", "num-integer", - "num-traits", + "num-traits 0.2.15", "rfc6979", "sha2", "starknet-crypto-codegen", @@ -1500,6 +2477,19 @@ dependencies = [ "hex", ] +[[package]] +name = "string_cache" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot 0.12.1", + "phf_shared", + "precomputed-hash", +] + [[package]] name = "strsim" version = "0.10.0" @@ -1548,11 +2538,22 @@ checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" dependencies = [ "cfg-if", "fastrand", - "redox_syscall", + "redox_syscall 0.3.5", "rustix", "windows-sys 0.45.0", ] +[[package]] +name = "term" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +dependencies = [ + "dirs-next", + "rustversion", + "winapi", +] + [[package]] name = "termcolor" version = "1.2.0" @@ -1617,6 +2618,44 @@ dependencies = [ "thiserror-impl-no-std", ] +[[package]] +name = "time" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890" +dependencies = [ + "itoa", + "libc", + "num_threads", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" + +[[package]] +name = "time-macros" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd80a657e71da814b8e5d60d3374fc6d35045062245d80224748ae522dd76f36" +dependencies = [ + "time-core", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + [[package]] name = "tinytemplate" version = "1.2.1" @@ -1627,6 +2666,15 @@ dependencies = [ "serde_json", ] +[[package]] +name = "toml" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" +dependencies = [ + "serde", +] + [[package]] name = "toml" version = "0.5.11" @@ -1648,18 +2696,45 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" +[[package]] +name = "unescaper" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "995483205de764db1185c9461a000fff73fa4b9ee2bbe4c8b4027a94692700fe" +dependencies = [ + "thiserror", +] + [[package]] name = "unicode-ident" version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +[[package]] +name = "unicode-segmentation" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" + [[package]] name = "unicode-width" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "version_check" version = "0.9.4" @@ -1969,6 +3044,21 @@ dependencies = [ "tap", ] +[[package]] +name = "xshell" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "962c039b3a7b16cf4e9a4248397c6585c07547412e7d6a6e035389a802dcfe90" +dependencies = [ + "xshell-macros", +] + +[[package]] +name = "xshell-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dbabb1cbd15a1d6d12d9ed6b35cc6777d4af87ab3ba155ea37215f20beab80c" + [[package]] name = "zeroize" version = "1.6.0" diff --git a/Cargo.toml b/Cargo.toml index f4df43e8d0..016701a9ba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,12 +20,13 @@ std = [ "parse-hyperlinks/std", "felt/std", ] +cairo-1-hints = ["cairo-lang-starknet", "cairo-lang-casm", "ark-ff", "ark-std"] # Note that these features are not retro-compatible with the cairo Python VM. test_utils = [ "skip_next_instruction_hint", - "hooks", + "hooks" ] # This feature will reference every test-oriented feature skip_next_instruction_hint = [] hooks = [] @@ -80,6 +81,14 @@ felt = { package = "cairo-felt", path = "./felt", version = "0.3.0-rc1", default ] } bitvec = { version = "1", default-features = false, features = ["alloc"] } +# Dependencies for cairo-1-hints feature +cairo-lang-starknet = { git = "https://github.com/starkware-libs/cairo.git", rev = "a08bedbf26b711e81cec8b7660698a3788e67d46", optional = true} +cairo-lang-casm = { git = "https://github.com/starkware-libs/cairo.git", rev = "a08bedbf26b711e81cec8b7660698a3788e67d46", optional = true } + +# TODO: check these dependencies for wasm compatibility +ark-ff = {version = "0.4.0-alpha.7", default-features = false, optional = true} +ark-std = {version = "0.3.0", default-features = false, optional = true} + [dev-dependencies] assert_matches = "1.5.0" rstest = { version = "0.17.0", default-features = false } diff --git a/Makefile b/Makefile index 3f3117260e..2db8e0d77e 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,15 @@ RELBIN:=target/release/cairo-rs-run DBGBIN:=target/debug/cairo-rs-run +STARKNET_COMPILE:=cairo/target/release/starknet-compile +STARKNET_SIERRA_COMPILE:=cairo/target/release/starknet-sierra-compile -.PHONY: deps deps-macos cargo-deps build run check test clippy coverage benchmark flamegraph \ +.PHONY: build-cairo-1-compiler deps deps-macos cargo-deps build run check test clippy coverage benchmark flamegraph \ compare_benchmarks_deps compare_benchmarks docs clean \ compare_vm_output compare_trace_memory compare_trace compare_memory \ compare_trace_memory_proof compare_trace_proof compare_memory_proof \ cairo_bench_programs cairo_proof_programs cairo_test_programs \ cairo_trace cairo-rs_trace cairo_proof_trace cairo-rs_proof_trace \ - $(RELBIN) $(DBGBIN) + $(RELBIN) $(DBGBIN) $(STARKNET_COMPILE) $(STARKNET_SIERRA_COMPILE) # Proof mode consumes too much memory with cairo-lang to execute # two instances at the same time in the CI without getting killed @@ -89,6 +91,29 @@ COMPILED_BAD_TESTS:=$(patsubst $(BAD_TEST_DIR)/%.cairo, $(BAD_TEST_DIR)/%.json, $(BAD_TEST_DIR)/%.json: $(BAD_TEST_DIR)/%.cairo cairo-compile $< --output $@ +# ====================== +# Test Cairo 1 Contracts +# ====================== + +CAIRO_1_CONTRACTS_TEST_DIR=cairo_programs/cairo-1-contracts +CAIRO_1_CONTRACTS_TEST_CAIRO_FILES:=$(wildcard $(CAIRO_1_CONTRACTS_TEST_DIR)/*.cairo) +COMPILED_SIERRA_CONTRACTS:=$(patsubst $(CAIRO_1_CONTRACTS_TEST_DIR)/%.cairo, $(CAIRO_1_CONTRACTS_TEST_DIR)/%.sierra, $(CAIRO_1_CONTRACTS_TEST_CAIRO_FILES)) +COMPILED_CASM_CONTRACTS:= $(patsubst $(CAIRO_1_CONTRACTS_TEST_DIR)/%.sierra, $(CAIRO_1_CONTRACTS_TEST_DIR)/%.casm, $(COMPILED_SIERRA_CONTRACTS)) + +$(CAIRO_1_CONTRACTS_TEST_DIR)/%.sierra: $(CAIRO_1_CONTRACTS_TEST_DIR)/%.cairo + $(STARKNET_COMPILE) --allowed-libfuncs-list-name experimental_v0.1.0 $< $@ + +$(CAIRO_1_CONTRACTS_TEST_DIR)/%.casm: $(CAIRO_1_CONTRACTS_TEST_DIR)/%.sierra + $(STARKNET_SIERRA_COMPILE) --allowed-libfuncs-list-name experimental_v0.1.0 $< $@ + +cairo-repo-dir = cairo + +build-cairo-1-compiler: | $(cairo-repo-dir) + +$(cairo-repo-dir): + git clone https://github.com/starkware-libs/cairo.git + cd cairo; cargo b --release --bin starknet-compile --bin starknet-sierra-compile + cargo-deps: cargo install --version 1.1.0 cargo-criterion cargo install --version 0.6.1 flamegraph @@ -97,8 +122,7 @@ cargo-deps: cargo install --version 0.5.9 cargo-llvm-cov cargo install --version 0.11.0 wasm-pack -deps: - $(MAKE) cargo-deps +deps: cargo-deps build-cairo-1-compiler pyenv install -s pypy3.9-7.3.9 PYENV_VERSION=pypy3.9-7.3.9 python -m venv cairo-rs-pypy-env . cairo-rs-pypy-env/bin/activate ; \ @@ -108,8 +132,7 @@ deps: . cairo-rs-env/bin/activate ; \ pip install -r requirements.txt ; \ -deps-macos: - $(MAKE) cargo-deps +deps-macos: cargo-deps build-cairo-1-compiler brew install gmp arch -x86_64 pyenv install -s pypy3.9-7.3.9 PYENV_VERSION=pypy3.9-7.3.9 python -m venv cairo-rs-pypy-env @@ -134,6 +157,7 @@ check: cairo_test_programs: $(COMPILED_TESTS) $(COMPILED_BAD_TESTS) $(COMPILED_NORETROCOMPAT_TESTS) cairo_proof_programs: $(COMPILED_PROOF_TESTS) cairo_bench_programs: $(COMPILED_BENCHES) +cairo_1_test_contracts: $(COMPILED_CASM_CONTRACTS) cairo_proof_trace: $(CAIRO_TRACE_PROOF) $(CAIRO_MEM_PROOF) cairo-rs_proof_trace: $(CAIRO_RS_TRACE_PROOF) $(CAIRO_RS_MEM_PROOF) @@ -141,8 +165,8 @@ cairo-rs_proof_trace: $(CAIRO_RS_TRACE_PROOF) $(CAIRO_RS_MEM_PROOF) cairo_trace: $(CAIRO_TRACE) $(CAIRO_MEM) cairo-rs_trace: $(CAIRO_RS_TRACE) $(CAIRO_RS_MEM) -test: $(COMPILED_PROOF_TESTS) $(COMPILED_TESTS) $(COMPILED_BAD_TESTS) $(COMPILED_NORETROCOMPAT_TESTS) - cargo llvm-cov nextest --no-report --workspace --features test_utils +test: $(COMPILED_PROOF_TESTS) $(COMPILED_TESTS) $(COMPILED_BAD_TESTS) $(COMPILED_NORETROCOMPAT_TESTS) $(COMPILED_CASM_CONTRACTS) + cargo llvm-cov nextest --no-report --workspace --features "test_utils, cairo-1-hints" test-no_std: $(COMPILED_PROOF_TESTS) $(COMPILED_TESTS) $(COMPILED_BAD_TESTS) $(COMPILED_NORETROCOMPAT_TESTS) cargo llvm-cov nextest --no-report --workspace --features test_utils --no-default-features test-wasm: $(COMPILED_PROOF_TESTS) $(COMPILED_TESTS) $(COMPILED_BAD_TESTS) $(COMPILED_NORETROCOMPAT_TESTS) @@ -202,8 +226,11 @@ clean: rm -f $(TEST_DIR)/*.trace rm -f $(BENCH_DIR)/*.json rm -f $(BAD_TEST_DIR)/*.json + rm -f $(CAIRO_1_CONTRACTS_TEST_DIR)/*.sierra + rm -f $(CAIRO_1_CONTRACTS_TEST_DIR)/*.casm rm -f $(TEST_PROOF_DIR)/*.json rm -f $(TEST_PROOF_DIR)/*.memory rm -f $(TEST_PROOF_DIR)/*.trace rm -rf cairo-rs-env rm -rf cairo-rs-pypy-env + rm -rf cairo diff --git a/cairo_programs/cairo-1-contracts/fib.cairo b/cairo_programs/cairo-1-contracts/fib.cairo new file mode 100644 index 0000000000..2c1396270d --- /dev/null +++ b/cairo_programs/cairo-1-contracts/fib.cairo @@ -0,0 +1,11 @@ +#[contract] +mod Fibonacci { + + #[external] + fn fib(a: felt252, b: felt252, n: felt252) -> felt252 { + match n { + 0 => a, + _ => fib(b, a + b, n - 1), + } + } +} diff --git a/src/hint_processor/cairo_1_hint_processor/dict_manager.rs b/src/hint_processor/cairo_1_hint_processor/dict_manager.rs new file mode 100644 index 0000000000..123adc01f9 --- /dev/null +++ b/src/hint_processor/cairo_1_hint_processor/dict_manager.rs @@ -0,0 +1,145 @@ +use crate::stdlib::collections::HashMap; +use crate::stdlib::prelude::*; +use num_traits::One; + +use crate::felt::Felt252; +use crate::vm::errors::hint_errors::HintError; +use crate::{types::relocatable::Relocatable, vm::vm_core::VirtualMachine}; + +/// Stores the data of a specific dictionary. +pub struct DictTrackerExecScope { + /// The data of the dictionary. + data: HashMap, + /// The index of the dictionary in the dict_infos segment. + #[allow(dead_code)] + idx: usize, +} + +/// Helper object to allocate, track and destruct all dictionaries in the run. +#[derive(Default)] +pub struct DictManagerExecScope { + /// Maps between a segment index and the DictTrackerExecScope associated with it. + trackers: HashMap, +} + +impl DictTrackerExecScope { + /// Creates a new tracker placed in index `idx` in the dict_infos segment. + pub fn new(idx: usize) -> Self { + Self { + data: HashMap::default(), + idx, + } + } +} + +impl DictManagerExecScope { + pub const DICT_DEFAULT_VALUE: usize = 0; + + /// Allocates a new segment for a new dictionary and return the start of the segment. + pub fn new_default_dict(&mut self, vm: &mut VirtualMachine) -> Result { + let dict_segment = vm.add_memory_segment(); + if self + .trackers + .insert( + dict_segment.segment_index, + DictTrackerExecScope::new(self.trackers.len()), + ) + .is_some() + { + return Err(HintError::CustomHint(String::from( + "Segment index already in use.", + ))); + } + + Ok(dict_segment) + } + + /// Returns a reference for a dict tracker corresponding to a given pointer to a dict segment. + fn get_dict_tracker(&self, dict_end: Relocatable) -> Result<&DictTrackerExecScope, HintError> { + self.trackers + .get(&dict_end.segment_index) + .ok_or(HintError::CustomHint(String::from( + "The given value does not point to a known dictionary.", + ))) + } + + /// Returns a mut reference for a dict tracker corresponding to a given pointer to a dict + /// segment. + fn get_dict_tracker_mut(&mut self, dict_end: Relocatable) -> &mut DictTrackerExecScope { + self.trackers + .get_mut(&dict_end.segment_index) + .expect("The given value does not point to a known dictionary.") + } + + /// Returns the index of the dict tracker corresponding to a given pointer to a dict segment. + pub fn get_dict_infos_index(&self, dict_end: Relocatable) -> Result { + Ok(self.get_dict_tracker(dict_end)?.idx) + } + + /// Inserts a value to the dict tracker corresponding to a given pointer to a dict segment. + pub fn insert_to_tracker(&mut self, dict_end: Relocatable, key: Felt252, value: Felt252) { + self.get_dict_tracker_mut(dict_end).data.insert(key, value); + } + + /// Gets a value from the dict tracker corresponding to a given pointer to a dict segment. + /// None if the key does not exist in the tracker data. + pub fn get_from_tracker(&self, dict_end: Relocatable, key: &Felt252) -> Option { + self.get_dict_tracker(dict_end).ok()?.data.get(key).cloned() + } +} + +/// Helper object for the management of dict_squash hints. +#[derive(Default, Debug)] +pub struct DictSquashExecScope { + /// A map from key to the list of indices accessing it, each list in reverse order. + pub(crate) access_indices: HashMap>, + /// Descending list of keys. + keys: Vec, +} + +impl DictSquashExecScope { + /// Returns the current key to process. + pub fn current_key(&self) -> Option { + self.keys.last().cloned() + } + + /// Removes the current key, and its access indices. Should be called when only the + /// last key access is in the corresponding indices list. + pub fn pop_current_key(&mut self) -> Result<(), HintError> { + let current_key = self + .current_key() + .ok_or(HintError::CustomHint(String::from( + "Failed to get current key", + )))?; + let key_accesses = + self.access_indices + .remove(¤t_key) + .ok_or(HintError::CustomHint(format!( + "No key accesses for key {}", + current_key + )))?; + if !key_accesses.len().is_one() { + return Err(HintError::CustomHint(String::from( + "Key popped but not all accesses were processed.", + ))); + } + self.keys.pop(); + Ok(()) + } + + /// Returns a reference to the access indices list of the current key. + pub fn current_access_indices(&mut self) -> Option<&mut Vec> { + let current_key = self.current_key()?; + self.access_indices.get_mut(¤t_key) + } + + /// Returns a reference to the last index in the current access indices list. + pub fn current_access_index(&mut self) -> Option<&Felt252> { + self.current_access_indices()?.last() + } + + /// Returns and removes the current access index. + pub fn pop_current_access_index(&mut self) -> Option { + self.current_access_indices()?.pop() + } +} diff --git a/src/hint_processor/cairo_1_hint_processor/hint_processor.rs b/src/hint_processor/cairo_1_hint_processor/hint_processor.rs new file mode 100644 index 0000000000..3763cff6e1 --- /dev/null +++ b/src/hint_processor/cairo_1_hint_processor/hint_processor.rs @@ -0,0 +1,703 @@ +use super::dict_manager::DictManagerExecScope; +use super::hint_processor_utils::*; +use crate::any_box; +use crate::felt::{felt_str, Felt252}; +use crate::hint_processor::cairo_1_hint_processor::dict_manager::DictSquashExecScope; +use crate::hint_processor::hint_processor_definition::HintReference; + +use crate::stdlib::collections::HashMap; +use crate::stdlib::prelude::*; +use crate::{ + hint_processor::hint_processor_definition::HintProcessor, + types::exec_scope::ExecutionScopes, + vm::errors::vm_errors::VirtualMachineError, + vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, +}; +use ark_ff::fields::{Fp256, MontBackend, MontConfig}; +use ark_ff::{Field, PrimeField}; +use ark_std::UniformRand; +use cairo_lang_casm::{ + hints::{CoreHint, Hint}, + operand::{CellRef, ResOperand}, +}; +use core::any::Any; +use core::ops::Mul; +use num_bigint::BigUint; +use num_integer::Integer; +use num_traits::{cast::ToPrimitive, Zero}; + +#[derive(MontConfig)] +#[modulus = "3618502788666131213697322783095070105623107215331596699973092056135872020481"] +#[generator = "3"] + +/// Returns the Beta value of the Starkware elliptic curve. +struct FqConfig; +type Fq = Fp256>; + +fn get_beta() -> Felt252 { + felt_str!("3141592653589793238462643383279502884197169399375105820974944592307816406665") +} + +/// HintProcessor for Cairo 1 compiler hints. +pub struct Cairo1HintProcessor { + hints: HashMap>, +} + +impl Cairo1HintProcessor { + pub fn new(hints: &[(usize, Vec)]) -> Self { + Self { + hints: hints.iter().cloned().collect(), + } + } + // Runs a single Hint + pub fn execute( + &self, + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + hint: &Hint, + ) -> Result<(), HintError> { + match hint { + Hint::Core(CoreHint::AllocSegment { dst }) => self.alloc_segment(vm, dst), + Hint::Core(CoreHint::TestLessThan { lhs, rhs, dst }) => { + self.test_less_than(vm, lhs, rhs, dst) + } + Hint::Core(CoreHint::TestLessThanOrEqual { lhs, rhs, dst }) => { + self.test_less_than_or_equal(vm, lhs, rhs, dst) + } + Hint::Core(CoreHint::Felt252DictRead { + dict_ptr, + key, + value_dst, + }) => self.dict_read(vm, exec_scopes, dict_ptr, key, value_dst), + Hint::Core(CoreHint::SquareRoot { value, dst }) => self.square_root(vm, value, dst), + Hint::Core(CoreHint::GetSegmentArenaIndex { + dict_end_ptr, + dict_index, + }) => self.get_segment_arena_index(vm, exec_scopes, dict_end_ptr, dict_index), + + Hint::Core(CoreHint::DivMod { + lhs, + rhs, + quotient, + remainder, + }) => self.div_mod(vm, lhs, rhs, quotient, remainder), + Hint::Core(CoreHint::DebugPrint { start, end }) => self.debug_print(vm, start, end), + + Hint::Core(CoreHint::Uint256SquareRoot { + value_low, + value_high, + sqrt0, + sqrt1, + remainder_low, + remainder_high, + sqrt_mul_2_minus_remainder_ge_u128, + }) => self.uint256_square_root( + vm, + value_low, + value_high, + sqrt0, + sqrt1, + remainder_low, + remainder_high, + sqrt_mul_2_minus_remainder_ge_u128, + ), + + Hint::Core(CoreHint::GetNextDictKey { next_key }) => { + self.get_next_dict_key(vm, exec_scopes, next_key) + } + + Hint::Core(CoreHint::Uint256DivMod { + dividend_low, + dividend_high, + divisor_low, + divisor_high, + quotient0, + quotient1, + divisor0, + divisor1, + extra0, + extra1, + remainder_low, + remainder_high, + }) => self.uint256_div_mod( + vm, + dividend_low, + dividend_high, + divisor_low, + divisor_high, + quotient0, + quotient1, + divisor0, + divisor1, + extra0, + extra1, + remainder_low, + remainder_high, + ), + Hint::Core(CoreHint::Felt252DictWrite { + dict_ptr, + key, + value, + }) => self.dict_write(exec_scopes, vm, dict_ptr, key, value), + Hint::Core(CoreHint::AssertLeIsFirstArcExcluded { + skip_exclude_a_flag, + }) => self.assert_le_if_first_arc_exclueded(vm, skip_exclude_a_flag, exec_scopes), + + Hint::Core(CoreHint::AssertAllAccessesUsed { n_used_accesses }) => { + self.assert_all_accesses_used(vm, exec_scopes, n_used_accesses) + } + + Hint::Core(CoreHint::AssertLeIsSecondArcExcluded { + skip_exclude_b_minus_a, + }) => self.assert_le_is_second_excluded(vm, skip_exclude_b_minus_a, exec_scopes), + + Hint::Core(CoreHint::LinearSplit { + value, + scalar, + max_x, + x, + y, + }) => self.linear_split(vm, value, scalar, max_x, x, y), + + Hint::Core(CoreHint::AllocFelt252Dict { segment_arena_ptr }) => { + self.alloc_felt_256_dict(vm, segment_arena_ptr, exec_scopes) + } + + Hint::Core(CoreHint::AssertLeFindSmallArcs { + range_check_ptr, + a, + b, + }) => self.assert_le_find_small_arcs(vm, exec_scopes, range_check_ptr, a, b), + + Hint::Core(CoreHint::RandomEcPoint { x, y }) => self.random_ec_point(vm, x, y), + + Hint::Core(CoreHint::ShouldSkipSquashLoop { should_skip_loop }) => { + self.should_skip_squash_loop(vm, exec_scopes, should_skip_loop) + } + hint => Err(HintError::UnknownHint(hint.to_string())), + } + } + + fn alloc_segment(&self, vm: &mut VirtualMachine, dst: &CellRef) -> Result<(), HintError> { + let segment = vm.add_memory_segment(); + vm.insert_value(cell_ref_to_relocatable(dst, vm)?, segment) + .map_err(HintError::from) + } + + fn test_less_than( + &self, + vm: &mut VirtualMachine, + lhs: &ResOperand, + rhs: &ResOperand, + dst: &CellRef, + ) -> Result<(), HintError> { + let lhs_value = res_operand_get_val(vm, lhs)?; + let rhs_value = res_operand_get_val(vm, rhs)?; + let result = Felt252::from((lhs_value < rhs_value) as u8); + + vm.insert_value(cell_ref_to_relocatable(dst, vm)?, result) + .map_err(HintError::from) + } + + fn square_root( + &self, + vm: &mut VirtualMachine, + value: &ResOperand, + dst: &CellRef, + ) -> Result<(), HintError> { + let value = res_operand_get_val(vm, value)?; + let result = value.sqrt(); + vm.insert_value(cell_ref_to_relocatable(dst, vm)?, result) + .map_err(HintError::from) + } + + fn test_less_than_or_equal( + &self, + vm: &mut VirtualMachine, + lhs: &ResOperand, + rhs: &ResOperand, + dst: &CellRef, + ) -> Result<(), HintError> { + let lhs_value = res_operand_get_val(vm, lhs)?; + let rhs_value = res_operand_get_val(vm, rhs)?; + let result = Felt252::from((lhs_value <= rhs_value) as u8); + + vm.insert_value(cell_ref_to_relocatable(dst, vm)?, result) + .map_err(HintError::from) + } + + fn assert_le_find_small_arcs( + &self, + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + range_check_ptr: &ResOperand, + a: &ResOperand, + b: &ResOperand, + ) -> Result<(), HintError> { + let a_val = res_operand_get_val(vm, a)?; + let b_val = res_operand_get_val(vm, b)?; + let mut lengths_and_indices = vec![ + (a_val.clone(), 0), + (b_val.clone() - a_val, 1), + (Felt252::from(-1) - b_val, 2), + ]; + lengths_and_indices.sort(); + exec_scopes.assign_or_update_variable("excluded_arc", Box::new(lengths_and_indices[2].1)); + // ceil((PRIME / 3) / 2 ** 128). + let prime_over_3_high = 3544607988759775765608368578435044694_u128; + // ceil((PRIME / 2) / 2 ** 128). + let prime_over_2_high = 5316911983139663648412552867652567041_u128; + let (range_check_base, range_check_offset) = extract_buffer(range_check_ptr)?; + let range_check_ptr = get_ptr(vm, range_check_base, &range_check_offset)?; + vm.insert_value( + range_check_ptr, + Felt252::from(lengths_and_indices[0].0.to_biguint() % prime_over_3_high), + )?; + vm.insert_value( + (range_check_ptr + 1)?, + Felt252::from(lengths_and_indices[0].0.to_biguint() / prime_over_3_high), + )?; + vm.insert_value( + (range_check_ptr + 2)?, + Felt252::from(lengths_and_indices[1].0.to_biguint() % prime_over_2_high), + )?; + vm.insert_value( + (range_check_ptr + 3)?, + Felt252::from(lengths_and_indices[1].0.to_biguint() / prime_over_2_high), + ) + .map_err(HintError::from) + } + + fn dict_read( + &self, + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + dict_ptr: &ResOperand, + key: &ResOperand, + value_dst: &CellRef, + ) -> Result<(), HintError> { + let (dict_base, dict_offset) = extract_buffer(dict_ptr)?; + let dict_address = get_ptr(vm, dict_base, &dict_offset)?; + let key = res_operand_get_val(vm, key)?; + let dict_manager_exec_scope = + exec_scopes.get_mut_ref::("dict_manager_exec_scope")?; + + let value = dict_manager_exec_scope + .get_from_tracker(dict_address, &key) + .unwrap_or_else(|| DictManagerExecScope::DICT_DEFAULT_VALUE.into()); + + vm.insert_value(cell_ref_to_relocatable(value_dst, vm)?, value) + .map_err(HintError::from) + } + + fn div_mod( + &self, + vm: &mut VirtualMachine, + lhs: &ResOperand, + rhs: &ResOperand, + quotient: &CellRef, + remainder: &CellRef, + ) -> Result<(), HintError> { + let lhs_value = res_operand_get_val(vm, lhs)?.to_biguint(); + let rhs_value = res_operand_get_val(vm, rhs)?.to_biguint(); + let quotient_value = Felt252::new(&lhs_value / &rhs_value); + let remainder_value = Felt252::new(lhs_value % rhs_value); + vm.insert_value(cell_ref_to_relocatable(quotient, vm)?, quotient_value)?; + vm.insert_value(cell_ref_to_relocatable(remainder, vm)?, remainder_value) + .map_err(HintError::from) + } + + fn get_segment_arena_index( + &self, + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + dict_end_ptr: &ResOperand, + dict_index: &CellRef, + ) -> Result<(), HintError> { + let (dict_base, dict_offset) = extract_buffer(dict_end_ptr)?; + let dict_address = get_ptr(vm, dict_base, &dict_offset)?; + let dict_manager_exec_scope = + exec_scopes.get_mut_ref::("dict_manager_exec_scope")?; + + let dict_infos_index = dict_manager_exec_scope.get_dict_infos_index(dict_address)?; + vm.insert_value(cell_ref_to_relocatable(dict_index, vm)?, dict_infos_index) + .map_err(HintError::from) + } + + #[allow(clippy::too_many_arguments)] + fn uint256_div_mod( + &self, + vm: &mut VirtualMachine, + dividend_low: &ResOperand, + dividend_high: &ResOperand, + divisor_low: &ResOperand, + divisor_high: &ResOperand, + quotient0: &CellRef, + quotient1: &CellRef, + divisor0: &CellRef, + divisor1: &CellRef, + extra0: &CellRef, + extra1: &CellRef, + remainder_low: &CellRef, + remainder_high: &CellRef, + ) -> Result<(), HintError> { + let pow_2_128 = Felt252::from(u128::MAX) + 1u32; + let pow_2_64 = Felt252::from(u64::MAX) + 1u32; + let dividend_low = res_operand_get_val(vm, dividend_low)?; + let dividend_high = res_operand_get_val(vm, dividend_high)?; + let divisor_low = res_operand_get_val(vm, divisor_low)?; + let divisor_high = res_operand_get_val(vm, divisor_high)?; + let dividend = dividend_low + dividend_high.mul(pow_2_128.clone()); + let divisor = divisor_low + (&divisor_high * &pow_2_128); + let quotient = ÷nd / &divisor; + let remainder = dividend % divisor.clone(); + + // Guess quotient limbs. + let (quotient, limb) = quotient.div_rem(&pow_2_64); + vm.insert_value(cell_ref_to_relocatable(quotient0, vm)?, limb)?; + let (quotient, limb) = quotient.div_rem(&pow_2_64); + vm.insert_value(cell_ref_to_relocatable(quotient1, vm)?, limb)?; + let (quotient, limb) = quotient.div_rem(&pow_2_64); + if divisor_high.is_zero() { + vm.insert_value(cell_ref_to_relocatable(extra0, vm)?, limb)?; + vm.insert_value(cell_ref_to_relocatable(extra1, vm)?, quotient)?; + } + + // Guess divisor limbs. + let (divisor, limb) = divisor.div_rem(&pow_2_64); + vm.insert_value(cell_ref_to_relocatable(divisor0, vm)?, limb)?; + let (divisor, limb) = divisor.div_rem(&pow_2_64); + vm.insert_value(cell_ref_to_relocatable(divisor1, vm)?, limb)?; + let (divisor, limb) = divisor.div_rem(&pow_2_64); + if !divisor_high.is_zero() { + vm.insert_value(cell_ref_to_relocatable(extra0, vm)?, limb)?; + vm.insert_value(cell_ref_to_relocatable(extra1, vm)?, divisor)?; + } + + // Guess remainder limbs. + vm.insert_value( + cell_ref_to_relocatable(remainder_low, vm)?, + remainder.clone() % pow_2_128.clone(), + )?; + vm.insert_value( + cell_ref_to_relocatable(remainder_high, vm)?, + remainder / pow_2_128, + )?; + Ok(()) + } + + fn assert_le_if_first_arc_exclueded( + &self, + vm: &mut VirtualMachine, + skip_exclude_a_flag: &CellRef, + exec_scopes: &mut ExecutionScopes, + ) -> Result<(), HintError> { + let excluded_arc: i32 = exec_scopes.get("excluded_arc")?; + let val = Felt252::from((excluded_arc != 0) as u8); + vm.insert_value(cell_ref_to_relocatable(skip_exclude_a_flag, vm)?, val)?; + Ok(()) + } + + fn linear_split( + &self, + vm: &mut VirtualMachine, + value: &ResOperand, + scalar: &ResOperand, + max_x: &ResOperand, + x: &CellRef, + y: &CellRef, + ) -> Result<(), HintError> { + let value = res_operand_get_val(vm, value)?; + let scalar = res_operand_get_val(vm, scalar)?; + let max_x = res_operand_get_val(vm, max_x)?; + let x_value = (&value / &scalar).min(max_x); + let y_value = value - &x_value * &scalar; + + vm.insert_value(cell_ref_to_relocatable(x, vm)?, x_value) + .map_err(HintError::from)?; + vm.insert_value(cell_ref_to_relocatable(y, vm)?, y_value) + .map_err(HintError::from)?; + + Ok(()) + } + + fn random_ec_point( + &self, + vm: &mut VirtualMachine, + x: &CellRef, + y: &CellRef, + ) -> Result<(), HintError> { + let beta = Fq::from(get_beta().to_biguint()); + + let mut rng = ark_std::test_rng(); + let (random_x, random_y_squared) = loop { + let random_x = Fq::rand(&mut rng); + let random_y_squared = random_x * random_x * random_x + random_x + beta; + if random_y_squared.legendre().is_qr() { + break (random_x, random_y_squared); + } + }; + + let x_bigint: BigUint = random_x.into_bigint().into(); + let y_bigint: BigUint = random_y_squared + .sqrt() + .ok_or(HintError::CustomHint("Failed to compute sqrt".to_string()))? + .into_bigint() + .into(); + + vm.insert_value(cell_ref_to_relocatable(x, vm)?, Felt252::from(x_bigint))?; + vm.insert_value(cell_ref_to_relocatable(y, vm)?, Felt252::from(y_bigint))?; + + Ok(()) + } + + fn get_next_dict_key( + &self, + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + next_key: &CellRef, + ) -> Result<(), HintError> { + let dict_squash_exec_scope: &mut DictSquashExecScope = + exec_scopes.get_mut_ref("dict_squash_exec_scope")?; + dict_squash_exec_scope.pop_current_key()?; + if let Some(current_key) = dict_squash_exec_scope.current_key() { + return vm + .insert_value(cell_ref_to_relocatable(next_key, vm)?, current_key) + .map_err(HintError::from); + } + Err(HintError::KeyNotFound) + } + + fn alloc_felt_256_dict( + &self, + vm: &mut VirtualMachine, + segment_arena_ptr: &ResOperand, + exec_scopes: &mut ExecutionScopes, + ) -> Result<(), HintError> { + let (cell, base_offset) = extract_buffer(segment_arena_ptr)?; + let dict_manager_address = get_ptr(vm, cell, &base_offset)?; + + let n_dicts = vm + .get_integer((dict_manager_address - 2)?)? + .into_owned() + .to_usize() + .ok_or(HintError::CustomHint( + "Invalid number of dictionaries.".to_string(), + ))?; + + let dict_infos_base = vm.get_relocatable((dict_manager_address - 3)?)?; + + let dict_manager_exec_scope = + match exec_scopes.get_mut_ref::("dict_manager_exec_scope") { + Ok(dict_manager_exec_scope) => dict_manager_exec_scope, + Err(_) => { + exec_scopes.assign_or_update_variable( + "dict_manager_exec_scope", + Box::::default(), + ); + exec_scopes.get_mut_ref::("dict_manager_exec_scope")? + } + }; + let new_dict_segment = dict_manager_exec_scope.new_default_dict(vm)?; + vm.insert_value((dict_infos_base + 3 * n_dicts)?, new_dict_segment)?; + + Ok(()) + } + + fn assert_le_is_second_excluded( + &self, + vm: &mut VirtualMachine, + skip_exclude_b_minus_a: &CellRef, + exec_scopes: &mut ExecutionScopes, + ) -> Result<(), HintError> { + let excluded_arc: i32 = exec_scopes.get("excluded_arc")?; + let val = Felt252::from((excluded_arc != 1) as u8); + + vm.insert_value(cell_ref_to_relocatable(skip_exclude_b_minus_a, vm)?, val)?; + + Ok(()) + } + + fn dict_write( + &self, + exec_scopes: &mut ExecutionScopes, + vm: &mut VirtualMachine, + dict_ptr: &ResOperand, + key: &ResOperand, + value: &ResOperand, + ) -> Result<(), HintError> { + let (dict_base, dict_offset) = extract_buffer(dict_ptr)?; + let dict_address = get_ptr(vm, dict_base, &dict_offset)?; + let key = res_operand_get_val(vm, key)?; + let value = res_operand_get_val(vm, value)?; + let dict_manager_exec_scope = + exec_scopes.get_mut_ref::("dict_manager_exec_scope")?; + + let prev_value = dict_manager_exec_scope + .get_from_tracker(dict_address, &key) + .unwrap_or_else(|| DictManagerExecScope::DICT_DEFAULT_VALUE.into()); + + vm.insert_value((dict_address + 1)?, prev_value)?; + dict_manager_exec_scope.insert_to_tracker(dict_address, key, value); + Ok(()) + } + + #[allow(clippy::too_many_arguments)] + fn uint256_square_root( + &self, + vm: &mut VirtualMachine, + value_low: &ResOperand, + value_high: &ResOperand, + sqrt0: &CellRef, + sqrt1: &CellRef, + remainder_low: &CellRef, + remainder_high: &CellRef, + sqrt_mul_2_minus_remainder_ge_u128: &CellRef, + ) -> Result<(), HintError> { + let pow_2_128 = Felt252::from(u128::MAX) + 1u32; + let pow_2_64 = Felt252::from(u64::MAX) + 1u32; + let value_low = res_operand_get_val(vm, value_low)?; + let value_high = res_operand_get_val(vm, value_high)?; + let value = value_low + value_high * &pow_2_128; + let sqrt = value.sqrt(); + let remainder = value - &sqrt * &sqrt; + let sqrt_mul_2_minus_remainder_ge_u128_val = + &sqrt * &Felt252::from(2u32) - &remainder >= pow_2_128; + + let (sqrt1_val, sqrt0_val) = sqrt.div_rem(&pow_2_64); + vm.insert_value(cell_ref_to_relocatable(sqrt0, vm)?, sqrt0_val)?; + vm.insert_value(cell_ref_to_relocatable(sqrt1, vm)?, sqrt1_val)?; + + let (remainder_high_val, remainder_low_val) = remainder.div_rem(&pow_2_128); + + vm.insert_value( + cell_ref_to_relocatable(remainder_low, vm)?, + remainder_low_val, + )?; + vm.insert_value( + cell_ref_to_relocatable(remainder_high, vm)?, + remainder_high_val, + )?; + vm.insert_value( + cell_ref_to_relocatable(sqrt_mul_2_minus_remainder_ge_u128, vm)?, + usize::from(sqrt_mul_2_minus_remainder_ge_u128_val), + )?; + + Ok(()) + } + + fn debug_print( + &self, + vm: &mut VirtualMachine, + start: &ResOperand, + end: &ResOperand, + ) -> Result<(), HintError> { + let mut curr = as_relocatable(vm, start)?; + let end = as_relocatable(vm, end)?; + + #[cfg(not(target_arch = "wasm32"))] + { + while curr != end { + let value = vm.get_integer(curr)?; + if let Some(shortstring) = as_cairo_short_string(&value) { + println!("[DEBUG]\t{shortstring: <31}\t(raw: {value: <31})"); + } else { + println!("[DEBUG]\t{0: <31}\t(raw: {value: <31}) ", ' '); + } + curr += 1; + } + println!(); + } + Ok(()) + } + + fn assert_all_accesses_used( + &self, + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + n_used_accesses: &CellRef, + ) -> Result<(), HintError> { + let key = exec_scopes.get::("key")?; + let n = get_cell_val(vm, n_used_accesses)?; + + let dict_squash_exec_scope: &mut DictSquashExecScope = + exec_scopes.get_mut_ref("dict_squash_exec_scope")?; + + let access_indices_at_key = dict_squash_exec_scope + .access_indices + .get(&key.clone()) + .ok_or_else(|| HintError::NoKeyInAccessIndices(key.clone()))?; + + if n != Felt252::new(access_indices_at_key.len()) { + return Err(HintError::NumUsedAccessesAssertFail( + n, + access_indices_at_key.len(), + key, + )); + } + + Ok(()) + } + + fn should_skip_squash_loop( + &self, + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + should_skip_loop: &CellRef, + ) -> Result<(), HintError> { + let dict_squash_exec_scope: &mut DictSquashExecScope = + exec_scopes.get_mut_ref("dict_squash_exec_scope")?; + + let val = Felt252::from( + (dict_squash_exec_scope + .current_access_indices() + .ok_or(HintError::CustomHint("no indices accessed".to_string()))? + .len() + > 1) as u8, + ); + + vm.insert_value(cell_ref_to_relocatable(should_skip_loop, vm)?, val)?; + + Ok(()) + } +} + +impl HintProcessor for Cairo1HintProcessor { + // Ignores all data except for the code that should contain + fn compile_hint( + &self, + //Block of hint code as String + hint_code: &str, + //Ap Tracking Data corresponding to the Hint + _ap_tracking_data: &crate::serde::deserialize_program::ApTracking, + //Map from variable name to reference id number + //(may contain other variables aside from those used by the hint) + _reference_ids: &HashMap, + //List of all references (key corresponds to element of the previous dictionary) + _references: &HashMap, + ) -> Result, VirtualMachineError> { + let data = hint_code.parse().ok().and_then(|x: usize| self.hints.get(&x).cloned()).ok_or(VirtualMachineError::CompileHintFail(format!("No hint found for pc {}. Cairo1HintProccesor can only be used when running CasmContractClass", hint_code)))?; + Ok(any_box!(data)) + } + + // Executes all the hints for a given pc + fn execute_hint( + &mut self, + //Proxy to VM, contains refrences to necessary data + //+ MemoryProxy, which provides the necessary methods to manipulate memory + vm: &mut VirtualMachine, + //Proxy to ExecutionScopes, provides the necessary methods to manipulate the scopes and + //access current scope variables + exec_scopes: &mut ExecutionScopes, + //Data structure that can be downcasted to the structure generated by compile_hint + hint_data: &Box, + //Constant values extracted from the program specification. + _constants: &HashMap, + ) -> Result<(), HintError> { + let hints: &Vec = hint_data.downcast_ref().ok_or(HintError::WrongHintData)?; + for hint in hints { + self.execute(vm, exec_scopes, hint)?; + } + Ok(()) + } +} diff --git a/src/hint_processor/cairo_1_hint_processor/hint_processor_utils.rs b/src/hint_processor/cairo_1_hint_processor/hint_processor_utils.rs new file mode 100644 index 0000000000..82d7942c43 --- /dev/null +++ b/src/hint_processor/cairo_1_hint_processor/hint_processor_utils.rs @@ -0,0 +1,108 @@ +use crate::stdlib::prelude::*; +use crate::types::{errors::math_errors::MathError, relocatable::Relocatable}; +use crate::vm::errors::{hint_errors::HintError, vm_errors::VirtualMachineError}; +use crate::vm::vm_core::VirtualMachine; +use cairo_lang_casm::operand::{CellRef, DerefOrImmediate, Operation, Register, ResOperand}; +use felt::Felt252; +/// Extracts a parameter assumed to be a buffer. +pub(crate) fn extract_buffer(buffer: &ResOperand) -> Result<(&CellRef, Felt252), HintError> { + let (cell, base_offset) = match buffer { + ResOperand::Deref(cell) => (cell, 0.into()), + ResOperand::BinOp(bin_op) => { + if let DerefOrImmediate::Immediate(val) = &bin_op.b { + (&bin_op.a, val.clone().value.into()) + } else { + return Err(HintError::CustomHint("Failed to extract buffer, expected ResOperand of BinOp type to have Inmediate b value".to_owned())); + } + } + _ => { + return Err(HintError::CustomHint( + "Illegal argument for a buffer.".to_string(), + )) + } + }; + Ok((cell, base_offset)) +} + +pub(crate) fn cell_ref_to_relocatable( + cell_ref: &CellRef, + vm: &VirtualMachine, +) -> Result { + let base = match cell_ref.register { + Register::AP => vm.get_ap(), + Register::FP => vm.get_fp(), + }; + base + (cell_ref.offset as i32) +} + +pub(crate) fn get_cell_val( + vm: &VirtualMachine, + cell: &CellRef, +) -> Result { + Ok(vm + .get_integer(cell_ref_to_relocatable(cell, vm)?)? + .as_ref() + .clone()) +} + +pub(crate) fn get_ptr( + vm: &VirtualMachine, + cell: &CellRef, + offset: &Felt252, +) -> Result { + Ok((vm.get_relocatable(cell_ref_to_relocatable(cell, vm)?)? + offset)?) +} + +pub(crate) fn as_relocatable( + vm: &mut VirtualMachine, + value: &ResOperand, +) -> Result { + let (base, offset) = extract_buffer(value)?; + get_ptr(vm, base, &offset).map_err(HintError::from) +} + +pub(crate) fn get_double_deref_val( + vm: &VirtualMachine, + cell: &CellRef, + offset: &Felt252, +) -> Result { + Ok(vm.get_integer(get_ptr(vm, cell, offset)?)?.as_ref().clone()) +} + +/// Fetches the value of `res_operand` from the vm. +pub(crate) fn res_operand_get_val( + vm: &VirtualMachine, + res_operand: &ResOperand, +) -> Result { + match res_operand { + ResOperand::Deref(cell) => get_cell_val(vm, cell), + ResOperand::DoubleDeref(cell, offset) => get_double_deref_val(vm, cell, &(*offset).into()), + ResOperand::Immediate(x) => Ok(Felt252::from(x.value.clone())), + ResOperand::BinOp(op) => { + let a = get_cell_val(vm, &op.a)?; + let b = match &op.b { + DerefOrImmediate::Deref(cell) => get_cell_val(vm, cell)?, + DerefOrImmediate::Immediate(x) => Felt252::from(x.value.clone()), + }; + match op.op { + Operation::Add => Ok(a + b), + Operation::Mul => Ok(a * b), + } + } + } +} + +pub(crate) fn as_cairo_short_string(value: &Felt252) -> Option { + let mut as_string = String::default(); + let mut is_end = false; + for byte in value.to_bytes_be() { + if byte == 0 { + is_end = true; + } else if is_end || !byte.is_ascii() { + return None; + } else { + as_string.push(byte as char); + } + } + Some(as_string) +} diff --git a/src/hint_processor/cairo_1_hint_processor/mod.rs b/src/hint_processor/cairo_1_hint_processor/mod.rs new file mode 100644 index 0000000000..29d5f47bd3 --- /dev/null +++ b/src/hint_processor/cairo_1_hint_processor/mod.rs @@ -0,0 +1,3 @@ +pub mod dict_manager; +pub mod hint_processor; +pub mod hint_processor_utils; diff --git a/src/hint_processor/mod.rs b/src/hint_processor/mod.rs index 095e3314a8..baba16f490 100644 --- a/src/hint_processor/mod.rs +++ b/src/hint_processor/mod.rs @@ -1,3 +1,5 @@ pub mod builtin_hint_processor; +#[cfg(feature = "cairo-1-hints")] +pub mod cairo_1_hint_processor; pub mod hint_processor_definition; pub mod hint_processor_utils; diff --git a/src/tests/cairo_1_run_from_entrypoint_tests.rs b/src/tests/cairo_1_run_from_entrypoint_tests.rs new file mode 100644 index 0000000000..da6432e7d8 --- /dev/null +++ b/src/tests/cairo_1_run_from_entrypoint_tests.rs @@ -0,0 +1,25 @@ +use crate::tests::*; + +#[test] +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +fn fibonacci_1() { + let program_data = include_bytes!("../../cairo_programs/cairo-1-contracts/fib.casm"); + run_cairo_1_entrypoint( + program_data.as_slice(), + 0, + &[1_usize.into(), 1_usize.into(), 1_usize.into()], + &[1_usize.into()], + ); +} + +#[test] +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +fn fibonacci_3() { + let program_data = include_bytes!("../../cairo_programs/cairo-1-contracts/fib.casm"); + run_cairo_1_entrypoint( + program_data.as_slice(), + 0, + &[3_usize.into(), 3_usize.into(), 3_usize.into()], + &[9_usize.into()], + ); +} diff --git a/src/tests/mod.rs b/src/tests/mod.rs index f2f77ecd79..bb853ea15c 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -1,3 +1,17 @@ +#[cfg(feature = "cairo-1-hints")] +use crate::{ + hint_processor::cairo_1_hint_processor::hint_processor::Cairo1HintProcessor, + types::relocatable::MaybeRelocatable, + vm::{ + runners::cairo_runner::{CairoArg, CairoRunner}, + vm_core::VirtualMachine, + }, +}; +#[cfg(feature = "cairo-1-hints")] +use cairo_lang_starknet::casm_contract_class::CasmContractClass; +#[cfg(feature = "cairo-1-hints")] +use felt::Felt252; + use crate::stdlib::prelude::*; use crate::{ @@ -10,6 +24,9 @@ use crate::{ use wasm_bindgen_test::*; mod bitwise_test; + +#[cfg(feature = "cairo-1-hints")] +mod cairo_1_run_from_entrypoint_tests; mod cairo_run_test; mod pedersen_test; mod struct_test; @@ -79,3 +96,112 @@ pub(self) fn run_program( assert_eq!(runner.get_memory_holes(&vm).unwrap(), holes); } } + +#[cfg(feature = "cairo-1-hints")] +// Runs a contract entrypoint with given arguments and checks its return values +// Doesn't use a syscall_handler +pub(self) fn run_cairo_1_entrypoint( + program_content: &[u8], + entrypoint_offset: usize, + args: &[MaybeRelocatable], + expected_retdata: &[Felt252], +) { + let contract_class: CasmContractClass = serde_json::from_slice(program_content).unwrap(); + let mut hint_processor = Cairo1HintProcessor::new(&contract_class.hints); + + let mut runner = CairoRunner::new( + &(contract_class.clone().try_into().unwrap()), + "all_cairo", + false, + ) + .unwrap(); + let mut vm = VirtualMachine::new(false); + + runner.initialize_function_runner(&mut vm, true).unwrap(); + + // Get builtin bases + // Extract builtins from CasmContractClass entrypoint data from the entrypoint which's offset is being ran + let builtins: Vec = contract_class + .entry_points_by_type + .external + .iter() + .find(|e| e.offset == entrypoint_offset) + .unwrap() + .builtins + .iter() + .map(|n| format!("{}_builtin", n)) + .collect(); + + // Implicit Args + let syscall_segment = MaybeRelocatable::from(vm.add_memory_segment()); + + let builtin_segment: Vec = vm + .get_builtin_runners() + .iter() + .filter(|b| builtins.contains(&(b.name().to_string()))) + .flat_map(|b| b.initial_stack()) + .collect(); + + let initial_gas = MaybeRelocatable::from(usize::MAX); + + let mut implicit_args = builtin_segment; + implicit_args.extend([initial_gas]); + implicit_args.extend([syscall_segment]); + + // Other args + + // Load builtin costs + let builtin_costs: Vec = + vec![0.into(), 0.into(), 0.into(), 0.into(), 0.into()]; + let builtin_costs_ptr = vm.add_memory_segment(); + vm.load_data(builtin_costs_ptr, &builtin_costs).unwrap(); + + // Load extra data + let core_program_end_ptr = + (runner.program_base.unwrap() + runner.program.shared_program_data.data.len()).unwrap(); + let program_extra_data: Vec = + vec![0x208B7FFF7FFF7FFE.into(), builtin_costs_ptr.into()]; + vm.load_data(core_program_end_ptr, &program_extra_data) + .unwrap(); + + // Load calldata + let calldata_start = vm.add_memory_segment(); + let calldata_end = vm.load_data(calldata_start, &args.to_vec()).unwrap(); + + // Create entrypoint_args + + let mut entrypoint_args: Vec = implicit_args + .iter() + .map(|m| CairoArg::from(m.clone())) + .collect(); + entrypoint_args.extend([ + MaybeRelocatable::from(calldata_start).into(), + MaybeRelocatable::from(calldata_end).into(), + ]); + let entrypoint_args: Vec<&CairoArg> = entrypoint_args.iter().collect(); + + // Run contract entrypoint + + runner + .run_from_entrypoint( + entrypoint_offset, + &entrypoint_args, + true, + Some(runner.program.shared_program_data.data.len() + program_extra_data.len()), + &mut vm, + &mut hint_processor, + ) + .unwrap(); + + // Check return values + let return_values = vm.get_return_values(5).unwrap(); + let retdata_start = return_values[3].get_relocatable().unwrap(); + let retdata_end = return_values[4].get_relocatable().unwrap(); + let retdata: Vec = vm + .get_integer_range(retdata_start, (retdata_end - retdata_start).unwrap()) + .unwrap() + .iter() + .map(|c| c.clone().into_owned()) + .collect(); + assert_eq!(expected_retdata, &retdata); +} diff --git a/src/types/program.rs b/src/types/program.rs index 3d29aeaa60..26750a179f 100644 --- a/src/types/program.rs +++ b/src/types/program.rs @@ -1,5 +1,7 @@ use crate::stdlib::{collections::HashMap, prelude::*, sync::Arc}; +#[cfg(feature = "cairo-1-hints")] +use crate::serde::deserialize_program::{ApTracking, FlowTrackingData}; use crate::{ serde::deserialize_program::{ deserialize_and_parse_program, Attribute, BuiltinName, HintParams, Identifier, @@ -7,6 +9,8 @@ use crate::{ }, types::{errors::program_errors::ProgramError, relocatable::MaybeRelocatable}, }; +#[cfg(feature = "cairo-1-hints")] +use cairo_lang_starknet::casm_contract_class::CasmContractClass; use felt::{Felt252, PRIME_STR}; #[cfg(feature = "std")] @@ -145,6 +149,52 @@ impl Default for Program { } } +#[cfg(feature = "cairo-1-hints")] +// Note: This Program will only work when using run_from_entrypoint, and the Cairo1Hintprocesso +impl TryFrom for Program { + type Error = ProgramError; + fn try_from(value: CasmContractClass) -> Result { + let data = value + .bytecode + .iter() + .map(|x| MaybeRelocatable::from(Felt252::from(&x.value))) + .collect(); + //Hint data is going to be hosted processor-side, hints field will only store the pc where hints are located. + // Only one pc will be stored, so the hint processor will be responsible for executing all hints for a given pc + let hints = value + .hints + .iter() + .map(|(x, _)| { + ( + *x, + vec![HintParams { + code: x.to_string(), + accessible_scopes: Vec::new(), + flow_tracking_data: FlowTrackingData { + ap_tracking: ApTracking::default(), + reference_ids: HashMap::new(), + }, + }], + ) + }) + .collect(); + let error_message_attributes = Vec::new(); + let reference_manager = ReferenceManager { + references: Vec::new(), + }; + Self::new( + vec![], + data, + None, + hints, + reference_manager, + HashMap::new(), + error_message_attributes, + None, + ) + } +} + #[cfg(test)] mod tests { use super::*;