diff --git a/Cargo.lock b/Cargo.lock index 9bbc26f..49999ed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,18 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "ahash" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" version = "1.0.4" @@ -11,6 +23,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" + [[package]] name = "anstream" version = "0.5.0" @@ -65,6 +83,70 @@ version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "derivative", + "digest", + "itertools 0.10.5", + "num-bigint", + "num-traits 0.2.16", + "paste", + "rustc_version", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits 0.2.16", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-std", + "digest", + "num-bigint", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits 0.2.16", + "rand", +] + [[package]] name = "arrayvec" version = "0.7.4" @@ -150,17 +232,29 @@ dependencies = [ "serde", ] +[[package]] +name = "bumpalo" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" + [[package]] name = "byte-slice-cast" version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "cairo-felt" -version = "0.8.7" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5972097b8800ca5dffb458040e74c724a2ac4fa4b5b480b50f5b96c7e67d6427" +checksum = "ae932292b9ba497a4e892b56aa4e0c6f329a455180fdbdc132700dfe68d9b153" dependencies = [ "lazy_static", "num-bigint", @@ -171,24 +265,22 @@ dependencies = [ [[package]] name = "cairo-lang-casm" -version = "2.2.0" -source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.2.0#ad5570f0f25dbbffd9daedf02df140ff9e7291e4" +version = "2.5.0" +source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.5.0#1a4ccb01f6fb0a74bfc23238ca1088fe2659d087" dependencies = [ "cairo-lang-utils", + "hashbrown 0.14.3", "indoc", "num-bigint", "num-traits 0.2.16", "parity-scale-codec", - "parity-scale-codec-derive", - "schemars", "serde", - "thiserror", ] [[package]] name = "cairo-lang-compiler" -version = "2.2.0" -source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.2.0#ad5570f0f25dbbffd9daedf02df140ff9e7291e4" +version = "2.5.0" +source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.5.0#1a4ccb01f6fb0a74bfc23238ca1088fe2659d087" dependencies = [ "anyhow", "cairo-lang-defs", @@ -196,32 +288,28 @@ dependencies = [ "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", - "itertools 0.11.0", - "log", "salsa", - "smol_str", "thiserror", ] [[package]] name = "cairo-lang-debug" -version = "2.2.0" -source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.2.0#ad5570f0f25dbbffd9daedf02df140ff9e7291e4" +version = "2.5.0" +source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.5.0#1a4ccb01f6fb0a74bfc23238ca1088fe2659d087" dependencies = [ "cairo-lang-utils", ] [[package]] name = "cairo-lang-defs" -version = "2.2.0" -source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.2.0#ad5570f0f25dbbffd9daedf02df140ff9e7291e4" +version = "2.5.0" +source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.5.0#1a4ccb01f6fb0a74bfc23238ca1088fe2659d087" dependencies = [ "cairo-lang-debug", "cairo-lang-diagnostics", @@ -229,7 +317,6 @@ dependencies = [ "cairo-lang-parser", "cairo-lang-syntax", "cairo-lang-utils", - "indexmap 2.0.0", "itertools 0.11.0", "salsa", "smol_str", @@ -237,31 +324,28 @@ dependencies = [ [[package]] name = "cairo-lang-diagnostics" -version = "2.2.0" -source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.2.0#ad5570f0f25dbbffd9daedf02df140ff9e7291e4" +version = "2.5.0" +source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.5.0#1a4ccb01f6fb0a74bfc23238ca1088fe2659d087" dependencies = [ "cairo-lang-debug", "cairo-lang-filesystem", "cairo-lang-utils", "itertools 0.11.0", - "salsa", ] [[package]] name = "cairo-lang-eq-solver" -version = "2.2.0" -source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.2.0#ad5570f0f25dbbffd9daedf02df140ff9e7291e4" +version = "2.5.0" +source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.5.0#1a4ccb01f6fb0a74bfc23238ca1088fe2659d087" dependencies = [ "cairo-lang-utils", "good_lp", - "indexmap 2.0.0", - "itertools 0.11.0", ] [[package]] name = "cairo-lang-filesystem" -version = "2.2.0" -source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.2.0#ad5570f0f25dbbffd9daedf02df140ff9e7291e4" +version = "2.5.0" +source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.5.0#1a4ccb01f6fb0a74bfc23238ca1088fe2659d087" dependencies = [ "cairo-lang-debug", "cairo-lang-utils", @@ -273,8 +357,8 @@ dependencies = [ [[package]] name = "cairo-lang-lowering" -version = "2.2.0" -source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.2.0#ad5570f0f25dbbffd9daedf02df140ff9e7291e4" +version = "2.5.0" +source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.5.0#1a4ccb01f6fb0a74bfc23238ca1088fe2659d087" dependencies = [ "cairo-lang-debug", "cairo-lang-defs", @@ -286,7 +370,6 @@ dependencies = [ "cairo-lang-syntax", "cairo-lang-utils", "id-arena", - "indexmap 2.0.0", "itertools 0.11.0", "log", "num-bigint", @@ -298,8 +381,8 @@ dependencies = [ [[package]] name = "cairo-lang-parser" -version = "2.2.0" -source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.2.0#ad5570f0f25dbbffd9daedf02df140ff9e7291e4" +version = "2.5.0" +source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.5.0#1a4ccb01f6fb0a74bfc23238ca1088fe2659d087" dependencies = [ "cairo-lang-diagnostics", "cairo-lang-filesystem", @@ -308,7 +391,6 @@ dependencies = [ "cairo-lang-utils", "colored", "itertools 0.11.0", - "log", "num-bigint", "num-traits 0.2.16", "salsa", @@ -318,8 +400,8 @@ dependencies = [ [[package]] name = "cairo-lang-plugins" -version = "2.2.0" -source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.2.0#ad5570f0f25dbbffd9daedf02df140ff9e7291e4" +version = "2.5.0" +source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.5.0#1a4ccb01f6fb0a74bfc23238ca1088fe2659d087" dependencies = [ "cairo-lang-defs", "cairo-lang-diagnostics", @@ -330,25 +412,24 @@ dependencies = [ "indent", "indoc", "itertools 0.11.0", - "num-bigint", "salsa", "smol_str", ] [[package]] name = "cairo-lang-proc-macros" -version = "2.2.0" -source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.2.0#ad5570f0f25dbbffd9daedf02df140ff9e7291e4" +version = "2.5.0" +source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.5.0#1a4ccb01f6fb0a74bfc23238ca1088fe2659d087" dependencies = [ "cairo-lang-debug", "quote", - "syn 2.0.29", + "syn 2.0.39", ] [[package]] name = "cairo-lang-project" -version = "2.2.0" -source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.2.0#ad5570f0f25dbbffd9daedf02df140ff9e7291e4" +version = "2.5.0" +source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.5.0#1a4ccb01f6fb0a74bfc23238ca1088fe2659d087" dependencies = [ "cairo-lang-filesystem", "cairo-lang-utils", @@ -360,8 +441,8 @@ dependencies = [ [[package]] name = "cairo-lang-semantic" -version = "2.2.0" -source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.2.0#ad5570f0f25dbbffd9daedf02df140ff9e7291e4" +version = "2.5.0" +source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.5.0#1a4ccb01f6fb0a74bfc23238ca1088fe2659d087" dependencies = [ "cairo-lang-debug", "cairo-lang-defs", @@ -373,8 +454,8 @@ dependencies = [ "cairo-lang-syntax", "cairo-lang-utils", "id-arena", + "indoc", "itertools 0.11.0", - "log", "num-bigint", "num-traits 0.2.16", "once_cell", @@ -384,9 +465,11 @@ dependencies = [ [[package]] name = "cairo-lang-sierra" -version = "2.2.0" -source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.2.0#ad5570f0f25dbbffd9daedf02df140ff9e7291e4" +version = "2.5.0" +source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.5.0#1a4ccb01f6fb0a74bfc23238ca1088fe2659d087" dependencies = [ + "anyhow", + "cairo-felt", "cairo-lang-utils", "const-fnv1a-hash", "convert_case", @@ -399,6 +482,7 @@ dependencies = [ "regex", "salsa", "serde", + "serde_json", "sha3", "smol_str", "thiserror", @@ -406,34 +490,36 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-ap-change" -version = "2.2.0" -source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.2.0#ad5570f0f25dbbffd9daedf02df140ff9e7291e4" +version = "2.5.0" +source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.5.0#1a4ccb01f6fb0a74bfc23238ca1088fe2659d087" dependencies = [ "cairo-lang-eq-solver", "cairo-lang-sierra", "cairo-lang-sierra-type-size", "cairo-lang-utils", "itertools 0.11.0", + "num-traits 0.2.16", "thiserror", ] [[package]] name = "cairo-lang-sierra-gas" -version = "2.2.0" -source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.2.0#ad5570f0f25dbbffd9daedf02df140ff9e7291e4" +version = "2.5.0" +source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.5.0#1a4ccb01f6fb0a74bfc23238ca1088fe2659d087" dependencies = [ "cairo-lang-eq-solver", "cairo-lang-sierra", "cairo-lang-sierra-type-size", "cairo-lang-utils", "itertools 0.11.0", + "num-traits 0.2.16", "thiserror", ] [[package]] name = "cairo-lang-sierra-generator" -version = "2.2.0" -source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.2.0#ad5570f0f25dbbffd9daedf02df140ff9e7291e4" +version = "2.5.0" +source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.5.0#1a4ccb01f6fb0a74bfc23238ca1088fe2659d087" dependencies = [ "cairo-lang-debug", "cairo-lang-defs", @@ -441,14 +527,10 @@ dependencies = [ "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 2.0.0", "itertools 0.11.0", "num-bigint", "once_cell", @@ -458,8 +540,8 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-to-casm" -version = "2.2.0" -source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.2.0#ad5570f0f25dbbffd9daedf02df140ff9e7291e4" +version = "2.5.0" +source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.5.0#1a4ccb01f6fb0a74bfc23238ca1088fe2659d087" dependencies = [ "assert_matches", "cairo-felt", @@ -471,7 +553,6 @@ dependencies = [ "cairo-lang-utils", "indoc", "itertools 0.11.0", - "log", "num-bigint", "num-traits 0.2.16", "thiserror", @@ -479,8 +560,8 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-type-size" -version = "2.2.0" -source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.2.0#ad5570f0f25dbbffd9daedf02df140ff9e7291e4" +version = "2.5.0" +source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.5.0#1a4ccb01f6fb0a74bfc23238ca1088fe2659d087" dependencies = [ "cairo-lang-sierra", "cairo-lang-utils", @@ -488,8 +569,8 @@ dependencies = [ [[package]] name = "cairo-lang-starknet" -version = "2.2.0" -source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.2.0#ad5570f0f25dbbffd9daedf02df140ff9e7291e4" +version = "2.5.0" +source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.5.0#1a4ccb01f6fb0a74bfc23238ca1088fe2659d087" dependencies = [ "anyhow", "cairo-felt", @@ -499,22 +580,17 @@ dependencies = [ "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", + "const_format", "convert_case", - "genco", "indent", "indoc", "itertools 0.11.0", - "log", "num-bigint", "num-integer", "num-traits 0.2.16", @@ -523,13 +599,14 @@ dependencies = [ "serde_json", "sha3", "smol_str", + "starknet-crypto", "thiserror", ] [[package]] name = "cairo-lang-syntax" -version = "2.2.0" -source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.2.0#ad5570f0f25dbbffd9daedf02df140ff9e7291e4" +version = "2.5.0" +source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.5.0#1a4ccb01f6fb0a74bfc23238ca1088fe2659d087" dependencies = [ "cairo-lang-debug", "cairo-lang-filesystem", @@ -538,14 +615,13 @@ dependencies = [ "num-traits 0.2.16", "salsa", "smol_str", - "thiserror", "unescaper", ] [[package]] name = "cairo-lang-syntax-codegen" -version = "2.2.0" -source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.2.0#ad5570f0f25dbbffd9daedf02df140ff9e7291e4" +version = "2.5.0" +source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.5.0#1a4ccb01f6fb0a74bfc23238ca1088fe2659d087" dependencies = [ "genco", "xshell", @@ -553,15 +629,14 @@ dependencies = [ [[package]] name = "cairo-lang-utils" -version = "2.2.0" -source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.2.0#ad5570f0f25dbbffd9daedf02df140ff9e7291e4" +version = "2.5.0" +source = "git+https://github.com/starkware-libs/cairo.git?tag=v2.5.0#1a4ccb01f6fb0a74bfc23238ca1088fe2659d087" dependencies = [ - "indexmap 2.0.0", + "hashbrown 0.14.3", + "indexmap 2.1.0", "itertools 0.11.0", "num-bigint", - "num-integer", "num-traits 0.2.16", - "parity-scale-codec", "schemars", "serde", ] @@ -584,12 +659,14 @@ dependencies = [ "cairo-lang-syntax", "cairo-lang-utils", "clap", + "fxhash", "graphviz-rust", "insta", "num-bigint", "num-integer", "num-traits 0.2.16", "once_cell", + "rayon", "serde_json", "smol_str", "termcolor", @@ -643,7 +720,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.39", ] [[package]] @@ -687,6 +764,26 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32b13ea120a812beba79e34316b3942a857c86ec1593cb34f27bb28272ce2cca" +[[package]] +name = "const_format" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a214c7af3d04997541b18d432afaff4c455e79e2029079647e72fc2bd27673" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f6ff08fd20f4f299298a28e2dfa8a8ba1036e6cd2460ac1de7b425d76f2500" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + [[package]] name = "convert_case" version = "0.6.0" @@ -705,11 +802,33 @@ dependencies = [ "libc", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fca89a0e215bab21874660c67903c5f143333cab1da83d041c7ded6053774751" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e3681d554572a651dda4186cd47240627c3d0114d45a95f6ad27f2f22e7548d" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" -version = "0.8.16" +version = "0.8.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +checksum = "c3a430a770ebd84726f584a90ee7f020d28db52c6d02138900f22341f866d39c" dependencies = [ "cfg-if", ] @@ -720,6 +839,17 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -755,6 +885,7 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", + "subtle", ] [[package]] @@ -871,11 +1002,20 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + [[package]] name = "genco" -version = "0.17.5" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6973ce8518068a71d404f428f6a5b563088545546a6bd8f9c0a7f2608149bc8a" +checksum = "98d7af598790738fee616426e669360fa361273b1b9c9b7f30c92fa627605cad" dependencies = [ "genco-macros", "relative-path", @@ -884,13 +1024,13 @@ dependencies = [ [[package]] name = "genco-macros" -version = "0.17.5" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c2c778cf01917d0fbed53900259d6604a421fab4916a2e738856ead9f1d926a" +checksum = "d4cf186fea4af17825116f72932fe52cce9a13bae39ff63b4dc0cfdb3fb4bde1" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.39", ] [[package]] @@ -910,8 +1050,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -929,9 +1071,9 @@ dependencies = [ [[package]] name = "good_lp" -version = "1.5.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7f3b0e0de4e671b6ffc1274b153a9394cb58bf04ee67505b0cb9915513115f" +checksum = "fa124423ded10046a849fa0ae9747c541895557f1af177e0890b09879e7e9e7d" dependencies = [ "fnv", "minilp", @@ -939,9 +1081,9 @@ dependencies = [ [[package]] name = "graphviz-rust" -version = "0.6.6" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27dafd1ac303e0dfb347a3861d9ac440859bab26ec2f534bbceb262ea492a1e0" +checksum = "f3f7a4f4b8db9d330c49744d0f98ce7c9a37e3e32a0d247a90338119b2040184" dependencies = [ "dot-generator", "dot-structures", @@ -961,9 +1103,14 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.0" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +dependencies = [ + "ahash", + "allocator-api2", + "serde", +] [[package]] name = "heck" @@ -986,6 +1133,21 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + [[package]] name = "id-arena" version = "2.2.1" @@ -1022,20 +1184,20 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" dependencies = [ "equivalent", - "hashbrown 0.14.0", + "hashbrown 0.14.3", "serde", ] [[package]] name = "indoc" -version = "2.0.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c785eefb63ebd0e33416dfcb8d6da0bf27ce752843a45632a67bf10d4d4b5c4" +checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8" [[package]] name = "insta" @@ -1118,6 +1280,15 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +[[package]] +name = "js-sys" +version = "0.3.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "keccak" version = "0.1.4" @@ -1310,22 +1481,23 @@ checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" [[package]] name = "parity-scale-codec" -version = "3.6.4" +version = "3.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8e946cc0cc711189c0b0249fb8b599cbeeab9784d83c415719368bb8d4ac64" +checksum = "0dec8a8073036902368c2cdc0387e85ff9a37054d7e7c98e592145e0c92cd4fb" dependencies = [ "arrayvec", "bitvec", "byte-slice-cast", "impl-trait-for-tuples", + "parity-scale-codec-derive", "serde", ] [[package]] name = "parity-scale-codec-derive" -version = "3.6.4" +version = "3.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a296c3079b5fefbc499e1de58dc26c09b1b9a5952d26694ee89f04a43ebbb3e" +checksum = "312270ee71e1cd70289dacf597cab7b207aa107d2f28191c2ae45b2ece18a260" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -1381,6 +1553,12 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + [[package]] name = "path-clean" version = "1.0.1" @@ -1417,7 +1595,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.39", ] [[package]] @@ -1438,7 +1616,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" dependencies = [ "fixedbitset", - "indexmap 2.0.0", + "indexmap 2.1.0", ] [[package]] @@ -1475,14 +1653,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" dependencies = [ "once_cell", - "toml_edit", + "toml_edit 0.19.15", ] [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" dependencies = [ "unicode-ident", ] @@ -1538,6 +1716,26 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" +[[package]] +name = "rayon" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "redox_syscall" version = "0.2.16" @@ -1602,12 +1800,31 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c707298afce11da2efef2f600116fa93ffa7a032b5d7b628aa17711ec81383ca" +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + [[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + [[package]] name = "rustix" version = "0.38.9" @@ -1673,9 +1890,9 @@ dependencies = [ [[package]] name = "schemars" -version = "0.8.12" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02c613288622e5f0c3fdc5dbd4db1c5fbe752746b1d1a56a0630b78fd00de44f" +checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" dependencies = [ "dyn-clone", "indexmap 1.9.3", @@ -1686,9 +1903,9 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "0.8.12" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "109da1e6b197438deb6db99952990c7f959572794b80ff93707d55a232545e7c" +checksum = "c767fd6fa65d9ccf9cf026122c1b555f2ef9a4f0cea69da4d7dbc3e258d30967" dependencies = [ "proc-macro2", "quote", @@ -1702,24 +1919,30 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "semver" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" + [[package]] name = "serde" -version = "1.0.188" +version = "1.0.192" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.188" +version = "1.0.192" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.39", ] [[package]] @@ -1746,9 +1969,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80" dependencies = [ "serde", ] @@ -1818,6 +2041,58 @@ dependencies = [ "num-traits 0.1.43", ] +[[package]] +name = "starknet-crypto" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33c03f5ac70f9b067f48db7d2d70bdf18ee0f731e8192b6cfa679136becfcdb0" +dependencies = [ + "crypto-bigint", + "hex", + "hmac", + "num-bigint", + "num-integer", + "num-traits 0.2.16", + "rfc6979", + "sha2", + "starknet-crypto-codegen", + "starknet-curve", + "starknet-ff", + "zeroize", +] + +[[package]] +name = "starknet-crypto-codegen" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af6527b845423542c8a16e060ea1bc43f67229848e7cd4c4d80be994a84220ce" +dependencies = [ + "starknet-curve", + "starknet-ff", + "syn 2.0.39", +] + +[[package]] +name = "starknet-curve" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a68a0d87ae56572abf83ddbfd44259a7c90dbeeee1629a1ffe223e7f9a8f3052" +dependencies = [ + "starknet-ff", +] + +[[package]] +name = "starknet-ff" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "067419451efdea1ee968df8438369960c167e0e905c05b84afd074f50e1d6f3d" +dependencies = [ + "ark-ff", + "crypto-bigint", + "getrandom", + "hex", +] + [[package]] name = "string_cache" version = "0.8.7" @@ -1837,6 +2112,12 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + [[package]] name = "syn" version = "1.0.109" @@ -1850,9 +2131,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.29" +version = "2.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" dependencies = [ "proc-macro2", "quote", @@ -1900,22 +2181,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.47" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f" +checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.47" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b" +checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.39", ] [[package]] @@ -1929,32 +2210,43 @@ dependencies = [ [[package]] name = "toml" -version = "0.7.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542" +checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit", + "toml_edit 0.21.0", ] [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.19.14" +version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.0.0", + "indexmap 2.1.0", + "toml_datetime", + "winnow", +] + +[[package]] +name = "toml_edit" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" +dependencies = [ + "indexmap 2.1.0", "serde", "serde_spanned", "toml_datetime", @@ -2028,6 +2320,60 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasm-bindgen" +version = "0.2.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.39", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" + [[package]] name = "winapi" version = "0.3.9" @@ -2232,3 +2578,43 @@ checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" dependencies = [ "linked-hash-map", ] + +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] diff --git a/Cargo.toml b/Cargo.toml index 5547afd..3761435 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,21 +16,24 @@ once_cell = "1.17" smol_str = "0.2" num-integer = "0.1" termcolor = "1.2" -graphviz-rust = "0.6.2" -cairo-felt = "0.8.7" +graphviz-rust = "0.7.0" +cairo-felt = "0.9.1" thiserror = "1.0.47" +rayon = "1.8" +fxhash = "0.2.1" + +cairo-lang-compiler = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.5.0" } +cairo-lang-defs = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.5.0" } +cairo-lang-plugins = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.5.0" } +cairo-lang-starknet = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.5.0" } +cairo-lang-filesystem = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.5.0" } +cairo-lang-parser = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.5.0" } +cairo-lang-syntax = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.5.0" } +cairo-lang-semantic = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.5.0" } +cairo-lang-utils = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.5.0" } +cairo-lang-sierra-generator = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.5.0" } +cairo-lang-sierra = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.5.0" } -cairo-lang-compiler = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.2.0" } -cairo-lang-defs = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.2.0" } -cairo-lang-plugins = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.2.0" } -cairo-lang-starknet = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.2.0" } -cairo-lang-filesystem = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.2.0" } -cairo-lang-parser = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.2.0" } -cairo-lang-syntax = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.2.0" } -cairo-lang-semantic = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.2.0" } -cairo-lang-utils = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.2.0" } -cairo-lang-sierra-generator = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.2.0" } -cairo-lang-sierra = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.2.0" } [dev-dependencies] insta = { version = "1.30", features = ["glob"] } diff --git a/corelib/Scarb.toml b/corelib/Scarb.toml index dabde0b..9bdbd33 100644 --- a/corelib/Scarb.toml +++ b/corelib/Scarb.toml @@ -1,6 +1,7 @@ [package] name = "core" -version = "2.2.0" +version = "2.5.0" +edition = "2023_11" # NOTE: This is non-public, unstable Scarb's field, which instructs resolver that this package does not # depend on `core`, which is only true for this particular package. Nobody else should use it. diff --git a/corelib/cairo_project.toml b/corelib/cairo_project.toml index db46c53..40985b4 100644 --- a/corelib/cairo_project.toml +++ b/corelib/cairo_project.toml @@ -1,2 +1,8 @@ [crate_roots] core = "src" + +[config.global] +edition = "2023_11" + +[config.global.experimental_features] +negative_impls = true diff --git a/corelib/src/array.cairo b/corelib/src/array.cairo index 0b1a2ed..30164a4 100644 --- a/corelib/src/array.cairo +++ b/corelib/src/array.cairo @@ -1,12 +1,13 @@ -use traits::IndexView; +use core::traits::IndexView; -use box::BoxTrait; -use gas::withdraw_gas; -use option::OptionTrait; -use serde::Serde; +use core::box::BoxTrait; +use core::gas::withdraw_gas; +use core::option::OptionTrait; +use core::serde::Serde; +use core::metaprogramming::TypeEqual; #[derive(Drop)] -extern type Array; +pub extern type Array; extern fn array_new() -> Array nopanic; extern fn array_append(ref arr: Array, value: T) nopanic; @@ -24,15 +25,24 @@ extern fn array_slice( extern fn array_len(arr: @Array) -> usize nopanic; #[generate_trait] -impl ArrayImpl of ArrayTrait { +pub impl ArrayImpl of ArrayTrait { #[inline(always)] fn new() -> Array { array_new() } #[inline(always)] - fn append(ref self: Array, value: T) { + fn append(ref self: Array, value: T) nopanic { array_append(ref self, value) } + fn append_span<+Clone, +Drop>(ref self: Array, mut span: Span) { + match span.pop_front() { + Option::Some(current) => { + self.append(current.clone()); + self.append_span(span); + }, + Option::None => {} + }; + } #[inline(always)] fn pop_front(ref self: Array) -> Option nopanic { match array_pop_front(ref self) { @@ -55,14 +65,21 @@ impl ArrayImpl of ArrayTrait { array_at(self, index).unbox() } #[inline(always)] + #[must_use] fn len(self: @Array) -> usize { array_len(self) } #[inline(always)] + #[must_use] fn is_empty(self: @Array) -> bool { - self.len() == 0_usize + let mut snapshot = self; + match array_snapshot_pop_front(ref snapshot) { + Option::Some(_) => false, + Option::None => true, + } } #[inline(always)] + #[must_use] fn span(self: @Array) -> Span { Span { snapshot: self } } @@ -81,7 +98,7 @@ impl ArrayIndex of IndexView, usize, @T> { } } -impl ArraySerde, impl TDrop: Drop> of Serde> { +impl ArraySerde, +Drop> of Serde> { fn serialize(self: @Array, ref output: Array) { self.len().serialize(ref output); serialize_array_helper(self.span(), ref output); @@ -93,9 +110,7 @@ impl ArraySerde, impl TDrop: Drop> of Serde } } -fn serialize_array_helper, impl TDrop: Drop>( - mut input: Span, ref output: Array -) { +fn serialize_array_helper, +Drop>(mut input: Span, ref output: Array) { match input.pop_front() { Option::Some(value) => { value.serialize(ref output); @@ -105,25 +120,39 @@ fn serialize_array_helper, impl TDrop: Drop>( } } -fn deserialize_array_helper, impl TDrop: Drop>( +fn deserialize_array_helper, +Drop>( ref serialized: Span, mut curr_output: Array, remaining: felt252 ) -> Option> { if remaining == 0 { return Option::Some(curr_output); } - curr_output.append(TSerde::deserialize(ref serialized)?); + curr_output.append(Serde::deserialize(ref serialized)?); deserialize_array_helper(ref serialized, curr_output, remaining - 1) } // Span. -struct Span { +pub struct Span { snapshot: @Array } impl SpanCopy of Copy>; impl SpanDrop of Drop>; -impl SpanSerde, impl TDrop: Drop> of Serde> { +impl SpanFelt252Serde of Serde> { + fn serialize(self: @Span, ref output: Array) { + (*self).len().serialize(ref output); + serialize_array_helper(*self, ref output) + } + + fn deserialize(ref serialized: Span) -> Option> { + let length: u32 = (*serialized.pop_front()?).try_into()?; + let res = serialized.slice(0, length); + serialized = serialized.slice(length, serialized.len() - length); + Option::Some(res) + } +} + +impl SpanSerde, +Drop, -TypeEqual> of Serde> { fn serialize(self: @Span, ref output: Array) { (*self).len().serialize(ref output); serialize_array_helper(*self, ref output) @@ -137,7 +166,7 @@ impl SpanSerde, impl TDrop: Drop> of Serde> } #[generate_trait] -impl SpanImpl of SpanTrait { +pub impl SpanImpl of SpanTrait { #[inline(always)] fn pop_front(ref self: Span) -> Option<@T> { let mut snapshot = self.snapshot; @@ -171,16 +200,22 @@ impl SpanImpl of SpanTrait { Span { snapshot: array_slice(self.snapshot, start, length).expect('Index out of bounds') } } #[inline(always)] + #[must_use] fn len(self: Span) -> usize { array_len(self.snapshot) } #[inline(always)] + #[must_use] fn is_empty(self: Span) -> bool { - self.len() == 0_usize + let mut snapshot = self.snapshot; + match array_snapshot_pop_front(ref snapshot) { + Option::Some(_) => false, + Option::None => true, + } } } -impl SpanIndex of IndexView, usize, @T> { +pub impl SpanIndex of IndexView, usize, @T> { #[inline(always)] fn index(self: @Span, index: usize) -> @T { array_at(*self.snapshot, index).unbox() @@ -188,25 +223,21 @@ impl SpanIndex of IndexView, usize, @T> { } // TODO(spapini): Remove TDrop. It is necessary to get rid of response in case of panic. -impl ArrayTCloneImpl, impl TDrop: Drop> of Clone> { +impl ArrayTCloneImpl, +Drop> of Clone> { fn clone(self: @Array) -> Array { let mut response = array_new(); let mut span = self.span(); loop { match span.pop_front() { - Option::Some(v) => { - response.append(TClone::clone(v)); - }, - Option::None => { - break (); - }, + Option::Some(v) => { response.append(v.clone()); }, + Option::None => { break (); }, }; }; response } } -impl ArrayPartialEq> of PartialEq> { +impl ArrayPartialEq> of PartialEq> { fn eq(lhs: @Array, rhs: @Array) -> bool { lhs.span() == rhs.span() } @@ -215,7 +246,7 @@ impl ArrayPartialEq> of PartialEq> } } -impl SpanPartialEq> of PartialEq> { +impl SpanPartialEq> of PartialEq> { fn eq(lhs: @Span, rhs: @Span) -> bool { if (*lhs).len() != (*rhs).len() { return false; @@ -229,9 +260,7 @@ impl SpanPartialEq> of PartialEq> { break false; } }, - Option::None => { - break true; - }, + Option::None => { break true; }, }; } } diff --git a/corelib/src/boolean.cairo b/corelib/src/boolean.cairo new file mode 100644 index 0000000..f51efba --- /dev/null +++ b/corelib/src/boolean.cairo @@ -0,0 +1,19 @@ +#[generate_trait] +pub impl BoolImpl> of BoolTrait { + /// Returns `Some(t)` if the `bool` is `true`, or `None` otherwise. + /// + /// # Examples + /// + /// ``` + /// assert(false.then_some(0) == Option::None); + /// assert(true.then_some(0) == Option::Some(0)); + /// ``` + #[inline(always)] + fn then_some(self: bool, t: T) -> Option nopanic { + if self { + Option::Some(t) + } else { + Option::None + } + } +} diff --git a/corelib/src/box.cairo b/corelib/src/box.cairo index 8321096..706bdaa 100644 --- a/corelib/src/box.cairo +++ b/corelib/src/box.cairo @@ -1,20 +1,34 @@ #[derive(Copy, Drop)] -extern type Box; +pub extern type Box; // These functions are only exposed in the corelib through the trait below since calling them // directly with tuples panics due to auto unpacking of the tuple. // TODO(Gil): Expose in the core lib when the described behaviour is fixed. extern fn into_box(value: T) -> Box nopanic; extern fn unbox(box: Box) -> T nopanic; +extern fn box_forward_snapshot(value: @Box) -> Box<@T> nopanic; #[generate_trait] -impl BoxImpl of BoxTrait { +pub impl BoxImpl of BoxTrait { #[inline(always)] + #[must_use] fn new(value: T) -> Box nopanic { into_box(value) } #[inline(always)] + #[must_use] fn unbox(self: Box) -> T nopanic { unbox(self) } + #[must_use] + fn as_snapshot(self: @Box) -> Box<@T> nopanic { + box_forward_snapshot(self) + } +} + +impl BoxDebug> of core::fmt::Debug> { + fn fmt(self: @Box, ref f: core::fmt::Formatter) -> Result<(), core::fmt::Error> { + write!(f, "&")?; + TDebug::fmt(self.as_snapshot().unbox(), ref f) + } } diff --git a/corelib/src/byte_array.cairo b/corelib/src/byte_array.cairo index 676f47a..ce6df4c 100644 --- a/corelib/src/byte_array.cairo +++ b/corelib/src/byte_array.cairo @@ -1,42 +1,44 @@ -use array::{ArrayTrait, SpanTrait}; -use bytes_31::{ +use core::array::{ArrayTrait, SpanTrait}; +use core::bytes_31::{ BYTES_IN_BYTES31, Bytes31Trait, one_shift_left_bytes_felt252, one_shift_left_bytes_u128, POW_2_128, POW_2_8, U128IntoBytes31, U8IntoBytes31 }; -use clone::Clone; -use cmp::min; -use integer::{u128_safe_divmod, U32TryIntoNonZero}; -use option::OptionTrait; -use traits::{Into, TryInto}; -use zeroable::NonZeroIntoImpl; - +use core::clone::Clone; +use core::cmp::min; +use core::integer::{u128_safe_divmod, U32TryIntoNonZero}; +use core::option::OptionTrait; +use core::traits::{Into, TryInto}; +use core::serde::Serde; +use core::zeroable::NonZeroIntoImpl; + +/// A magic constant for identifying serialization of ByteArrays. An array of felt252s with this +/// magic as one of the felt252s indicates that right after it you should expect a serialized +/// ByteArray. This is currently used mainly for prints and panics. +pub(crate) const BYTE_ARRAY_MAGIC: felt252 = + 0x46a6158a16a947e5916b2a2ca68501a45e93d7110e81aa2d6438b1c57c879a3; const BYTES_IN_U128: usize = 16; // TODO(yuval): change to `BYTES_IN_BYTES31 - 1` once consteval_int supports non-literals. const BYTES_IN_BYTES31_MINUS_ONE: usize = consteval_int!(31 - 1); // TODO(yuval): don't allow creation of invalid ByteArray? -#[derive(Drop, Clone, PartialEq)] -struct ByteArray { +#[derive(Drop, Clone, PartialEq, Serde, Default)] +pub struct ByteArray { // Full "words" of 31 bytes each. The first byte of each word in the byte array // is the most significant byte in the word. - data: Array, + pub(crate) data: Array, // This felt252 actually represents a bytes31, with < 31 bytes. // It is represented as a felt252 to improve performance of building the byte array. // The number of bytes in here is specified in `pending_word_len`. // The first byte is the most significant byte among the `pending_word_len` bytes in the word. - pending_word: felt252, + pub(crate) pending_word: felt252, // Should be in range [0, 30]. - pending_word_len: usize, + pub(crate) pending_word_len: usize, } -impl ByteArrayDefault of Default { - fn default() -> ByteArray { - ByteArray { data: Default::default(), pending_word: 0, pending_word_len: 0 } - } -} +pub(crate) impl ByteArrayStringLiteral of core::string::StringLiteral; #[generate_trait] -impl ByteArrayImpl of ByteArrayTrait { +pub impl ByteArrayImpl of ByteArrayTrait { // TODO(yuval): add a `new` function for initialization. // Appends a single word of `len` bytes to the end of the ByteArray. @@ -88,16 +90,7 @@ impl ByteArrayImpl of ByteArrayTrait { let mut other_data = other.data.span(); if self.pending_word_len == 0 { - loop { - match other_data.pop_front() { - Option::Some(current_word) => { - self.data.append(*current_word); - }, - Option::None => { - break; - } - }; - }; + self.data.append_span(other_data); self.pending_word = *other.pending_word; self.pending_word_len = *other.pending_word_len; return; @@ -111,9 +104,7 @@ impl ByteArrayImpl of ByteArrayTrait { Option::Some(current_word) => { self.append_split_index_16((*current_word).into()); }, - Option::None => { - break; - } + Option::None => { break; } }; }; } else if self.pending_word_len < BYTES_IN_U128 { @@ -125,9 +116,7 @@ impl ByteArrayImpl of ByteArrayTrait { (*current_word).into(), self.pending_word_len ); }, - Option::None => { - break; - } + Option::None => { break; } }; }; } else { @@ -140,9 +129,7 @@ impl ByteArrayImpl of ByteArrayTrait { (*current_word).into(), self.pending_word_len ); }, - Option::None => { - break; - } + Option::None => { break; } }; }; } @@ -180,6 +167,7 @@ impl ByteArrayImpl of ByteArrayTrait { self.pending_word_len = 0; } + #[must_use] fn len(self: @ByteArray) -> usize { self.data.len() * BYTES_IN_BYTES31.into() + (*self.pending_word_len).into() } @@ -223,9 +211,7 @@ impl ByteArrayImpl of ByteArrayTrait { Option::Some(current_word) => { result.append_word_rev((*current_word).into(), BYTES_IN_BYTES31); }, - Option::None => { - break; - } + Option::None => { break; } }; }; result @@ -356,7 +342,7 @@ impl ByteArrayImpl of ByteArrayTrait { } } -impl U128Add of Add { +impl ByteArrayAdd of Add { #[inline] fn add(lhs: ByteArray, rhs: ByteArray) -> ByteArray { ByteArrayTrait::concat(@lhs, @rhs) @@ -369,7 +355,7 @@ impl ByteArrayAddEq of AddEq { } } -impl ByteArrayIndexView of IndexView { +pub(crate) impl ByteArrayIndexView of IndexView { fn index(self: @ByteArray, index: usize) -> u8 { self.at(index).expect('Index out of bounds') } diff --git a/corelib/src/bytes_31.cairo b/corelib/src/bytes_31.cairo index d4a913b..a5763c0 100644 --- a/corelib/src/bytes_31.cairo +++ b/corelib/src/bytes_31.cairo @@ -1,21 +1,21 @@ -use traits::{Into, TryInto}; -use option::OptionTrait; -use integer::{u256_from_felt252, u128_safe_divmod, u128_to_felt252}; +use core::traits::{Into, TryInto}; +use core::option::OptionTrait; +use core::integer::{u128_safe_divmod, u128_to_felt252}; -const BYTES_IN_BYTES31: usize = 31; +pub(crate) const BYTES_IN_BYTES31: usize = 31; const BYTES_IN_U128: usize = 16; -const POW_2_128: felt252 = 0x100000000000000000000000000000000; -const POW_2_8: u128 = 0x100; +pub(crate) const POW_2_128: felt252 = 0x100000000000000000000000000000000; +pub(crate) const POW_2_8: u128 = 0x100; #[derive(Copy, Drop)] -extern type bytes31; +pub extern type bytes31; -extern fn bytes31_const() -> bytes31 nopanic; +pub(crate) extern fn bytes31_const() -> bytes31 nopanic; extern fn bytes31_try_from_felt252(value: felt252) -> Option implicits(RangeCheck) nopanic; extern fn bytes31_to_felt252(value: bytes31) -> felt252 nopanic; #[generate_trait] -impl Bytes31Impl of Bytes31Trait { +pub impl Bytes31Impl of Bytes31Trait { // Gets the byte at the given index (LSB's index is 0), assuming that // `index < BYTES_IN_BYTES31`. If the assumption is not met, the behavior is undefined. fn at(self: @bytes31, index: usize) -> u8 { @@ -29,60 +29,62 @@ impl Bytes31Impl of Bytes31Trait { } } -impl Bytes31IndexView of IndexView { +pub(crate) impl Bytes31IndexView of IndexView { fn index(self: @bytes31, index: usize) -> u8 { self.at(index) } } -impl Bytes31IntoFelt252 of Into { +impl Bytes31BitSize of core::num::traits::BitSize { + fn bits() -> usize { + 248 + } +} + +pub(crate) impl Bytes31IntoFelt252 of Into { fn into(self: bytes31) -> felt252 { bytes31_to_felt252(self) } } -impl Bytes31IntoU256 of Into { +pub(crate) impl Bytes31IntoU256 of Into { fn into(self: bytes31) -> u256 { let as_felt: felt252 = self.into(); as_felt.into() } } -impl Felt252TryIntoBytes31 of TryInto { +pub(crate) impl Felt252TryIntoBytes31 of TryInto { fn try_into(self: felt252) -> Option { bytes31_try_from_felt252(self) } } -// TODO(yuval): implement all `into`s using `integer::upcast(self)`. -impl U8IntoBytes31 of Into { +impl Bytes31Serde = core::serde::into_felt252_based::SerdeImpl; + +pub(crate) impl U8IntoBytes31 of Into { fn into(self: u8) -> bytes31 { - let as_felt: felt252 = self.into(); - as_felt.try_into().unwrap() + core::integer::upcast(self) } } impl U16IntoBytes31 of Into { fn into(self: u16) -> bytes31 { - let as_felt: felt252 = self.into(); - as_felt.try_into().unwrap() + core::integer::upcast(self) } } impl U32IntoBytes31 of Into { fn into(self: u32) -> bytes31 { - let as_felt: felt252 = self.into(); - as_felt.try_into().unwrap() + core::integer::upcast(self) } } impl U64IntoBytes31 of Into { fn into(self: u64) -> bytes31 { - let as_felt: felt252 = self.into(); - as_felt.try_into().unwrap() + core::integer::upcast(self) } } -impl U128IntoBytes31 of Into { +pub(crate) impl U128IntoBytes31 of Into { fn into(self: u128) -> bytes31 { - let as_felt: felt252 = self.into(); - as_felt.try_into().unwrap() + core::integer::upcast(self) } } @@ -94,7 +96,7 @@ impl U128IntoBytes31 of Into { // 3. len <= BYTES_IN_BYTES31. // If these assumptions are not met, it can corrupt the ByteArray. Thus, this should be a // private function. We could add masking/assertions but it would be more expansive. -fn split_bytes31(word: felt252, len: usize, index: usize) -> (felt252, felt252) { +pub(crate) fn split_bytes31(word: felt252, len: usize, index: usize) -> (felt252, felt252) { if index == 0 { return (0, word); } @@ -139,7 +141,7 @@ fn split_bytes31(word: felt252, len: usize, index: usize) -> (felt252, felt252) // Note: if `n_bytes >= BYTES_IN_BYTES31`, the behavior is undefined. If one wants to assert that in // the callsite, it's sufficient to assert that `n_bytes != BYTES_IN_BYTES31` because if // `n_bytes > 31` then `n_bytes - 16 > 15` and `one_shift_left_bytes_u128` would panic. -fn one_shift_left_bytes_felt252(n_bytes: usize) -> felt252 { +pub(crate) fn one_shift_left_bytes_felt252(n_bytes: usize) -> felt252 { if n_bytes < BYTES_IN_U128 { one_shift_left_bytes_u128(n_bytes).into() } else { @@ -150,7 +152,7 @@ fn one_shift_left_bytes_felt252(n_bytes: usize) -> felt252 { // Returns 1 << (8 * `n_bytes`) as u128, where `n_bytes` must be < BYTES_IN_U128. // // Panics if `n_bytes >= BYTES_IN_U128`. -fn one_shift_left_bytes_u128(n_bytes: usize) -> u128 { +pub(crate) fn one_shift_left_bytes_u128(n_bytes: usize) -> u128 { // TODO(yuval): change to match once it's supported for integers. if n_bytes == 0 { 0x1_u128 @@ -185,7 +187,7 @@ fn one_shift_left_bytes_u128(n_bytes: usize) -> u128 { } else if n_bytes == 15 { 0x1000000000000000000000000000000_u128 } else { - panic_with_felt252('n_bytes too big') + core::panic_with_felt252('n_bytes too big') } } diff --git a/corelib/src/clone.cairo b/corelib/src/clone.cairo index fc71f20..3a27f99 100644 --- a/corelib/src/clone.cairo +++ b/corelib/src/clone.cairo @@ -1,8 +1,9 @@ -trait Clone { +pub trait Clone { + #[must_use] fn clone(self: @T) -> T; } -impl TCopyClone> of Clone { +impl TCopyClone> of Clone { fn clone(self: @T) -> T { *self } diff --git a/corelib/src/cmp.cairo b/corelib/src/cmp.cairo index 3031ce1..a458570 100644 --- a/corelib/src/cmp.cairo +++ b/corelib/src/cmp.cairo @@ -1,15 +1,13 @@ -fn min, impl DropT: Drop, impl CopyT: Copy>( - a: T, b: T -) -> T { +#[must_use] +pub fn min, +Drop, +Copy>(a: T, b: T) -> T { if a > b { return b; } a } -fn max, impl DropT: Drop, impl CopyT: Copy>( - a: T, b: T -) -> T { +#[must_use] +pub fn max, +Drop, +Copy>(a: T, b: T) -> T { if a > b { return a; } diff --git a/corelib/src/debug.cairo b/corelib/src/debug.cairo index e5ce405..f325f34 100644 --- a/corelib/src/debug.cairo +++ b/corelib/src/debug.cairo @@ -1,10 +1,10 @@ -use array::ArrayTrait; -use traits::Into; -use option::Option; +use core::array::ArrayTrait; +use core::traits::Into; +use core::option::Option; // Usage: // -// use debug::PrintTrait; +// use core::debug::PrintTrait; // // 1.print(); // @@ -18,23 +18,23 @@ use option::Option; // arr.append('SomeVeryLongMessage'); // arr.print(); -extern fn print(message: Array) nopanic; +pub(crate) extern fn print(message: Array) nopanic; fn print_felt252(message: felt252) { print(array![message]); } -trait PrintTrait { +pub(crate) trait PrintTrait { fn print(self: T); } -impl Felt252PrintImpl of PrintTrait { +pub(crate) impl Felt252PrintImpl of PrintTrait { fn print(self: felt252) { print_felt252(self); } } -impl BoolPrintImpl of PrintTrait { +pub(crate) impl BoolPrintImpl of PrintTrait { fn print(self: bool) { if self { 'true'.print(); @@ -44,51 +44,89 @@ impl BoolPrintImpl of PrintTrait { } } -impl ContractAddressPrintImpl of PrintTrait { +pub(crate) impl ContractAddressPrintImpl of PrintTrait { fn print(self: starknet::ContractAddress) { Into::<_, felt252>::into(self).print(); } } -impl U8PrintImpl of PrintTrait { +pub(crate) impl U8PrintImpl of PrintTrait { fn print(self: u8) { Into::<_, felt252>::into(self).print(); } } -impl U16PrintImpl of PrintTrait { +pub(crate) impl U16PrintImpl of PrintTrait { fn print(self: u16) { Into::<_, felt252>::into(self).print(); } } -impl U32PrintImpl of PrintTrait { +pub(crate) impl U32PrintImpl of PrintTrait { fn print(self: u32) { Into::<_, felt252>::into(self).print(); } } -impl U64PrintImpl of PrintTrait { +pub(crate) impl U64PrintImpl of PrintTrait { fn print(self: u64) { Into::<_, felt252>::into(self).print(); } } -impl U128PrintImpl of PrintTrait { +pub(crate) impl U128PrintImpl of PrintTrait { fn print(self: u128) { Into::<_, felt252>::into(self).print(); } } -impl U256PrintImpl of PrintTrait { +pub(crate) impl U256PrintImpl of PrintTrait { fn print(self: u256) { Into::::into(self.low).print(); Into::::into(self.high).print(); } } -impl ArrayGenericPrintImpl of PrintTrait> { +pub(crate) impl I8PrintImpl of PrintTrait { + fn print(self: i8) { + Into::<_, felt252>::into(self).print(); + } +} + +pub(crate) impl I16PrintImpl of PrintTrait { + fn print(self: i16) { + Into::<_, felt252>::into(self).print(); + } +} + +pub(crate) impl I32PrintImpl of PrintTrait { + fn print(self: i32) { + Into::<_, felt252>::into(self).print(); + } +} + +pub(crate) impl I64PrintImpl of PrintTrait { + fn print(self: i64) { + Into::<_, felt252>::into(self).print(); + } +} + +pub(crate) impl I128PrintImpl of PrintTrait { + fn print(self: i128) { + Into::<_, felt252>::into(self).print(); + } +} + +pub(crate) impl ArrayGenericPrintImpl of PrintTrait> { fn print(mut self: Array) { print(self); } } + +/// Prints a byte array as a string. +pub fn print_byte_array_as_string(self: @ByteArray) { + let mut serialized = array![core::byte_array::BYTE_ARRAY_MAGIC]; + self.serialize(ref serialized); + print(serialized) +} + diff --git a/corelib/src/dict.cairo b/corelib/src/dict.cairo index ba6f294..b6de59f 100644 --- a/corelib/src/dict.cairo +++ b/corelib/src/dict.cairo @@ -1,11 +1,11 @@ -use traits::{Index, Default}; +use core::traits::{Index, Default, Felt252DictValue}; -extern type Felt252Dict; -extern type SquashedFelt252Dict; -extern type Felt252DictEntry; -impl SquashedFelt252DictDrop> of Drop>; +pub extern type Felt252Dict; +pub extern type SquashedFelt252Dict; +pub extern type Felt252DictEntry; +impl SquashedFelt252DictDrop> of Drop>; -extern fn felt252_dict_new() -> Felt252Dict implicits(SegmentArena) nopanic; +pub(crate) extern fn felt252_dict_new() -> Felt252Dict implicits(SegmentArena) nopanic; extern fn felt252_dict_entry_get( dict: Felt252Dict, key: felt252 @@ -20,31 +20,32 @@ extern fn felt252_dict_entry_finalize( /// NOTE: Never use this libfunc directly. Use Felt252DictTrait::squash() instead. Using this /// libfunc directly will result in multiple unnecessary copies of the libfunc in the compiled CASM /// code. -extern fn felt252_dict_squash( +pub(crate) extern fn felt252_dict_squash( dict: Felt252Dict ) -> SquashedFelt252Dict implicits(RangeCheck, GasBuiltin, SegmentArena) nopanic; -trait Felt252DictTrait { +pub trait Felt252DictTrait { /// Inserts the given value for the given key. /// /// Requires the `Destruct` trait, as the previous value is dropped. - fn insert>(ref self: Felt252Dict, key: felt252, value: T); + fn insert<+Destruct>(ref self: Felt252Dict, key: felt252, value: T); /// Returns a copy of the value at the given key. /// /// Requires the `Copy` trait. - fn get>(ref self: Felt252Dict, key: felt252) -> T; + fn get<+Copy>(ref self: Felt252Dict, key: felt252) -> T; fn squash(self: Felt252Dict) -> SquashedFelt252Dict nopanic; + #[must_use] fn entry(self: Felt252Dict, key: felt252) -> (Felt252DictEntry, T) nopanic; } -impl Felt252DictImpl> of Felt252DictTrait { +impl Felt252DictImpl> of Felt252DictTrait { #[inline] - fn insert>(ref self: Felt252Dict, key: felt252, value: T) { + fn insert<+Destruct>(ref self: Felt252Dict, key: felt252, value: T) { let (entry, _prev_value) = felt252_dict_entry_get(self, key); self = felt252_dict_entry_finalize(entry, value); } #[inline] - fn get>(ref self: Felt252Dict, key: felt252) -> T { + fn get<+Copy>(ref self: Felt252Dict, key: felt252) -> T { let (entry, prev_value) = felt252_dict_entry_get(self, key); let return_value = prev_value; self = felt252_dict_entry_finalize(entry, prev_value); @@ -62,11 +63,11 @@ impl Felt252DictImpl> of Felt252DictTrait< } } -trait Felt252DictEntryTrait { +pub trait Felt252DictEntryTrait { fn finalize(self: Felt252DictEntry, new_value: T) -> Felt252Dict; } -impl Felt252DictEntryImpl> of Felt252DictEntryTrait { +impl Felt252DictEntryImpl> of Felt252DictEntryTrait { #[inline(always)] fn finalize(self: Felt252DictEntry, new_value: T) -> Felt252Dict { felt252_dict_entry_finalize(self, new_value) @@ -80,29 +81,22 @@ impl Felt252DictDefault of Default> { } } -impl Felt252DictDestruct< - T, impl TDrop: Drop, impl TDefault: Felt252DictValue -> of Destruct> { +impl Felt252DictDestruct, +Felt252DictValue> of Destruct> { #[inline(always)] fn destruct(self: Felt252Dict) nopanic { self.squash(); } } -impl Felt252DictEntryDestruct< - T, impl TDrop: Drop, impl TDefault: Felt252DictValue -> of Destruct> { +impl Felt252DictEntryDestruct, +Felt252DictValue> of Destruct> { #[inline(always)] fn destruct(self: Felt252DictEntry::) nopanic { - felt252_dict_entry_finalize(self, TDefault::zero_default()); + felt252_dict_entry_finalize(self, Felt252DictValue::zero_default()); } } impl Felt252DictIndex< - T, - impl TDictImpl: Felt252DictTrait, - impl TCopy: Copy, - impl EntryDestruct: Destruct> + T, +Felt252DictTrait, +Copy, +Destruct> > of Index, felt252, T> { #[inline(always)] fn index(ref self: Felt252Dict, index: felt252) -> T { diff --git a/corelib/src/ec.cairo b/corelib/src/ec.cairo index 46c4da9..91123fe 100644 --- a/corelib/src/ec.cairo +++ b/corelib/src/ec.cairo @@ -1,27 +1,27 @@ //! This module contains functions and constructs related to elliptic curve operations on the Stark //! curve. -use array::ArrayTrait; -use traits::{Into, TryInto}; -use zeroable::IsZeroResult; +use core::array::ArrayTrait; +use core::traits::{Into, TryInto}; +use core::zeroable::IsZeroResult; -mod stark_curve { +pub mod stark_curve { /// The STARK Curve is defined by the equation `y^2 = x^3 + ALPHA*x + BETA`. - const ALPHA: felt252 = 1; + pub const ALPHA: felt252 = 1; /// The STARK Curve is defined by the equation `y^2 = x^3 + ALPHA*x + BETA`. - const BETA: felt252 = 0x6f21413efbe40de150e596d72f7a8c5609ad26c15c915c1f4cdfcb99cee9e89; + pub const BETA: felt252 = 0x6f21413efbe40de150e596d72f7a8c5609ad26c15c915c1f4cdfcb99cee9e89; /// The order (number of points) of the STARK Curve. - const ORDER: felt252 = 0x800000000000010ffffffffffffffffb781126dcae7b2321e66a241adc64d2f; + pub const ORDER: felt252 = 0x800000000000010ffffffffffffffffb781126dcae7b2321e66a241adc64d2f; /// The x coordinate of the generator point used in the ECDSA signature. - const GEN_X: felt252 = 0x1ef15c18599971b7beced415a40f0c7deacfd9b0d1819e03d723d8bc943cfca; + pub const GEN_X: felt252 = 0x1ef15c18599971b7beced415a40f0c7deacfd9b0d1819e03d723d8bc943cfca; /// The y coordinate of the generator point used in the ECDSA signature. - const GEN_Y: felt252 = 0x5668060aa49730b7be4801df46ec62de53ecd11abe43a32873000c36e8dc1f; + pub const GEN_Y: felt252 = 0x5668060aa49730b7be4801df46ec62de53ecd11abe43a32873000c36e8dc1f; } -extern type EcOp; +pub extern type EcOp; #[derive(Copy, Drop)] -extern type EcPoint; -type NonZeroEcPoint = NonZero; +pub extern type EcPoint; +pub type NonZeroEcPoint = NonZero; /// Returns the zero point of the curve ("the point at infinity"). extern fn ec_point_zero() -> EcPoint nopanic; @@ -32,7 +32,7 @@ extern fn ec_point_try_new_nz(x: felt252, y: felt252) -> Option /// Returns `None` if no point of form (x, _) is on the curve. extern fn ec_point_from_x_nz(x: felt252) -> Option implicits(RangeCheck) nopanic; /// Unwraps a non-zero point into its (x, y) coordinates. -extern fn ec_point_unwrap(p: NonZeroEcPoint) -> (felt252, felt252) nopanic; +pub extern fn ec_point_unwrap(p: NonZeroEcPoint) -> (felt252, felt252) nopanic; /// Computes the negation of an elliptic curve point (-p). extern fn ec_neg(p: EcPoint) -> EcPoint nopanic; /// Checks whether the given `EcPoint` is the zero point. @@ -53,7 +53,7 @@ impl EcPointTryIntoNonZero of TryInto { // TODO(lior): Allow explicit clone() for EcState, since we don't allow implicit dup (Copy). #[derive(Drop)] -extern type EcState; +pub extern type EcState; /// Initializes an EC computation with the zero point. extern fn ec_state_init() -> EcState nopanic; @@ -69,8 +69,9 @@ extern fn ec_state_add_mul( extern fn ec_state_try_finalize_nz(s: EcState) -> Option nopanic; #[generate_trait] -impl EcStateImpl of EcStateTrait { +pub impl EcStateImpl of EcStateTrait { /// Initializes an EC computation with the zero point. + #[must_use] fn init() -> EcState { ec_state_init() } @@ -101,7 +102,7 @@ impl EcStateImpl of EcStateTrait { } #[generate_trait] -impl EcPointImpl of EcPointTrait { +pub impl EcPointImpl of EcPointTrait { /// Creates a new EC point from its (x, y) coordinates. #[inline(always)] fn new(x: felt252, y: felt252) -> Option { @@ -142,15 +143,11 @@ impl EcPointAdd of Add { fn add(lhs: EcPoint, rhs: EcPoint) -> EcPoint { let lhs_nz = match lhs.try_into() { Option::Some(pt) => pt, - Option::None => { - return rhs; - }, + Option::None => { return rhs; }, }; let rhs_nz = match rhs.try_into() { Option::Some(pt) => pt, - Option::None => { - return lhs; - }, + Option::None => { return lhs; }, }; let mut state = ec_state_init(); state.add(lhs_nz); @@ -169,7 +166,8 @@ impl EcPointAddEq of AddEq { impl EcPointSub of Sub { /// Computes the difference between two points on the curve. fn sub(lhs: EcPoint, rhs: EcPoint) -> EcPoint { - match rhs.try_into() { + let nz_point: Option> = rhs.try_into(); + match nz_point { Option::Some(_) => {}, Option::None => { // lhs - 0 = lhs. diff --git a/corelib/src/ecdsa.cairo b/corelib/src/ecdsa.cairo index 6037b30..450e586 100644 --- a/corelib/src/ecdsa.cairo +++ b/corelib/src/ecdsa.cairo @@ -1,7 +1,8 @@ -use ec::EcPointTrait; -use option::OptionTrait; -use traits::{Into, TryInto}; -use zeroable::IsZeroResult; +use core::{ec, ec::{EcPoint, EcPointTrait}}; +use core::option::OptionTrait; +use core::math; +use core::traits::{Into, TryInto}; +use core::zeroable::IsZeroResult; // Checks if (`signature_r`, `signature_s`) is a valid ECDSA signature for the given `public_key` // on the given `message`. @@ -21,7 +22,7 @@ use zeroable::IsZeroResult; // Returns: // `true` if the signature is valid and `false` otherwise. // TODO(lior): Make this function nopanic once possible. -fn check_ecdsa_signature( +pub fn check_ecdsa_signature( message_hash: felt252, public_key: felt252, signature_r: felt252, signature_s: felt252 ) -> bool { // TODO(orizi): Change to || once it does not prevent `a == 0` comparison optimization. @@ -37,28 +38,22 @@ fn check_ecdsa_signature( } // Check that the public key is the x coordinate of a point on the curve and get such a point. - let public_key_point = match ec::EcPointTrait::new_from_x(public_key) { + let public_key_point = match EcPointTrait::new_from_x(public_key) { Option::Some(point) => point, - Option::None => { - return false; - }, + Option::None => { return false; }, }; // Check that `r` is the x coordinate of a point on the curve and get such a point. // Note that this ensures that `r != 0`. let signature_r_point = match EcPointTrait::new_from_x(signature_r) { Option::Some(point) => point, - Option::None => { - return false; - }, + Option::None => { return false; }, }; // Retrieve the generator point. let gen_point = match EcPointTrait::new(ec::stark_curve::GEN_X, ec::stark_curve::GEN_Y) { Option::Some(point) => point, - Option::None => { - return false; - }, + Option::None => { return false; }, }; // To verify ECDSA, obtain: @@ -74,9 +69,7 @@ fn check_ecdsa_signature( let (x, _) = ec::ec_point_unwrap(pt); x }, - Option::None => { - return false; - }, + Option::None => { return false; }, }; let zG: EcPoint = gen_point.mul(message_hash); @@ -106,7 +99,7 @@ fn check_ecdsa_signature( /// Receives a signature and the signed message hash. /// Returns the public key associated with the signer. -fn recover_public_key( +pub fn recover_public_key( message_hash: felt252, signature_r: felt252, signature_s: felt252, y_parity: bool ) -> Option { let mut signature_r_point = EcPointTrait::new_from_x(signature_r)?; @@ -136,7 +129,7 @@ fn recover_public_key( let r_nz = r_nz.try_into()?; let ord_nz: u256 = ec::stark_curve::ORDER.into(); let ord_nz = ord_nz.try_into()?; - let r_inv = math::inv_mod(r_nz, ord_nz)?; + let r_inv = math::u256_inv_mod(r_nz, ord_nz)?.into(); let s_div_r: felt252 = math::u256_mul_mod_n(signature_s.into(), r_inv, ord_nz).try_into()?; let z_div_r: felt252 = math::u256_mul_mod_n(message_hash.into(), r_inv, ord_nz).try_into()?; let s_div_rR: EcPoint = signature_r_point.mul(s_div_r); diff --git a/corelib/src/felt_252.cairo b/corelib/src/felt_252.cairo new file mode 100644 index 0000000..f1f9f1e --- /dev/null +++ b/corelib/src/felt_252.cairo @@ -0,0 +1,31 @@ +pub(crate) impl Felt252Zero of core::num::traits::Zero { + fn zero() -> felt252 { + 0 + } + + #[inline(always)] + fn is_zero(self: @felt252) -> bool { + *self == Felt252Zero::zero() + } + + #[inline(always)] + fn is_non_zero(self: @felt252) -> bool { + !self.is_zero() + } +} + +pub(crate) impl Felt252One of core::num::traits::One { + fn one() -> felt252 { + 1 + } + + #[inline(always)] + fn is_one(self: @felt252) -> bool { + *self == Felt252One::one() + } + + #[inline(always)] + fn is_non_one(self: @felt252) -> bool { + !self.is_one() + } +} diff --git a/corelib/src/fmt.cairo b/corelib/src/fmt.cairo new file mode 100644 index 0000000..506d72a --- /dev/null +++ b/corelib/src/fmt.cairo @@ -0,0 +1,198 @@ +#[derive(Drop)] +pub struct Error {} + +/// Configuration for formatting. +#[derive(Default, Drop)] +pub struct Formatter { + /// The pending result of formatting. + pub buffer: ByteArray, +} + +/// A trait for standard formatting, using the empty format ("{}"). +pub trait Display { + fn fmt(self: @T, ref f: Formatter) -> Result<(), Error>; +} + +impl DisplayByteArray of Display { + fn fmt(self: @ByteArray, ref f: Formatter) -> Result<(), Error> { + f.buffer.append(self); + Result::Ok(()) + } +} + +impl DisplayInteger< + T, +to_byte_array::AppendFormattedToByteArray, +Into, +TryInto> +> of Display { + fn fmt(self: @T, ref f: Formatter) -> Result<(), Error> { + // TODO(yuval): determine base according to Formatter parameters. + let base: T = 10_u8.into(); + self.append_formatted_to_byte_array(ref f.buffer, base.try_into().unwrap()); + Result::Ok(()) + } +} + +impl DisplayNonZero, +Copy, +Drop> of Display> { + fn fmt(self: @NonZero, ref f: Formatter) -> Result<(), Error> { + let value: T = (*self).into(); + write!(f, "{value}") + } +} + +impl DisplayBool of Display { + fn fmt(self: @bool, ref f: Formatter) -> Result<(), Error> { + if *self { + write!(f, "true") + } else { + write!(f, "false") + } + } +} + +/// A trait for debug formatting, using the empty format ("{:?}"). +pub trait Debug { + fn fmt(self: @T, ref f: Formatter) -> Result<(), Error>; +} + +impl DebugByteArray of Debug { + fn fmt(self: @ByteArray, ref f: Formatter) -> Result<(), Error> { + write!(f, "\"")?; + Display::fmt(self, ref f)?; + write!(f, "\"") + } +} + +impl DebugInteger< + T, +to_byte_array::AppendFormattedToByteArray, +Into, +TryInto> +> of Debug { + fn fmt(self: @T, ref f: Formatter) -> Result<(), Error> { + Display::fmt(self, ref f) + } +} + +impl DebugNonZero, +Copy, +Drop> of Debug> { + fn fmt(self: @NonZero, ref f: Formatter) -> Result<(), Error> { + let value: T = (*self).into(); + write!(f, "{value:?}") + } +} + +impl DebugBool of Debug { + fn fmt(self: @bool, ref f: Formatter) -> Result<(), Error> { + Display::fmt(self, ref f) + } +} + +impl DebugSnapshot> of Debug<@T> { + fn fmt(self: @@T, ref f: Formatter) -> Result<(), Error> { + write!(f, "@")?; + Debug::fmt(*self, ref f) + } +} + +impl DebugTuple0 of Debug<()> { + fn fmt(self: @(), ref f: Formatter) -> Result<(), Error> { + write!(f, "()") + } +} + +impl DebugTuple1> of Debug<(E0,)> { + fn fmt(self: @(E0,), ref f: Formatter) -> Result<(), Error> { + let (e0,) = self; + write!(f, "(")?; + E0Debug::fmt(e0, ref f)?; + write!(f, ",)") + } +} + +impl DebugTuple2, impl E1Debug: Debug> of Debug<(E0, E1)> { + fn fmt(self: @(E0, E1), ref f: Formatter) -> Result<(), Error> { + let (e0, e1) = self; + write!(f, "(")?; + E0Debug::fmt(e0, ref f)?; + write!(f, ", ")?; + E1Debug::fmt(e1, ref f)?; + write!(f, ")") + } +} + +impl DebugTuple3< + E0, E1, E2, impl E0Debug: Debug, impl E1Debug: Debug, impl E2Debug: Debug +> of Debug<(E0, E1, E2)> { + fn fmt(self: @(E0, E1, E2), ref f: Formatter) -> Result<(), Error> { + let (e0, e1, e2) = self; + write!(f, "(")?; + E0Debug::fmt(e0, ref f)?; + write!(f, ", ")?; + E1Debug::fmt(e1, ref f)?; + write!(f, ", ")?; + E2Debug::fmt(e2, ref f)?; + write!(f, ")") + } +} + +impl DebugTuple4< + E0, + E1, + E2, + E3, + impl E0Debug: Debug, + impl E1Debug: Debug, + impl E2Debug: Debug, + impl E3Debug: Debug +> of Debug<(E0, E1, E2, E3)> { + fn fmt(self: @(E0, E1, E2, E3), ref f: Formatter) -> Result<(), Error> { + let (e0, e1, e2, e3) = self; + write!(f, "(")?; + E0Debug::fmt(e0, ref f)?; + write!(f, ", ")?; + E1Debug::fmt(e1, ref f)?; + write!(f, ", ")?; + E2Debug::fmt(e2, ref f)?; + write!(f, ", ")?; + E3Debug::fmt(e3, ref f)?; + write!(f, ")") + } +} + +impl ArrayTDebug> of Debug> { + fn fmt(self: @Array, ref f: Formatter) -> Result<(), Error> { + Debug::fmt(@self.span(), ref f) + } +} + +impl SpanTDebug> of Debug> { + fn fmt(self: @Span, ref f: Formatter) -> Result<(), Error> { + let mut self = *self; + write!(f, "[")?; + loop { + match self.pop_front() { + Option::Some(value) => { + if Debug::fmt(value, ref f).is_err() { + break Result::Err(Error {}); + }; + if self.is_empty() { + break Result::Ok(()); + } + if write!(f, ", ").is_err() { + break Result::Err(Error {}); + }; + }, + Option::None => { break Result::Ok(()); } + }; + }?; + write!(f, "]") + } +} + +/// Impls for `Debug` for types that can be converted into `felt252` using the `Into` trait. +/// Usage example: +/// ```ignore +/// impl MyTypeDebug = core::fmt::into_felt252_based::DebugImpl;` +/// ``` +pub mod into_felt252_based { + pub impl DebugImpl, +Copy> of core::fmt::Debug { + fn fmt(self: @T, ref f: core::fmt::Formatter) -> Result<(), core::fmt::Error> { + core::fmt::DebugInteger::::fmt(@(*self).into(), ref f) + } + } +} diff --git a/corelib/src/gas.cairo b/corelib/src/gas.cairo index 229dce2..6ef2c70 100644 --- a/corelib/src/gas.cairo +++ b/corelib/src/gas.cairo @@ -1,9 +1,9 @@ #[derive(Copy, Drop)] -extern type BuiltinCosts; -extern type GasBuiltin; +pub extern type BuiltinCosts; +pub extern type GasBuiltin; -extern fn withdraw_gas() -> Option<()> implicits(RangeCheck, GasBuiltin) nopanic; -extern fn withdraw_gas_all( +pub extern fn withdraw_gas() -> Option<()> implicits(RangeCheck, GasBuiltin) nopanic; +pub extern fn withdraw_gas_all( costs: BuiltinCosts ) -> Option<()> implicits(RangeCheck, GasBuiltin) nopanic; -extern fn get_builtin_costs() -> BuiltinCosts nopanic; +pub extern fn get_builtin_costs() -> BuiltinCosts nopanic; diff --git a/corelib/src/hash.cairo b/corelib/src/hash.cairo index effea00..5556f02 100644 --- a/corelib/src/hash.cairo +++ b/corelib/src/hash.cairo @@ -1,128 +1,94 @@ -use traits::Into; -use starknet::ContractAddress; +use core::traits::Into; /// A trait for hash state accumulators. -trait HashStateTrait { +pub trait HashStateTrait { + #[must_use] fn update(self: S, value: felt252) -> S; + #[must_use] fn finalize(self: S) -> felt252; } /// A trait for values that can be hashed. -trait Hash> { +pub trait Hash> { /// Updates the hash state with the given value. + #[must_use] fn update_state(state: S, value: T) -> S; } /// Trait for hashing values. /// Used for backwards compatibility. /// NOTE: Implement `Hash` instead of this trait if possible. -trait LegacyHash { +pub trait LegacyHash { + #[must_use] fn hash(state: felt252, value: T) -> felt252; } /// Implementation of `LegacyHash` for types that have `Hash` for backwards compatibility. -impl LegacyHashForHash< - T, impl THash: Hash -> of LegacyHash { +impl LegacyHashForHash> of LegacyHash { #[inline(always)] fn hash(state: felt252, value: T) -> felt252 { - THash::update_state(pedersen::HashState { state }, value).state + core::pedersen::HashState { state }.update_with(value).state } } /// Extension trait for hash state accumulators. -trait HashStateExTrait { +pub trait HashStateExTrait { /// Updates the hash state with the given value. + #[must_use] fn update_with(self: S, value: T) -> S; } -impl HashStateEx< - S, impl SHashState: HashStateTrait, T, impl THash: Hash -> of HashStateExTrait { +impl HashStateEx, T, +Hash> of HashStateExTrait { #[inline(always)] fn update_with(self: S, value: T) -> S { - THash::update_state(self, value) + Hash::update_state(self, value) } } -impl HashFelt252> of Hash { +impl HashFelt252> of Hash { #[inline(always)] fn update_state(state: S, value: felt252) -> S { state.update(value) } } -impl HashBool< - S, impl SHashState: HashStateTrait, impl SDrop: Drop -> of Hash { - #[inline(always)] - fn update_state(state: S, value: bool) -> S { - state.update(value.into()) - } -} - -impl HashU8, impl SDrop: Drop> of Hash { - #[inline(always)] - fn update_state(state: S, value: u8) -> S { - state.update(value.into()) - } -} - -impl HashU16< - S, impl SHashState: HashStateTrait, impl SDrop: Drop -> of Hash { - #[inline(always)] - fn update_state(state: S, value: u16) -> S { - state.update(value.into()) +/// Impl for `Hash` for types that can be converted into `felt252` using the `Into` trait. +/// Usage example: +/// ```ignore +/// impl MyTypeHash, +Drop> = +/// core::hash::into_felt252_based::HashImpl;` +/// ``` +pub mod into_felt252_based { + pub impl HashImpl< + T, S, +Into, +super::HashStateTrait, +Drop + > of super::Hash { + #[inline(always)] + fn update_state(state: S, value: T) -> S { + state.update(value.into()) + } } } -impl HashU32< - S, impl SHashState: HashStateTrait, impl SDrop: Drop -> of Hash { - #[inline(always)] - fn update_state(state: S, value: u32) -> S { - state.update(value.into()) - } -} +impl HashBool, +Drop> = into_felt252_based::HashImpl; +impl HashU8, +Drop> = into_felt252_based::HashImpl; +impl HashU16, +Drop> = into_felt252_based::HashImpl; +impl HashU32, +Drop> = into_felt252_based::HashImpl; +impl HashU64, +Drop> = into_felt252_based::HashImpl; +impl HashU128, +Drop> = into_felt252_based::HashImpl; +impl HashI8, +Drop> = into_felt252_based::HashImpl; +impl HashI16, +Drop> = into_felt252_based::HashImpl; +impl HashI32, +Drop> = into_felt252_based::HashImpl; +impl HashI64, +Drop> = into_felt252_based::HashImpl; +impl HashI128, +Drop> = into_felt252_based::HashImpl; -impl HashU64< - S, impl SHashState: HashStateTrait, impl SDrop: Drop -> of Hash { - #[inline(always)] - fn update_state(state: S, value: u64) -> S { - state.update(value.into()) - } -} - -impl HashU128< - S, impl SHashState: HashStateTrait, impl SDrop: Drop -> of Hash { - #[inline(always)] - fn update_state(state: S, value: u128) -> S { - state.update(value.into()) - } -} - -impl HashContractAddress< - S, impl SHashState: HashStateTrait, impl SDrop: Drop -> of Hash { - #[inline(always)] - fn update_state(state: S, value: ContractAddress) -> S { - state.update(value.into()) - } -} - -impl TupleSize0Hash> of Hash<(), S, SHashState> { +impl TupleSize0Hash> of Hash<(), S> { #[inline(always)] fn update_state(state: S, value: ()) -> S { state } } -impl TupleSize1Hash< - E0, S, impl E0Hash: Hash, impl SHashState: HashStateTrait -> of Hash<(E0,), S, SHashState> { +impl TupleSize1Hash, +HashStateTrait> of Hash<(E0,), S> { #[inline(always)] fn update_state(state: S, value: (E0,)) -> S { let (e0,) = value; @@ -131,15 +97,8 @@ impl TupleSize1Hash< } impl TupleSize2Hash< - E0, - E1, - S, - impl SHashState: HashStateTrait, - impl E0Hash: Hash, - impl E1Hash: Hash, - impl E0Drop: Drop, - impl E1Drop: Drop, -> of Hash<(E0, E1), S, SHashState> { + E0, E1, S, +HashStateTrait, +Hash, +Hash, +Drop, +Drop, +> of Hash<(E0, E1), S> { #[inline(always)] fn update_state(state: S, value: (E0, E1,)) -> S { let (e0, e1) = value; @@ -152,14 +111,14 @@ impl TupleSize3Hash< E1, E2, S, - impl SHashState: HashStateTrait, - impl E0Hash: Hash, - impl E1Hash: Hash, - impl E2Hash: Hash, - impl E0Drop: Drop, - impl E1Drop: Drop, - impl E2Drop: Drop, -> of Hash<(E0, E1, E2), S, SHashState> { + +HashStateTrait, + +Hash, + +Hash, + +Hash, + +Drop, + +Drop, + +Drop, +> of Hash<(E0, E1, E2), S> { #[inline(always)] fn update_state(state: S, value: (E0, E1, E2)) -> S { let (e0, e1, e2) = value; @@ -173,16 +132,16 @@ impl TupleSize4Hash< E2, E3, S, - impl SHashState: HashStateTrait, - impl E0Hash: Hash, - impl E1Hash: Hash, - impl E2Hash: Hash, - impl E3Hash: Hash, - impl E0Drop: Drop, - impl E1Drop: Drop, - impl E2Drop: Drop, - impl E3Drop: Drop, -> of Hash<(E0, E1, E2, E3), S, SHashState> { + +HashStateTrait, + +Hash, + +Hash, + +Hash, + +Hash, + +Drop, + +Drop, + +Drop, + +Drop, +> of Hash<(E0, E1, E2, E3), S> { #[inline(always)] fn update_state(state: S, value: (E0, E1, E2, E3)) -> S { let (e0, e1, e2, e3) = value; diff --git a/corelib/src/integer.cairo b/corelib/src/integer.cairo index 27681b4..d813425 100644 --- a/corelib/src/integer.cairo +++ b/corelib/src/integer.cairo @@ -1,28 +1,19 @@ -use option::OptionTrait; -use result::ResultTrait; -use traits::{Into, TryInto, Default, Felt252DictValue}; -use zeroable::{IsZeroResult, NonZeroIntoImpl, Zeroable}; -use serde::Serde; -use array::ArrayTrait; -use array::SpanTrait; +use core::option::OptionTrait; +use core::result::ResultTrait; +use core::traits::{Into, TryInto, Default, Felt252DictValue}; +use core::zeroable::{IsZeroResult, NonZeroIntoImpl, Zeroable}; +use core::array::ArrayTrait; +use core::array::SpanTrait; // TODO(spapini): Add method for const creation from Integer. -trait NumericLiteral; +pub trait NumericLiteral; impl NumericLiteralfelt252 of NumericLiteral; #[derive(Copy, Drop)] -extern type u128; +pub extern type u128; impl NumericLiteralu128 of NumericLiteral; -extern fn u128_const() -> u128 nopanic; -impl U128Serde of Serde { - fn serialize(self: @u128, ref output: Array) { - Into::::into(*self).serialize(ref output); - } - fn deserialize(ref serialized: Span) -> Option { - Option::Some(((*serialized.pop_front()?).try_into())?) - } -} +impl U128Serde = core::serde::into_felt252_based::SerdeImpl; enum U128sFromFelt252Result { Narrow: u128, @@ -34,11 +25,11 @@ extern fn u128s_from_felt252(a: felt252) -> U128sFromFelt252Result implicits(Ran fn u128_try_from_felt252(a: felt252) -> Option implicits(RangeCheck) nopanic { match u128s_from_felt252(a) { U128sFromFelt252Result::Narrow(x) => Option::Some(x), - U128sFromFelt252Result::Wide(x) => Option::None, + U128sFromFelt252Result::Wide(_x) => Option::None, } } -extern fn u128_to_felt252(a: u128) -> felt252 nopanic; +pub(crate) extern fn u128_to_felt252(a: u128) -> felt252 nopanic; extern fn u128_overflowing_add( lhs: u128, rhs: u128 @@ -54,7 +45,7 @@ fn u128_wrapping_add(lhs: u128, rhs: u128) -> u128 implicits(RangeCheck) nopanic } } -fn u128_wrapping_sub(a: u128, b: u128) -> u128 implicits(RangeCheck) nopanic { +pub fn u128_wrapping_sub(a: u128, b: u128) -> u128 implicits(RangeCheck) nopanic { match u128_overflowing_sub(a, b) { Result::Ok(x) => x, Result::Err(x) => x, @@ -65,7 +56,7 @@ fn u128_wrapping_sub(a: u128, b: u128) -> u128 implicits(RangeCheck) nopanic { /// /// The guarantee is verified by `u128_mul_guarantee_verify`, which is the only way to destruct this /// type. This way, one can trust that the guarantee holds although it has not yet been verified. -extern type U128MulGuarantee; +pub extern type U128MulGuarantee; /// Multiplies two u128s and returns a `U128MulGuarantee` for the result of `a * b`. extern fn u128_guarantee_mul(a: u128, b: u128) -> (u128, u128, U128MulGuarantee) nopanic; @@ -75,7 +66,7 @@ extern fn u128_mul_guarantee_verify(guarantee: U128MulGuarantee) implicits(Range /// Multiplies two u128s and returns `(high, low)` - the 128-bit parts of the result. #[inline(always)] -fn u128_wide_mul(a: u128, b: u128) -> (u128, u128) nopanic { +pub fn u128_wide_mul(a: u128, b: u128) -> (u128, u128) nopanic { let (high, low, _) = u128_guarantee_mul(a, b); (high, low) } @@ -86,7 +77,7 @@ impl U128MulGuaranteeDestruct of Destruct { } } -extern fn u128_sqrt(value: u128) -> u64 implicits(RangeCheck) nopanic; +pub extern fn u128_sqrt(value: u128) -> u64 implicits(RangeCheck) nopanic; fn u128_overflowing_mul(lhs: u128, rhs: u128) -> (u128, bool) implicits(RangeCheck) nopanic { let (top_word, bottom_word) = u128_wide_mul(lhs, rhs); @@ -100,7 +91,7 @@ fn u128_overflowing_mul(lhs: u128, rhs: u128) -> (u128, bool) implicits(RangeChe fn u128_checked_add(lhs: u128, rhs: u128) -> Option implicits(RangeCheck) nopanic { match u128_overflowing_add(lhs, rhs) { Result::Ok(r) => Option::Some(r), - Result::Err(r) => Option::None, + Result::Err(_r) => Option::None, } } @@ -120,7 +111,7 @@ impl U128AddEq of AddEq { fn u128_checked_sub(lhs: u128, rhs: u128) -> Option implicits(RangeCheck) nopanic { match u128_overflowing_sub(lhs, rhs) { Result::Ok(r) => Option::Some(r), - Result::Err(r) => Option::None, + Result::Err(_r) => Option::None, } } @@ -164,7 +155,7 @@ fn u128_try_as_non_zero(a: u128) -> Option> nopanic { } } -impl U128TryIntoNonZero of TryInto> { +pub(crate) impl U128TryIntoNonZero of TryInto> { fn try_into(self: u128) -> Option> { Option::Some(u128_as_non_zero(self)) } @@ -172,7 +163,7 @@ impl U128TryIntoNonZero of TryInto> { impl U128Div of Div { fn div(lhs: u128, rhs: u128) -> u128 { - let (q, r) = u128_safe_divmod(lhs, rhs.try_into().expect('Division by 0')); + let (q, _r) = u128_safe_divmod(lhs, rhs.try_into().expect('Division by 0')); q } } @@ -185,7 +176,7 @@ impl U128DivEq of DivEq { impl U128Rem of Rem { fn rem(lhs: u128, rhs: u128) -> u128 { - let (q, r) = u128_safe_divmod(lhs, rhs.try_into().expect('Division by 0')); + let (_q, r) = u128_safe_divmod(lhs, rhs.try_into().expect('Division by 0')); r } } @@ -202,7 +193,7 @@ impl U128DivRem of DivRem { } } -extern fn u128_safe_divmod( +pub extern fn u128_safe_divmod( lhs: u128, rhs: NonZero ) -> (u128, u128) implicits(RangeCheck) nopanic; @@ -238,7 +229,7 @@ impl U128PartialOrd of PartialOrd { } } -extern type Bitwise; +pub extern type Bitwise; extern fn bitwise(lhs: u128, rhs: u128) -> (u128, u128, u128) implicits(Bitwise) nopanic; impl U128BitAnd of BitAnd { #[inline(always)] @@ -267,14 +258,19 @@ impl U128BitNot of BitNot { } } -extern fn u128_is_zero(a: u128) -> IsZeroResult implicits() nopanic; +impl U128BitSize of core::num::traits::BitSize { + fn bits() -> usize { + 128 + } +} + +pub(crate) extern fn u128_is_zero(a: u128) -> IsZeroResult implicits() nopanic; -extern fn u128_byte_reverse(input: u128) -> u128 implicits(Bitwise) nopanic; +pub extern fn u128_byte_reverse(input: u128) -> u128 implicits(Bitwise) nopanic; #[derive(Copy, Drop)] -extern type u8; +pub extern type u8; impl NumericLiteralu8 of NumericLiteral; -extern fn u8_const() -> u8 nopanic; extern fn u8_to_felt252(a: u8) -> felt252 nopanic; #[panic_with('u8_from Overflow', u8_from_felt252)] @@ -282,14 +278,7 @@ extern fn u8_try_from_felt252(a: felt252) -> Option implicits(RangeCheck) no extern fn u8_eq(lhs: u8, rhs: u8) -> bool implicits() nopanic; -impl U8Serde of Serde { - fn serialize(self: @u8, ref output: Array) { - Into::::into(*self).serialize(ref output); - } - fn deserialize(ref serialized: Span) -> Option { - Option::Some(((*serialized.pop_front()?).try_into())?) - } -} +impl U8Serde = core::serde::into_felt252_based::SerdeImpl; impl U8PartialEq of PartialEq { #[inline(always)] @@ -321,17 +310,19 @@ impl U8PartialOrd of PartialOrd { } } -extern fn u8_overflowing_add(lhs: u8, rhs: u8) -> Result implicits(RangeCheck) nopanic; +pub(crate) extern fn u8_overflowing_add( + lhs: u8, rhs: u8 +) -> Result implicits(RangeCheck) nopanic; extern fn u8_overflowing_sub(lhs: u8, rhs: u8) -> Result implicits(RangeCheck) nopanic; -fn u8_wrapping_add(lhs: u8, rhs: u8) -> u8 implicits(RangeCheck) nopanic { +pub fn u8_wrapping_add(lhs: u8, rhs: u8) -> u8 implicits(RangeCheck) nopanic { match u8_overflowing_add(lhs, rhs) { Result::Ok(x) => x, Result::Err(x) => x, } } -fn u8_wrapping_sub(lhs: u8, rhs: u8) -> u8 implicits(RangeCheck) nopanic { +pub fn u8_wrapping_sub(lhs: u8, rhs: u8) -> u8 implicits(RangeCheck) nopanic { match u8_overflowing_sub(lhs, rhs) { Result::Ok(x) => x, Result::Err(x) => x, @@ -341,7 +332,7 @@ fn u8_wrapping_sub(lhs: u8, rhs: u8) -> u8 implicits(RangeCheck) nopanic { fn u8_checked_add(lhs: u8, rhs: u8) -> Option implicits(RangeCheck) nopanic { match u8_overflowing_add(lhs, rhs) { Result::Ok(r) => Option::Some(r), - Result::Err(r) => Option::None, + Result::Err(_r) => Option::None, } } @@ -360,7 +351,7 @@ impl U8AddEq of AddEq { fn u8_checked_sub(lhs: u8, rhs: u8) -> Option implicits(RangeCheck) nopanic { match u8_overflowing_sub(lhs, rhs) { Result::Ok(r) => Option::Some(r), - Result::Err(r) => Option::None, + Result::Err(_r) => Option::None, } } @@ -376,8 +367,8 @@ impl U8SubEq of SubEq { } } -extern fn u8_wide_mul(lhs: u8, rhs: u8) -> u16 implicits() nopanic; -extern fn u8_sqrt(value: u8) -> u8 implicits(RangeCheck) nopanic; +pub extern fn u8_wide_mul(lhs: u8, rhs: u8) -> u16 implicits() nopanic; +pub extern fn u8_sqrt(value: u8) -> u8 implicits(RangeCheck) nopanic; impl U8Mul of Mul { fn mul(lhs: u8, rhs: u8) -> u8 { @@ -392,7 +383,7 @@ impl U8MulEq of MulEq { } extern fn u8_is_zero(a: u8) -> IsZeroResult implicits() nopanic; -extern fn u8_safe_divmod(lhs: u8, rhs: NonZero) -> (u8, u8) implicits(RangeCheck) nopanic; +pub extern fn u8_safe_divmod(lhs: u8, rhs: NonZero) -> (u8, u8) implicits(RangeCheck) nopanic; #[panic_with('u8 is 0', u8_as_non_zero)] fn u8_try_as_non_zero(a: u8) -> Option> nopanic { @@ -410,7 +401,7 @@ impl U8TryIntoNonZero of TryInto> { impl U8Div of Div { fn div(lhs: u8, rhs: u8) -> u8 { - let (q, r) = u8_safe_divmod(lhs, rhs.try_into().expect('Division by 0')); + let (q, _r) = u8_safe_divmod(lhs, rhs.try_into().expect('Division by 0')); q } } @@ -423,7 +414,7 @@ impl U8DivEq of DivEq { impl U8Rem of Rem { fn rem(lhs: u8, rhs: u8) -> u8 { - let (q, r) = u8_safe_divmod(lhs, rhs.try_into().expect('Division by 0')); + let (_q, r) = u8_safe_divmod(lhs, rhs.try_into().expect('Division by 0')); r } } @@ -468,10 +459,15 @@ impl U8BitOr of BitOr { } } +impl U8BitSize of core::num::traits::BitSize { + fn bits() -> usize { + 8 + } +} + #[derive(Copy, Drop)] -extern type u16; +pub extern type u16; impl NumericLiteralu16 of NumericLiteral; -extern fn u16_const() -> u16 nopanic; extern fn u16_to_felt252(a: u16) -> felt252 nopanic; #[panic_with('u16_from Overflow', u16_from_felt252)] @@ -479,14 +475,7 @@ extern fn u16_try_from_felt252(a: felt252) -> Option implicits(RangeCheck) extern fn u16_eq(lhs: u16, rhs: u16) -> bool implicits() nopanic; -impl U16Serde of Serde { - fn serialize(self: @u16, ref output: Array) { - Into::::into(*self).serialize(ref output); - } - fn deserialize(ref serialized: Span) -> Option { - Option::Some(((*serialized.pop_front()?).try_into())?) - } -} +impl U16Serde = core::serde::into_felt252_based::SerdeImpl; impl U16PartialEq of PartialEq { #[inline(always)] @@ -528,7 +517,7 @@ fn u16_wrapping_add(lhs: u16, rhs: u16) -> u16 implicits(RangeCheck) nopanic { } } -fn u16_wrapping_sub(lhs: u16, rhs: u16) -> u16 implicits(RangeCheck) nopanic { +pub fn u16_wrapping_sub(lhs: u16, rhs: u16) -> u16 implicits(RangeCheck) nopanic { match u16_overflowing_sub(lhs, rhs) { Result::Ok(x) => x, Result::Err(x) => x, @@ -538,7 +527,7 @@ fn u16_wrapping_sub(lhs: u16, rhs: u16) -> u16 implicits(RangeCheck) nopanic { fn u16_checked_add(lhs: u16, rhs: u16) -> Option implicits(RangeCheck) nopanic { match u16_overflowing_add(lhs, rhs) { Result::Ok(r) => Option::Some(r), - Result::Err(r) => Option::None, + Result::Err(_r) => Option::None, } } @@ -557,7 +546,7 @@ impl U16AddEq of AddEq { fn u16_checked_sub(lhs: u16, rhs: u16) -> Option implicits(RangeCheck) nopanic { match u16_overflowing_sub(lhs, rhs) { Result::Ok(r) => Option::Some(r), - Result::Err(r) => Option::None, + Result::Err(_r) => Option::None, } } @@ -573,8 +562,8 @@ impl U16SubEq of SubEq { } } -extern fn u16_wide_mul(lhs: u16, rhs: u16) -> u32 implicits() nopanic; -extern fn u16_sqrt(value: u16) -> u8 implicits(RangeCheck) nopanic; +pub extern fn u16_wide_mul(lhs: u16, rhs: u16) -> u32 implicits() nopanic; +pub extern fn u16_sqrt(value: u16) -> u8 implicits(RangeCheck) nopanic; impl U16Mul of Mul { fn mul(lhs: u16, rhs: u16) -> u16 { @@ -589,7 +578,9 @@ impl U16MulEq of MulEq { } extern fn u16_is_zero(a: u16) -> IsZeroResult implicits() nopanic; -extern fn u16_safe_divmod(lhs: u16, rhs: NonZero) -> (u16, u16) implicits(RangeCheck) nopanic; +pub extern fn u16_safe_divmod( + lhs: u16, rhs: NonZero +) -> (u16, u16) implicits(RangeCheck) nopanic; #[panic_with('u16 is 0', u16_as_non_zero)] fn u16_try_as_non_zero(a: u16) -> Option> nopanic { @@ -607,7 +598,7 @@ impl U16TryIntoNonZero of TryInto> { impl U16Div of Div { fn div(lhs: u16, rhs: u16) -> u16 { - let (q, r) = u16_safe_divmod(lhs, rhs.try_into().expect('Division by 0')); + let (q, _r) = u16_safe_divmod(lhs, rhs.try_into().expect('Division by 0')); q } } @@ -620,7 +611,7 @@ impl U16DivEq of DivEq { impl U16Rem of Rem { fn rem(lhs: u16, rhs: u16) -> u16 { - let (q, r) = u16_safe_divmod(lhs, rhs.try_into().expect('Division by 0')); + let (_q, r) = u16_safe_divmod(lhs, rhs.try_into().expect('Division by 0')); r } } @@ -665,10 +656,15 @@ impl U16BitOr of BitOr { } } +impl U16BitSize of core::num::traits::BitSize { + fn bits() -> usize { + 16 + } +} + #[derive(Copy, Drop)] -extern type u32; +pub extern type u32; impl NumericLiteralu32 of NumericLiteral; -extern fn u32_const() -> u32 nopanic; extern fn u32_to_felt252(a: u32) -> felt252 nopanic; #[panic_with('u32_from Overflow', u32_from_felt252)] @@ -676,14 +672,7 @@ extern fn u32_try_from_felt252(a: felt252) -> Option implicits(RangeCheck) extern fn u32_eq(lhs: u32, rhs: u32) -> bool implicits() nopanic; -impl U32Serde of Serde { - fn serialize(self: @u32, ref output: Array) { - Into::::into(*self).serialize(ref output); - } - fn deserialize(ref serialized: Span) -> Option { - Option::Some(((*serialized.pop_front()?).try_into())?) - } -} +impl U32Serde = core::serde::into_felt252_based::SerdeImpl; impl U32PartialEq of PartialEq { #[inline(always)] @@ -725,7 +714,7 @@ fn u32_wrapping_add(lhs: u32, rhs: u32) -> u32 implicits(RangeCheck) nopanic { } } -fn u32_wrapping_sub(lhs: u32, rhs: u32) -> u32 implicits(RangeCheck) nopanic { +pub fn u32_wrapping_sub(lhs: u32, rhs: u32) -> u32 implicits(RangeCheck) nopanic { match u32_overflowing_sub(lhs, rhs) { Result::Ok(x) => x, Result::Err(x) => x, @@ -735,7 +724,7 @@ fn u32_wrapping_sub(lhs: u32, rhs: u32) -> u32 implicits(RangeCheck) nopanic { fn u32_checked_add(lhs: u32, rhs: u32) -> Option implicits(RangeCheck) nopanic { match u32_overflowing_add(lhs, rhs) { Result::Ok(r) => Option::Some(r), - Result::Err(r) => Option::None, + Result::Err(_r) => Option::None, } } @@ -754,7 +743,7 @@ impl U32AddEq of AddEq { fn u32_checked_sub(lhs: u32, rhs: u32) -> Option implicits(RangeCheck) nopanic { match u32_overflowing_sub(lhs, rhs) { Result::Ok(r) => Option::Some(r), - Result::Err(r) => Option::None, + Result::Err(_r) => Option::None, } } @@ -770,8 +759,8 @@ impl U32SubEq of SubEq { } } -extern fn u32_wide_mul(lhs: u32, rhs: u32) -> u64 implicits() nopanic; -extern fn u32_sqrt(value: u32) -> u16 implicits(RangeCheck) nopanic; +pub extern fn u32_wide_mul(lhs: u32, rhs: u32) -> u64 implicits() nopanic; +pub extern fn u32_sqrt(value: u32) -> u16 implicits(RangeCheck) nopanic; impl U32Mul of Mul { fn mul(lhs: u32, rhs: u32) -> u32 { @@ -786,7 +775,9 @@ impl U32MulEq of MulEq { } extern fn u32_is_zero(a: u32) -> IsZeroResult implicits() nopanic; -extern fn u32_safe_divmod(lhs: u32, rhs: NonZero) -> (u32, u32) implicits(RangeCheck) nopanic; +pub extern fn u32_safe_divmod( + lhs: u32, rhs: NonZero +) -> (u32, u32) implicits(RangeCheck) nopanic; #[panic_with('u32 is 0', u32_as_non_zero)] fn u32_try_as_non_zero(a: u32) -> Option> nopanic { @@ -796,7 +787,7 @@ fn u32_try_as_non_zero(a: u32) -> Option> nopanic { } } -impl U32TryIntoNonZero of TryInto> { +pub(crate) impl U32TryIntoNonZero of TryInto> { fn try_into(self: u32) -> Option> { Option::Some(u32_as_non_zero(self)) } @@ -804,7 +795,7 @@ impl U32TryIntoNonZero of TryInto> { impl U32Div of Div { fn div(lhs: u32, rhs: u32) -> u32 { - let (q, r) = u32_safe_divmod(lhs, rhs.try_into().expect('Division by 0')); + let (q, _r) = u32_safe_divmod(lhs, rhs.try_into().expect('Division by 0')); q } } @@ -817,7 +808,7 @@ impl U32DivEq of DivEq { impl U32Rem of Rem { fn rem(lhs: u32, rhs: u32) -> u32 { - let (q, r) = u32_safe_divmod(lhs, rhs.try_into().expect('Division by 0')); + let (_q, r) = u32_safe_divmod(lhs, rhs.try_into().expect('Division by 0')); r } } @@ -862,10 +853,15 @@ impl U32BitOr of BitOr { } } +impl U32BitSize of core::num::traits::BitSize { + fn bits() -> usize { + 32 + } +} + #[derive(Copy, Drop)] -extern type u64; +pub extern type u64; impl NumericLiteralu64 of NumericLiteral; -extern fn u64_const() -> u64 nopanic; extern fn u64_to_felt252(a: u64) -> felt252 nopanic; #[panic_with('u64_from Overflow', u64_from_felt252)] @@ -873,14 +869,7 @@ extern fn u64_try_from_felt252(a: felt252) -> Option implicits(RangeCheck) extern fn u64_eq(lhs: u64, rhs: u64) -> bool implicits() nopanic; -impl U64Serde of Serde { - fn serialize(self: @u64, ref output: Array) { - Into::::into(*self).serialize(ref output); - } - fn deserialize(ref serialized: Span) -> Option { - Option::Some(((*serialized.pop_front()?).try_into())?) - } -} +impl U64Serde = core::serde::into_felt252_based::SerdeImpl; impl U64PartialEq of PartialEq { #[inline(always)] @@ -922,7 +911,7 @@ fn u64_wrapping_add(lhs: u64, rhs: u64) -> u64 implicits(RangeCheck) nopanic { } } -fn u64_wrapping_sub(lhs: u64, rhs: u64) -> u64 implicits(RangeCheck) nopanic { +pub fn u64_wrapping_sub(lhs: u64, rhs: u64) -> u64 implicits(RangeCheck) nopanic { match u64_overflowing_sub(lhs, rhs) { Result::Ok(x) => x, Result::Err(x) => x, @@ -932,7 +921,7 @@ fn u64_wrapping_sub(lhs: u64, rhs: u64) -> u64 implicits(RangeCheck) nopanic { fn u64_checked_add(lhs: u64, rhs: u64) -> Option implicits(RangeCheck) nopanic { match u64_overflowing_add(lhs, rhs) { Result::Ok(r) => Option::Some(r), - Result::Err(r) => Option::None, + Result::Err(_r) => Option::None, } } @@ -951,7 +940,7 @@ impl U64AddEq of AddEq { fn u64_checked_sub(lhs: u64, rhs: u64) -> Option implicits(RangeCheck) nopanic { match u64_overflowing_sub(lhs, rhs) { Result::Ok(r) => Option::Some(r), - Result::Err(r) => Option::None, + Result::Err(_r) => Option::None, } } @@ -967,8 +956,8 @@ impl U64SubEq of SubEq { } } -extern fn u64_wide_mul(lhs: u64, rhs: u64) -> u128 implicits() nopanic; -extern fn u64_sqrt(value: u64) -> u32 implicits(RangeCheck) nopanic; +pub extern fn u64_wide_mul(lhs: u64, rhs: u64) -> u128 implicits() nopanic; +pub extern fn u64_sqrt(value: u64) -> u32 implicits(RangeCheck) nopanic; impl U64Mul of Mul { fn mul(lhs: u64, rhs: u64) -> u64 { @@ -983,7 +972,9 @@ impl U64MulEq of MulEq { } extern fn u64_is_zero(a: u64) -> IsZeroResult implicits() nopanic; -extern fn u64_safe_divmod(lhs: u64, rhs: NonZero) -> (u64, u64) implicits(RangeCheck) nopanic; +pub extern fn u64_safe_divmod( + lhs: u64, rhs: NonZero +) -> (u64, u64) implicits(RangeCheck) nopanic; #[panic_with('u64 is 0', u64_as_non_zero)] fn u64_try_as_non_zero(a: u64) -> Option> nopanic { @@ -1001,7 +992,7 @@ impl U64TryIntoNonZero of TryInto> { impl U64Div of Div { fn div(lhs: u64, rhs: u64) -> u64 { - let (q, r) = u64_safe_divmod(lhs, rhs.try_into().expect('Division by 0')); + let (q, _r) = u64_safe_divmod(lhs, rhs.try_into().expect('Division by 0')); q } } @@ -1014,7 +1005,7 @@ impl U64DivEq of DivEq { impl U64Rem of Rem { fn rem(lhs: u64, rhs: u64) -> u64 { - let (q, r) = u64_safe_divmod(lhs, rhs.try_into().expect('Division by 0')); + let (_q, r) = u64_safe_divmod(lhs, rhs.try_into().expect('Division by 0')); r } } @@ -1059,10 +1050,16 @@ impl U64BitOr of BitOr { } } +impl U64BitSize of core::num::traits::BitSize { + fn bits() -> usize { + 64 + } +} + #[derive(Copy, Drop, Hash, PartialEq, Serde, starknet::Store)] -struct u256 { - low: u128, - high: u128, +pub struct u256 { + pub low: u128, + pub high: u128, } impl NumericLiteralU256 of NumericLiteral; @@ -1246,7 +1243,7 @@ fn u256_safe_div_rem(lhs: u256, rhs: NonZero) -> (u256, u256) implicits(Ra let (q, r, _) = u256_safe_divmod(lhs, rhs); (q, r) } -extern fn u256_sqrt(a: u256) -> u128 implicits(RangeCheck) nopanic; +pub extern fn u256_sqrt(a: u256) -> u128 implicits(RangeCheck) nopanic; #[panic_with('u256 is 0', u256_as_non_zero)] fn u256_try_as_non_zero(a: u256) -> Option> nopanic { @@ -1256,7 +1253,7 @@ fn u256_try_as_non_zero(a: u256) -> Option> nopanic { } } -impl U256TryIntoNonZero of TryInto> { +pub(crate) impl U256TryIntoNonZero of TryInto> { fn try_into(self: u256) -> Option> { Option::Some(u256_as_non_zero(self)) } @@ -1264,7 +1261,7 @@ impl U256TryIntoNonZero of TryInto> { impl U256Div of Div { fn div(lhs: u256, rhs: u256) -> u256 { - let (q, r) = u256_safe_div_rem(lhs, rhs.try_into().expect('Division by 0')); + let (q, _r) = u256_safe_div_rem(lhs, rhs.try_into().expect('Division by 0')); q } } @@ -1277,7 +1274,7 @@ impl U256DivEq of DivEq { impl U256Rem of Rem { fn rem(lhs: u256, rhs: u256) -> u256 { - let (q, r) = u256_safe_div_rem(lhs, rhs.try_into().expect('Division by 0')); + let (_q, r) = u256_safe_div_rem(lhs, rhs.try_into().expect('Division by 0')); r } } @@ -1300,12 +1297,18 @@ impl U256BitNot of BitNot { } } -#[derive(Copy, Drop, PartialEq, Serde)] -struct u512 { - limb0: u128, - limb1: u128, - limb2: u128, - limb3: u128, +impl U256BitSize of core::num::traits::BitSize { + fn bits() -> usize { + 256 + } +} + +#[derive(Copy, Drop, Hash, PartialEq, Serde)] +pub struct u512 { + pub limb0: u128, + pub limb1: u128, + pub limb2: u128, + pub limb3: u128, } // Returns the result of u128 addition, including an overflow word. @@ -1316,7 +1319,7 @@ fn u128_add_with_carry(a: u128, b: u128) -> (u128, u128) nopanic { } } -fn u256_wide_mul(a: u256, b: u256) -> u512 nopanic { +pub fn u256_wide_mul(a: u256, b: u256) -> u512 nopanic { let (limb1, limb0) = u128_wide_mul(a.low, b.low); let (limb2, limb1_part) = u128_wide_mul(a.low, b.high); let (limb1, limb1_overflow0) = u128_add_with_carry(limb1, limb1_part); @@ -1339,7 +1342,7 @@ fn u256_wide_mul(a: u256, b: u256) -> u512 nopanic { /// Calculates division with remainder of a u512 by a non-zero u256. #[inline(always)] -fn u512_safe_div_rem_by_u256( +pub fn u512_safe_div_rem_by_u256( lhs: u512, rhs: NonZero ) -> (u512, u256) implicits(RangeCheck) nopanic { let (q, r, _, _, _, _, _) = u512_safe_divmod_by_u256(lhs, rhs); @@ -1361,8 +1364,10 @@ extern fn u512_safe_divmod_by_u256( ) implicits(RangeCheck) nopanic; /// Bounded -trait BoundedInt { +pub trait BoundedInt { + #[must_use] fn min() -> T nopanic; + #[must_use] fn max() -> T nopanic; } @@ -1432,63 +1437,118 @@ impl BoundedU256 of BoundedInt { } } +impl BoundedI8 of BoundedInt { + #[inline(always)] + fn min() -> i8 nopanic { + -0x80 + } + #[inline(always)] + fn max() -> i8 nopanic { + 0x7f + } +} + +impl BoundedI16 of BoundedInt { + #[inline(always)] + fn min() -> i16 nopanic { + -0x8000 + } + #[inline(always)] + fn max() -> i16 nopanic { + 0x7fff + } +} + +impl BoundedI32 of BoundedInt { + #[inline(always)] + fn min() -> i32 nopanic { + -0x80000000 + } + #[inline(always)] + fn max() -> i32 nopanic { + 0x7fffffff + } +} + +impl BoundedI64 of BoundedInt { + #[inline(always)] + fn min() -> i64 nopanic { + -0x8000000000000000 + } + #[inline(always)] + fn max() -> i64 nopanic { + 0x7fffffffffffffff + } +} + +impl BoundedI128 of BoundedInt { + #[inline(always)] + fn min() -> i128 nopanic { + -0x80000000000000000000000000000000 + } + #[inline(always)] + fn max() -> i128 nopanic { + 0x7fffffffffffffffffffffffffffffff + } +} + /// Conversions. -impl Felt252TryIntoU8 of TryInto { +pub(crate) impl Felt252TryIntoU8 of TryInto { fn try_into(self: felt252) -> Option { u8_try_from_felt252(self) } } -impl U8IntoFelt252 of Into { +pub(crate) impl U8IntoFelt252 of Into { fn into(self: u8) -> felt252 { u8_to_felt252(self) } } -impl Felt252TryIntoU16 of TryInto { +pub(crate) impl Felt252TryIntoU16 of TryInto { fn try_into(self: felt252) -> Option { u16_try_from_felt252(self) } } -impl U16IntoFelt252 of Into { +pub(crate) impl U16IntoFelt252 of Into { fn into(self: u16) -> felt252 { u16_to_felt252(self) } } -impl Felt252TryIntoU32 of TryInto { +pub(crate) impl Felt252TryIntoU32 of TryInto { fn try_into(self: felt252) -> Option { u32_try_from_felt252(self) } } -impl U32IntoFelt252 of Into { +pub(crate) impl U32IntoFelt252 of Into { fn into(self: u32) -> felt252 { u32_to_felt252(self) } } -impl Felt252TryIntoU64 of TryInto { +pub(crate) impl Felt252TryIntoU64 of TryInto { fn try_into(self: felt252) -> Option { u64_try_from_felt252(self) } } -impl U64IntoFelt252 of Into { +pub(crate) impl U64IntoFelt252 of Into { fn into(self: u64) -> felt252 { u64_to_felt252(self) } } -impl Felt252TryIntoU128 of TryInto { +pub(crate) impl Felt252TryIntoU128 of TryInto { fn try_into(self: felt252) -> Option { u128_try_from_felt252(self) } } -impl U128IntoFelt252 of Into { +pub(crate) impl U128IntoFelt252 of Into { fn into(self: u128) -> felt252 { u128_to_felt252(self) } } -impl Felt252IntoU256 of Into { +pub(crate) impl Felt252IntoU256 of Into { fn into(self: felt252) -> u256 { u256_from_felt252(self) } } -impl U256TryIntoFelt252 of TryInto { +pub(crate) impl U256TryIntoFelt252 of TryInto { fn try_into(self: u256) -> Option { let FELT252_PRIME_HIGH = 0x8000000000000110000000000000000_u128; if self.high > FELT252_PRIME_HIGH { @@ -1510,7 +1570,7 @@ impl Felt252TryIntoI8 of TryInto { i8_try_from_felt252(self) } } -impl I8IntoFelt252 of Into { +pub(crate) impl I8IntoFelt252 of Into { fn into(self: i8) -> felt252 { i8_to_felt252(self) } @@ -1520,7 +1580,7 @@ impl Felt252TryIntoI16 of TryInto { i16_try_from_felt252(self) } } -impl I16IntoFelt252 of Into { +pub(crate) impl I16IntoFelt252 of Into { fn into(self: i16) -> felt252 { i16_to_felt252(self) } @@ -1530,7 +1590,7 @@ impl Felt252TryIntoI32 of TryInto { i32_try_from_felt252(self) } } -impl I32IntoFelt252 of Into { +pub(crate) impl I32IntoFelt252 of Into { fn into(self: i32) -> felt252 { i32_to_felt252(self) } @@ -1540,7 +1600,7 @@ impl Felt252TryIntoI64 of TryInto { i64_try_from_felt252(self) } } -impl I64IntoFelt252 of Into { +pub(crate) impl I64IntoFelt252 of Into { fn into(self: i64) -> felt252 { i64_to_felt252(self) } @@ -1550,7 +1610,7 @@ impl Felt252TryIntoI128 of TryInto { i128_try_from_felt252(self) } } -impl I128IntoFelt252 of Into { +pub(crate) impl I128IntoFelt252 of Into { fn into(self: i128) -> felt252 { i128_to_felt252(self) } @@ -1558,7 +1618,7 @@ impl I128IntoFelt252 of Into { // TODO(lior): Restrict the function (using traits) in the high-level compiler so that wrong types // will not lead to Sierra errors. -extern fn upcast(x: FromType) -> ToType nopanic; +pub(crate) extern fn upcast(x: FromType) -> ToType nopanic; // TODO(lior): Restrict the function (using traits) in the high-level compiler so that wrong types // will not lead to Sierra errors. @@ -1567,32 +1627,50 @@ extern fn downcast(x: FromType) -> Option implicits(Ra // Marks `FromType` as upcastable to `ToType`. // Do not add user code implementing this trait. trait Upcastable; -impl UpcastableU8U16 of Upcastable {} -impl UpcastableU8U32 of Upcastable {} -impl UpcastableU8U64 of Upcastable {} -impl UpcastableU8U128 of Upcastable {} -impl UpcastableU16U32 of Upcastable {} -impl UpcastableU16U64 of Upcastable {} -impl UpcastableU16U128 of Upcastable {} -impl UpcastableU32U64 of Upcastable {} -impl UpcastableU32U128 of Upcastable {} -impl UpcastableU64U128 of Upcastable {} -// Marks `FromType` as downcastable to `ToType`. +impl UpcastableU8U16 of Upcastable; +impl UpcastableU8I16 of Upcastable; +impl UpcastableU8U32 of Upcastable; +impl UpcastableU8I32 of Upcastable; +impl UpcastableU8U64 of Upcastable; +impl UpcastableU8I64 of Upcastable; +impl UpcastableU8U128 of Upcastable; +impl UpcastableU8I128 of Upcastable; +impl UpcastableI8I16 of Upcastable; +impl UpcastableI8I32 of Upcastable; +impl UpcastableI8I64 of Upcastable; +impl UpcastableI8I128 of Upcastable; +impl UpcastableU16U32 of Upcastable; +impl UpcastableU16I32 of Upcastable; +impl UpcastableU16U64 of Upcastable; +impl UpcastableU16I64 of Upcastable; +impl UpcastableU16U128 of Upcastable; +impl UpcastableU16I128 of Upcastable; +impl UpcastableI16I32 of Upcastable; +impl UpcastableI16I64 of Upcastable; +impl UpcastableI16I128 of Upcastable; +impl UpcastableU32U64 of Upcastable; +impl UpcastableU32I64 of Upcastable; +impl UpcastableU32U128 of Upcastable; +impl UpcastableU32I128 of Upcastable; +impl UpcastableI32I64 of Upcastable; +impl UpcastableI32I128 of Upcastable; +impl UpcastableU64U128 of Upcastable; +impl UpcastableU64I128 of Upcastable; +impl UpcastableI64I128 of Upcastable; +// Marks a type as an int that is downcastable to other downcastable ints. // Do not add user code implementing this trait. -trait Downcastable; -impl DowncastableU128U64 of Downcastable {} -impl DowncastableU128U32 of Downcastable {} -impl DowncastableU128U16 of Downcastable {} -impl DowncastableU128U8 of Downcastable {} +trait DowncastableInt; +impl DowncastableU8 of DowncastableInt; +impl DowncastableI8 of DowncastableInt; +impl DowncastableU16 of DowncastableInt; +impl DowncastableI16 of DowncastableInt; +impl DowncastableU32 of DowncastableInt; +impl DowncastableI32 of DowncastableInt; +impl DowncastableU64 of DowncastableInt; +impl DowncastableI64 of DowncastableInt; +impl DowncastableU128 of DowncastableInt; +impl DowncastableI128 of DowncastableInt; -impl DowncastableU64U32 of Downcastable {} -impl DowncastableU64U16 of Downcastable {} -impl DowncastableU64U8 of Downcastable {} - -impl DowncastableU32U16 of Downcastable {} -impl DowncastableU32U8 of Downcastable {} - -impl DowncastableU16U8 of Downcastable {} /// Default values impl U8Default of Default { @@ -1674,14 +1752,14 @@ impl U128Felt252DictValue of Felt252DictValue { } } -impl UpcastableInto> of Into { +impl UpcastableInto> of Into { fn into(self: From) -> To { upcast(self) } } -impl DowncastableTryInto< - From, To, impl FromToDowncastable: Downcastable +impl DowncastableIntTryInto< + From, To, +DowncastableInt, +DowncastableInt, -Into > of TryInto { fn try_into(self: From) -> Option { downcast(self) @@ -1778,109 +1856,24 @@ impl U256TryIntoU128 of TryInto { } } -// === Zeroable === - -impl U8Zeroable of Zeroable { - fn zero() -> u8 { - 0 - } - #[inline(always)] - fn is_zero(self: u8) -> bool { - self == U8Zeroable::zero() - } - #[inline(always)] - fn is_non_zero(self: u8) -> bool { - self != U8Zeroable::zero() - } -} - -impl U16Zeroable of Zeroable { - fn zero() -> u16 { - 0 - } - #[inline(always)] - fn is_zero(self: u16) -> bool { - self == U16Zeroable::zero() - } - #[inline(always)] - fn is_non_zero(self: u16) -> bool { - self != U16Zeroable::zero() - } -} - -impl U32Zeroable of Zeroable { - fn zero() -> u32 { - 0 - } - #[inline(always)] - fn is_zero(self: u32) -> bool { - self == U32Zeroable::zero() - } - #[inline(always)] - fn is_non_zero(self: u32) -> bool { - self != U32Zeroable::zero() - } -} - -impl U64Zeroable of Zeroable { - fn zero() -> u64 { - 0 - } - #[inline(always)] - fn is_zero(self: u64) -> bool { - self == U64Zeroable::zero() - } - #[inline(always)] - fn is_non_zero(self: u64) -> bool { - self != U64Zeroable::zero() - } -} - -impl U128Zeroable of Zeroable { - fn zero() -> u128 { - 0 - } - #[inline(always)] - fn is_zero(self: u128) -> bool { - self == U128Zeroable::zero() - } - #[inline(always)] - fn is_non_zero(self: u128) -> bool { - self != U128Zeroable::zero() - } -} - -impl U256Zeroable of Zeroable { - fn zero() -> u256 { - 0 - } - #[inline(always)] - fn is_zero(self: u256) -> bool { - self == U256Zeroable::zero() - } - #[inline(always)] - fn is_non_zero(self: u256) -> bool { - self != U256Zeroable::zero() - } -} - enum SignedIntegerResult { InRange: T, Underflow: T, Overflow: T, } -impl SignedIntegerResultDrop> of Drop>; +impl SignedIntegerResultDrop> of Drop>; #[derive(Copy, Drop)] -extern type i8; +pub extern type i8; impl NumericLiterali8 of NumericLiteral; -extern fn i8_const() -> i8 nopanic; extern fn i8_try_from_felt252(a: felt252) -> Option implicits(RangeCheck) nopanic; extern fn i8_to_felt252(a: i8) -> felt252 nopanic; extern fn i8_is_zero(a: i8) -> IsZeroResult implicits() nopanic; extern fn i8_eq(lhs: i8, rhs: i8) -> bool implicits() nopanic; +impl I8Serde = core::serde::into_felt252_based::SerdeImpl; + impl I8PartialEq of PartialEq { #[inline(always)] fn eq(lhs: @i8, rhs: @i8) -> bool { @@ -1902,8 +1895,8 @@ impl I8Add of Add { fn add(lhs: i8, rhs: i8) -> i8 { match i8_overflowing_add_impl(lhs, rhs) { SignedIntegerResult::InRange(result) => result, - SignedIntegerResult::Underflow(_) => panic_with_felt252('i8_add Underflow'), - SignedIntegerResult::Overflow(_) => panic_with_felt252('i8_add Overflow'), + SignedIntegerResult::Underflow(_) => core::panic_with_felt252('i8_add Underflow'), + SignedIntegerResult::Overflow(_) => core::panic_with_felt252('i8_add Overflow'), } } } @@ -1917,8 +1910,8 @@ impl I8Sub of Sub { fn sub(lhs: i8, rhs: i8) -> i8 { match i8_overflowing_sub_impl(lhs, rhs) { SignedIntegerResult::InRange(result) => result, - SignedIntegerResult::Underflow(_) => panic_with_felt252('i8_sub Underflow'), - SignedIntegerResult::Overflow(_) => panic_with_felt252('i8_sub Overflow'), + SignedIntegerResult::Underflow(_) => core::panic_with_felt252('i8_sub Underflow'), + SignedIntegerResult::Overflow(_) => core::panic_with_felt252('i8_sub Overflow'), } } } @@ -1936,10 +1929,10 @@ impl I8Neg of Neg { } } -extern fn i8_wide_mul(lhs: i8, rhs: i8) -> i16 implicits() nopanic; +pub extern fn i8_wide_mul(lhs: i8, rhs: i8) -> i16 implicits() nopanic; impl I8Mul of Mul { fn mul(lhs: i8, rhs: i8) -> i8 { - i8_try_from_felt252(i16_to_felt252(i8_wide_mul(lhs, rhs))).expect('i8_mul Overflow') + i8_wide_mul(lhs, rhs).try_into().expect('i8_mul Overflow') } } impl I8MulEq of MulEq { @@ -1950,7 +1943,7 @@ impl I8MulEq of MulEq { } /// If `lhs` >= `rhs` returns `Ok(lhs - rhs)` else returns `Err(2**8 + lhs - rhs)`. -extern fn i8_diff(lhs: i8, rhs: i8) -> Result implicits(RangeCheck) nopanic; +pub extern fn i8_diff(lhs: i8, rhs: i8) -> Result implicits(RangeCheck) nopanic; impl I8PartialOrd of PartialOrd { #[inline(always)] fn le(lhs: i8, rhs: i8) -> bool { @@ -1970,16 +1963,23 @@ impl I8PartialOrd of PartialOrd { } } +impl I8BitSize of core::num::traits::BitSize { + fn bits() -> usize { + 8 + } +} + #[derive(Copy, Drop)] -extern type i16; +pub extern type i16; impl NumericLiterali16 of NumericLiteral; -extern fn i16_const() -> i16 nopanic; extern fn i16_try_from_felt252(a: felt252) -> Option implicits(RangeCheck) nopanic; extern fn i16_to_felt252(a: i16) -> felt252 nopanic; extern fn i16_is_zero(a: i16) -> IsZeroResult implicits() nopanic; extern fn i16_eq(lhs: i16, rhs: i16) -> bool implicits() nopanic; +impl I16Serde = core::serde::into_felt252_based::SerdeImpl; + impl I16PartialEq of PartialEq { #[inline(always)] fn eq(lhs: @i16, rhs: @i16) -> bool { @@ -2001,8 +2001,8 @@ impl I16Add of Add { fn add(lhs: i16, rhs: i16) -> i16 { match i16_overflowing_add_impl(lhs, rhs) { SignedIntegerResult::InRange(result) => result, - SignedIntegerResult::Underflow(_) => panic_with_felt252('i16_add Underflow'), - SignedIntegerResult::Overflow(_) => panic_with_felt252('i16_add Overflow'), + SignedIntegerResult::Underflow(_) => core::panic_with_felt252('i16_add Underflow'), + SignedIntegerResult::Overflow(_) => core::panic_with_felt252('i16_add Overflow'), } } } @@ -2016,8 +2016,8 @@ impl I16Sub of Sub { fn sub(lhs: i16, rhs: i16) -> i16 { match i16_overflowing_sub_impl(lhs, rhs) { SignedIntegerResult::InRange(result) => result, - SignedIntegerResult::Underflow(_) => panic_with_felt252('i16_sub Underflow'), - SignedIntegerResult::Overflow(_) => panic_with_felt252('i16_sub Overflow'), + SignedIntegerResult::Underflow(_) => core::panic_with_felt252('i16_sub Underflow'), + SignedIntegerResult::Overflow(_) => core::panic_with_felt252('i16_sub Overflow'), } } } @@ -2035,10 +2035,10 @@ impl I16Neg of Neg { } } -extern fn i16_wide_mul(lhs: i16, rhs: i16) -> i32 implicits() nopanic; +pub extern fn i16_wide_mul(lhs: i16, rhs: i16) -> i32 implicits() nopanic; impl I16Mul of Mul { fn mul(lhs: i16, rhs: i16) -> i16 { - i16_try_from_felt252(i32_to_felt252(i16_wide_mul(lhs, rhs))).expect('i16_mul Overflow') + i16_wide_mul(lhs, rhs).try_into().expect('i16_mul Overflow') } } impl I16MulEq of MulEq { @@ -2049,7 +2049,7 @@ impl I16MulEq of MulEq { } /// If `lhs` >= `rhs` returns `Ok(lhs - rhs)` else returns `Err(2**16 + lhs - rhs)`. -extern fn i16_diff(lhs: i16, rhs: i16) -> Result implicits(RangeCheck) nopanic; +pub extern fn i16_diff(lhs: i16, rhs: i16) -> Result implicits(RangeCheck) nopanic; impl I16PartialOrd of PartialOrd { #[inline(always)] fn le(lhs: i16, rhs: i16) -> bool { @@ -2069,16 +2069,23 @@ impl I16PartialOrd of PartialOrd { } } +impl I16BitSize of core::num::traits::BitSize { + fn bits() -> usize { + 16 + } +} + #[derive(Copy, Drop)] -extern type i32; +pub extern type i32; impl NumericLiterali32 of NumericLiteral; -extern fn i32_const() -> i32 nopanic; extern fn i32_try_from_felt252(a: felt252) -> Option implicits(RangeCheck) nopanic; extern fn i32_to_felt252(a: i32) -> felt252 nopanic; extern fn i32_is_zero(a: i32) -> IsZeroResult implicits() nopanic; extern fn i32_eq(lhs: i32, rhs: i32) -> bool implicits() nopanic; +impl I32Serde = core::serde::into_felt252_based::SerdeImpl; + impl I32PartialEq of PartialEq { #[inline(always)] fn eq(lhs: @i32, rhs: @i32) -> bool { @@ -2100,8 +2107,8 @@ impl I32Add of Add { fn add(lhs: i32, rhs: i32) -> i32 { match i32_overflowing_add_impl(lhs, rhs) { SignedIntegerResult::InRange(result) => result, - SignedIntegerResult::Underflow(_) => panic_with_felt252('i32_add Underflow'), - SignedIntegerResult::Overflow(_) => panic_with_felt252('i32_add Overflow'), + SignedIntegerResult::Underflow(_) => core::panic_with_felt252('i32_add Underflow'), + SignedIntegerResult::Overflow(_) => core::panic_with_felt252('i32_add Overflow'), } } } @@ -2115,8 +2122,8 @@ impl I32Sub of Sub { fn sub(lhs: i32, rhs: i32) -> i32 { match i32_overflowing_sub_impl(lhs, rhs) { SignedIntegerResult::InRange(result) => result, - SignedIntegerResult::Underflow(_) => panic_with_felt252('i32_sub Underflow'), - SignedIntegerResult::Overflow(_) => panic_with_felt252('i32_sub Overflow'), + SignedIntegerResult::Underflow(_) => core::panic_with_felt252('i32_sub Underflow'), + SignedIntegerResult::Overflow(_) => core::panic_with_felt252('i32_sub Overflow'), } } } @@ -2134,10 +2141,10 @@ impl I32Neg of Neg { } } -extern fn i32_wide_mul(lhs: i32, rhs: i32) -> i64 implicits() nopanic; +pub extern fn i32_wide_mul(lhs: i32, rhs: i32) -> i64 implicits() nopanic; impl I32Mul of Mul { fn mul(lhs: i32, rhs: i32) -> i32 { - i32_try_from_felt252(i64_to_felt252(i32_wide_mul(lhs, rhs))).expect('i32_mul Overflow') + i32_wide_mul(lhs, rhs).try_into().expect('i32_mul Overflow') } } impl I32MulEq of MulEq { @@ -2148,7 +2155,7 @@ impl I32MulEq of MulEq { } /// If `lhs` >= `rhs` returns `Ok(lhs - rhs)` else returns `Err(2**32 + lhs - rhs)`. -extern fn i32_diff(lhs: i32, rhs: i32) -> Result implicits(RangeCheck) nopanic; +pub extern fn i32_diff(lhs: i32, rhs: i32) -> Result implicits(RangeCheck) nopanic; impl I32PartialOrd of PartialOrd { #[inline(always)] fn le(lhs: i32, rhs: i32) -> bool { @@ -2168,16 +2175,23 @@ impl I32PartialOrd of PartialOrd { } } +impl I32BitSize of core::num::traits::BitSize { + fn bits() -> usize { + 32 + } +} + #[derive(Copy, Drop)] -extern type i64; +pub extern type i64; impl NumericLiterali64 of NumericLiteral; -extern fn i64_const() -> i64 nopanic; extern fn i64_try_from_felt252(a: felt252) -> Option implicits(RangeCheck) nopanic; extern fn i64_to_felt252(a: i64) -> felt252 nopanic; extern fn i64_is_zero(a: i64) -> IsZeroResult implicits() nopanic; extern fn i64_eq(lhs: i64, rhs: i64) -> bool implicits() nopanic; +impl I64Serde = core::serde::into_felt252_based::SerdeImpl; + impl I64PartialEq of PartialEq { #[inline(always)] fn eq(lhs: @i64, rhs: @i64) -> bool { @@ -2199,8 +2213,8 @@ impl I64Add of Add { fn add(lhs: i64, rhs: i64) -> i64 { match i64_overflowing_add_impl(lhs, rhs) { SignedIntegerResult::InRange(result) => result, - SignedIntegerResult::Underflow(_) => panic_with_felt252('i64_add Underflow'), - SignedIntegerResult::Overflow(_) => panic_with_felt252('i64_add Overflow'), + SignedIntegerResult::Underflow(_) => core::panic_with_felt252('i64_add Underflow'), + SignedIntegerResult::Overflow(_) => core::panic_with_felt252('i64_add Overflow'), } } } @@ -2214,8 +2228,8 @@ impl I64Sub of Sub { fn sub(lhs: i64, rhs: i64) -> i64 { match i64_overflowing_sub_impl(lhs, rhs) { SignedIntegerResult::InRange(result) => result, - SignedIntegerResult::Underflow(_) => panic_with_felt252('i64_sub Underflow'), - SignedIntegerResult::Overflow(_) => panic_with_felt252('i64_sub Overflow'), + SignedIntegerResult::Underflow(_) => core::panic_with_felt252('i64_sub Underflow'), + SignedIntegerResult::Overflow(_) => core::panic_with_felt252('i64_sub Overflow'), } } } @@ -2233,10 +2247,10 @@ impl I64Neg of Neg { } } -extern fn i64_wide_mul(lhs: i64, rhs: i64) -> i128 implicits() nopanic; +pub extern fn i64_wide_mul(lhs: i64, rhs: i64) -> i128 implicits() nopanic; impl I64Mul of Mul { fn mul(lhs: i64, rhs: i64) -> i64 { - i64_try_from_felt252(i128_to_felt252(i64_wide_mul(lhs, rhs))).expect('i64_mul Overflow') + i64_wide_mul(lhs, rhs).try_into().expect('i64_mul Overflow') } } impl I64MulEq of MulEq { @@ -2247,7 +2261,7 @@ impl I64MulEq of MulEq { } /// If `lhs` >= `rhs` returns `Ok(lhs - rhs)` else returns `Err(2**64 + lhs - rhs)`. -extern fn i64_diff(lhs: i64, rhs: i64) -> Result implicits(RangeCheck) nopanic; +pub extern fn i64_diff(lhs: i64, rhs: i64) -> Result implicits(RangeCheck) nopanic; impl I64PartialOrd of PartialOrd { #[inline(always)] fn le(lhs: i64, rhs: i64) -> bool { @@ -2267,16 +2281,23 @@ impl I64PartialOrd of PartialOrd { } } +impl I64BitSize of core::num::traits::BitSize { + fn bits() -> usize { + 64 + } +} + #[derive(Copy, Drop)] -extern type i128; +pub extern type i128; impl NumericLiterali128 of NumericLiteral; -extern fn i128_const() -> i128 nopanic; extern fn i128_try_from_felt252(a: felt252) -> Option implicits(RangeCheck) nopanic; extern fn i128_to_felt252(a: i128) -> felt252 nopanic; extern fn i128_is_zero(a: i128) -> IsZeroResult implicits() nopanic; extern fn i128_eq(lhs: i128, rhs: i128) -> bool implicits() nopanic; +impl I128Serde = core::serde::into_felt252_based::SerdeImpl; + impl I128PartialEq of PartialEq { #[inline(always)] fn eq(lhs: @i128, rhs: @i128) -> bool { @@ -2298,8 +2319,8 @@ impl I128Add of Add { fn add(lhs: i128, rhs: i128) -> i128 { match i128_overflowing_add_impl(lhs, rhs) { SignedIntegerResult::InRange(result) => result, - SignedIntegerResult::Underflow(_) => panic_with_felt252('i128_add Underflow'), - SignedIntegerResult::Overflow(_) => panic_with_felt252('i128_add Overflow'), + SignedIntegerResult::Underflow(_) => core::panic_with_felt252('i128_add Underflow'), + SignedIntegerResult::Overflow(_) => core::panic_with_felt252('i128_add Overflow'), } } } @@ -2313,8 +2334,8 @@ impl I128Sub of Sub { fn sub(lhs: i128, rhs: i128) -> i128 { match i128_overflowing_sub_impl(lhs, rhs) { SignedIntegerResult::InRange(result) => result, - SignedIntegerResult::Underflow(_) => panic_with_felt252('i128_sub Underflow'), - SignedIntegerResult::Overflow(_) => panic_with_felt252('i128_sub Overflow'), + SignedIntegerResult::Underflow(_) => core::panic_with_felt252('i128_sub Underflow'), + SignedIntegerResult::Overflow(_) => core::panic_with_felt252('i128_sub Overflow'), } } } @@ -2332,8 +2353,34 @@ impl I128Neg of Neg { } } +impl I128Mul of Mul { + fn mul(lhs: i128, rhs: i128) -> i128 { + let (lhs_u127, lhs_neg) = match i128_diff(lhs, 0) { + Result::Ok(v) => (v, false), + Result::Err(v) => (~v + 1, true), + }; + let (rhs_u127, res_neg) = match i128_diff(rhs, 0) { + Result::Ok(v) => (v, lhs_neg), + Result::Err(v) => (~v + 1, !lhs_neg), + }; + let res_as_u128 = lhs_u127 * rhs_u127; + let res_as_felt252: felt252 = if res_neg { + -res_as_u128.into() + } else { + res_as_u128.into() + }; + res_as_felt252.try_into().expect('i128_mul Overflow') + } +} +impl I128MulEq of MulEq { + #[inline(always)] + fn mul_eq(ref self: i128, other: i128) { + self = Mul::mul(self, other); + } +} + /// If `lhs` >= `rhs` returns `Ok(lhs - rhs)` else returns `Err(2**128 + lhs - rhs)`. -extern fn i128_diff(lhs: i128, rhs: i128) -> Result implicits(RangeCheck) nopanic; +pub extern fn i128_diff(lhs: i128, rhs: i128) -> Result implicits(RangeCheck) nopanic; impl I128PartialOrd of PartialOrd { #[inline(always)] fn le(lhs: i128, rhs: i128) -> bool { @@ -2352,3 +2399,338 @@ impl I128PartialOrd of PartialOrd { i128_diff(rhs, lhs).into_is_err() } } + +// Zeroable impls +pub(crate) impl U8Zeroable = core::zeroable::zero_based::ZeroableImpl; +pub(crate) impl U16Zeroable = core::zeroable::zero_based::ZeroableImpl; +pub(crate) impl U32Zeroable = core::zeroable::zero_based::ZeroableImpl; +pub(crate) impl U64Zeroable = core::zeroable::zero_based::ZeroableImpl; +pub(crate) impl U128Zeroable = core::zeroable::zero_based::ZeroableImpl; +pub(crate) impl U256Zeroable = core::zeroable::zero_based::ZeroableImpl; + +impl I128BitSize of core::num::traits::BitSize { + fn bits() -> usize { + 128 + } +} + +// Zero trait implementations +impl U8Zero of core::num::traits::Zero { + fn zero() -> u8 { + 0 + } + #[inline(always)] + fn is_zero(self: @u8) -> bool { + *self == U8Zero::zero() + } + #[inline(always)] + fn is_non_zero(self: @u8) -> bool { + !self.is_zero() + } +} + +impl U16Zero of core::num::traits::Zero { + fn zero() -> u16 { + 0 + } + #[inline(always)] + fn is_zero(self: @u16) -> bool { + *self == U16Zero::zero() + } + #[inline(always)] + fn is_non_zero(self: @u16) -> bool { + !self.is_zero() + } +} + +impl U32Zero of core::num::traits::Zero { + fn zero() -> u32 { + 0 + } + #[inline(always)] + fn is_zero(self: @u32) -> bool { + *self == U32Zero::zero() + } + #[inline(always)] + fn is_non_zero(self: @u32) -> bool { + !self.is_zero() + } +} + +impl U64Zero of core::num::traits::Zero { + fn zero() -> u64 { + 0 + } + #[inline(always)] + fn is_zero(self: @u64) -> bool { + *self == U64Zero::zero() + } + #[inline(always)] + fn is_non_zero(self: @u64) -> bool { + !self.is_zero() + } +} + +impl U128Zero of core::num::traits::Zero { + fn zero() -> u128 { + 0 + } + #[inline(always)] + fn is_zero(self: @u128) -> bool { + *self == U128Zero::zero() + } + #[inline(always)] + fn is_non_zero(self: @u128) -> bool { + !self.is_zero() + } +} + +impl U256Zero of core::num::traits::Zero { + fn zero() -> u256 { + 0 + } + #[inline(always)] + fn is_zero(self: @u256) -> bool { + *self == U256Zero::zero() + } + #[inline(always)] + fn is_non_zero(self: @u256) -> bool { + !self.is_zero() + } +} + +impl I8Zero of core::num::traits::Zero { + fn zero() -> i8 { + 0 + } + #[inline(always)] + fn is_zero(self: @i8) -> bool { + *self == I8Zero::zero() + } + #[inline(always)] + fn is_non_zero(self: @i8) -> bool { + !self.is_zero() + } +} + +impl I16Zero of core::num::traits::Zero { + fn zero() -> i16 { + 0 + } + #[inline(always)] + fn is_zero(self: @i16) -> bool { + *self == I16Zero::zero() + } + #[inline(always)] + fn is_non_zero(self: @i16) -> bool { + !self.is_zero() + } +} + +impl I32Zero of core::num::traits::Zero { + fn zero() -> i32 { + 0 + } + #[inline(always)] + fn is_zero(self: @i32) -> bool { + *self == I32Zero::zero() + } + #[inline(always)] + fn is_non_zero(self: @i32) -> bool { + !self.is_zero() + } +} + +impl I64Zero of core::num::traits::Zero { + fn zero() -> i64 { + 0 + } + #[inline(always)] + fn is_zero(self: @i64) -> bool { + *self == I64Zero::zero() + } + #[inline(always)] + fn is_non_zero(self: @i64) -> bool { + !self.is_zero() + } +} + +impl I128Zero of core::num::traits::Zero { + fn zero() -> i128 { + 0 + } + #[inline(always)] + fn is_zero(self: @i128) -> bool { + *self == I128Zero::zero() + } + #[inline(always)] + fn is_non_zero(self: @i128) -> bool { + !self.is_zero() + } +} + + +// One trait implementations +impl U8One of core::num::traits::One { + fn one() -> u8 { + 1 + } + #[inline(always)] + fn is_one(self: @u8) -> bool { + *self == U8One::one() + } + #[inline(always)] + fn is_non_one(self: @u8) -> bool { + !self.is_one() + } +} + +impl U16One of core::num::traits::One { + fn one() -> u16 { + 1 + } + #[inline(always)] + fn is_one(self: @u16) -> bool { + *self == U16One::one() + } + #[inline(always)] + fn is_non_one(self: @u16) -> bool { + !self.is_one() + } +} + +impl U32One of core::num::traits::One { + fn one() -> u32 { + 1 + } + #[inline(always)] + fn is_one(self: @u32) -> bool { + *self == U32One::one() + } + #[inline(always)] + fn is_non_one(self: @u32) -> bool { + !self.is_one() + } +} + +impl U64One of core::num::traits::One { + fn one() -> u64 { + 1 + } + #[inline(always)] + fn is_one(self: @u64) -> bool { + *self == U64One::one() + } + #[inline(always)] + fn is_non_one(self: @u64) -> bool { + !self.is_one() + } +} + +impl U128One of core::num::traits::One { + fn one() -> u128 { + 1 + } + #[inline(always)] + fn is_one(self: @u128) -> bool { + *self == U128One::one() + } + #[inline(always)] + fn is_non_one(self: @u128) -> bool { + !self.is_one() + } +} + +impl U256One of core::num::traits::One { + fn one() -> u256 { + 1 + } + #[inline(always)] + fn is_one(self: @u256) -> bool { + *self == U256One::one() + } + #[inline(always)] + fn is_non_one(self: @u256) -> bool { + !self.is_one() + } +} + +impl I8One of core::num::traits::One { + fn one() -> i8 { + 1 + } + + #[inline(always)] + fn is_one(self: @i8) -> bool { + *self == I8One::one() + } + + #[inline(always)] + fn is_non_one(self: @i8) -> bool { + !self.is_one() + } +} + +impl I16One of core::num::traits::One { + fn one() -> i16 { + 1 + } + + #[inline(always)] + fn is_one(self: @i16) -> bool { + *self == I16One::one() + } + + #[inline(always)] + fn is_non_one(self: @i16) -> bool { + !self.is_one() + } +} + +impl I32One of core::num::traits::One { + fn one() -> i32 { + 1 + } + + #[inline(always)] + fn is_one(self: @i32) -> bool { + *self == I32One::one() + } + + #[inline(always)] + fn is_non_one(self: @i32) -> bool { + !self.is_one() + } +} + +impl I64One of core::num::traits::One { + fn one() -> i64 { + 1 + } + + #[inline(always)] + fn is_one(self: @i64) -> bool { + *self == I64One::one() + } + + #[inline(always)] + fn is_non_one(self: @i64) -> bool { + !self.is_one() + } +} + +impl I128One of core::num::traits::One { + fn one() -> i128 { + 1 + } + + #[inline(always)] + fn is_one(self: @i128) -> bool { + *self == I128One::one() + } + + #[inline(always)] + fn is_non_one(self: @i128) -> bool { + !self.is_one() + } +} diff --git a/corelib/src/internal.cairo b/corelib/src/internal.cairo index 49a4ee6..5e2a736 100644 --- a/corelib/src/internal.cairo +++ b/corelib/src/internal.cairo @@ -1,6 +1,12 @@ -extern fn revoke_ap_tracking() implicits() nopanic; +pub extern fn revoke_ap_tracking() implicits() nopanic; /// Function to enforce that `Implicit` is used by a function calling it. /// Note: This extern function is not mapped to a Sierra function, and all usages of it are removed /// during compilation. -extern fn require_implicit() implicits(Implicit) nopanic; +pub extern fn require_implicit() implicits(Implicit) nopanic; + +extern type index_enum_type; + +extern type BoundedInt; + +extern fn constrain_range(value: T) -> Option implicits(RangeCheck) nopanic; diff --git a/corelib/src/keccak.cairo b/corelib/src/keccak.cairo index 080fffc..3bad213 100644 --- a/corelib/src/keccak.cairo +++ b/corelib/src/keccak.cairo @@ -1,7 +1,7 @@ -use array::{Span, ArrayTrait, SpanTrait}; -use integer::TryInto; -use option::OptionTrait; -use starknet::SyscallResultTrait; +use core::array::{Span, ArrayTrait, SpanTrait}; +use core::traits::TryInto; +use core::option::OptionTrait; +use core::starknet::SyscallResultTrait; const KECCAK_FULL_RATE_IN_BYTES: usize = 136; const KECCAK_FULL_RATE_IN_U64S: usize = 17; @@ -13,7 +13,7 @@ fn u128_to_u64(input: u128) -> u64 { } fn u128_split(input: u128) -> (u64, u64) { - let (high, low) = integer::u128_safe_divmod( + let (high, low) = core::integer::u128_safe_divmod( input, 0x10000000000000000_u128.try_into().unwrap() ); @@ -33,17 +33,13 @@ fn keccak_add_u256_le(ref keccak_input: Array::, v: u256) { // Computes the keccak256 of multiple u256 values. // The input values are interpreted as little-endian. // The 32-byte result is represented as a little-endian u256. -fn keccak_u256s_le_inputs(mut input: Span) -> u256 { +pub fn keccak_u256s_le_inputs(mut input: Span) -> u256 { let mut keccak_input: Array:: = Default::default(); loop { match input.pop_front() { - Option::Some(v) => { - keccak_add_u256_le(ref keccak_input, *v); - }, - Option::None => { - break (); - }, + Option::Some(v) => { keccak_add_u256_le(ref keccak_input, *v); }, + Option::None => { break (); }, }; }; @@ -52,10 +48,10 @@ fn keccak_u256s_le_inputs(mut input: Span) -> u256 { } fn keccak_add_u256_be(ref keccak_input: Array::, v: u256) { - let (high, low) = u128_split(integer::u128_byte_reverse(v.high)); + let (high, low) = u128_split(core::integer::u128_byte_reverse(v.high)); keccak_input.append(low); keccak_input.append(high); - let (high, low) = u128_split(integer::u128_byte_reverse(v.low)); + let (high, low) = u128_split(core::integer::u128_byte_reverse(v.low)); keccak_input.append(low); keccak_input.append(high); } @@ -63,17 +59,13 @@ fn keccak_add_u256_be(ref keccak_input: Array::, v: u256) { // Computes the keccak256 of multiple u256 values. // The input values are interpreted as big-endian. // The 32-byte result is represented as a little-endian u256. -fn keccak_u256s_be_inputs(mut input: Span) -> u256 { +pub fn keccak_u256s_be_inputs(mut input: Span) -> u256 { let mut keccak_input: Array:: = Default::default(); loop { match input.pop_front() { - Option::Some(v) => { - keccak_add_u256_be(ref keccak_input, *v); - }, - Option::None => { - break (); - }, + Option::Some(v) => { keccak_add_u256_be(ref keccak_input, *v); }, + Option::None => { break (); }, }; }; @@ -90,7 +82,9 @@ fn keccak_u256s_be_inputs(mut input: Span) -> u256 { // 560229490 == int.from_bytes(b'rld!', 'little') // // Returns the hash as a little endian u256. -fn cairo_keccak(ref input: Array, last_input_word: u64, last_input_num_bytes: usize) -> u256 { +pub fn cairo_keccak( + ref input: Array, last_input_word: u64, last_input_num_bytes: usize +) -> u256 { add_padding(ref input, last_input_word, last_input_num_bytes); starknet::syscalls::keccak_syscall(input.span()).unwrap_syscall() } @@ -100,9 +94,7 @@ fn cairo_keccak(ref input: Array, last_input_word: u64, last_input_num_byte fn add_padding(ref input: Array, last_input_word: u64, last_input_num_bytes: usize) { let words_divisor = KECCAK_FULL_RATE_IN_U64S.try_into().unwrap(); // `last_block_num_full_words` is in range [0, KECCAK_FULL_RATE_IN_U64S - 1] - let (_, last_block_num_full_words) = integer::u32_safe_divmod(input.len(), words_divisor); - // `last_block_num_bytes` is in range [0, KECCAK_FULL_RATE_IN_BYTES - 1] - let last_block_num_bytes = last_block_num_full_words * BYTES_IN_U64_WORD + last_input_num_bytes; + let (_, last_block_num_full_words) = core::integer::u32_safe_divmod(input.len(), words_divisor); // The first word to append would be of the form // 0x1<`last_input_num_bytes` LSB bytes of `last_input_word`>. @@ -127,9 +119,9 @@ fn add_padding(ref input: Array, last_input_word: u64, last_input_num_bytes } else if last_input_num_bytes == 7 { 0x100000000000000 } else { - panic_with_felt252('Keccak last input word >7b') + core::panic_with_felt252('Keccak last input word >7b') }; - let (_, r) = integer::u64_safe_divmod( + let (_, r) = core::integer::u64_safe_divmod( last_input_word, first_padding_byte_part.try_into().unwrap() ); first_padding_byte_part + r diff --git a/corelib/src/lib.cairo b/corelib/src/lib.cairo index e41b936..677f931 100644 --- a/corelib/src/lib.cairo +++ b/corelib/src/lib.cairo @@ -1,4 +1,4 @@ -mod traits; +pub mod traits; use traits::{ Add, AddEq, BitAnd, BitNot, BitOr, BitXor, Copy, Div, DivEq, DivRem, Drop, Mul, MulEq, PartialEq, PartialOrd, Rem, RemEq, Sub, SubEq, TupleSize0Copy, TupleSize0Drop, Not, Neg, Into, @@ -6,10 +6,10 @@ use traits::{ }; use serde::Serde; -type usize = u32; +pub type usize = u32; #[derive(Copy, Drop, Default)] -enum bool { +pub enum bool { #[default] False, True, @@ -18,9 +18,9 @@ enum bool { impl BoolSerde of Serde { fn serialize(self: @bool, ref output: Array) { if *self { - 1 + 1_felt252 } else { - 0 + 0_felt252 }.serialize(ref output); } fn deserialize(ref serialized: Span) -> Option { @@ -69,15 +69,15 @@ impl BoolPartialEq of PartialEq { #[inline(always)] fn eq(lhs: @bool, rhs: @bool) -> bool { match lhs { - bool::False => !*rhs, - bool::True => *rhs, + false => !*rhs, + true => *rhs, } } #[inline(always)] fn ne(lhs: @bool, rhs: @bool) -> bool { match lhs { - bool::False => *rhs, - bool::True => !*rhs, + false => *rhs, + true => !*rhs, } } } @@ -97,14 +97,18 @@ impl BoolIntoFelt252 of Into { bool_to_felt252(self) } } +pub mod boolean; // General purpose implicits. -extern type RangeCheck; -extern type SegmentArena; +pub extern type RangeCheck; +pub extern type SegmentArena; // felt252. +mod felt_252; +use felt_252::{Felt252One, Felt252Zero}; + #[derive(Copy, Drop)] -extern type felt252; +pub extern type felt252; extern fn felt252_const() -> felt252 nopanic; impl Felt252Serde of Serde { @@ -166,14 +170,14 @@ impl Felt252Neg of Neg { } } -extern fn felt252_div(lhs: felt252, rhs: NonZero) -> felt252 nopanic; +pub extern fn felt252_div(lhs: felt252, rhs: NonZero) -> felt252 nopanic; impl Felt252PartialEq of PartialEq { #[inline(always)] fn eq(lhs: @felt252, rhs: @felt252) -> bool { match *lhs - *rhs { - 0 => bool::True(()), - _ => bool::False(()), + 0 => true, + _ => false, } } #[inline(always)] @@ -212,127 +216,144 @@ extern fn dup(obj: T) -> (T, T) nopanic; extern fn drop(obj: T) nopanic; // Boxes. -mod box; +pub mod box; use box::{Box, BoxTrait}; // Nullable -mod nullable; +pub mod nullable; use nullable::{Nullable, NullableTrait, match_nullable, null, nullable_from_box}; // Array. -mod array; +pub mod array; use array::{Array, ArrayTrait}; // Span. use array::{Span, SpanTrait}; // Dictionary. -mod dict; +pub mod dict; use dict::{ Felt252Dict, SquashedFelt252Dict, felt252_dict_new, felt252_dict_squash, Felt252DictTrait }; // Result. -mod result; +pub mod result; use result::{Result, ResultTrait}; // Option. -mod option; +pub mod option; use option::{Option, OptionTrait}; // Clone. -mod clone; +pub mod clone; use clone::Clone; // EC. -mod ec; +pub mod ec; use ec::{EcOp, EcPoint, EcState}; -mod ecdsa; +pub mod ecdsa; // Integer. -mod integer; +pub mod integer; use integer::{ - i8, i8_const, I8IntoFelt252, i16, i16_const, I16IntoFelt252, i32, i32_const, I32IntoFelt252, - i64, i64_const, I64IntoFelt252, i128, i128_const, I128IntoFelt252, NumericLiteral, u128, - u128_const, u128_sqrt, u128_is_zero, u8, u8_const, u16, u16_const, u32, u32_const, u64, - u64_const, u256, u256_sqrt, Felt252TryIntoU8, U8IntoFelt252, Felt252TryIntoU16, U16IntoFelt252, + i8, I8IntoFelt252, i16, I16IntoFelt252, i32, I32IntoFelt252, i64, I64IntoFelt252, i128, + I128IntoFelt252, NumericLiteral, u128, u128_sqrt, u128_is_zero, u8, u16, u32, u64, u256, + u256_sqrt, Felt252TryIntoU8, U8IntoFelt252, Felt252TryIntoU16, U16IntoFelt252, Felt252TryIntoU32, U32IntoFelt252, Felt252TryIntoU64, U64IntoFelt252, Felt252TryIntoU128, U128IntoFelt252, Felt252IntoU256, Bitwise }; // Math. -mod math; +pub mod math; + +// Num. +pub mod num; // Cmp. -mod cmp; +pub mod cmp; // Gas. -mod gas; +pub mod gas; use gas::{BuiltinCosts, GasBuiltin, get_builtin_costs}; // Panics. -mod panics; +pub mod panics; use panics::{panic, Panic, PanicResult}; -enum never {} +pub enum never {} #[inline(always)] -fn panic_with_felt252(err_code: felt252) -> never { +pub fn panic_with_felt252(err_code: felt252) -> never { panic(array![err_code]) } #[inline(always)] -fn assert(cond: bool, err_code: felt252) { +pub fn assert(cond: bool, err_code: felt252) { if !cond { panic_with_felt252(err_code) } } // Serialization and Deserialization. -mod serde; +pub mod serde; // Hash functions. -mod hash; +pub mod hash; -mod keccak; +pub mod keccak; // Pedersen -mod pedersen; +pub mod pedersen; use pedersen::Pedersen; // Poseidon -mod poseidon; +pub mod poseidon; use poseidon::Poseidon; // Debug. -mod debug; +pub mod debug; + +pub mod fmt; // Starknet -mod starknet; +pub mod starknet; use starknet::System; // Internals. -mod internal; +pub mod internal; // Zeroable. -mod zeroable; +pub mod zeroable; use zeroable::{Zeroable, NonZero}; // bytes31. -mod bytes_31; +pub mod bytes_31; use bytes_31::{ bytes31, bytes31_const, Bytes31IndexView, Bytes31IntoFelt252, Bytes31Trait, Felt252TryIntoBytes31 }; // BytesArray. -mod byte_array; -use byte_array::{ByteArray, ByteArrayIndexView, ByteArrayTrait}; +pub mod byte_array; +use byte_array::{ByteArray, ByteArrayIndexView, ByteArrayStringLiteral, ByteArrayTrait}; + +// String. +pub mod string; +use string::StringLiteral; + +// to_byte_array. +pub mod to_byte_array; #[cfg(test)] mod test; // Module for testing only. -mod testing; +pub mod testing; + +// Metaprogramming. +pub mod metaprogramming; + +// Preludes. +mod prelude; diff --git a/corelib/src/math.cairo b/corelib/src/math.cairo index 708222e..e1ea082 100644 --- a/corelib/src/math.cairo +++ b/corelib/src/math.cairo @@ -1,7 +1,7 @@ -use zeroable::{IsZeroResult, NonZeroIntoImpl, Zeroable}; -use traits::{Into, TryInto}; -use option::OptionTrait; -use integer::{u256_wide_mul, u512_safe_div_rem_by_u256}; +use core::zeroable::{IsZeroResult, NonZeroIntoImpl, Zeroable}; +use core::traits::{Into, TryInto}; +use core::option::OptionTrait; +use core::integer::{u256_wide_mul, u512_safe_div_rem_by_u256, U128MulGuarantee}; // TODO(yuval): use signed integers once supported. // TODO(yuval): use a single impl of a trait with associated impls, once associated impls are @@ -12,23 +12,23 @@ use integer::{u256_wide_mul, u512_safe_div_rem_by_u256}; /// `(s, -t)` or `(-s, t)` are the Bezout coefficients (according to `sub_direction`). /// /// Uses the Extended Euclidean algorithm. -fn egcd< +pub fn egcd< T, - impl TCopyImpl: Copy, - impl TDropImpl: Drop, - impl TAddImpl: Add, - impl TMulImpl: Mul, - impl TDivRemImpl: DivRem, - impl TZeroableImpl: Zeroable, - impl TOneableImpl: Oneable, - impl TTryIntoNonZeroImpl: TryInto>, + +Copy, + +Drop, + +Add, + +Mul, + +DivRem, + +Zeroable, + +Oneable, + +TryInto>, >( a: NonZero, b: NonZero ) -> (T, T, T, bool) { - let (q, r) = TDivRemImpl::div_rem(a.into(), b); + let (q, r) = DivRem::::div_rem(a.into(), b); if r.is_zero() { - return (b.into(), TZeroableImpl::zero(), TOneableImpl::one(), false); + return (b.into(), Zeroable::zero(), Oneable::one(), false); } // `sign` (1 for true, -1 for false) is the sign of `g` in the current iteration. @@ -42,22 +42,22 @@ fn egcd< // TODO(yuval): use signed integers once supported. /// Returns the inverse of `a` modulo `n`, or None if `gcd(a, n) > 1`. -fn inv_mod< +pub fn inv_mod< T, - impl TCopyImpl: Copy, - impl TDropImpl: Drop, - impl TAddImpl: Add, - impl TSubImpl: Sub, - impl TMulImpl: Mul, - impl TDivRemImpl: DivRem, - impl TZeroableImpl: Zeroable, - impl TOneableImpl: Oneable, - impl TTryIntoNonZeroImpl: TryInto>, + +Copy, + +Drop, + +Add, + +Sub, + +Mul, + +DivRem, + +Zeroable, + +Oneable, + +TryInto>, >( a: NonZero, n: NonZero ) -> Option { - if TOneableImpl::is_one(n.into()) { - return Option::Some(TZeroableImpl::zero()); + if Oneable::::is_one(n.into()) { + return Option::Some(Zeroable::zero()); } let (g, s, _, sub_direction) = egcd(a, n); if g.is_one() { @@ -77,13 +77,44 @@ fn inv_mod< } } +/// Returns `1 / b (mod n)`, or None if `b` is not invertible modulo `n`. +/// All `b`s will be considered not invertible for `n == 1`. +/// Additionally returns several `U128MulGuarantee`s that are required for validating the +/// calculation. +extern fn u256_guarantee_inv_mod_n( + b: u256, n: NonZero +) -> Result< + ( + NonZero, + U128MulGuarantee, + U128MulGuarantee, + U128MulGuarantee, + U128MulGuarantee, + U128MulGuarantee, + U128MulGuarantee, + U128MulGuarantee, + U128MulGuarantee + ), + (U128MulGuarantee, U128MulGuarantee) +> implicits(RangeCheck) nopanic; + +/// Returns the inverse of `a` modulo `n`, or None if `a` is not invertible modulo `n`. +/// All `b`s will be considered not invertible for `n == 1`. +#[inline(always)] +pub fn u256_inv_mod(a: u256, n: NonZero) -> Option> { + match u256_guarantee_inv_mod_n(a, n) { + Result::Ok((inv_a, _, _, _, _, _, _, _, _)) => Option::Some(inv_a), + Result::Err(_) => Option::None(()) + } +} + /// Returns `a / b (mod n)`, or None if `b` is not invertible modulo `n`. -fn u256_div_mod_n(a: u256, b: NonZero, n: NonZero) -> Option { - Option::Some(u256_mul_mod_n(a, inv_mod(b, n)?, n)) +pub fn u256_div_mod_n(a: u256, b: u256, n: NonZero) -> Option { + Option::Some(u256_mul_mod_n(a, u256_inv_mod(b, n)?.into(), n)) } /// Returns `a * b (mod n)`. -fn u256_mul_mod_n(a: u256, b: u256, n: NonZero) -> u256 { +pub fn u256_mul_mod_n(a: u256, b: u256, n: NonZero) -> u256 { let (_, r) = u512_safe_div_rem_by_u256(u256_wide_mul(a, b), n); r } @@ -92,93 +123,38 @@ fn u256_mul_mod_n(a: u256, b: u256, n: NonZero) -> u256 { trait Oneable { /// Returns the multiplicative identity element of Self, 1. + #[must_use] fn one() -> T; /// Returns whether self is equal to 1, the multiplicative identity element. + #[must_use] fn is_one(self: T) -> bool; /// Returns whether self is not equal to 1, the multiplicative identity element. + #[must_use] fn is_non_one(self: T) -> bool; } -impl U8Oneable of Oneable { - fn one() -> u8 { - 1 - } - #[inline(always)] - fn is_one(self: u8) -> bool { - self == U8Oneable::one() - } - #[inline(always)] - fn is_non_one(self: u8) -> bool { - self != U8Oneable::one() - } -} - -impl U16Oneable of Oneable { - fn one() -> u16 { - 1 - } - #[inline(always)] - fn is_one(self: u16) -> bool { - self == U16Oneable::one() - } - #[inline(always)] - fn is_non_one(self: u16) -> bool { - self != U16Oneable::one() - } -} - -impl U32Oneable of Oneable { - fn one() -> u32 { - 1 - } - #[inline(always)] - fn is_one(self: u32) -> bool { - self == U32Oneable::one() - } - #[inline(always)] - fn is_non_one(self: u32) -> bool { - self != U32Oneable::one() - } -} - -impl U64Oneable of Oneable { - fn one() -> u64 { - 1 - } - #[inline(always)] - fn is_one(self: u64) -> bool { - self == U64Oneable::one() - } - #[inline(always)] - fn is_non_one(self: u64) -> bool { - self != U64Oneable::one() - } -} - -impl U128Oneable of Oneable { - fn one() -> u128 { - 1 - } - #[inline(always)] - fn is_one(self: u128) -> bool { - self == U128Oneable::one() - } - #[inline(always)] - fn is_non_one(self: u128) -> bool { - self != U128Oneable::one() +pub(crate) mod one_based { + pub(crate) impl OneableImpl< + T, impl OneImpl: core::num::traits::One, +Drop, +Copy + > of super::Oneable { + fn one() -> T { + OneImpl::one() + } + #[inline(always)] + fn is_one(self: T) -> bool { + OneImpl::is_one(@self) + } + #[inline(always)] + fn is_non_one(self: T) -> bool { + OneImpl::is_non_one(@self) + } } } -impl U256Oneable of Oneable { - fn one() -> u256 { - 1 - } - #[inline(always)] - fn is_one(self: u256) -> bool { - self == U256Oneable::one() - } - #[inline(always)] - fn is_non_one(self: u256) -> bool { - self != U256Oneable::one() - } -} +// Oneable impls +impl U8Oneable = math::one_based::OneableImpl; +impl U16Oneable = math::one_based::OneableImpl; +impl U32Oneable = math::one_based::OneableImpl; +impl U64Oneable = math::one_based::OneableImpl; +impl U128Oneable = math::one_based::OneableImpl; +impl U256Oneable = math::one_based::OneableImpl; diff --git a/corelib/src/metaprogramming.cairo b/corelib/src/metaprogramming.cairo new file mode 100644 index 0000000..87ed62e --- /dev/null +++ b/corelib/src/metaprogramming.cairo @@ -0,0 +1,5 @@ +/// A trait that can be used to disable implementations based on the types of the generic args. +/// Assumes that `TypeEqualImpl` is the only implementation of this trait. +pub trait TypeEqual {} + +impl TypeEqualImpl of TypeEqual; diff --git a/corelib/src/nullable.cairo b/corelib/src/nullable.cairo index a7a35fd..5f2c37b 100644 --- a/corelib/src/nullable.cairo +++ b/corelib/src/nullable.cairo @@ -1,38 +1,53 @@ -use box::BoxTrait; -use traits::Default; -use traits::Felt252DictValue; +use core::box::BoxTrait; +use core::traits::Default; +use core::traits::Felt252DictValue; #[derive(Copy, Drop)] -extern type Nullable; +pub extern type Nullable; -enum FromNullableResult { +pub enum FromNullableResult { Null, NotNull: Box, } -extern fn null() -> Nullable nopanic; -extern fn nullable_from_box(value: Box) -> Nullable nopanic; -extern fn match_nullable(value: Nullable) -> FromNullableResult nopanic; +pub extern fn null() -> Nullable nopanic; +pub(crate) extern fn nullable_from_box(value: Box) -> Nullable nopanic; +pub extern fn match_nullable(value: Nullable) -> FromNullableResult nopanic; +extern fn nullable_forward_snapshot(value: @Nullable) -> Nullable<@T> nopanic; -trait NullableTrait { - fn deref(self: Nullable) -> T; - fn new(value: T) -> Nullable; -} - -impl NullableImpl of NullableTrait { +#[generate_trait] +pub impl NullableImpl of NullableTrait { fn deref(self: Nullable) -> T { match match_nullable(self) { - FromNullableResult::Null => panic_with_felt252('Attempted to deref null value'), + FromNullableResult::Null => core::panic_with_felt252('Attempted to deref null value'), FromNullableResult::NotNull(value) => value.unbox(), } } + fn deref_or<+Drop>(self: Nullable, default: T) -> T { + match match_nullable(self) { + FromNullableResult::Null => default, + FromNullableResult::NotNull(value) => value.unbox(), + } + } + #[must_use] fn new(value: T) -> Nullable { nullable_from_box(BoxTrait::new(value)) } + #[must_use] + fn is_null(self: @Nullable) -> bool { + match match_nullable(self.as_snapshot()) { + FromNullableResult::Null => true, + FromNullableResult::NotNull(_) => false, + } + } + fn as_snapshot(self: @Nullable) -> Nullable<@T> nopanic { + nullable_forward_snapshot(self) + } } impl NullableDefault of Default> { #[inline(always)] + #[must_use] fn default() -> Nullable nopanic { null() } @@ -40,7 +55,20 @@ impl NullableDefault of Default> { impl NullableFelt252DictValue of Felt252DictValue> { #[inline(always)] + #[must_use] fn zero_default() -> Nullable nopanic { null() } } + +impl NullableDebug> of core::fmt::Debug> { + fn fmt(self: @Nullable, ref f: core::fmt::Formatter) -> Result<(), core::fmt::Error> { + match match_nullable(self.as_snapshot()) { + FromNullableResult::Null => write!(f, "null"), + FromNullableResult::NotNull(value) => { + write!(f, "&")?; + TDebug::fmt(value.unbox(), ref f) + }, + } + } +} diff --git a/corelib/src/num.cairo b/corelib/src/num.cairo new file mode 100644 index 0000000..f6ac8fc --- /dev/null +++ b/corelib/src/num.cairo @@ -0,0 +1 @@ +pub mod traits; diff --git a/corelib/src/num/traits.cairo b/corelib/src/num/traits.cairo new file mode 100644 index 0000000..75f57a4 --- /dev/null +++ b/corelib/src/num/traits.cairo @@ -0,0 +1,8 @@ +pub mod zero; +pub use zero::Zero; + +pub mod one; +pub use one::One; + +pub mod bit_size; +pub use bit_size::BitSize; diff --git a/corelib/src/num/traits/bit_size.cairo b/corelib/src/num/traits/bit_size.cairo new file mode 100644 index 0000000..76d50a4 --- /dev/null +++ b/corelib/src/num/traits/bit_size.cairo @@ -0,0 +1,6 @@ +/// Trait used to retrieve the size in bits of a type. +pub trait BitSize { + /// Returns the size in bits of T as usize. + #[must_use] + fn bits() -> usize; +} diff --git a/corelib/src/num/traits/one.cairo b/corelib/src/num/traits/one.cairo new file mode 100644 index 0000000..34ff7a0 --- /dev/null +++ b/corelib/src/num/traits/one.cairo @@ -0,0 +1,9 @@ +/// Defines a multiplicative identity element for `T`. +pub trait One { + /// Returns the multiplicative identity element of `T`, `1`. + fn one() -> T; + /// Returns `true` if `self` is equal to the multiplicative identity. + fn is_one(self: @T) -> bool; + /// Returns `false` if `self` is equal to the multiplicative identity. + fn is_non_one(self: @T) -> bool; +} diff --git a/corelib/src/num/traits/zero.cairo b/corelib/src/num/traits/zero.cairo new file mode 100644 index 0000000..c43bd5d --- /dev/null +++ b/corelib/src/num/traits/zero.cairo @@ -0,0 +1,9 @@ +/// Defines an additive identity element for `T`. +pub trait Zero { + /// Returns the additive identity element of `T`, `0`. + fn zero() -> T; + /// Returns `true` if `self` is equal to the additive identity. + fn is_zero(self: @T) -> bool; + /// Returns `false` if `self` is equal to the additive identity. + fn is_non_zero(self: @T) -> bool; +} diff --git a/corelib/src/option.cairo b/corelib/src/option.cairo index 79672c5..6db7b30 100644 --- a/corelib/src/option.cairo +++ b/corelib/src/option.cairo @@ -1,35 +1,62 @@ -use array::ArrayTrait; -use serde::Serde; -use array::SpanTrait; - -#[derive(Copy, Drop, Serde, PartialEq)] -enum Option { +#[must_use] +#[derive(Copy, Drop, Debug, Serde, PartialEq)] +pub enum Option { Some: T, None, } -trait OptionTrait { +pub impl DestructOption, -Drop>> of Destruct> { + #[inline(always)] + fn destruct(self: Option) nopanic { + match self { + Option::Some(x) => x.destruct(), + Option::None => (), + }; + } +} + +pub trait OptionTrait { /// If `val` is `Option::Some(x)`, returns `x`. Otherwise, panics with `err`. fn expect(self: Option, err: felt252) -> T; /// If `val` is `Option::Some(x)`, returns `x`. Otherwise, panics. fn unwrap(self: Option) -> T; + /// Transforms the `Option` into a `Result`, mapping `Option::Some(v)` to + /// `Result::Ok(v)` and `Option::None` to `Result::Err(err)`. + fn ok_or>(self: Option, err: E) -> Result; /// Returns `true` if the `Option` is `Option::Some`. + #[must_use] fn is_some(self: @Option) -> bool; /// Returns `true` if the `Option` is `Option::None`. + #[must_use] fn is_none(self: @Option) -> bool; + /// If `self` is `Option::Some(x)`, returns `x`. Otherwise, returns the provided default. + fn unwrap_or<+Drop>(self: Option, default: T) -> T; + /// If `self` is `Option::Some(x)`, returns `x`. Otherwise, returns `Default::::default()`. + fn unwrap_or_default<+Default>(self: Option) -> T; } -impl OptionTraitImpl of OptionTrait { + +pub impl OptionTraitImpl of OptionTrait { #[inline(always)] fn expect(self: Option, err: felt252) -> T { match self { Option::Some(x) => x, - Option::None => panic_with_felt252(err), + Option::None => core::panic_with_felt252(err), } } + #[inline(always)] fn unwrap(self: Option) -> T { self.expect('Option::unwrap failed.') } + + #[inline] + fn ok_or>(self: Option, err: E) -> Result { + match self { + Option::Some(v) => Result::Ok(v), + Option::None => Result::Err(err), + } + } + #[inline(always)] fn is_some(self: @Option) -> bool { match self { @@ -37,6 +64,7 @@ impl OptionTraitImpl of OptionTrait { Option::None => false, } } + #[inline(always)] fn is_none(self: @Option) -> bool { match self { @@ -44,4 +72,20 @@ impl OptionTraitImpl of OptionTrait { Option::None => true, } } + + #[inline] + fn unwrap_or<+Drop>(self: Option, default: T) -> T { + match self { + Option::Some(x) => x, + Option::None => default, + } + } + + #[inline] + fn unwrap_or_default<+Default>(self: Option) -> T { + match self { + Option::Some(x) => x, + Option::None => Default::default(), + } + } } diff --git a/corelib/src/panics.cairo b/corelib/src/panics.cairo index 1541a81..c6b49cc 100644 --- a/corelib/src/panics.cairo +++ b/corelib/src/panics.cairo @@ -1,10 +1,19 @@ -use array::Array; +use core::array::Array; -struct Panic {} +pub struct Panic {} -enum PanicResult { +pub enum PanicResult { Ok: T, Err: (Panic, Array), } -extern fn panic(data: Array) -> never; +pub extern fn panic(data: Array) -> core::never; + +/// Panics with the given ByteArray. That is, panics with an `Array` with +/// `BYTE_ARRAY_MAGIC`, and then the serialized given ByteArray. +#[inline(always)] +pub fn panic_with_byte_array(err: @ByteArray) -> core::never { + let mut serialized = array![core::byte_array::BYTE_ARRAY_MAGIC]; + err.serialize(ref serialized); + panic(serialized) +} diff --git a/corelib/src/pedersen.cairo b/corelib/src/pedersen.cairo index 11f9129..8a5bf72 100644 --- a/corelib/src/pedersen.cairo +++ b/corelib/src/pedersen.cairo @@ -1,16 +1,16 @@ -extern type Pedersen; +pub extern type Pedersen; -extern fn pedersen(a: felt252, b: felt252) -> felt252 implicits(Pedersen) nopanic; +pub extern fn pedersen(a: felt252, b: felt252) -> felt252 implicits(Pedersen) nopanic; /// State for Pedersen hash. -#[derive(Copy, Drop)] -struct HashState { - state: felt252, +#[derive(Copy, Drop, Debug)] +pub struct HashState { + pub state: felt252, } #[generate_trait] -impl PedersenImpl of PedersenTrait { +pub impl PedersenImpl of PedersenTrait { /// Creates a state from a base value. #[inline(always)] fn new(base: felt252) -> HashState { @@ -18,7 +18,7 @@ impl PedersenImpl of PedersenTrait { } } -impl HashStateImpl of hash::HashStateTrait { +impl HashStateImpl of core::hash::HashStateTrait { #[inline(always)] fn update(self: HashState, value: felt252) -> HashState { HashState { state: pedersen(self.state, value) } diff --git a/corelib/src/poseidon.cairo b/corelib/src/poseidon.cairo index 360e8f8..9540160 100644 --- a/corelib/src/poseidon.cairo +++ b/corelib/src/poseidon.cairo @@ -1,25 +1,25 @@ -use array::Span; -use array::SpanTrait; -use option::OptionTrait; -use hash::HashStateTrait; +use core::array::Span; +use core::array::SpanTrait; +use core::option::OptionTrait; +use core::hash::HashStateTrait; -extern type Poseidon; +pub extern type Poseidon; -extern fn hades_permutation( +pub extern fn hades_permutation( s0: felt252, s1: felt252, s2: felt252 ) -> (felt252, felt252, felt252) implicits(Poseidon) nopanic; /// State for Poseidon hash. -#[derive(Copy, Drop)] -struct HashState { - s0: felt252, - s1: felt252, - s2: felt252, - odd: bool, +#[derive(Copy, Drop, Debug)] +pub struct HashState { + pub s0: felt252, + pub s1: felt252, + pub s2: felt252, + pub odd: bool, } #[generate_trait] -impl PoseidonImpl of PoseidonTrait { +pub impl PoseidonImpl of PoseidonTrait { /// Creates an initial state. #[inline(always)] fn new() -> HashState { @@ -62,28 +62,26 @@ impl HashStateImpl of HashStateTrait { /// To distinguish between use cases, the capacity element is initialized to 0. /// To distinguish between different input sizes always pads with 1, and possibly with another 0 to /// complete to an even-sized input. -fn poseidon_hash_span(mut span: Span) -> felt252 { - _poseidon_hash_span_inner(get_builtin_costs(), (0, 0, 0), ref span) +pub fn poseidon_hash_span(mut span: Span) -> felt252 { + _poseidon_hash_span_inner(core::gas::get_builtin_costs(), (0, 0, 0), ref span) } /// Helper function for poseidon_hash_span. fn _poseidon_hash_span_inner( - builtin_costs: gas::BuiltinCosts, state: (felt252, felt252, felt252), ref span: Span + builtin_costs: core::gas::BuiltinCosts, + state: (felt252, felt252, felt252), + ref span: Span ) -> felt252 { let (s0, s1, s2) = state; let x = *match span.pop_front() { Option::Some(x) => x, - Option::None => { - return HashState { s0, s1, s2, odd: false }.finalize(); - }, + Option::None => { return HashState { s0, s1, s2, odd: false }.finalize(); }, }; let y = *match span.pop_front() { Option::Some(y) => y, - Option::None => { - return HashState { s0: s0 + x, s1, s2, odd: true }.finalize(); - }, + Option::None => { return HashState { s0: s0 + x, s1, s2, odd: true }.finalize(); }, }; let next_state = hades_permutation(s0 + x, s1 + y, s2); - gas::withdraw_gas_all(builtin_costs).expect('Out of gas'); + core::gas::withdraw_gas_all(builtin_costs).expect('Out of gas'); _poseidon_hash_span_inner(builtin_costs, next_state, ref span) } diff --git a/corelib/src/prelude.cairo b/corelib/src/prelude.cairo new file mode 100644 index 0000000..c82d932 --- /dev/null +++ b/corelib/src/prelude.cairo @@ -0,0 +1,2 @@ +mod v2023_01; +mod v2023_10; diff --git a/corelib/src/prelude/v2023_01.cairo b/corelib/src/prelude/v2023_01.cairo new file mode 100644 index 0000000..d2bf4f2 --- /dev/null +++ b/corelib/src/prelude/v2023_01.cairo @@ -0,0 +1,70 @@ +use core::{ + BoolBitAnd, BoolBitOr, BoolBitXor, BoolFelt252DictValue, BoolIntoFelt252, BoolNot, + BoolPartialEq, BoolSerde, Felt252Add, Felt252AddEq, Felt252Default, Felt252Felt252DictValue, + Felt252Mul, Felt252MulEq, Felt252Neg, Felt252PartialEq, Felt252Serde, Felt252Sub, Felt252SubEq, + Felt252TryIntoNonZero, RangeCheck, SegmentArena, assert, bool, bool_and_impl, bool_not_impl, + bool_or_impl, bool_to_felt252, bool_xor_impl, drop, dup, felt252, felt252_add, felt252_const, + felt252_div, felt252_is_zero, felt252_mul, felt252_sub, never, panic_with_felt252, usize +}; + +use core::{array, array::{Array, ArrayTrait, Span, SpanTrait}}; +use core::{box, box::{Box, BoxTrait}}; +use core::{ + bytes_31, + bytes_31::{ + Bytes31IndexView, Bytes31IntoFelt252, Bytes31Trait, Felt252TryIntoBytes31, bytes31, + bytes31_const + } +}; +use core::{ + byte_array, byte_array::{ByteArray, ByteArrayIndexView, ByteArrayStringLiteral, ByteArrayTrait} +}; +use core::{clone, clone::Clone}; +use core::cmp; +use core::debug; +use core::{ + dict, + dict::{ + Felt252Dict, Felt252DictTrait, SquashedFelt252Dict, felt252_dict_new, felt252_dict_squash + } +}; +use core::{ec, ec::{EcOp, EcPoint, EcState}}; +use core::ecdsa; +use core::{gas, gas::{BuiltinCosts, GasBuiltin, get_builtin_costs}}; +use core::hash; +use core::{ + integer, + integer::{ + Bitwise, Felt252IntoU256, Felt252TryIntoU128, Felt252TryIntoU16, Felt252TryIntoU32, + Felt252TryIntoU64, Felt252TryIntoU8, I128IntoFelt252, I16IntoFelt252, I32IntoFelt252, + I64IntoFelt252, I8IntoFelt252, NumericLiteral, U128IntoFelt252, U16IntoFelt252, + U32IntoFelt252, U64IntoFelt252, U8IntoFelt252, i128, i16, i32, i64, i8, u128, u128_is_zero, + u128_sqrt, u16, u256, u256_sqrt, u32, u64, u8 + } +}; +use core::internal; +use core::keccak; +use core::math; +use core::{nullable, nullable::{Nullable, NullableTrait, match_nullable, null, nullable_from_box}}; +use core::{option, option::{Option, OptionTrait}}; +use core::{panics, panics::{Panic, PanicResult, panic}}; +use core::{pedersen, pedersen::Pedersen}; +use core::{poseidon, poseidon::Poseidon}; +use core::{result, result::{Result, ResultTrait}}; +use core::{serde, serde::Serde}; +use core::{starknet, starknet::System}; +use core::{string, string::StringLiteral}; +use core::testing; +use core::to_byte_array; +use core::{ + traits, + traits::{ + Add, AddEq, BitAnd, BitNot, BitOr, BitXor, Copy, Default, Destruct, Div, DivEq, DivRem, + Drop, Felt252DictValue, Index, IndexView, Into, Mul, MulEq, Neg, Not, PanicDestruct, + PartialEq, PartialOrd, Rem, RemEq, Sub, SubEq, TryInto, TupleSize0Copy, TupleSize0Drop + } +}; +use core::{zeroable, zeroable::{NonZero, Zeroable}}; + +#[cfg(test)] +use core::test; diff --git a/corelib/src/prelude/v2023_10.cairo b/corelib/src/prelude/v2023_10.cairo new file mode 100644 index 0000000..61e714d --- /dev/null +++ b/corelib/src/prelude/v2023_10.cairo @@ -0,0 +1,27 @@ +pub use core::{RangeCheck, SegmentArena, assert, bool, felt252, usize}; + +pub use core::array::{Array, ArrayTrait, Span, SpanTrait}; +pub use core::box::{Box, BoxTrait}; +pub use core::bytes_31::{Bytes31Trait, bytes31}; +pub use core::byte_array::{ByteArray, ByteArrayTrait}; +pub use core::clone::Clone; +pub use core::dict::{Felt252Dict, Felt252DictTrait, SquashedFelt252Dict}; +pub use core::gas::GasBuiltin; +pub use core::integer::{Bitwise, i128, i16, i32, i64, i8, u128, u16, u256, u32, u64, u8}; +pub use core::keccak; +pub use core::math; +pub use core::nullable::{Nullable, NullableTrait}; +pub use core::option::{Option, OptionTrait}; +pub use core::panics::{Panic, PanicResult, panic}; +pub use core::pedersen::Pedersen; +pub use core::poseidon::Poseidon; +pub use core::result::{Result, ResultTrait}; +pub use core::serde::Serde; +pub use core::{starknet, starknet::System}; +pub use core::to_byte_array; +pub use core::traits::{ + Add, AddEq, BitAnd, BitNot, BitOr, BitXor, Copy, Default, Destruct, Div, DivEq, DivRem, Drop, + Felt252DictValue, Index, IndexView, Into, Mul, MulEq, Neg, Not, PanicDestruct, PartialEq, + PartialOrd, Rem, RemEq, Sub, SubEq, TryInto +}; +pub use core::zeroable::NonZero; diff --git a/corelib/src/result.cairo b/corelib/src/result.cairo index 6c0b5c8..b9eb9aa 100644 --- a/corelib/src/result.cairo +++ b/corelib/src/result.cairo @@ -1,35 +1,52 @@ -use array::ArrayTrait; -use serde::Serde; -use array::SpanTrait; +use core::array::ArrayTrait; +use core::serde::Serde; +use core::array::SpanTrait; -#[derive(Copy, Drop, Serde, PartialEq)] -enum Result { +#[must_use] +#[derive(Copy, Drop, Debug, Serde, PartialEq)] +pub enum Result { Ok: T, Err: E, } #[generate_trait] -impl ResultTraitImpl of ResultTrait { +pub impl ResultTraitImpl of ResultTrait { /// If `val` is `Result::Ok(x)`, returns `x`. Otherwise, panics with `err`. - fn expect>(self: Result, err: felt252) -> T { + fn expect<+Drop>(self: Result, err: felt252) -> T { match self { Result::Ok(x) => x, - Result::Err(_) => panic_with_felt252(err), + Result::Err(_) => core::panic_with_felt252(err), } } /// If `val` is `Result::Ok(x)`, returns `x`. Otherwise, panics. - fn unwrap>(self: Result) -> T { + fn unwrap<+Drop>(self: Result) -> T { self.expect('Result::unwrap failed.') } + /// If `val` is `Result::Ok(x)`, returns `x`. Otherwise, returns `default`. + fn unwrap_or<+Drop, +Drop>(self: Result, default: T) -> T { + match self { + Result::Ok(x) => x, + Result::Err(_) => default, + } + } + /// If `val` is `Result::Ok(x)`, returns `x`. + /// Otherwise returns `Default::::default()`. + fn unwrap_or_default<+Drop, +Default>(self: Result) -> T { + match self { + Result::Ok(x) => x, + Result::Err(_) => Default::default(), + } + } + /// If `val` is `Result::Err(x)`, returns `x`. Otherwise, panics with `err`. - fn expect_err>(self: Result, err: felt252) -> E { + fn expect_err<+Drop>(self: Result, err: felt252) -> E { match self { - Result::Ok(_) => panic_with_felt252(err), + Result::Ok(_) => core::panic_with_felt252(err), Result::Err(x) => x, } } /// If `val` is `Result::Err(x)`, returns `x`. Otherwise, panics. - fn unwrap_err>(self: Result) -> E { + fn unwrap_err<+Drop>(self: Result) -> E { self.expect_err('Result::unwrap_err failed.') } /// Returns `true` if the `Result` is `Result::Ok`. @@ -50,7 +67,7 @@ impl ResultTraitImpl of ResultTrait { } /// Returns `true` if the `Result` is `Result::Ok`, and consumes the value. #[inline] - fn into_is_err, impl EDrop: Drop>(self: Result) -> bool { + fn into_is_err<+Drop, +Drop>(self: Result) -> bool { match self { Result::Ok(_) => false, Result::Err(_) => true, @@ -58,7 +75,7 @@ impl ResultTraitImpl of ResultTrait { } /// Returns `true` if the `Result` is `Result::Err`, and consumes the value. #[inline] - fn into_is_ok, impl EDrop: Drop>(self: Result) -> bool { + fn into_is_ok<+Drop, +Drop>(self: Result) -> bool { match self { Result::Ok(_) => true, Result::Err(_) => false, diff --git a/corelib/src/serde.cairo b/corelib/src/serde.cairo index 9d1891a..98b0419 100644 --- a/corelib/src/serde.cairo +++ b/corelib/src/serde.cairo @@ -1,9 +1,7 @@ -use array::ArrayTrait; -use array::SpanTrait; -use traits::Into; -use traits::TryInto; +use core::array::ArrayTrait; +use core::array::SpanTrait; -trait Serde { +pub trait Serde { fn serialize(self: @T, ref output: Array); fn deserialize(ref serialized: Span) -> Option; } @@ -15,44 +13,29 @@ impl TupleSize0Serde of Serde<()> { } } -impl TupleSize1Serde> of Serde<(E0,)> { +impl TupleSize1Serde> of Serde<(E0,)> { fn serialize(self: @(E0,), ref output: Array) { let (e0,) = self; e0.serialize(ref output) } fn deserialize(ref serialized: Span) -> Option<(E0,)> { - Option::Some((E0Serde::deserialize(ref serialized)?,)) + Option::Some((Serde::deserialize(ref serialized)?,)) } } -impl TupleSize2Serde< - E0, - E1, - impl E0Serde: Serde, - impl E0Drop: Drop, - impl E1Serde: Serde, - impl E0Drop: Drop -> of Serde<(E0, E1)> { +impl TupleSize2Serde, +Drop, +Serde, +Drop> of Serde<(E0, E1)> { fn serialize(self: @(E0, E1), ref output: Array) { let (e0, e1) = self; e0.serialize(ref output); e1.serialize(ref output) } fn deserialize(ref serialized: Span) -> Option<(E0, E1)> { - Option::Some((E0Serde::deserialize(ref serialized)?, E1Serde::deserialize(ref serialized)?)) + Option::Some((Serde::deserialize(ref serialized)?, Serde::deserialize(ref serialized)?)) } } impl TupleSize3Serde< - E0, - E1, - E2, - impl E0Serde: Serde, - impl E0Drop: Drop, - impl E1Serde: Serde, - impl E1Drop: Drop, - impl E2Serde: Serde, - impl E2Drop: Drop + E0, E1, E2, +Serde, +Drop, +Serde, +Drop, +Serde, +Drop > of Serde<(E0, E1, E2)> { fn serialize(self: @(E0, E1, E2), ref output: Array) { let (e0, e1, e2) = self; @@ -63,9 +46,9 @@ impl TupleSize3Serde< fn deserialize(ref serialized: Span) -> Option<(E0, E1, E2)> { Option::Some( ( - E0Serde::deserialize(ref serialized)?, - E1Serde::deserialize(ref serialized)?, - E2Serde::deserialize(ref serialized)? + Serde::deserialize(ref serialized)?, + Serde::deserialize(ref serialized)?, + Serde::deserialize(ref serialized)? ) ) } @@ -76,14 +59,14 @@ impl TupleSize4Serde< E1, E2, E3, - impl E0Serde: Serde, - impl E0Drop: Drop, - impl E1Serde: Serde, - impl E1Drop: Drop, - impl E2Serde: Serde, - impl E2Drop: Drop, - impl E3Serde: Serde, - impl E3Drop: Drop + +Serde, + +Drop, + +Serde, + +Drop, + +Serde, + +Drop, + +Serde, + +Drop > of Serde<(E0, E1, E2, E3)> { fn serialize(self: @(E0, E1, E2, E3), ref output: Array) { let (e0, e1, e2, e3) = self; @@ -95,11 +78,31 @@ impl TupleSize4Serde< fn deserialize(ref serialized: Span) -> Option<(E0, E1, E2, E3)> { Option::Some( ( - E0Serde::deserialize(ref serialized)?, - E1Serde::deserialize(ref serialized)?, - E2Serde::deserialize(ref serialized)?, - E3Serde::deserialize(ref serialized)? + Serde::deserialize(ref serialized)?, + Serde::deserialize(ref serialized)?, + Serde::deserialize(ref serialized)?, + Serde::deserialize(ref serialized)? ) ) } } + +/// Impl for `Serde` for types that can be converted into `felt252` using the `Into` trait and from `felt252` using the `TryInto` trait. +/// Usage example: +/// ```ignore +/// impl MyTypeSerde = core::serde::into_felt252_based::SerdeImpl;` +/// ``` +pub mod into_felt252_based { + use core::traits::{Into, TryInto}; + use core::array::ArrayTrait; + pub impl SerdeImpl, +Into, +TryInto> of super::Serde { + #[inline(always)] + fn serialize(self: @T, ref output: Array) { + output.append((*self).into()); + } + #[inline(always)] + fn deserialize(ref serialized: Span) -> Option { + Option::Some((*serialized.pop_front()?).try_into()?) + } + } +} diff --git a/corelib/src/starknet.cairo b/corelib/src/starknet.cairo index 21d3791..f556235 100644 --- a/corelib/src/starknet.cairo +++ b/corelib/src/starknet.cairo @@ -1,22 +1,22 @@ -use box::Box; -use option::OptionTrait; -use array::Span; -use traits::Into; -use traits::TryInto; -use zeroable::Zeroable; +use core::box::Box; +use core::option::OptionTrait; +use core::array::Span; +use core::traits::Into; +use core::traits::TryInto; +use core::zeroable::Zeroable; // Re-imports // Store -mod storage_access; +pub mod storage_access; +pub use storage_access::{Store, StorageAddress}; use storage_access::{ - Store, StorePacking, StorageAddress, StorageBaseAddress, storage_base_address_const, - storage_base_address_from_felt252, storage_address_from_base, - storage_address_from_base_and_offset, storage_address_to_felt252, + StorePacking, StorageBaseAddress, storage_base_address_const, storage_base_address_from_felt252, + storage_address_from_base, storage_address_from_base_and_offset, storage_address_to_felt252, storage_address_try_from_felt252 }; // Module containing all the extern declaration of the syscalls. -mod syscalls; +pub mod syscalls; use syscalls::{ call_contract_syscall, deploy_syscall, emit_event_syscall, get_block_hash_syscall, get_execution_info_syscall, library_call_syscall, send_message_to_l1_syscall, @@ -24,51 +24,61 @@ use syscalls::{ }; // secp256 -mod secp256_trait; -mod secp256k1; -mod secp256r1; +pub mod secp256_trait; +pub mod secp256k1; +pub mod secp256r1; // ContractAddress -mod contract_address; +pub mod contract_address; +pub use contract_address::{ContractAddress, contract_address_const}; use contract_address::{ - ContractAddress, ContractAddressIntoFelt252, Felt252TryIntoContractAddress, - contract_address_const, contract_address_to_felt252, contract_address_try_from_felt252 + ContractAddressIntoFelt252, Felt252TryIntoContractAddress, contract_address_to_felt252, + contract_address_try_from_felt252 }; // EthAddress -mod eth_address; +pub mod eth_address; +pub use eth_address::EthAddress; use eth_address::{ - EthAddress, EthAddressIntoFelt252, EthAddressSerde, EthAddressZeroable, Felt252TryIntoEthAddress + EthAddressIntoFelt252, EthAddressSerde, EthAddressZeroable, Felt252TryIntoEthAddress }; +// EthSignature +pub mod eth_signature; +use eth_signature::verify_eth_signature; + // ClassHash -mod class_hash; +pub mod class_hash; +pub use class_hash::ClassHash; use class_hash::{ - ClassHash, ClassHashIntoFelt252, Felt252TryIntoClassHash, class_hash_const, - class_hash_to_felt252, class_hash_try_from_felt252 + ClassHashIntoFelt252, Felt252TryIntoClassHash, class_hash_const, class_hash_to_felt252, + class_hash_try_from_felt252 }; +// Not `pub` on purpose, only used for direct reexport by the next line. mod info; -use info::{ - ExecutionInfo, BlockInfo, TxInfo, get_execution_info, get_caller_address, get_contract_address, - get_block_info, get_tx_info, get_block_timestamp +pub use info::{ + v2::ExecutionInfo as ExecutionInfo, BlockInfo, v2::TxInfo as TxInfo, get_execution_info, + get_caller_address, get_contract_address, get_block_info, get_tx_info, get_block_timestamp }; -mod event; -use event::Event; +pub mod event; +pub use event::Event; + +pub mod account; +pub use account::AccountContract; -mod account; -use account::AccountContract; +pub mod storage; -extern type System; +pub extern type System; // An Helper function to force the inclusion of `System` in the list of implicits. fn use_system_implicit() implicits(System) {} /// The result type for a syscall. -type SyscallResult = Result>; +pub type SyscallResult = Result>; -trait SyscallResultTrait { +pub trait SyscallResultTrait { /// If `val` is `Result::Ok(x)`, returns `x`. Otherwise, panics with the revert reason. fn unwrap_syscall(self: SyscallResult) -> T; } @@ -82,7 +92,7 @@ impl SyscallResultTraitImpl of SyscallResultTrait { } /// The expected return value of the `__validate*__` functions of an accounted contract. -const VALIDATED: felt252 = 'VALID'; +pub const VALIDATED: felt252 = 'VALID'; // Module for starknet testing only. -mod testing; +pub mod testing; diff --git a/corelib/src/starknet/account.cairo b/corelib/src/starknet/account.cairo index 4765a71..121efff 100644 --- a/corelib/src/starknet/account.cairo +++ b/corelib/src/starknet/account.cairo @@ -1,14 +1,14 @@ use starknet::ContractAddress; -#[derive(Drop, Serde)] -struct Call { - to: ContractAddress, - selector: felt252, - calldata: Array +#[derive(Drop, Serde, Debug)] +pub struct Call { + pub to: ContractAddress, + pub selector: felt252, + pub calldata: Span } #[starknet::interface] -trait AccountContract { +pub trait AccountContract { fn __validate_declare__(self: @TContractState, class_hash: felt252) -> felt252; fn __validate__(ref self: TContractState, calls: Array) -> felt252; fn __execute__(ref self: TContractState, calls: Array) -> Array>; diff --git a/corelib/src/starknet/class_hash.cairo b/corelib/src/starknet/class_hash.cairo index 5d52693..17cdf9f 100644 --- a/corelib/src/starknet/class_hash.cairo +++ b/corelib/src/starknet/class_hash.cairo @@ -1,50 +1,50 @@ -use zeroable::Zeroable; -use serde::Serde; +use core::serde::Serde; +use core::hash::{Hash, HashStateTrait}; #[derive(Copy, Drop)] -extern type ClassHash; +pub extern type ClassHash; +pub extern fn class_hash_const() -> ClassHash nopanic; +pub(crate) extern fn class_hash_to_felt252(address: ClassHash) -> felt252 nopanic; -extern fn class_hash_const() -> ClassHash nopanic; -extern fn class_hash_to_felt252(address: ClassHash) -> felt252 nopanic; - -extern fn class_hash_try_from_felt252( +pub(crate) extern fn class_hash_try_from_felt252( address: felt252 ) -> Option implicits(RangeCheck) nopanic; -impl Felt252TryIntoClassHash of TryInto { +pub(crate) impl Felt252TryIntoClassHash of TryInto { fn try_into(self: felt252) -> Option { class_hash_try_from_felt252(self) } } -impl ClassHashIntoFelt252 of Into { +pub(crate) impl ClassHashIntoFelt252 of Into { fn into(self: ClassHash) -> felt252 { class_hash_to_felt252(self) } } -impl ClassHashZeroable of Zeroable { +impl ClassHashZero of core::num::traits::Zero { fn zero() -> ClassHash { class_hash_const::<0>() } #[inline(always)] - fn is_zero(self: ClassHash) -> bool { - class_hash_to_felt252(self).is_zero() + fn is_zero(self: @ClassHash) -> bool { + core::num::traits::Zero::::is_zero(@class_hash_to_felt252(*self)) } #[inline(always)] - fn is_non_zero(self: ClassHash) -> bool { + fn is_non_zero(self: @ClassHash) -> bool { !self.is_zero() } } -impl ClassHashSerde of serde::Serde { +pub(crate) impl ClassHashZeroable = + core::zeroable::zero_based::ZeroableImpl; + +impl ClassHashSerde of Serde { fn serialize(self: @ClassHash, ref output: Array) { class_hash_to_felt252(*self).serialize(ref output); } fn deserialize(ref serialized: Span) -> Option { - Option::Some( - class_hash_try_from_felt252(serde::Serde::::deserialize(ref serialized)?)? - ) + Option::Some(class_hash_try_from_felt252(Serde::::deserialize(ref serialized)?)?) } } @@ -58,3 +58,8 @@ impl ClassHashPartialEq of PartialEq { !(lhs == rhs) } } + +impl HashClassHash, +Drop> = + core::hash::into_felt252_based::HashImpl; + +impl DebugClassHash = core::fmt::into_felt252_based::DebugImpl; diff --git a/corelib/src/starknet/contract_address.cairo b/corelib/src/starknet/contract_address.cairo index 1e36eb1..c4d7353 100644 --- a/corelib/src/starknet/contract_address.cairo +++ b/corelib/src/starknet/contract_address.cairo @@ -1,51 +1,54 @@ -use zeroable::Zeroable; -use serde::Serde; +use core::zeroable::Zeroable; +use core::serde::Serde; +use core::hash::{Hash, HashStateTrait}; #[derive(Copy, Drop)] -extern type ContractAddress; +pub extern type ContractAddress; -extern fn contract_address_const() -> ContractAddress nopanic; -extern fn contract_address_to_felt252(address: ContractAddress) -> felt252 nopanic; +pub extern fn contract_address_const() -> ContractAddress nopanic; +pub(crate) extern fn contract_address_to_felt252(address: ContractAddress) -> felt252 nopanic; -extern fn contract_address_try_from_felt252( +pub(crate) extern fn contract_address_try_from_felt252( address: felt252 ) -> Option implicits(RangeCheck) nopanic; -impl Felt252TryIntoContractAddress of TryInto { +pub(crate) impl Felt252TryIntoContractAddress of TryInto { fn try_into(self: felt252) -> Option { contract_address_try_from_felt252(self) } } -impl ContractAddressIntoFelt252 of Into { +pub(crate) impl ContractAddressIntoFelt252 of Into { fn into(self: ContractAddress) -> felt252 { contract_address_to_felt252(self) } } -impl ContractAddressZeroable of Zeroable { + +impl ContractAddressZero of core::num::traits::Zero { fn zero() -> ContractAddress { contract_address_const::<0>() } #[inline(always)] - fn is_zero(self: ContractAddress) -> bool { - contract_address_to_felt252(self).is_zero() + fn is_zero(self: @ContractAddress) -> bool { + core::num::traits::Zero::::is_zero(@contract_address_to_felt252(*self)) } #[inline(always)] - fn is_non_zero(self: ContractAddress) -> bool { + fn is_non_zero(self: @ContractAddress) -> bool { !self.is_zero() } } -impl ContractAddressSerde of serde::Serde { +pub(crate) impl ContractAddressZeroable = + core::zeroable::zero_based::ZeroableImpl; + +impl ContractAddressSerde of Serde { fn serialize(self: @ContractAddress, ref output: Array) { contract_address_to_felt252(*self).serialize(ref output); } fn deserialize(ref serialized: Span) -> Option { Option::Some( - contract_address_try_from_felt252( - serde::Serde::::deserialize(ref serialized)? - )? + contract_address_try_from_felt252(Serde::::deserialize(ref serialized)?)? ) } } @@ -60,3 +63,28 @@ impl ContractAddressPartialEq of PartialEq { !(lhs == rhs) } } + +impl ContractAddressPartialOrd of PartialOrd { + fn lt(lhs: ContractAddress, rhs: ContractAddress) -> bool { + // TODO(orizi): Check if implementing a libfunc for `felt252` ordering is more efficient. + let lhs: u256 = contract_address_to_felt252(lhs).into(); + lhs < contract_address_to_felt252(rhs).into() + } + #[inline(always)] + fn le(lhs: ContractAddress, rhs: ContractAddress) -> bool { + !(rhs < lhs) + } + #[inline(always)] + fn gt(lhs: ContractAddress, rhs: ContractAddress) -> bool { + rhs < lhs + } + #[inline(always)] + fn ge(lhs: ContractAddress, rhs: ContractAddress) -> bool { + !(lhs < rhs) + } +} + +impl HashContractAddress, +Drop> = + core::hash::into_felt252_based::HashImpl; + +impl DebugContractAddress = core::fmt::into_felt252_based::DebugImpl; diff --git a/corelib/src/starknet/eth_address.cairo b/corelib/src/starknet/eth_address.cairo index 857bd4a..2053506 100644 --- a/corelib/src/starknet/eth_address.cairo +++ b/corelib/src/starknet/eth_address.cairo @@ -1,16 +1,15 @@ -use debug::PrintTrait; -use integer::{u128_safe_divmod, U128TryIntoNonZero, U256TryIntoFelt252}; -use option::{Option, OptionTrait}; -use serde::Serde; -use traits::{Into, TryInto}; -use zeroable::Zeroable; +use core::debug::PrintTrait; +use core::integer::{u128_safe_divmod, U128TryIntoNonZero, U256TryIntoFelt252}; +use core::option::{Option, OptionTrait}; +use core::serde::Serde; +use core::traits::{Into, TryInto}; // An Ethereum address (160 bits). -#[derive(Copy, Drop, starknet::Store, PartialEq)] -struct EthAddress { +#[derive(Copy, Drop, Hash, PartialEq, starknet::Store)] +pub struct EthAddress { address: felt252, } -impl Felt252TryIntoEthAddress of TryInto { +pub(crate) impl Felt252TryIntoEthAddress of TryInto { fn try_into(self: felt252) -> Option { let ETH_ADDRESS_BOUND = 0x10000000000000000000000000000000000000000_u256; // 2 ** 160 @@ -21,12 +20,12 @@ impl Felt252TryIntoEthAddress of TryInto { } } } -impl EthAddressIntoFelt252 of Into { +pub(crate) impl EthAddressIntoFelt252 of Into { fn into(self: EthAddress) -> felt252 { self.address } } -impl U256IntoEthAddress of Into { +pub(crate) impl U256IntoEthAddress of Into { fn into(self: u256) -> EthAddress { // The Ethereum address is the 20 least significant bytes (=160=128+32 bits) of the value. let high_32_bits = self.high % 0x100000000_u128; @@ -36,7 +35,7 @@ impl U256IntoEthAddress of Into { } } } -impl EthAddressSerde of Serde { +pub(crate) impl EthAddressSerde of Serde { fn serialize(self: @EthAddress, ref output: Array) { self.address.serialize(ref output); } @@ -44,22 +43,27 @@ impl EthAddressSerde of Serde { Serde::::deserialize(ref serialized)?.try_into() } } -impl EthAddressZeroable of Zeroable { +impl EthAddressZero of core::num::traits::Zero { fn zero() -> EthAddress { 0.try_into().unwrap() } #[inline(always)] - fn is_zero(self: EthAddress) -> bool { - self.address.is_zero() + fn is_zero(self: @EthAddress) -> bool { + core::num::traits::Zero::::is_zero(self.address) } #[inline(always)] - fn is_non_zero(self: EthAddress) -> bool { + fn is_non_zero(self: @EthAddress) -> bool { !self.is_zero() } } -impl EthAddressPrintImpl of PrintTrait { +pub(crate) impl EthAddressZeroable = + core::zeroable::zero_based::ZeroableImpl; + +pub(crate) impl EthAddressPrintImpl of PrintTrait { fn print(self: EthAddress) { self.address.print(); } } + +impl DebugEthAddress = core::fmt::into_felt252_based::DebugImpl; diff --git a/corelib/src/starknet/eth_signature.cairo b/corelib/src/starknet/eth_signature.cairo new file mode 100644 index 0000000..eaa91f3 --- /dev/null +++ b/corelib/src/starknet/eth_signature.cairo @@ -0,0 +1,59 @@ +use core::option::OptionTrait; +use starknet::{ + EthAddress, + secp256_trait::{ + Secp256Trait, Secp256PointTrait, recover_public_key, is_signature_entry_valid, Signature + }, + secp256k1::Secp256k1Point, SyscallResult, SyscallResultTrait +}; +use core::keccak::keccak_u256s_be_inputs; + +/// Asserts that an Ethereum signature is valid w.r.t. a given Eth address +/// Also verifies that r and s components of the signature are in the range (0, N), +/// where N is the size of the curve. +pub fn verify_eth_signature(msg_hash: u256, signature: Signature, eth_address: EthAddress) { + match is_eth_signature_valid(:msg_hash, :signature, :eth_address) { + Result::Ok(()) => {}, + Result::Err(err) => core::panic_with_felt252(err), + } +} + +/// Asserts that an Ethereum signature is valid w.r.t. a given Eth address +/// Also verifies that r and s components of the signature are in the range (0, N), +/// where N is the size of the curve. +/// Returns a Result with an error string if the signature is invalid. +pub fn is_eth_signature_valid( + msg_hash: u256, signature: Signature, eth_address: EthAddress +) -> Result<(), felt252> { + if !is_signature_entry_valid::(signature.r) { + return Result::Err('Signature out of range'); + } + if !is_signature_entry_valid::(signature.s) { + return Result::Err('Signature out of range'); + } + + let public_key_point = recover_public_key::(:msg_hash, :signature).unwrap(); + let calculated_eth_address = public_key_point_to_eth_address(:public_key_point); + if eth_address != calculated_eth_address { + return Result::Err('Invalid signature'); + } + Result::Ok(()) +} + +/// Converts a public key point to the corresponding Ethereum address. +pub fn public_key_point_to_eth_address< + Secp256Point, +Drop, +Secp256Trait, +Secp256PointTrait +>( + public_key_point: Secp256Point +) -> EthAddress { + let (x, y) = public_key_point.get_coordinates().unwrap_syscall(); + + // Keccak output is little endian. + let point_hash_le = keccak_u256s_be_inputs(array![x, y].span()); + let point_hash = u256 { + low: core::integer::u128_byte_reverse(point_hash_le.high), + high: core::integer::u128_byte_reverse(point_hash_le.low) + }; + + point_hash.into() +} diff --git a/corelib/src/starknet/event.cairo b/corelib/src/starknet/event.cairo index 3689932..157ca97 100644 --- a/corelib/src/starknet/event.cairo +++ b/corelib/src/starknet/event.cairo @@ -1,8 +1,8 @@ -trait Event { +pub trait Event { fn append_keys_and_data(self: @T, ref keys: Array, ref data: Array); fn deserialize(ref keys: Span, ref data: Span) -> Option; } -trait EventEmitter { - fn emit>(ref self: T, event: S); +pub trait EventEmitter { + fn emit>(ref self: T, event: S); } diff --git a/corelib/src/starknet/info.cairo b/corelib/src/starknet/info.cairo index cd8a888..631db1b 100644 --- a/corelib/src/starknet/info.cairo +++ b/corelib/src/starknet/info.cairo @@ -2,70 +2,132 @@ use starknet::{ SyscallResultTrait, SyscallResult, syscalls::get_execution_info_syscall, contract_address::ContractAddress }; -use box::BoxTrait; +use core::box::BoxTrait; -#[derive(Copy, Drop)] -struct ExecutionInfo { - block_info: Box, - tx_info: Box, - caller_address: ContractAddress, - contract_address: ContractAddress, - entry_point_selector: felt252, +#[derive(Copy, Drop, Debug)] +pub struct ExecutionInfo { + pub block_info: Box, + pub tx_info: Box, + pub caller_address: ContractAddress, + pub contract_address: ContractAddress, + pub entry_point_selector: felt252, } -#[derive(Copy, Drop, Serde)] -struct BlockInfo { - block_number: u64, - block_timestamp: u64, - sequencer_address: ContractAddress, +#[derive(Copy, Drop, Debug, Serde)] +pub struct BlockInfo { + pub block_number: u64, + pub block_timestamp: u64, + pub sequencer_address: ContractAddress, } -#[derive(Copy, Drop, Serde)] -struct TxInfo { +#[derive(Copy, Drop, Debug, Serde)] +pub struct TxInfo { // The version of the transaction. It is fixed (currently, 1) in the OS, and should be // signed by the account contract. // This field allows invalidating old transactions, whenever the meaning of the other // transaction fields is changed (in the OS). - version: felt252, + pub version: felt252, // The account contract from which this transaction originates. - account_contract_address: ContractAddress, + pub account_contract_address: ContractAddress, // The max_fee field of the transaction. - max_fee: u128, + pub max_fee: u128, // The signature of the transaction. - signature: Span, + pub signature: Span, // The hash of the transaction. - transaction_hash: felt252, + pub transaction_hash: felt252, // The identifier of the chain. // This field can be used to prevent replay of testnet transactions on mainnet. - chain_id: felt252, + pub chain_id: felt252, // The transaction's nonce. - nonce: felt252, + pub nonce: felt252, } -fn get_execution_info() -> Box { - get_execution_info_syscall().unwrap_syscall() +pub fn get_execution_info() -> Box { + starknet::syscalls::get_execution_info_v2_syscall().unwrap_syscall() } -fn get_caller_address() -> ContractAddress { +pub fn get_caller_address() -> ContractAddress { get_execution_info().unbox().caller_address } -fn get_contract_address() -> ContractAddress { +pub fn get_contract_address() -> ContractAddress { get_execution_info().unbox().contract_address } -fn get_block_info() -> Box { +pub fn get_block_info() -> Box { get_execution_info().unbox().block_info } -fn get_tx_info() -> Box { +pub fn get_tx_info() -> Box { get_execution_info().unbox().tx_info } -fn get_block_timestamp() -> u64 { +pub fn get_block_timestamp() -> u64 { get_block_info().unbox().block_timestamp } -fn get_block_number() -> u64 { +pub fn get_block_number() -> u64 { get_block_info().unbox().block_number } + +/// The extended version of the `get_execution_info` syscall result. +pub mod v2 { + use starknet::contract_address::ContractAddress; + use super::BlockInfo; + + #[derive(Copy, Drop, Debug)] + pub struct ExecutionInfo { + pub block_info: Box, + pub tx_info: Box, + pub caller_address: ContractAddress, + pub contract_address: ContractAddress, + pub entry_point_selector: felt252, + } + + #[derive(Copy, Drop, Debug, Serde)] + pub struct TxInfo { + // The version of the transaction. It is fixed (currently, 1) in the OS, and should be + // signed by the account contract. + // This field allows invalidating old transactions, whenever the meaning of the other + // transaction fields is changed (in the OS). + pub version: felt252, + // The account contract from which this transaction originates. + pub account_contract_address: ContractAddress, + // The max_fee field of the transaction. + pub max_fee: u128, + // The signature of the transaction. + pub signature: Span, + // The hash of the transaction. + pub transaction_hash: felt252, + // The identifier of the chain. + // This field can be used to prevent replay of testnet transactions on mainnet. + pub chain_id: felt252, + // The transaction's nonce. + pub nonce: felt252, + // A span of ResourceBounds structs. + pub resource_bounds: Span, + // The tip. + pub tip: u128, + // If specified, the paymaster should pay for the execution of the tx. + // The data includes the address of the paymaster sponsoring the transaction, followed by + // extra data to send to the paymaster. + pub paymaster_data: Span, + // The data availability mode for the nonce. + pub nonce_data_availability_mode: u32, + // The data availability mode for the account balance from which fee will be taken. + pub fee_data_availability_mode: u32, + // If nonempty, will contain the required data for deploying and initializing an account + // contract: its class hash, address salt and constructor calldata. + pub account_deployment_data: Span, + } + + #[derive(Copy, Drop, Debug, Serde)] + pub struct ResourceBounds { + // The name of the resource. + pub resource: felt252, + // The maximum amount of the resource allowed for usage during the execution. + pub max_amount: u64, + // The maximum price the user is willing to pay for the resource unit. + pub max_price_per_unit: u128, + } +} diff --git a/corelib/src/starknet/secp256_trait.cairo b/corelib/src/starknet/secp256_trait.cairo index 72db7e7..1fda813 100644 --- a/corelib/src/starknet/secp256_trait.cairo +++ b/corelib/src/starknet/secp256_trait.cairo @@ -1,21 +1,20 @@ -use array::ArrayTrait; -use keccak::keccak_u256s_be_inputs; -use math::{u256_mul_mod_n, inv_mod}; -use option::OptionTrait; +use core::array::ArrayTrait; +use core::math::{u256_mul_mod_n, u256_inv_mod}; +use core::option::OptionTrait; use starknet::{eth_address::U256IntoEthAddress, EthAddress, SyscallResult, SyscallResultTrait}; -use traits::{Into, TryInto}; -use integer::U256TryIntoNonZero; +use core::traits::{Into, TryInto}; +use core::integer::U256TryIntoNonZero; /// Secp256{k/r}1 ECDSA signature. -#[derive(Copy, Drop, PartialEq, Serde, starknet::Store)] -struct Signature { - r: u256, - s: u256, +#[derive(Copy, Drop, Debug, PartialEq, Serde, starknet::Store, Hash)] +pub struct Signature { + pub r: u256, + pub s: u256, // The parity of the y coordinate of the ec point whose x coordinate is `r`. // `y_parity` == true means that the y coordinate is odd. // Some places use non boolean v instead of y_parity. // In that case, `signature_from_vrs` should be used. - y_parity: bool, + pub y_parity: bool, } @@ -23,11 +22,11 @@ struct Signature { /// `v` is the sum of an odd number and the parity of the y coordinate of the ec point whose x /// coordinate is `r`. /// See https://eips.ethereum.org/EIPS/eip-155 for more details. -fn signature_from_vrs(v: u32, r: u256, s: u256) -> Signature { +pub fn signature_from_vrs(v: u32, r: u256, s: u256) -> Signature { Signature { r, s, y_parity: v % 2 == 0 } } -trait Secp256Trait { +pub trait Secp256Trait { fn get_curve_size() -> u256; fn get_generator_point() -> Secp256Point; @@ -37,20 +36,55 @@ trait Secp256Trait { ) -> SyscallResult>; } -trait Secp256PointTrait { +pub trait Secp256PointTrait { fn get_coordinates(self: Secp256Point) -> SyscallResult<(u256, u256)>; fn add(self: Secp256Point, other: Secp256Point) -> SyscallResult; fn mul(self: Secp256Point, scalar: u256) -> SyscallResult; } +/// Checks whether `value` is in the range [1, N), where N is the size of the curve. +pub fn is_signature_entry_valid< + Secp256Point, +Drop, impl Secp256Impl: Secp256Trait +>( + value: u256 +) -> bool { + value != 0_u256 && value < Secp256Impl::get_curve_size() +} + +pub fn is_valid_signature< + Secp256Point, + +Drop, + impl Secp256Impl: Secp256Trait, + +Secp256PointTrait +>( + msg_hash: u256, r: u256, s: u256, public_key: Secp256Point +) -> bool { + if !is_signature_entry_valid::(r) + || !is_signature_entry_valid::(s) { + return false; + } + + let n_nz = Secp256Impl::get_curve_size().try_into().unwrap(); + let s_inv = u256_inv_mod(s.try_into().unwrap(), n_nz).unwrap().into(); + let u1 = u256_mul_mod_n(msg_hash, s_inv, n_nz); + let u2 = u256_mul_mod_n(r, s_inv, n_nz); + + let generator_point = Secp256Impl::get_generator_point(); + let point1 = generator_point.mul(u1).unwrap_syscall(); + let point2 = public_key.mul(u2).unwrap_syscall(); + let sum = point1.add(point2).unwrap_syscall(); + + let (x, _y) = sum.get_coordinates().unwrap_syscall(); + x == r +} /// Receives a signature and the signed message hash. /// Returns the public key associated with the signer, represented as a point on the curve. -fn recover_public_key< +pub fn recover_public_key< Secp256Point, - impl Secp256PointDrop: Drop, + +Drop, impl Secp256Impl: Secp256Trait, - impl Secp256PointImpl: Secp256PointTrait + +Secp256PointTrait >( msg_hash: u256, signature: Signature ) -> Option { @@ -64,7 +98,7 @@ fn recover_public_key< // where the divisions by `r` are modulo `N` (the size of the curve). let n_nz = Secp256Impl::get_curve_size().try_into().unwrap(); - let r_inv = inv_mod(r.try_into().unwrap(), n_nz).unwrap(); + let r_inv = u256_inv_mod(r.try_into().unwrap(), n_nz).unwrap().into(); let u1 = u256_mul_mod_n(msg_hash, r_inv, n_nz); let minus_u1 = secp256_ec_negate_scalar::(u1); @@ -79,88 +113,9 @@ fn recover_public_key< /// Computes the negation of a scalar modulo N (the size of the curve). fn secp256_ec_negate_scalar< - Secp256Point, - impl Secp256PointDrop: Drop, - impl Secp256Impl: Secp256Trait + Secp256Point, +Drop, impl Secp256Impl: Secp256Trait >( c: u256 ) -> u256 { Secp256Impl::get_curve_size() - c } - - -/// Checks a Secp256 ECDSA signature. -/// Also verifies that r and s components of the signature are in the range (0, N), -/// where N is the size of the curve. -/// Returns a Result with an error string if the signature is invalid. -fn is_eth_signature_valid< - Secp256Point, - impl Secp256PointDrop: Drop, - impl Secp256Impl: Secp256Trait, - impl Secp256PointImpl: Secp256PointTrait ->( - msg_hash: u256, signature: Signature, eth_address: EthAddress -) -> Result<(), felt252> { - if !is_signature_entry_valid::(signature.r) { - return Result::Err('Signature out of range'); - } - if !is_signature_entry_valid::(signature.s) { - return Result::Err('Signature out of range'); - } - - let public_key_point = recover_public_key::(:msg_hash, :signature).unwrap(); - let calculated_eth_address = public_key_point_to_eth_address(:public_key_point); - if eth_address != calculated_eth_address { - return Result::Err('Invalid signature'); - } - Result::Ok(()) -} - -/// Asserts that a Secp256 ECDSA signature is valid. -/// Also verifies that r and s components of the signature are in the range (0, N), -/// where N is the size of the curve. -fn verify_eth_signature< - Secp256Point, - impl Secp256PointDrop: Drop, - impl Secp256Impl: Secp256Trait, - impl Secp256PointImpl: Secp256PointTrait ->( - msg_hash: u256, signature: Signature, eth_address: EthAddress -) { - match is_eth_signature_valid::(:msg_hash, :signature, :eth_address) { - Result::Ok(()) => {}, - Result::Err(err) => panic_with_felt252(err), - } -} - -/// Checks whether `value` is in the range [1, N), where N is the size of the curve. -fn is_signature_entry_valid< - Secp256Point, - impl Secp256PointDrop: Drop, - impl Secp256Impl: Secp256Trait ->( - value: u256 -) -> bool { - value != 0_u256 && value < Secp256Impl::get_curve_size() -} - -/// Converts a public key point to the corresponding Ethereum address. -fn public_key_point_to_eth_address< - Secp256Point, - impl Secp256PointDrop: Drop, - impl Secp256Impl: Secp256Trait, - impl Secp256PointImpl: Secp256PointTrait ->( - public_key_point: Secp256Point -) -> EthAddress { - let (x, y) = public_key_point.get_coordinates().unwrap_syscall(); - - // Keccak output is little endian. - let point_hash_le = keccak_u256s_be_inputs(array![x, y].span()); - let point_hash = u256 { - low: integer::u128_byte_reverse(point_hash_le.high), - high: integer::u128_byte_reverse(point_hash_le.low) - }; - - point_hash.into() -} diff --git a/corelib/src/starknet/secp256k1.cairo b/corelib/src/starknet/secp256k1.cairo index 7030844..a3a4f24 100644 --- a/corelib/src/starknet/secp256k1.cairo +++ b/corelib/src/starknet/secp256k1.cairo @@ -1,15 +1,18 @@ //! This module contains functions and constructs related to elliptic curve operations on the //! secp256k1 curve. -use option::OptionTrait; +use core::option::OptionTrait; use starknet::{ - EthAddress, secp256_trait::{Secp256Trait, Secp256PointTrait}, SyscallResult, SyscallResultTrait + secp256_trait::{ + Secp256Trait, Secp256PointTrait, recover_public_key, is_signature_entry_valid, Signature + }, + SyscallResult, SyscallResultTrait }; #[derive(Copy, Drop)] -extern type Secp256k1Point; +pub extern type Secp256k1Point; -impl Secp256k1Impl of Secp256Trait { +pub(crate) impl Secp256k1Impl of Secp256Trait { // TODO(yuval): change to constant once u256 constants are supported. fn get_curve_size() -> u256 { 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141 @@ -34,7 +37,7 @@ impl Secp256k1Impl of Secp256Trait { } } -impl Secp256k1PointImpl of Secp256PointTrait { +pub(crate) impl Secp256k1PointImpl of Secp256PointTrait { fn get_coordinates(self: Secp256k1Point) -> SyscallResult<(u256, u256)> { secp256k1_get_xy_syscall(self) } diff --git a/corelib/src/starknet/secp256r1.cairo b/corelib/src/starknet/secp256r1.cairo index 65fdfcc..362fe79 100644 --- a/corelib/src/starknet/secp256r1.cairo +++ b/corelib/src/starknet/secp256r1.cairo @@ -1,15 +1,15 @@ //! This module contains functions and constructs related to elliptic curve operations on the //! secp256r1 curve. -use option::OptionTrait; +use core::option::OptionTrait; use starknet::{ EthAddress, secp256_trait::{Secp256Trait, Secp256PointTrait}, SyscallResult, SyscallResultTrait }; #[derive(Copy, Drop)] -extern type Secp256r1Point; +pub extern type Secp256r1Point; -impl Secp256r1Impl of Secp256Trait { +pub(crate) impl Secp256r1Impl of Secp256Trait { // TODO(yuval): change to constant once u256 constants are supported. fn get_curve_size() -> u256 { 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551 @@ -34,7 +34,7 @@ impl Secp256r1Impl of Secp256Trait { } } -impl Secp256r1PointImpl of Secp256PointTrait { +pub(crate) impl Secp256r1PointImpl of Secp256PointTrait { fn get_coordinates(self: Secp256r1Point) -> SyscallResult<(u256, u256)> { secp256r1_get_xy_syscall(self) } diff --git a/corelib/src/starknet/storage.cairo b/corelib/src/starknet/storage.cairo new file mode 100644 index 0000000..ac2dabc --- /dev/null +++ b/corelib/src/starknet/storage.cairo @@ -0,0 +1,71 @@ +/// Trait for getting the address of any contract/component storage member. +pub trait StorageMemberAddressTrait { + fn address(self: @TMemberState) -> starknet::StorageBaseAddress nopanic; +} + +/// Trait for accessing any contract/component storage member. +pub trait StorageMemberAccessTrait { + fn read(self: @TMemberState) -> TValue; + fn write(ref self: TMemberState, value: TValue); +} + +/// Implementation of StorageMemberAccessTrait for types that implement StorageMemberAddressTrait. +pub impl StorageMemberAccessImpl< + TMemberState, + TValue, + +StorageMemberAddressTrait, + +starknet::Store, + +Drop, +> of StorageMemberAccessTrait { + fn read(self: @TMemberState) -> TValue { + // Only address_domain 0 is currently supported. + let address_domain = 0_u32; + starknet::SyscallResultTrait::unwrap_syscall( + starknet::Store::::read(address_domain, self.address()) + ) + } + fn write(ref self: TMemberState, value: TValue) { + // Only address_domain 0 is currently supported. + let address_domain = 0_u32; + let write_result = starknet::Store::::write(address_domain, self.address(), value); + starknet::SyscallResultTrait::unwrap_syscall(write_result) + } +} + +/// Trait for getting the address of any contract/component mapping storage member. +pub trait StorageMapMemberAddressTrait { + fn address(self: @TMemberState, key: TKey) -> starknet::StorageBaseAddress; +} + +/// Trait for accessing any contract/component storage member. +pub trait StorageMapMemberAccessTrait { + fn read(self: @TMemberState, key: TKey) -> TValue; + fn write(ref self: TMemberState, key: TKey, value: TValue); +} + +/// Implementation of StorageMapMemberAccessTrait for types that implement +/// StorageMapMemberAddressTrait. +pub impl StorageMapMemberAccessImpl< + TMemberState, + TKey, + TValue, + +StorageMapMemberAddressTrait, + +starknet::Store, + +Drop, + +PanicDestruct, +> of StorageMapMemberAccessTrait { + fn read(self: @TMemberState, key: TKey) -> TValue { + // Only address_domain 0 is currently supported. + let address_domain = 0_u32; + starknet::SyscallResultTrait::unwrap_syscall( + starknet::Store::::read(address_domain, self.address(key)) + ) + } + fn write(ref self: TMemberState, key: TKey, value: TValue) { + // Only address_domain 0 is currently supported. + let address_domain = 0_u32; + starknet::SyscallResultTrait::unwrap_syscall( + starknet::Store::::write(address_domain, self.address(key), value) + ) + } +} diff --git a/corelib/src/starknet/storage_access.cairo b/corelib/src/starknet/storage_access.cairo index 8cbae63..ad88367 100644 --- a/corelib/src/starknet/storage_access.cairo +++ b/corelib/src/starknet/storage_access.cairo @@ -1,33 +1,35 @@ use core::array::ArrayTrait; -use traits::{Into, TryInto}; -use option::OptionTrait; +use core::traits::{Into, TryInto}; +use core::option::OptionTrait; +use core::byte_array::ByteArrayTrait; +use core::bytes_31::BYTES_IN_BYTES31; use starknet::{ SyscallResult, syscalls::{storage_read_syscall, storage_write_syscall}, contract_address::{ContractAddress, Felt252TryIntoContractAddress, ContractAddressIntoFelt252}, class_hash::{ClassHash, Felt252TryIntoClassHash, ClassHashIntoFelt252} }; -use serde::Serde; +use core::serde::Serde; #[derive(Copy, Drop)] -extern type StorageAddress; +pub extern type StorageAddress; #[derive(Copy, Drop)] -extern type StorageBaseAddress; +pub extern type StorageBaseAddress; // Storage. -extern fn storage_base_address_const() -> StorageBaseAddress nopanic; -extern fn storage_base_address_from_felt252( +pub extern fn storage_base_address_const() -> StorageBaseAddress nopanic; +pub extern fn storage_base_address_from_felt252( addr: felt252 ) -> StorageBaseAddress implicits(RangeCheck) nopanic; -extern fn storage_address_to_felt252(address: StorageAddress) -> felt252 nopanic; -extern fn storage_address_from_base_and_offset( +pub(crate) extern fn storage_address_to_felt252(address: StorageAddress) -> felt252 nopanic; +pub extern fn storage_address_from_base_and_offset( base: StorageBaseAddress, offset: u8 ) -> StorageAddress nopanic; -extern fn storage_address_from_base(base: StorageBaseAddress) -> StorageAddress nopanic; +pub extern fn storage_address_from_base(base: StorageBaseAddress) -> StorageAddress nopanic; -extern fn storage_address_try_from_felt252( +pub(crate) extern fn storage_address_try_from_felt252( address: felt252 ) -> Option implicits(RangeCheck) nopanic; @@ -42,31 +44,49 @@ impl StorageAddressIntoFelt252 of Into { } } -impl StorageAddressSerde of serde::Serde { +impl StorageAddressSerde of Serde { fn serialize(self: @StorageAddress, ref output: Array) { storage_address_to_felt252(*self).serialize(ref output); } fn deserialize(ref serialized: Span) -> Option { Option::Some( - storage_address_try_from_felt252(serde::Serde::::deserialize(ref serialized)?)? + storage_address_try_from_felt252(Serde::::deserialize(ref serialized)?)? ) } } -trait Store { +impl DebugStorageAddress = core::fmt::into_felt252_based::DebugImpl; +impl DebugStorageBaseAddress of core::fmt::Debug { + fn fmt(self: @StorageBaseAddress, ref f: core::fmt::Formatter) -> Result<(), core::fmt::Error> { + DebugStorageAddress::fmt(@storage_address_from_base(*self), ref f) + } +} + +/// Trait for types that can be used as a value in Starknet storage variables. +pub trait Store { + /// Reads a value from storage from domain `address_domain` and base address `base`. fn read(address_domain: u32, base: StorageBaseAddress) -> SyscallResult; + /// Writes a value to storage to domain `address_domain` and base address `base`. fn write(address_domain: u32, base: StorageBaseAddress, value: T) -> SyscallResult<()>; + /// Reads a value from storage from domain `address_domain` and base address `base` at offset + /// `offset`. fn read_at_offset( address_domain: u32, base: StorageBaseAddress, offset: u8 ) -> SyscallResult; + /// Writes a value to storage to domain `address_domain` and base address `base` at offset + /// `offset`. fn write_at_offset( address_domain: u32, base: StorageBaseAddress, offset: u8, value: T ) -> SyscallResult<()>; fn size() -> u8; } -trait StorePacking { +/// Trait for easier implementation of `Store` used for packing and unpacking values into values +/// that already implement `Store`, and having `Store` implemented using this conversion. +pub trait StorePacking { + /// Packs a value of type `T` into a value of type `PackedT`. fn pack(value: T) -> PackedT; + /// Unpacks a value of type `PackedT` into a value of type `T`. fn unpack(value: PackedT) -> T; } @@ -128,295 +148,163 @@ impl StoreFelt252 of Store { } } -impl StoreBool of Store { - fn read(address_domain: u32, base: StorageBaseAddress) -> SyscallResult { - Result::Ok(Store::::read(address_domain, base)? != 0) - } - #[inline(always)] - fn write(address_domain: u32, base: StorageBaseAddress, value: bool) -> SyscallResult<()> { - Store::::write(address_domain, base, if value { - 1 - } else { - 0 - }) +impl StorePackingBool of StorePacking { + fn pack(value: bool) -> felt252 { + value.into() } - #[inline(always)] - fn read_at_offset( - address_domain: u32, base: StorageBaseAddress, offset: u8 - ) -> SyscallResult { - Result::Ok(Store::::read_at_offset(address_domain, base, offset)? != 0) - } - #[inline(always)] - fn write_at_offset( - address_domain: u32, base: StorageBaseAddress, offset: u8, value: bool - ) -> SyscallResult<()> { - Store::::write_at_offset(address_domain, base, offset, if value { - 1 - } else { - 0 - }) - } - #[inline(always)] - fn size() -> u8 { - 1_u8 + #[inline] + fn unpack(value: felt252) -> bool { + value != 0 } } -impl StoreU8 of Store { - fn read(address_domain: u32, base: StorageBaseAddress) -> SyscallResult { - Result::Ok( - Store::::read(address_domain, base)?.try_into().expect('StoreU8 - non u8') - ) - } - #[inline(always)] - fn write(address_domain: u32, base: StorageBaseAddress, value: u8) -> SyscallResult<()> { - Store::::write(address_domain, base, value.into()) - } - #[inline(always)] - fn read_at_offset( - address_domain: u32, base: StorageBaseAddress, offset: u8 - ) -> SyscallResult { - Result::Ok( - Store::::read_at_offset(address_domain, base, offset)? - .try_into() - .expect('StoreU8 - non u8') - ) - } - #[inline(always)] - fn write_at_offset( - address_domain: u32, base: StorageBaseAddress, offset: u8, value: u8 - ) -> SyscallResult<()> { - Store::::write_at_offset(address_domain, base, offset, value.into()) +impl StorePackingU8 of StorePacking { + fn pack(value: u8) -> felt252 { + value.into() } - #[inline(always)] - fn size() -> u8 { - 1_u8 + #[inline] + fn unpack(value: felt252) -> u8 { + value.try_into().expect('StoreU8 - non u8') } } -impl StoreU16 of Store { - fn read(address_domain: u32, base: StorageBaseAddress) -> SyscallResult { - Result::Ok( - Store::::read(address_domain, base)?.try_into().expect('StoreU16 - non u16') - ) +impl StorePackingI8 of StorePacking { + fn pack(value: i8) -> felt252 { + value.into() } - #[inline(always)] - fn write(address_domain: u32, base: StorageBaseAddress, value: u16) -> SyscallResult<()> { - Store::::write(address_domain, base, value.into()) + #[inline] + fn unpack(value: felt252) -> i8 { + value.try_into().expect('StoreI8 - non i8') } - #[inline(always)] - fn read_at_offset( - address_domain: u32, base: StorageBaseAddress, offset: u8 - ) -> SyscallResult { - Result::Ok( - Store::::read_at_offset(address_domain, base, offset)? - .try_into() - .expect('StoreU16 - non u16') - ) - } - #[inline(always)] - fn write_at_offset( - address_domain: u32, base: StorageBaseAddress, offset: u8, value: u16 - ) -> SyscallResult<()> { - Store::::write_at_offset(address_domain, base, offset, value.into()) +} + +impl StorePackingU16 of StorePacking { + fn pack(value: u16) -> felt252 { + value.into() } - #[inline(always)] - fn size() -> u8 { - 1_u8 + #[inline] + fn unpack(value: felt252) -> u16 { + value.try_into().expect('StoreU16 - non u16') } } -impl StoreU32 of Store { - fn read(address_domain: u32, base: StorageBaseAddress) -> SyscallResult { - Result::Ok( - Store::::read(address_domain, base)?.try_into().expect('StoreU32 - non u32') - ) +impl StorePackingI16 of StorePacking { + fn pack(value: i16) -> felt252 { + value.into() } - #[inline(always)] - fn write(address_domain: u32, base: StorageBaseAddress, value: u32) -> SyscallResult<()> { - Store::::write(address_domain, base, value.into()) - } - #[inline(always)] - fn read_at_offset( - address_domain: u32, base: StorageBaseAddress, offset: u8 - ) -> SyscallResult { - Result::Ok( - Store::::read_at_offset(address_domain, base, offset)? - .try_into() - .expect('StoreU32 - non u32') - ) + #[inline] + fn unpack(value: felt252) -> i16 { + value.try_into().expect('StoreI16 - non i16') } - #[inline(always)] - fn write_at_offset( - address_domain: u32, base: StorageBaseAddress, offset: u8, value: u32 - ) -> SyscallResult<()> { - Store::::write_at_offset(address_domain, base, offset, value.into()) +} + +impl StorePackingU32 of StorePacking { + fn pack(value: u32) -> felt252 { + value.into() } - #[inline(always)] - fn size() -> u8 { - 1_u8 + #[inline] + fn unpack(value: felt252) -> u32 { + value.try_into().expect('StoreU32 - non u32') } } -impl StoreU64 of Store { - fn read(address_domain: u32, base: StorageBaseAddress) -> SyscallResult { - Result::Ok( - Store::::read(address_domain, base)?.try_into().expect('StoreU64 - non u64') - ) +impl StorePackingI32 of StorePacking { + fn pack(value: i32) -> felt252 { + value.into() } - #[inline(always)] - fn write(address_domain: u32, base: StorageBaseAddress, value: u64) -> SyscallResult<()> { - Store::::write(address_domain, base, value.into()) - } - #[inline(always)] - fn read_at_offset( - address_domain: u32, base: StorageBaseAddress, offset: u8 - ) -> SyscallResult { - Result::Ok( - Store::::read_at_offset(address_domain, base, offset)? - .try_into() - .expect('StoreU64 - non u64') - ) + #[inline] + fn unpack(value: felt252) -> i32 { + value.try_into().expect('StoreI32 - non i32') } - #[inline(always)] - fn write_at_offset( - address_domain: u32, base: StorageBaseAddress, offset: u8, value: u64 - ) -> SyscallResult<()> { - Store::::write_at_offset(address_domain, base, offset, value.into()) +} + +impl StorePackingU64 of StorePacking { + fn pack(value: u64) -> felt252 { + value.into() } - #[inline(always)] - fn size() -> u8 { - 1_u8 + #[inline] + fn unpack(value: felt252) -> u64 { + value.try_into().expect('StoreU64 - non u64') } } -impl StoreU128 of Store { - fn read(address_domain: u32, base: StorageBaseAddress) -> SyscallResult { - Result::Ok( - Store::::read(address_domain, base)?.try_into().expect('StoreU128 - non u128') - ) +impl StorePackingI64 of StorePacking { + fn pack(value: i64) -> felt252 { + value.into() } - #[inline(always)] - fn write(address_domain: u32, base: StorageBaseAddress, value: u128) -> SyscallResult<()> { - Store::::write(address_domain, base, value.into()) + #[inline] + fn unpack(value: felt252) -> i64 { + value.try_into().expect('StoreI64 - non i64') } - #[inline(always)] - fn read_at_offset( - address_domain: u32, base: StorageBaseAddress, offset: u8 - ) -> SyscallResult { - Result::Ok( - Store::::read_at_offset(address_domain, base, offset)? - .try_into() - .expect('StoreU128 - non u128') - ) - } - #[inline(always)] - fn write_at_offset( - address_domain: u32, base: StorageBaseAddress, offset: u8, value: u128 - ) -> SyscallResult<()> { - Store::::write_at_offset(address_domain, base, offset, value.into()) +} + +impl StorePackingU128 of StorePacking { + fn pack(value: u128) -> felt252 { + value.into() } - #[inline(always)] - fn size() -> u8 { - 1_u8 + #[inline] + fn unpack(value: felt252) -> u128 { + value.try_into().expect('StoreU128 - non u128') } } -impl StoreStorageAddress of Store { - fn read(address_domain: u32, base: StorageBaseAddress) -> SyscallResult { - Result::Ok( - Store::::read(address_domain, base)?.try_into().expect('Non StorageAddress') - ) - } - #[inline(always)] - fn write( - address_domain: u32, base: StorageBaseAddress, value: StorageAddress - ) -> SyscallResult<()> { - Store::::write(address_domain, base, value.into()) +impl StorePackingI128 of StorePacking { + fn pack(value: i128) -> felt252 { + value.into() } - #[inline(always)] - fn read_at_offset( - address_domain: u32, base: StorageBaseAddress, offset: u8 - ) -> SyscallResult { - Result::Ok( - Store::::read_at_offset(address_domain, base, offset)? - .try_into() - .expect('Non StorageAddress') - ) + #[inline] + fn unpack(value: felt252) -> i128 { + value.try_into().expect('StoreI128 - non i128') } - #[inline(always)] - fn write_at_offset( - address_domain: u32, base: StorageBaseAddress, offset: u8, value: StorageAddress - ) -> SyscallResult<()> { - Store::::write_at_offset(address_domain, base, offset, value.into()) +} + +impl StorePackingBytes31 of StorePacking { + fn pack(value: bytes31) -> felt252 { + value.into() } - #[inline(always)] - fn size() -> u8 { - 1_u8 + #[inline] + fn unpack(value: felt252) -> bytes31 { + value.try_into().expect('StoreBytes31 - non bytes31') } } -impl StoreContractAddress of Store { - fn read(address_domain: u32, base: StorageBaseAddress) -> SyscallResult { - Result::Ok( - Store::::read(address_domain, base)?.try_into().expect('Non ContractAddress') - ) - } - #[inline(always)] - fn write( - address_domain: u32, base: StorageBaseAddress, value: ContractAddress - ) -> SyscallResult<()> { - Store::::write(address_domain, base, value.into()) +impl StorePackingNonZero>> of StorePacking, T> { + fn pack(value: NonZero) -> T { + value.into() } - #[inline(always)] - fn read_at_offset( - address_domain: u32, base: StorageBaseAddress, offset: u8 - ) -> SyscallResult { - Result::Ok( - Store::::read_at_offset(address_domain, base, offset)? - .try_into() - .expect('Non ContractAddress') - ) + #[inline] + fn unpack(value: T) -> NonZero { + value.try_into().expect('StoreNonZero - zero value') } - #[inline(always)] - fn write_at_offset( - address_domain: u32, base: StorageBaseAddress, offset: u8, value: ContractAddress - ) -> SyscallResult<()> { - Store::::write_at_offset(address_domain, base, offset, value.into()) +} + +impl StorePackingStorageAddress of StorePacking { + fn pack(value: StorageAddress) -> felt252 { + value.into() } - #[inline(always)] - fn size() -> u8 { - 1_u8 + #[inline] + fn unpack(value: felt252) -> StorageAddress { + value.try_into().expect('Non StorageAddress') } } -impl StoreClassHash of Store { - fn read(address_domain: u32, base: StorageBaseAddress) -> SyscallResult { - Result::Ok(Store::::read(address_domain, base)?.try_into().expect('Non ClassHash')) +impl StorePackingContractAddress of StorePacking { + fn pack(value: ContractAddress) -> felt252 { + value.into() } - #[inline(always)] - fn write(address_domain: u32, base: StorageBaseAddress, value: ClassHash) -> SyscallResult<()> { - Store::::write(address_domain, base, value.into()) - } - #[inline(always)] - fn read_at_offset( - address_domain: u32, base: StorageBaseAddress, offset: u8 - ) -> SyscallResult { - Result::Ok( - Store::::read_at_offset(address_domain, base, offset)? - .try_into() - .expect('Non ClassHash') - ) + #[inline] + fn unpack(value: felt252) -> ContractAddress { + value.try_into().expect('Non ContractAddress') } - #[inline(always)] - fn write_at_offset( - address_domain: u32, base: StorageBaseAddress, offset: u8, value: ClassHash - ) -> SyscallResult<()> { - Store::::write_at_offset(address_domain, base, offset, value.into()) +} + +impl StorePackingClassHash of StorePacking { + fn pack(value: ClassHash) -> felt252 { + value.into() } - #[inline(always)] - fn size() -> u8 { - 1_u8 + #[inline] + fn unpack(value: felt252) -> ClassHash { + value.try_into().expect('Non ClassHash') } } @@ -447,7 +335,7 @@ impl TupleSize0Store of Store<()> { } } -impl TupleSize1Store, impl E0Drop: Drop> of Store<(E0,)> { +impl TupleSize1Store, +Drop> of Store<(E0,)> { #[inline(always)] fn read(address_domain: u32, base: StorageBaseAddress) -> SyscallResult<(E0,)> { Result::Ok((E0Store::read(address_domain, base)?,)) @@ -477,12 +365,7 @@ impl TupleSize1Store, impl E0Drop: Drop> of Stor } impl TupleSize2Store< - E0, - E1, - impl E0Store: Store, - impl E0Drop: Drop, - impl E1Store: Store, - impl E0Drop: Drop + E0, E1, impl E0Store: Store, +Drop, impl E1Store: Store, +Drop > of Store<(E0, E1)> { #[inline(always)] fn read(address_domain: u32, base: StorageBaseAddress) -> SyscallResult<(E0, E1)> { @@ -525,11 +408,11 @@ impl TupleSize3Store< E1, E2, impl E0Store: Store, - impl E0Drop: Drop, + +Drop, impl E1Store: Store, - impl E1Drop: Drop, + +Drop, impl E2Store: Store, - impl E2Drop: Drop + +Drop > of Store<(E0, E1, E2)> { #[inline(always)] fn read(address_domain: u32, base: StorageBaseAddress) -> SyscallResult<(E0, E1, E2)> { @@ -585,13 +468,13 @@ impl TupleSize4Store< E2, E3, impl E0Store: Store, - impl E0Drop: Drop, + +Drop, impl E1Store: Store, - impl E1Drop: Drop, + +Drop, impl E2Store: Store, - impl E2Drop: Drop, + +Drop, impl E3Store: Store, - impl E3Drop: Drop + +Drop > of Store<(E0, E1, E2, E3)> { #[inline(always)] fn read(address_domain: u32, base: StorageBaseAddress) -> SyscallResult<(E0, E1, E2, E3)> { @@ -649,10 +532,7 @@ impl TupleSize4Store< } } - -impl ResultStore< - T, E, impl TStore: Store, impl EStore: Store, impl TDrop: Drop, impl EDrop: Drop, -> of Store> { +impl ResultStore, +Store, +Drop, +Drop> of Store> { #[inline(always)] fn read(address_domain: u32, base: StorageBaseAddress) -> SyscallResult> { let idx = Store::::read(address_domain, base)?; @@ -719,11 +599,11 @@ impl ResultStore< } #[inline(always)] fn size() -> u8 { - 1 + cmp::max(Store::::size(), Store::::size()) + 1 + core::cmp::max(Store::::size(), Store::::size()) } } -impl OptionStore, impl TDrop: Drop,> of Store> { +impl OptionStore, +Drop,> of Store> { #[inline(always)] fn read(address_domain: u32, base: StorageBaseAddress) -> SyscallResult> { let idx = Store::::read(address_domain, base)?; @@ -732,7 +612,7 @@ impl OptionStore, impl TDrop: Drop,> of Store