From 5e60089288c461eca98bf3dbe03cc882778ff677 Mon Sep 17 00:00:00 2001 From: Edgar Date: Wed, 20 Nov 2024 16:05:44 +0100 Subject: [PATCH] cairo 2.9.0-dev (native v0.2.3 branch) (#877) * update to cairo 2.9.0-dev * compile * avoid semver auto update * Implement get_class_hash_at syscall (#880) * implement get_class_hash_at syscall * fix * int range * upd * add fixes * fix test * fi * Version 0.2.2-alpha.0 * fix * ci * upd replay * fix * fix * fixes * seq rev * version 0.2.3 * update ci * fix * readme * Update examples/erc20.rs Co-authored-by: MrAzteca * Update examples/starknet.rs Co-authored-by: MrAzteca * edits * native panic --------- Co-authored-by: Pedro Fontana Co-authored-by: MrAzteca --- .github/workflows/daily.yml | 2 +- .github/workflows/starknet-blocks.yml | 4 +- Cargo.lock | 184 +++++++++++-------- Cargo.toml | 36 ++-- Makefile | 2 +- README.md | 2 +- examples/erc20.rs | 8 + examples/starknet.rs | 8 + runtime/Cargo.toml | 4 +- scripts/bench-hyperfine.sh | 1 - src/bin/cairo-native-test.rs | 18 +- src/bin/utils/mod.rs | 1 + src/debug.rs | 6 + src/executor.rs | 2 + src/executor/contract.rs | 4 +- src/libfuncs.rs | 4 + src/libfuncs/int_range.rs | 181 ++++++++++++++++++ src/libfuncs/starknet.rs | 161 ++++++++++++++++ src/starknet.rs | 45 ++++- src/starknet_stub.rs | 8 + src/types.rs | 23 ++- src/types/int_range.rs | 46 +++++ src/values.rs | 59 ++++++ tests/common.rs | 27 +-- tests/tests/starknet/keccak.rs | 2 +- tests/tests/starknet/programs/syscalls.cairo | 7 +- tests/tests/starknet/secp256.rs | 8 + tests/tests/starknet/syscalls.rs | 28 +++ 28 files changed, 754 insertions(+), 127 deletions(-) create mode 100644 src/libfuncs/int_range.rs create mode 100644 src/types/int_range.rs diff --git a/.github/workflows/daily.yml b/.github/workflows/daily.yml index afc85ace7..b8f26d7f1 100644 --- a/.github/workflows/daily.yml +++ b/.github/workflows/daily.yml @@ -7,7 +7,7 @@ on: env: RANGE_SIZE: 25 - SEQUENCER_REV: 93b6da848802297626556950a0c715952aca552d + SEQUENCER_REV: 8d3e6b5515e7b62e7ab173026b2c81c750dbb853 jobs: run: diff --git a/.github/workflows/starknet-blocks.yml b/.github/workflows/starknet-blocks.yml index 74d9df246..50f1b2759 100644 --- a/.github/workflows/starknet-blocks.yml +++ b/.github/workflows/starknet-blocks.yml @@ -27,7 +27,7 @@ jobs: components: clippy - uses: Swatinem/rust-cache@v2 with: - key: "ref-3da09d1b6f3d5c089900f5521cf05b6444893e61" + key: "ref-16302c859b1aacc019eea154a58eddc7b32050c1" - name: Check and free hdd space left if: ${{ matrix.runner == 'native' }} @@ -76,7 +76,7 @@ jobs: uses: actions/checkout@v4 with: repository: lambdaclass/starknet-replay - ref: 3da09d1b6f3d5c089900f5521cf05b6444893e61 + ref: 16302c859b1aacc019eea154a58eddc7b32050c1 path: replay - name: Install Starknet Replay deps diff --git a/Cargo.lock b/Cargo.lock index 54aafac03..ad90db644 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -427,9 +427,9 @@ dependencies = [ [[package]] name = "cairo-lang-casm" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd4d6659539ace9649c8e8a7434e51b0c50a7a700111d0a2b967dde220ddff49" +checksum = "e1e0dcdb6358bb639dd729546611bd99bada94c86e3f262c3637855abea9a972" dependencies = [ "cairo-lang-utils", "indoc", @@ -441,9 +441,9 @@ dependencies = [ [[package]] name = "cairo-lang-compiler" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2016966ed29f3a44487fd1bbdb05320fb6ea8ec46201c04c6b222ccb5264e0a" +checksum = "b8657f5a5611f341a85e80ba0b21848fc34bfdf391bfd93df0baf4516c3e4159" dependencies = [ "anyhow", "cairo-lang-defs", @@ -467,18 +467,18 @@ dependencies = [ [[package]] name = "cairo-lang-debug" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c804649297ca417206435ee3e8041d2100cc31ebf4a95bc4b92ed02dc63469" +checksum = "0635aa554d297acefe6a35b495aba2795d0af5b7f97c4ab63829c7d62291ef41" dependencies = [ "cairo-lang-utils", ] [[package]] name = "cairo-lang-defs" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8fbda467ac36f73bb1879e1f741898fc719d6f9239a01cc422e6a023281319b" +checksum = "86b356e1c09898e8b8cfdd9731579d89365a13d8b4f7e717962e0cc7d125b83c" dependencies = [ "cairo-lang-debug", "cairo-lang-diagnostics", @@ -493,9 +493,9 @@ dependencies = [ [[package]] name = "cairo-lang-diagnostics" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c843ef4715e3d21de5388d02206db2506e2d2ec0e80e2629e0ae9900a08b8674" +checksum = "2dfe7c6ff96182da29012b707a3554e34a50f19cc96013ee45b0eb36dd396ec8" dependencies = [ "cairo-lang-debug", "cairo-lang-filesystem", @@ -505,9 +505,9 @@ dependencies = [ [[package]] name = "cairo-lang-eq-solver" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33a416c5871960fb4823160ebef2abc51e0c1b86fef1e97a1ebb2e5f3c3795d3" +checksum = "723d244465309d5409e297b5486d62cbec06f2c47b05044414bb640e3f14caab" dependencies = [ "cairo-lang-utils", "good_lp", @@ -515,9 +515,9 @@ dependencies = [ [[package]] name = "cairo-lang-filesystem" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47189e0cb84b21defd201af4cf24a94c6b0d09f48706cf659c9ffa0def8a7a43" +checksum = "237030772ae5368f19a9247e1f63f753f8ad8de963477166e402f4825c0a141d" dependencies = [ "cairo-lang-debug", "cairo-lang-utils", @@ -526,13 +526,14 @@ dependencies = [ "semver", "serde", "smol_str", + "toml", ] [[package]] name = "cairo-lang-formatter" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6409ff1f4a93ce7c0968d9d857d2a8c03657617a827159d33f978110b718b31d" +checksum = "5b71f0eb3a36a6cb5f7f07843926783c4c17e44c9516b53171727a108782f3eb" dependencies = [ "anyhow", "cairo-lang-diagnostics", @@ -545,15 +546,14 @@ dependencies = [ "itertools 0.12.1", "rust-analyzer-salsa", "serde", - "smol_str", "thiserror", ] [[package]] name = "cairo-lang-lowering" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e224e006c82ef21bd9e243390992de2be25ae6fbbdaa8544067b3f0c31977f1" +checksum = "7d095d78e2f1de499429c95655d6135a3d24c384b36d8de9f84e0aa4e07ee152" dependencies = [ "cairo-lang-debug", "cairo-lang-defs", @@ -568,6 +568,7 @@ dependencies = [ "itertools 0.12.1", "log", "num-bigint", + "num-integer", "num-traits 0.2.19", "rust-analyzer-salsa", "smol_str", @@ -575,9 +576,9 @@ dependencies = [ [[package]] name = "cairo-lang-parser" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb260ba349c2b699639e56f9b64deb969ff01179a0253087e2c8ceec7e32157" +checksum = "bb828af7f948a3ef7fa65de14e3f639daedefb046dfefcad6e3116d2cb0f89a0" dependencies = [ "cairo-lang-diagnostics", "cairo-lang-filesystem", @@ -595,9 +596,9 @@ dependencies = [ [[package]] name = "cairo-lang-plugins" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05a2e500dc8ddea4d25a866d8a839158b0e4c41a6c023f21911e2da252bd91b3" +checksum = "135a600043bf7030eacc6ebf2a609c2364d6ffeb04e1f3c809a2738f6b02c829" dependencies = [ "cairo-lang-defs", "cairo-lang-diagnostics", @@ -614,9 +615,9 @@ dependencies = [ [[package]] name = "cairo-lang-proc-macros" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d72f17373740f242d6995e896b9195c2cedff7e8b14e496afdd16b405039d1fb" +checksum = "ac857ec4b564712f3e16e3314e23cc0787ab1c05cdfee83f1c8f9989a6eee40f" dependencies = [ "cairo-lang-debug", "quote", @@ -625,9 +626,9 @@ dependencies = [ [[package]] name = "cairo-lang-project" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13294f08d2013fcd6e815e7235935680963dec3390e5baf454f33da866fc44b6" +checksum = "23cc37b7f8889cdea631aeea3bcc70d5c86ac8fb1d98aabc83f16283d60f1643" dependencies = [ "cairo-lang-filesystem", "cairo-lang-utils", @@ -639,9 +640,9 @@ dependencies = [ [[package]] name = "cairo-lang-runner" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5b9e6a21d92255b92f64c60658b4224dd7d290cde8beea783fadc10fbfcd8c" +checksum = "7474375528ffa7f47e343983d32051898e4e7b05ac0bdc48ee84b1325d8b562a" dependencies = [ "ark-ff", "ark-secp256k1", @@ -655,7 +656,7 @@ dependencies = [ "cairo-lang-sierra-type-size", "cairo-lang-starknet", "cairo-lang-utils", - "cairo-vm", + "cairo-vm 1.0.1", "itertools 0.12.1", "keccak", "num-bigint", @@ -670,9 +671,9 @@ dependencies = [ [[package]] name = "cairo-lang-semantic" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6936215bca75c23e71873998420a3d46c322507a09917ce676c8d39f8c1bd6fe" +checksum = "c560cf4b4a89325d3a9594f490fffee38cf30e0990e808bb927619de9d0c973a" dependencies = [ "cairo-lang-debug", "cairo-lang-defs", @@ -696,9 +697,9 @@ dependencies = [ [[package]] name = "cairo-lang-sierra" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "424f55450494e959c1ae26c52a71075767a90f76e3ecca6e81056dd7517e8ba0" +checksum = "8118f55ca7d567bfc60960b445d388564d04bf48335c983b1595cb35f67a01c5" dependencies = [ "anyhow", "cairo-lang-utils", @@ -723,9 +724,9 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-ap-change" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053dd520e0b9d1c1078d93ea69045f6f334c3d41b4b75db183ab33e32cfd8570" +checksum = "2716ef8d4ce0fb700f83ed3281f3656436570e60249d41c65c79dc1ca27be002" dependencies = [ "cairo-lang-eq-solver", "cairo-lang-sierra", @@ -739,9 +740,9 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-gas" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a73227867377efc62ebb893cddaa88df3940bf2be5dbdc2f0b00f9edf69288e" +checksum = "24a44da87a35845470c4f4c648225232a15e0875fe809045b6088464491f838b" dependencies = [ "cairo-lang-eq-solver", "cairo-lang-sierra", @@ -755,9 +756,9 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-generator" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3752cacd475ea089d9a536357804150e693a124e703fcc33a55566d568094b3" +checksum = "15bc5cf9f3965a7030a114dfe3d31d183287fbfbfbf904deaaa2468cadb936aa" dependencies = [ "cairo-lang-debug", "cairo-lang-defs", @@ -779,9 +780,9 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-to-casm" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7162fb3c93960dfc6d8005b65064e518e3f1ed6102e8981b42ea41879c331184" +checksum = "18b7616f1a3c41c4646094b5abf774e558428e9c1eda5d78d7b0638ec5c264e5" dependencies = [ "assert_matches", "cairo-lang-casm", @@ -800,9 +801,9 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-type-size" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a51b80c117e2b05a6d300f2e2247892cc99e42e950e79f6085e6ed6cbcb44d12" +checksum = "871077dbc08df5d134dc3975538171c14b266ba405d1298085afdb227216f0a3" dependencies = [ "cairo-lang-sierra", "cairo-lang-utils", @@ -810,9 +811,9 @@ dependencies = [ [[package]] name = "cairo-lang-starknet" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aafaabc43f78dfa2f45d935993ba21c05c164bbb3bf277d348847a51e5939a9f" +checksum = "9f21804eb8931d41e258e7a393afc8ee8858308e95b3ed2e9b6b469ef68a6a50" dependencies = [ "anyhow", "cairo-lang-compiler", @@ -840,9 +841,9 @@ dependencies = [ [[package]] name = "cairo-lang-starknet-classes" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "832fd9072ddf4204ca6d227c0238929349f10146bd066a98025d51ac15d27fad" +checksum = "b2496bccd68fa0286b35b72c98439316a3a872ef7ec6d881f0dac90b17997490" dependencies = [ "cairo-lang-casm", "cairo-lang-sierra", @@ -863,9 +864,9 @@ dependencies = [ [[package]] name = "cairo-lang-syntax" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cebe67c0d68f9acf8709d170c1308ca57a778d22f70da38a57f74ae250eee28a" +checksum = "8d77ea2e35d3610098ff13e373fc519aedc6a5096ed8547081aacfc104ef4422" dependencies = [ "cairo-lang-debug", "cairo-lang-filesystem", @@ -879,9 +880,9 @@ dependencies = [ [[package]] name = "cairo-lang-syntax-codegen" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31cef5b4347626e61bad8f070495cd35d637a5cb6744c34d20dd382c7431aff8" +checksum = "6b01d505ab26ca9ce829faf3a8dd097f5d7962d2eb8f136017a260694a6a72e8" dependencies = [ "genco", "xshell", @@ -889,9 +890,9 @@ dependencies = [ [[package]] name = "cairo-lang-test-plugin" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d5f036132e07b7829cb1d61b1ecc02789a70c7d16b2733722a2aca992492bc3" +checksum = "05f83e082c8ebf81295156f13399f880037c749a9f1fc3f55b1be7e49fe124c6" dependencies = [ "anyhow", "cairo-lang-compiler", @@ -916,9 +917,9 @@ dependencies = [ [[package]] name = "cairo-lang-test-utils" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "060c61ac4a3ae0428771244ff8db903105f127392b7d725d919fe3fb1ec4132f" +checksum = "eb143a22f5a3510df8c4dec76e17c1e36bbcbddcd7915601f6a51a72418c454f" dependencies = [ "cairo-lang-formatter", "cairo-lang-utils", @@ -929,9 +930,9 @@ dependencies = [ [[package]] name = "cairo-lang-utils" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bfc6372538143afad658c853a35bdc9f5210c5cb54e0c8f04ab78e268139466" +checksum = "35df943ebcf8e1db11ee9f4f46f843dde5b71639ca79ea0d8caa7973f91d8b12" dependencies = [ "hashbrown 0.14.5", "indexmap 2.6.0", @@ -944,7 +945,7 @@ dependencies = [ [[package]] name = "cairo-native" -version = "0.2.0-alpha.4" +version = "0.2.3" dependencies = [ "anyhow", "aquamarine", @@ -967,7 +968,7 @@ dependencies = [ "cairo-lang-test-plugin", "cairo-lang-utils", "cairo-native-runtime", - "cairo-vm", + "cairo-vm 2.0.0-rc0", "cc", "clap", "colored", @@ -1007,7 +1008,7 @@ dependencies = [ [[package]] name = "cairo-native-runtime" -version = "0.2.0-alpha.4" +version = "0.2.3" dependencies = [ "cairo-lang-sierra-gas", "itertools 0.13.0", @@ -1023,6 +1024,37 @@ name = "cairo-vm" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58363ad8065ed891e3b14a8191b707677c7c7cb5b9d10030822506786d8d8108" +dependencies = [ + "anyhow", + "bincode", + "bitvec", + "generic-array", + "hashbrown 0.14.5", + "hex", + "keccak", + "lazy_static", + "nom", + "num-bigint", + "num-integer", + "num-prime", + "num-traits 0.2.19", + "rand", + "rust_decimal", + "serde", + "serde_json", + "sha2", + "sha3", + "starknet-crypto", + "starknet-types-core", + "thiserror-no-std", + "zip", +] + +[[package]] +name = "cairo-vm" +version = "2.0.0-rc0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db4375450795765e55bf6c58974b26742a1a3935afd07f996062d7d2e545b4a4" dependencies = [ "anyhow", "ark-ff", @@ -1051,6 +1083,7 @@ dependencies = [ "starknet-crypto", "starknet-types-core", "thiserror-no-std", + "wasm-bindgen", "zip", ] @@ -2132,9 +2165,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.72" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] @@ -3898,20 +3931,19 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.95" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", - "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.95" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", @@ -3924,9 +3956,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.95" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3934,9 +3966,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.95" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", @@ -3947,15 +3979,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.95" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "web-sys" -version = "0.3.72" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/Cargo.toml b/Cargo.toml index cd5988623..01020d53e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cairo-native" -version = "0.2.0-alpha.4" +version = "0.2.3" edition = "2021" license = "Apache-2.0" description = "A compiler to convert Cairo's intermediate representation Sierra code to MLIR." @@ -59,12 +59,12 @@ normal = ["aquamarine"] [dependencies] aquamarine = "0.5.0" bumpalo = "3.16.0" -cairo-lang-compiler = "2.8.4" -cairo-lang-defs = "2.8.4" -cairo-lang-filesystem = "2.8.4" -cairo-lang-semantic = "2.8.4" -cairo-lang-sierra = "2.8.4" -cairo-lang-sierra-generator = "2.8.4" +cairo-lang-compiler = "2.9.0-dev.0" +cairo-lang-defs = "2.9.0-dev.0" +cairo-lang-filesystem = "2.9.0-dev.0" +cairo-lang-semantic = "2.9.0-dev.0" +cairo-lang-sierra = "2.9.0-dev.0" +cairo-lang-sierra-generator = "2.9.0-dev.0" educe = "0.5.11" # can't update until https://github.com/magiclen/educe/issues/27 itertools = "0.13.0" lazy_static = "1.5" @@ -86,12 +86,12 @@ utf8_iter = "1.0.4" # CLI dependencies -cairo-lang-sierra-ap-change = "2.8.4" -cairo-lang-sierra-gas = "2.8.4" -cairo-lang-starknet = "2.8.4" -cairo-lang-utils = "2.8.4" -cairo-lang-starknet-classes = "2.8.4" -cairo-native-runtime = { version = "0.2.0-alpha.4", path = "runtime", optional = true } +cairo-lang-sierra-ap-change = "2.9.0-dev.0" +cairo-lang-sierra-gas = "2.9.0-dev.0" +cairo-lang-starknet = "2.9.0-dev.0" +cairo-lang-utils = "2.9.0-dev.0" +cairo-lang-starknet-classes = "2.9.0-dev.0" +cairo-native-runtime = { version = "0.2.3", path = "runtime", optional = true } clap = { version = "4.5.19", features = ["derive"], optional = true } libloading = "0.8.5" tracing-subscriber = { version = "0.3.18", features = [ @@ -101,8 +101,8 @@ tracing-subscriber = { version = "0.3.18", features = [ ], optional = true } serde = { version = "1.0", features = ["derive"] } anyhow = { version = "1.0", optional = true } -cairo-lang-test-plugin = { version = "2.8.4", optional = true } -cairo-lang-runner = { version = "2.8.4", optional = true } +cairo-lang-test-plugin = { version = "2.9.0-dev.0", optional = true } +cairo-lang-runner = { version = "2.9.0-dev.0", optional = true } colored = { version = "2.1.0", optional = true } # needed to interface with cairo-lang-* keccak = "0.1.5" @@ -120,9 +120,9 @@ ark-ff = "0.4.2" num-integer = "0.1.46" [dev-dependencies] -cairo-vm = { version = "1.0.1", features = ["cairo-1-hints"] } -cairo-lang-runner = "2.8.4" -cairo-lang-semantic = { version = "2.8.4", features = ["testing"] } +cairo-vm = { version = "2.0.0-rc0", features = ["cairo-1-hints"] } +cairo-lang-runner = "2.9.0-dev.0" +cairo-lang-semantic = { version = "2.9.0-dev.0", features = ["testing"] } criterion = { version = "0.5.1", features = ["html_reports"] } lambdaworks-math = "0.10.0" pretty_assertions_sorted = "1.2.3" diff --git a/Makefile b/Makefile index 6c6c75318..b028dbcd2 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # Environment detection. UNAME := $(shell uname) -CAIRO_2_VERSION = 2.8.4 +CAIRO_2_VERSION = 2.9.0-dev.0 SCARB_VERSION = 2.8.4 # Usage is the default target for newcomers running `make`. diff --git a/README.md b/README.md index 9a831e594..80ccd68d8 100644 --- a/README.md +++ b/README.md @@ -350,7 +350,7 @@ Options: ### Requirements - [hyperfine](https://github.com/sharkdp/hyperfine): `cargo install hyperfine` -- [cairo 2.8.2](https://github.com/starkware-libs/cairo) +- [cairo 2.9.0-dev.0](https://github.com/starkware-libs/cairo) - Cairo Corelibs - LLVM 19 with MLIR diff --git a/examples/erc20.rs b/examples/erc20.rs index 346b4decf..b36d2947d 100644 --- a/examples/erc20.rs +++ b/examples/erc20.rs @@ -274,6 +274,14 @@ impl StarknetSyscallHandler for SyscallHandler { ) -> SyscallResult<()> { unimplemented!() } + + fn get_class_hash_at( + &mut self, + _contract_address: Felt, + _remaining_gas: &mut u64, + ) -> SyscallResult { + unimplemented!() + } } fn main() { diff --git a/examples/starknet.rs b/examples/starknet.rs index 2a9c570e7..e64716325 100644 --- a/examples/starknet.rs +++ b/examples/starknet.rs @@ -405,6 +405,14 @@ impl StarknetSyscallHandler for SyscallHandler { ) -> SyscallResult<()> { unimplemented!() } + + fn get_class_hash_at( + &mut self, + _contract_address: Felt, + _remaining_gas: &mut u64, + ) -> SyscallResult { + unimplemented!() + } } fn main() { diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index cdf46ad32..ac403ac91 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cairo-native-runtime" -version = "0.2.0-alpha.4" +version = "0.2.3" description = "The runtime for cairo-native." edition = "2021" license = "Apache-2.0" @@ -15,7 +15,7 @@ starknet-types-core = { version = "0.1.7", default-features = false, features = "serde", "hash", ] } -cairo-lang-sierra-gas = "2.8.4" +cairo-lang-sierra-gas = "2.9.0-dev.0" starknet-curve = "0.5.1" lazy_static = "1.5.0" rand = "0.8.5" diff --git a/scripts/bench-hyperfine.sh b/scripts/bench-hyperfine.sh index 473c67265..aa02a1e94 100755 --- a/scripts/bench-hyperfine.sh +++ b/scripts/bench-hyperfine.sh @@ -57,7 +57,6 @@ run_bench() { -L"$OUTPUT_DIR/" \ -Wl,-rpath "$MLIR_DIR/lib" \ -Wl,-rpath "$OUTPUT_DIR" \ - -Wl,--rpath-link "$OUTPUT_DIR" \ -l"$base_name" \ -lm \ -o "$OUTPUT_DIR/$base_name-march-native" \ diff --git a/src/bin/cairo-native-test.rs b/src/bin/cairo-native-test.rs index b69a48b5c..cb39f4f8d 100644 --- a/src/bin/cairo-native-test.rs +++ b/src/bin/cairo-native-test.rs @@ -1,6 +1,7 @@ use anyhow::bail; use cairo_lang_compiler::{ db::RootDatabase, + diagnostics::DiagnosticsReporter, project::{check_compiler_path, setup_project}, }; use cairo_lang_filesystem::cfg::{Cfg, CfgSet}; @@ -83,15 +84,18 @@ fn main() -> anyhow::Result<()> { starknet: args.starknet, add_statements_functions: false, add_statements_code_locations: false, + contract_declarations: None, + contract_crate_ids: None, + executable_crate_ids: None, }; - let build_test_compilation = compile_test_prepared_db( - &db, - test_config, - main_crate_ids.clone(), - test_crate_ids.clone(), - args.allow_warnings, - )?; + let mut diag_reporter = DiagnosticsReporter::stderr().with_crates(&main_crate_ids); + if args.allow_warnings { + diag_reporter = diag_reporter.allow_warnings(); + } + + let build_test_compilation = + compile_test_prepared_db(&db, test_config, test_crate_ids.clone(), diag_reporter)?; let (compiled, filtered_out) = filter_test_cases( build_test_compilation, diff --git a/src/bin/utils/mod.rs b/src/bin/utils/mod.rs index fc145c5b1..b4cce9a1f 100644 --- a/src/bin/utils/mod.rs +++ b/src/bin/utils/mod.rs @@ -178,6 +178,7 @@ fn jitvalue_to_felt(value: &Value) -> Vec { vec![x.lo.into(), x.hi.into(), y.lo.into(), y.hi.into()] } Value::Null => vec![0.into()], + Value::IntRange { x, y } => [jitvalue_to_felt(x), jitvalue_to_felt(y)].concat(), } } diff --git a/src/debug.rs b/src/debug.rs index 93c0555b4..0c3799290 100644 --- a/src/debug.rs +++ b/src/debug.rs @@ -24,6 +24,7 @@ use cairo_lang_sierra::extensions::{ nullable::NullableConcreteLibfunc, pedersen::PedersenConcreteLibfunc, poseidon::PoseidonConcreteLibfunc, + range::IntRangeConcreteLibfunc, starknet::{ secp256::{Secp256ConcreteLibfunc, Secp256OpConcreteLibfunc}, testing::TestingConcreteLibfunc, @@ -371,6 +372,7 @@ pub fn libfunc_to_name(value: &CoreConcreteLibfunc) -> &'static str { StarkNetConcreteLibfunc::Sha256ProcessBlock(_) => "sha256_process_block", StarkNetConcreteLibfunc::Sha256StateHandleInit(_) => "sha256_state_handle_init", StarkNetConcreteLibfunc::Sha256StateHandleDigest(_) => "sha256_state_handle_digest", + StarkNetConcreteLibfunc::GetClassHashAt(_) => "get_class_hash_at_syscall", }, CoreConcreteLibfunc::Debug(value) => match value { DebugConcreteLibfunc::Print(_) => "debug_print", @@ -407,5 +409,9 @@ pub fn libfunc_to_name(value: &CoreConcreteLibfunc) -> &'static str { BoundedIntConcreteLibfunc::IsZero(_) => "bounded_int_is_zero", BoundedIntConcreteLibfunc::WrapNonZero(_) => "bounded_int_wrap_non_zero", }, + CoreConcreteLibfunc::IntRange(selector) => match selector { + IntRangeConcreteLibfunc::TryNew(_) => "int_range_try_new", + IntRangeConcreteLibfunc::PopFront(_) => "int_range_pop_front", + }, } } diff --git a/src/executor.rs b/src/executor.rs index 86a967193..dad147b76 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -624,6 +624,8 @@ fn parse_result( | CoreTypeConcrete::Uint128MulGuarantee(_) | CoreTypeConcrete::Circuit(_) | CoreTypeConcrete::RangeCheck96(_) => todo!(), + // 2.9.0 + CoreTypeConcrete::IntRange(_) => todo!(), } } diff --git a/src/executor/contract.rs b/src/executor/contract.rs index 3051d46d7..848c9ea98 100644 --- a/src/executor/contract.rs +++ b/src/executor/contract.rs @@ -727,7 +727,7 @@ mod tests { .unwrap(); assert_eq!(result.return_values, vec![Felt::from(n), Felt::from(n * 2)]); - assert_eq!(result.remaining_gas, 18446744073709548175); + assert_eq!(result.remaining_gas, 18446744073709548475); }); } @@ -797,7 +797,7 @@ mod tests { .unwrap(); assert_eq!(result.return_values, vec![Felt::from(3628800)]); - assert_eq!(result.remaining_gas, 18446744073709533805); + assert_eq!(result.remaining_gas, 18446744073709534105); } #[rstest] diff --git a/src/libfuncs.rs b/src/libfuncs.rs index 7fa94b4cb..b7405efaa 100644 --- a/src/libfuncs.rs +++ b/src/libfuncs.rs @@ -43,6 +43,7 @@ mod felt252_dict; mod felt252_dict_entry; mod function_call; mod gas; +mod int_range; mod mem; mod nullable; mod pedersen; @@ -233,6 +234,9 @@ impl LibfuncBuilder for CoreConcreteLibfunc { Self::BoundedInt(info) => { self::bounded_int::build(context, registry, entry, location, helper, metadata, info) } + Self::IntRange(selector) => self::int_range::build( + context, registry, entry, location, helper, metadata, selector, + ), } } diff --git a/src/libfuncs/int_range.rs b/src/libfuncs/int_range.rs new file mode 100644 index 000000000..38e337bd7 --- /dev/null +++ b/src/libfuncs/int_range.rs @@ -0,0 +1,181 @@ +//! # Int range libfuncs + +use super::LibfuncHelper; +use crate::{ + error::Result, + metadata::MetadataStorage, + types::TypeBuilder, + utils::{BlockExt, ProgramRegistryExt}, +}; +use cairo_lang_sierra::{ + extensions::{ + core::{CoreLibfunc, CoreType}, + lib_func::SignatureOnlyConcreteLibfunc, + range::IntRangeConcreteLibfunc, + ConcreteLibfunc, + }, + program_registry::ProgramRegistry, +}; +use melior::{ + dialect::{ + arith::{self, CmpiPredicate}, + ods, + }, + ir::{Block, Location}, + Context, +}; +use num_bigint::BigInt; + +/// Select and call the correct libfunc builder function from the selector. +pub fn build<'ctx, 'this>( + context: &'ctx Context, + registry: &ProgramRegistry, + entry: &'this Block<'ctx>, + location: Location<'ctx>, + helper: &LibfuncHelper<'ctx, 'this>, + metadata: &mut MetadataStorage, + selector: &IntRangeConcreteLibfunc, +) -> Result<()> { + match selector { + IntRangeConcreteLibfunc::TryNew(info) => { + build_int_range_try_new(context, registry, entry, location, helper, metadata, info) + } + IntRangeConcreteLibfunc::PopFront(info) => { + build_int_range_pop_front(context, registry, entry, location, helper, metadata, info) + } + } +} + +/// Generate MLIR operations for the `int_range_try_new` libfunc. +pub fn build_int_range_try_new<'ctx, 'this>( + context: &'ctx Context, + registry: &ProgramRegistry, + entry: &'this Block<'ctx>, + location: Location<'ctx>, + helper: &LibfuncHelper<'ctx, 'this>, + metadata: &mut MetadataStorage, + info: &SignatureOnlyConcreteLibfunc, +) -> Result<()> { + let range_check = entry.argument(0)?.into(); + let x = entry.argument(1)?.into(); + let y = entry.argument(2)?.into(); + let range_ty = registry.build_type( + context, + helper, + registry, + metadata, + &info.branch_signatures()[0].vars[1].ty, + )?; + let inner = registry.get_type(&info.param_signatures()[1].ty)?; + // to know if it is signed + let inner_range = inner.integer_range(registry)?; + + let is_valid = if inner_range.lower < BigInt::ZERO { + entry.append_op_result(arith::cmpi(context, CmpiPredicate::Sle, x, y, location))? + } else { + entry.append_op_result(arith::cmpi(context, CmpiPredicate::Ule, x, y, location))? + }; + + let range = + entry.append_op_result(ods::llvm::mlir_undef(context, range_ty, location).into())?; + + // if the range is not valid, return the empty range [y, y) + let x_val = entry.append_op_result(arith::select(is_valid, x, y, location))?; + let range = entry.insert_values(context, location, range, &[x_val, y])?; + + entry.append_operation(helper.cond_br( + context, + is_valid, + [0, 1], + [&[range_check, range], &[range_check, range]], + location, + )); + Ok(()) +} + +/// Generate MLIR operations for the `int_range_pop_front` libfunc. +pub fn build_int_range_pop_front<'ctx, 'this>( + context: &'ctx Context, + registry: &ProgramRegistry, + entry: &'this Block<'ctx>, + location: Location<'ctx>, + helper: &LibfuncHelper<'ctx, 'this>, + metadata: &mut MetadataStorage, + info: &SignatureOnlyConcreteLibfunc, +) -> Result<()> { + let range = entry.argument(0)?.into(); + + let inner_ty = registry.build_type( + context, + helper, + registry, + metadata, + &info.branch_signatures()[1].vars[1].ty, + )?; + + let inner = registry.get_type(&info.branch_signatures()[1].vars[1].ty)?; + + let x = entry.extract_value(context, location, range, inner_ty, 0)?; + let k1 = entry.const_int_from_type(context, location, 1, inner_ty)?; + let x_p_1 = entry.append_op_result(arith::addi(x, k1, location))?; + let y = entry.extract_value(context, location, range, inner_ty, 1)?; + + // to know if it is signed + let inner_range = inner.integer_range(registry)?; + + let is_valid = if inner_range.lower < BigInt::ZERO { + entry.append_op_result(arith::cmpi(context, CmpiPredicate::Slt, x, y, location))? + } else { + entry.append_op_result(arith::cmpi(context, CmpiPredicate::Ult, x, y, location))? + }; + let range = entry.insert_value(context, location, range, x_p_1, 0)?; + + entry.append_operation(helper.cond_br( + context, + is_valid, + [1, 0], // failure, success + [&[range, x], &[]], + location, + )); + Ok(()) +} + +#[cfg(test)] +mod test { + use crate::{ + utils::test::{jit_enum, jit_struct, load_cairo, run_program_assert_output}, + values::Value, + }; + use cairo_lang_sierra::program::Program; + use lazy_static::lazy_static; + + lazy_static! { + static ref INT_RANGE_TRY_NEW: (String, Program) = load_cairo! { + #[derive(Copy, Drop)] + pub extern type IntRange; + pub extern fn int_range_try_new( + x: T, y: T + ) -> Result, IntRange> implicits(core::RangeCheck) nopanic; + + fn run_test(lhs: u64, rhs: u64) -> IntRange { + int_range_try_new(lhs, rhs).unwrap() + } + }; + } + + #[test] + fn int_range_try_new() { + run_program_assert_output( + &INT_RANGE_TRY_NEW, + "run_test", + &[2u64.into(), 4u64.into()], + jit_enum!( + 0, + jit_struct!(Value::IntRange { + x: Box::new(2u64.into()), + y: Box::new(4u64.into()), + }) + ), + ); + } +} diff --git a/src/libfuncs/starknet.rs b/src/libfuncs/starknet.rs index f90cd05ad..9302d5d66 100644 --- a/src/libfuncs/starknet.rs +++ b/src/libfuncs/starknet.rs @@ -142,6 +142,9 @@ pub fn build<'ctx, 'this>( StarkNetConcreteLibfunc::Sha256StateHandleDigest(info) => build_sha256_state_handle_digest( context, registry, entry, location, helper, metadata, info, ), + StarkNetConcreteLibfunc::GetClassHashAt(info) => { + build_get_class_hash_at(context, registry, entry, location, helper, metadata, info) + } #[cfg(feature = "with-cheatcode")] StarkNetConcreteLibfunc::Testing(TestingConcreteLibfunc::Cheatcode(info)) => { self::testing::build(context, registry, entry, location, helper, metadata, info) @@ -2836,6 +2839,164 @@ pub fn build_sha256_process_block_syscall<'ctx, 'this>( Ok(()) } +pub fn build_get_class_hash_at<'ctx, 'this>( + context: &'ctx Context, + registry: &ProgramRegistry, + entry: &'this Block<'ctx>, + location: Location<'ctx>, + helper: &LibfuncHelper<'ctx, 'this>, + metadata: &mut MetadataStorage, + info: &SignatureOnlyConcreteLibfunc, +) -> Result<()> { + // Extract self pointer. + let ptr = entry.load( + context, + location, + entry.argument(1)?.into(), + llvm::r#type::pointer(context, 0), + )?; + + // Allocate space for the return value. + let (result_layout, (result_tag_ty, _), variant_tys) = + crate::types::r#enum::get_type_for_variants( + context, + helper, + registry, + metadata, + &[ + info.branch_signatures()[0].vars[2].ty.clone(), + info.branch_signatures()[1].vars[2].ty.clone(), + ], + )?; + + let result_ptr = helper.init_block().alloca1( + context, + location, + llvm::r#type::r#struct( + context, + &[ + result_tag_ty, + llvm::r#type::array( + IntegerType::new(context, 8).into(), + (result_layout.size() - 1).try_into()?, + ), + ], + false, + ), + result_layout.align(), + )?; + + // Allocate space and write the current gas. + let (gas_ty, gas_layout) = registry.build_type_with_layout( + context, + helper, + registry, + metadata, + &info.param_signatures()[0].ty, + )?; + let gas_builtin_ptr = + helper + .init_block() + .alloca1(context, location, gas_ty, gas_layout.align())?; + entry.append_operation(llvm::store( + context, + entry.argument(0)?.into(), + gas_builtin_ptr, + location, + LoadStoreOptions::default(), + )); + + // Allocate `contract_address` argument and write the value. + let contract_address_ptr = helper.init_block().alloca_int(context, location, 252)?; + entry.store( + context, + location, + contract_address_ptr, + entry.argument(2)?.into(), + )?; + + // Extract function pointer. + let fn_ptr = entry.gep( + context, + location, + entry.argument(1)?.into(), + &[GepIndex::Const( + StarknetSyscallHandlerCallbacks::<()>::GET_CLASS_HASH_AT.try_into()?, + )], + pointer(context, 0), + )?; + let fn_ptr = entry.load(context, location, fn_ptr, llvm::r#type::pointer(context, 0))?; + + entry.append_operation( + OperationBuilder::new("llvm.call", location) + .add_operands(&[ + fn_ptr, + result_ptr, + ptr, + gas_builtin_ptr, + contract_address_ptr, + ]) + .build()?, + ); + + let result = entry.load( + context, + location, + result_ptr, + llvm::r#type::r#struct( + context, + &[ + result_tag_ty, + llvm::r#type::array( + IntegerType::new(context, 8).into(), + (result_layout.size() - 1).try_into()?, + ), + ], + false, + ), + )?; + let result_tag = entry.extract_value( + context, + location, + result, + IntegerType::new(context, 1).into(), + 0, + )?; + + let payload_ok = { + let value = entry.load( + context, + location, + result_ptr, + llvm::r#type::r#struct(context, &[result_tag_ty, variant_tys[0].0], false), + )?; + entry.extract_value(context, location, value, variant_tys[0].0, 1)? + }; + let payload_err = { + let value = entry.load( + context, + location, + result_ptr, + llvm::r#type::r#struct(context, &[result_tag_ty, variant_tys[1].0], false), + )?; + entry.extract_value(context, location, value, variant_tys[1].0, 1)? + }; + + let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; + + entry.append_operation(helper.cond_br( + context, + result_tag, + [1, 0], + [ + &[remaining_gas, entry.argument(1)?.into(), payload_err], + &[remaining_gas, entry.argument(1)?.into(), payload_ok], + ], + location, + )); + Ok(()) +} + #[cfg(test)] mod test { use crate::utils::test::{jit_enum, jit_struct, load_cairo, run_program_assert_output}; diff --git a/src/starknet.rs b/src/starknet.rs index 58dc42935..58e8faf4c 100644 --- a/src/starknet.rs +++ b/src/starknet.rs @@ -321,6 +321,12 @@ pub trait StarknetSyscallHandler { remaining_gas: &mut u64, ) -> SyscallResult<()>; + fn get_class_hash_at( + &mut self, + contract_address: Felt, + remaining_gas: &mut u64, + ) -> SyscallResult; + #[cfg(feature = "with-cheatcode")] fn cheatcode(&mut self, _selector: Felt, _input: &[Felt]) -> Vec { unimplemented!(); @@ -521,6 +527,14 @@ impl StarknetSyscallHandler for DummySyscallHandler { ) -> SyscallResult<()> { unimplemented!() } + + fn get_class_hash_at( + &mut self, + _contract_address: Felt, + _remaining_gas: &mut u64, + ) -> SyscallResult { + unimplemented!() + } } // TODO: Move to the correct place or remove if unused. @@ -797,6 +811,12 @@ pub(crate) mod handler { state: *mut [u32; 8], block: &[u32; 16], ), + get_class_hash_at: extern "C" fn( + result_ptr: &mut SyscallResultAbi, + ptr: &mut T, + gas: &mut u64, + contract_address: &Felt252Abi, + ), // testing syscalls #[cfg(feature = "with-cheatcode")] pub cheatcode: extern "C" fn( @@ -837,7 +857,10 @@ pub(crate) mod handler { pub const SECP256R1_GET_POINT_FROM_X: usize = field_offset!(Self, secp256r1_get_point_from_x) >> 3; pub const SECP256R1_GET_XY: usize = field_offset!(Self, secp256r1_get_xy) >> 3; + pub const SHA256_PROCESS_BLOCK: usize = field_offset!(Self, sha256_process_block) >> 3; + + pub const GET_CLASS_HASH_AT: usize = field_offset!(Self, get_class_hash_at) >> 3; } #[allow(unused_variables)] @@ -871,6 +894,7 @@ pub(crate) mod handler { secp256r1_get_point_from_x: Self::wrap_secp256r1_get_point_from_x, secp256r1_get_xy: Self::wrap_secp256r1_get_xy, sha256_process_block: Self::wrap_sha256_process_block, + get_class_hash_at: Self::wrap_get_class_hash_at, #[cfg(feature = "with-cheatcode")] cheatcode: Self::wrap_cheatcode, } @@ -1116,8 +1140,6 @@ pub(crate) mod handler { }; } - // TODO: change all from_bytes_be to from_bytes_ne when added and undo byte swapping. - extern "C" fn wrap_deploy( result_ptr: &mut SyscallResultAbi<(Felt252Abi, ArrayAbi)>, ptr: &mut T, @@ -1632,6 +1654,25 @@ pub(crate) mod handler { Err(e) => Self::wrap_error(&e), }; } + + extern "C" fn wrap_get_class_hash_at( + result_ptr: &mut SyscallResultAbi, + ptr: &mut T, + gas: &mut u64, + contract_address: &Felt252Abi, + ) { + let result = ptr.get_class_hash_at(contract_address.into(), gas); + + *result_ptr = match result { + Ok(x) => SyscallResultAbi { + ok: ManuallyDrop::new(SyscallResultAbiOk { + tag: 0u8, + payload: ManuallyDrop::new(Felt252Abi(x.to_bytes_le())), + }), + }, + Err(e) => Self::wrap_error(&e), + }; + } } } diff --git a/src/starknet_stub.rs b/src/starknet_stub.rs index 228dc722b..ca8ec9779 100644 --- a/src/starknet_stub.rs +++ b/src/starknet_stub.rs @@ -647,6 +647,14 @@ impl StarknetSyscallHandler for &mut StubSyscallHandler { sha2::compress256(state, &[data_as_bytes]); Ok(()) } + + fn get_class_hash_at( + &mut self, + contract_address: Felt, + _remaining_gas: &mut u64, + ) -> SyscallResult { + Ok(contract_address) + } } #[cfg(test)] diff --git a/src/types.rs b/src/types.rs index 3878d8400..0682b73f0 100644 --- a/src/types.rs +++ b/src/types.rs @@ -45,6 +45,7 @@ mod felt252; mod felt252_dict; mod felt252_dict_entry; mod gas_builtin; +mod int_range; mod non_zero; mod nullable; mod pedersen; @@ -430,6 +431,13 @@ impl TypeBuilder for CoreTypeConcrete { metadata, WithSelf::new(self_ty, info), ), + Self::IntRange(info) => self::int_range::build( + context, + module, + registry, + metadata, + WithSelf::new(self_ty, info), + ), } } @@ -533,7 +541,9 @@ impl TypeBuilder for CoreTypeConcrete { | CoreTypeConcrete::StarkNet(StarkNetTypeConcrete::Sha256StateHandle(_)) => todo!(), CoreTypeConcrete::Coupon(_) => false, - CoreTypeConcrete::Circuit(info) => circuit::is_complex(info) + CoreTypeConcrete::Circuit(info) => circuit::is_complex(info), + + CoreTypeConcrete::IntRange(_info) => false }) } @@ -613,6 +623,11 @@ impl TypeBuilder for CoreTypeConcrete { } CoreTypeConcrete::Span(_) => todo!(), CoreTypeConcrete::Circuit(info) => circuit::is_zst(info), + + CoreTypeConcrete::IntRange(info) => { + let type_info = registry.get_type(&info.ty)?; + type_info.is_zst(registry)? + } }) } @@ -718,6 +733,11 @@ impl TypeBuilder for CoreTypeConcrete { CoreTypeConcrete::Coupon(_) => Layout::new::<()>(), CoreTypeConcrete::RangeCheck96(_) => get_integer_layout(64), CoreTypeConcrete::Circuit(info) => circuit::layout(registry, info)?, + + CoreTypeConcrete::IntRange(info) => { + let inner = registry.get_type(&info.ty)?.layout(registry)?; + inner.extend(inner).unwrap().0 + } } .pad_to_align()) } @@ -729,6 +749,7 @@ impl TypeBuilder for CoreTypeConcrete { // Right now, only enums and other structures which may end up passing a flattened enum as // arguments. Ok(match self { + CoreTypeConcrete::IntRange(_) => false, CoreTypeConcrete::Array(_) => false, CoreTypeConcrete::Bitwise(_) => false, CoreTypeConcrete::Box(_) => false, diff --git a/src/types/int_range.rs b/src/types/int_range.rs new file mode 100644 index 000000000..11d901663 --- /dev/null +++ b/src/types/int_range.rs @@ -0,0 +1,46 @@ +//! # Int range of type T +//! +//! A range [x, y) where x <= y +//! +//! ## Layout +//! +//! A struct with 2 fields of type T +//! +//! ``` +//! #[repr(transparent)] +//! pub struct NonZero(pub T); +//! ``` + +use super::WithSelf; +use crate::{error::Result, metadata::MetadataStorage, utils::ProgramRegistryExt}; +use cairo_lang_sierra::{ + extensions::{ + core::{CoreLibfunc, CoreType}, + types::InfoAndTypeConcreteType, + }, + program_registry::ProgramRegistry, +}; +use melior::{ + ir::{Module, Type}, + Context, +}; + +/// Build the MLIR type. +/// +/// Check out [the module](self) for more info. +pub fn build<'ctx>( + context: &'ctx Context, + module: &Module<'ctx>, + registry: &ProgramRegistry, + metadata: &mut MetadataStorage, + info: WithSelf, +) -> Result> { + // TODO: Can its inner type require dup or drop? probably not since they are integers + let inner = registry.build_type(context, module, registry, metadata, &info.ty)?; + + Ok(melior::dialect::llvm::r#type::r#struct( + context, + &[inner, inner], + false, + )) +} diff --git a/src/values.rs b/src/values.rs index 796933dec..5b9d1ff76 100644 --- a/src/values.rs +++ b/src/values.rs @@ -4,6 +4,7 @@ use crate::{ error::{CompilerError, Error}, + native_panic, starknet::{Secp256k1Point, Secp256r1Point}, types::TypeBuilder, utils::{ @@ -76,6 +77,10 @@ pub enum Value { #[serde(with = "range_serde")] range: Range, }, + IntRange { + x: Box, + y: Box, + }, /// Used as return value for Nullables that are null. Null, } @@ -511,6 +516,38 @@ impl Value { Self::Null => { unimplemented!("null is meant as return value for nullable for now") } + Self::IntRange { x, y } => { + if let CoreTypeConcrete::IntRange(info) = Self::resolve_type(ty, registry)? { + let inner = registry.get_type(&info.ty)?; + let inner_layout = inner.layout(registry)?; + + let x_ptr = x.to_ptr(arena, registry, &info.ty)?; + + let (struct_layout, y_offset) = inner_layout.extend(inner_layout)?; + + let y_ptr = y.to_ptr(arena, registry, &info.ty)?; + + let ptr = arena.alloc_layout(struct_layout.pad_to_align()).as_ptr(); + + std::ptr::copy_nonoverlapping( + x_ptr.cast::().as_ptr(), + ptr, + inner_layout.size(), + ); + + std::ptr::copy_nonoverlapping( + y_ptr.cast::().as_ptr(), + ptr.byte_add(y_offset), + inner_layout.size(), + ); + + NonNull::new_unchecked(ptr).cast() + } else { + native_panic!( + "an IntRange value should always have an IntRange CoreTypeConcrete" + ) + } + } } }) } @@ -802,6 +839,28 @@ impl Value { CoreTypeConcrete::Coupon(_) | CoreTypeConcrete::Circuit(_) | CoreTypeConcrete::RangeCheck96(_) => todo!(), + CoreTypeConcrete::IntRange(info) => { + let member = registry.get_type(&info.ty)?; + let member_layout = member.layout(registry)?; + + let x = + Self::from_ptr(NonNull::new(ptr.as_ptr()).unwrap(), &info.ty, registry)?; + + let y = Self::from_ptr( + NonNull::new( + ptr.as_ptr() + .byte_add(member_layout.extend(member_layout)?.1), + ) + .unwrap(), + &info.ty, + registry, + )?; + + Self::IntRange { + x: x.into(), + y: y.into(), + } + } } }) } diff --git a/tests/common.rs b/tests/common.rs index 1ee6d0c4c..39ade8c19 100644 --- a/tests/common.rs +++ b/tests/common.rs @@ -21,13 +21,16 @@ use cairo_lang_sierra::{ program::Program, program_registry::ProgramRegistry, }; -use cairo_lang_sierra_generator::replace_ids::DebugReplacer; +use cairo_lang_sierra_generator::replace_ids::{DebugReplacer, SierraIdReplacer}; use cairo_lang_starknet::{ - compile::compile_contract_in_prepared_db, contract::get_contracts_info, starknet_plugin_suite, + compile::compile_contract_in_prepared_db, + contract::{find_contracts, get_contracts_info}, + starknet_plugin_suite, }; use cairo_lang_starknet_classes::{ casm_contract_class::CasmContractClass, contract_class::ContractClass, }; +use cairo_lang_utils::Upcast; use cairo_native::{ context::NativeContext, execution_result::{ContractExecutionResult, ExecutionResult}, @@ -113,11 +116,7 @@ pub fn load_cairo_str(program_str: &str) -> (String, Program, SierraCasmRunner) .unwrap(); fs::write(&mut program_file, program_str).unwrap(); - let mut db = RootDatabase::default(); - init_dev_corelib( - &mut db, - Path::new(&var("CARGO_MANIFEST_DIR").unwrap()).join("corelib/src"), - ); + let mut db = RootDatabase::builder().detect_corelib().build().unwrap(); let main_crate_ids = setup_project(&mut db, program_file.path()).unwrap(); let sierra_program_with_dbg = compile_prepared_db( &db, @@ -134,7 +133,9 @@ pub fn load_cairo_str(program_str: &str) -> (String, Program, SierraCasmRunner) let module_name = module_name.file_name().unwrap().to_str().unwrap(); let replacer = DebugReplacer { db: &db }; - let contracts_info = get_contracts_info(&db, main_crate_ids, &replacer).unwrap(); + + let contracts = find_contracts((db).upcast(), &main_crate_ids); + let contracts_info = get_contracts_info(&db, contracts, &replacer).unwrap(); let runner = SierraCasmRunner::new( program.clone(), @@ -165,13 +166,17 @@ pub fn load_cairo_path(program_path: &str) -> (String, Program, SierraCasmRunner }, ) .unwrap(); - let program = sierra_program_with_dbg.program; + let mut program = sierra_program_with_dbg.program; let module_name = program_file.with_extension(""); let module_name = module_name.file_name().unwrap().to_str().unwrap(); let replacer = DebugReplacer { db: &db }; - let contracts_info = get_contracts_info(&db, main_crate_ids, &replacer).unwrap(); + replacer.enrich_function_names(&mut program); + let contracts = find_contracts((db).upcast(), &main_crate_ids); + let contracts_info = get_contracts_info(&db, contracts, &replacer).unwrap(); + + let program = replacer.apply(&program); let runner = SierraCasmRunner::new( program.clone(), @@ -283,7 +288,7 @@ pub fn run_vm_contract( .expect("failed to extract program from casm contract"); // Initialize runner and builtins - let mut runner = CairoRunner::new(&program, LayoutName::all_cairo, false, false) + let mut runner = CairoRunner::new(&program, LayoutName::all_cairo, None, false, false) .expect("failed to build runner"); let program_builtins = contract diff --git a/tests/tests/starknet/keccak.rs b/tests/tests/starknet/keccak.rs index 9de56a5f8..71babc3c7 100644 --- a/tests/tests/starknet/keccak.rs +++ b/tests/tests/starknet/keccak.rs @@ -36,7 +36,7 @@ fn keccak_test() { ); assert!(!result.failure_flag); - assert_eq!(result.remaining_gas, 18446744073709483675); + assert_eq!(result.remaining_gas, 18446744073709483875); assert_eq!(result.return_values, vec![1.into()]); let result_aot_ct = run_native_starknet_aot_contract( diff --git a/tests/tests/starknet/programs/syscalls.cairo b/tests/tests/starknet/programs/syscalls.cairo index c57362bc4..72d6d5266 100644 --- a/tests/tests/starknet/programs/syscalls.cairo +++ b/tests/tests/starknet/programs/syscalls.cairo @@ -4,10 +4,11 @@ use core::starknet::{ keccak_syscall, library_call_syscall, replace_class_syscall, send_message_to_l1_syscall, storage_address_try_from_felt252, storage_read_syscall, storage_write_syscall, SyscallResult, - testing::cheatcode, + testing::cheatcode, class_hash::ClassHash }; use core::starknet::syscalls::get_execution_info_syscall; use core::starknet::syscalls::get_execution_info_v2_syscall; +use core::starknet::syscalls::get_class_hash_at_syscall; use core::sha256::{sha256_state_handle_init, sha256_state_handle_digest, SHA256_INITIAL_STATE}; use core::box::BoxTrait; use core::starknet::SyscallResultTrait; @@ -16,6 +17,10 @@ fn get_block_hash() -> SyscallResult { get_block_hash_syscall(0) } +fn get_class_hash_at() -> SyscallResult { + get_class_hash_at_syscall(contract_address_const::<2>()) +} + fn get_execution_info() -> SyscallResult> { get_execution_info_syscall() } diff --git a/tests/tests/starknet/secp256.rs b/tests/tests/starknet/secp256.rs index 891efbcfe..e3f41ba90 100644 --- a/tests/tests/starknet/secp256.rs +++ b/tests/tests/starknet/secp256.rs @@ -256,6 +256,14 @@ impl StarknetSyscallHandler for &mut SyscallHandler { ) -> SyscallResult<()> { unimplemented!() } + + fn get_class_hash_at( + &mut self, + _contract_address: Felt, + _remaining_gas: &mut u64, + ) -> SyscallResult { + unimplemented!() + } } lazy_static! { diff --git a/tests/tests/starknet/syscalls.rs b/tests/tests/starknet/syscalls.rs index 12c94f817..2a7d9bbad 100644 --- a/tests/tests/starknet/syscalls.rs +++ b/tests/tests/starknet/syscalls.rs @@ -502,6 +502,14 @@ impl StarknetSyscallHandler for SyscallHandler { ) -> SyscallResult<()> { Ok(()) } + + fn get_class_hash_at( + &mut self, + contract_address: Felt, + _remaining_gas: &mut u64, + ) -> SyscallResult { + Ok(contract_address) + } } lazy_static! { @@ -1200,3 +1208,23 @@ fn sha256_process() { }, ); } + +#[test] +fn get_class_hash_at() { + let result = run_native_program( + &SYSCALLS_PROGRAM, + "get_class_hash_at", + &[], + Some(u64::MAX), + Some(SyscallHandler::new()), + ); + + assert_eq_sorted!( + result.return_value, + Value::Enum { + tag: 0, + value: Box::new(Value::Felt252(2.into())), + debug_name: None, + }, + ); +}