From fe72ee0e95cf9f1761cfdc0759af12a68294c081 Mon Sep 17 00:00:00 2001 From: Pedro Fontana Date: Thu, 21 Dec 2023 18:35:07 -0300 Subject: [PATCH] Use `starknet-types-core` `Felt` (#1408) * Initial swap * Misc changes * Misc changes * Add felt_to_biguint util * Misc changes * Move to_signed_felt to math_utils * Fix code * Fix code * Fix code * Remove felt crate * Remove felt crate * Restore felt_str macro + other changes * Fix parsing utils * Add changes * Add changes * Add fixes * Add fixes * Add fixes * Add fixes * Fix maybe_add_padding * Pad bytes in keccak hints * Fix bigint to felt conversion * Restore tests * Fix test * Fix recover_y * Fix biguint to felt conversion * Fix is_addr_bounded hint * Fix test * Make safe_div safe again * Fix negative number parsing in felt_str * Revert "Fix negative number parsing in felt_str" This reverts commit 3feb9a268249d639c073a28ea4ccb5185ca503aa. * Remove negative handling in deserialization util * Fix byte conversions in keccak auto-deduction * Update felt commit * Remove felt crate * Fix EC OP tests * Fix sqrt * Fix unsafe keccak hints * fix keccak integration test * Fix deserialize_scientific_notation * Fix error when deserializing big numbers * cargo clippy * fix merge main changes * Improve Add<&Felt252> for Relocatable * Indicate type-rs commit * Fix merge conflicts * Update type-rs commit * Fix wasm and hint accountant imports (#1436) * Add import for string * Cargo fmt * Update air_public_input.rs --------- Co-authored-by: juan.mv * Bump commit * Fix felt display * Fix deps for fuzzing (#1432) * Fix deps for fuzzing * Revert stark-felt import change * Cargo fmt * Merge use-felt --------- Co-authored-by: juan.mv * cargo clippy * fix bench/criterion_benchmark.rs * cargo clippy in fuzzer * Remove lambdaworks-felt workflows * Missed a spot * Remove dep in ensure-no_std * don't create an extra implicit feature (slows down build checks) * air public memory is hex * Remove old import * Remove panic handler * improve find_element_hint * Restore MaybeRelocatable formatting * stark-felt no-default-features * more feature work * Update types-rs * Update RELEASE docs * Update stark-felt, expect slowdown here * Remove double import * Clippy * changelog * fix fuzzer * cargo.lock * Faster split * faster bitwise * clippy * clippy * Use vec of powers of 2 * address comments * remove special features * Apply suggestion Co-authored-by: fmoletta <99273364+fmoletta@users.noreply.github.com> * add todo * fix build * unwrap_or_default * nostd * clippy * typo codecov cache * codecov cache typo * Update type-rs commit * Update fuzzer/Cargo.lock * Use starknet-types-core to 0.0.3 v * Empty-Commit * Empty-Commit * Update starknet-types-core version * n_elms_iter: u32 * fix warnings * Include extensive-hints in coverage * fix stuff * Update Changelog * Update Changelog --------- Co-authored-by: Federica Co-authored-by: Juan-M-V <102986292+Juan-M-V@users.noreply.github.com> Co-authored-by: juan.mv Co-authored-by: Mario Rugiero Co-authored-by: Mario Rugiero Co-authored-by: fmoletta <99273364+fmoletta@users.noreply.github.com> Co-authored-by: Edgar --- .github/workflows/publish.yml | 8 - .github/workflows/rust.yml | 40 +- CHANGELOG.md | 4 +- Cargo.lock | 126 +- Cargo.toml | 5 - RELEASE.md | 3 +- bench/criterion_benchmark.rs | 40 +- cairo-vm-cli/Cargo.toml | 3 +- cairo1-run/Cargo.toml | 3 +- cairo1-run/src/main.rs | 27 +- ensure-no_std/Cargo.toml | 14 - ensure-no_std/src/main.rs | 2 +- examples/custom_hint/src/main.rs | 2 +- felt/Cargo.toml | 32 - felt/proptest-regressions/lib.txt | 9 - felt/src/arbitrary_bigint_felt.rs | 58 - felt/src/arbitrary_lambdaworks.rs | 47 - felt/src/bigint_felt.rs | 1220 ------------ felt/src/lib.rs | 42 - felt/src/lib_bigint_felt.rs | 1719 ---------------- felt/src/lib_lambdaworks.rs | 1770 ----------------- fuzzer/Cargo.lock | 457 ++--- fuzzer/Cargo.toml | 4 +- fuzzer/src/cairo_compiled_programs_fuzzer.rs | 17 +- fuzzer/src/fuzz_json.rs | 31 +- fuzzer/src/py_export.rs | 4 +- vm/Cargo.toml | 15 +- vm/src/air_public_input.rs | 10 +- vm/src/cairo_run.rs | 8 +- .../builtin_hint_processor/bigint.rs | 16 +- .../builtin_hint_processor/blake2s_utils.rs | 78 +- .../builtin_hint_processor_definition.rs | 23 +- .../cairo_keccak/keccak_hints.rs | 58 +- .../builtin_hint_processor/ec_utils.rs | 183 +- .../field_arithmetic.rs | 2 +- .../find_element_hint.rs | 85 +- .../builtin_hint_processor/garaga.rs | 16 +- .../builtin_hint_processor/hint_utils.rs | 4 +- .../builtin_hint_processor/keccak_utils.rs | 59 +- .../builtin_hint_processor/math_utils.rs | 368 ++-- .../memcpy_hint_utils.rs | 4 +- .../builtin_hint_processor/memset_utils.rs | 20 +- .../builtin_hint_processor/poseidon_utils.rs | 4 +- .../builtin_hint_processor/pow_utils.rs | 18 +- .../builtin_hint_processor/print.rs | 9 +- .../secp/bigint_utils.rs | 41 +- .../builtin_hint_processor/secp/ec_utils.rs | 42 +- .../secp/field_utils.rs | 19 +- .../builtin_hint_processor/secp/secp_utils.rs | 5 +- .../builtin_hint_processor/secp/signature.rs | 18 +- .../builtin_hint_processor/set.rs | 12 +- .../builtin_hint_processor/sha256_utils.rs | 22 +- .../squash_dict_utils.rs | 173 +- .../builtin_hint_processor/uint256_utils.rs | 95 +- .../builtin_hint_processor/uint384.rs | 44 +- .../uint384_extension.rs | 9 +- .../builtin_hint_processor/uint_utils.rs | 9 +- .../builtin_hint_processor/usort.rs | 19 +- .../vrf/inv_mod_p_uint512.rs | 45 +- .../cairo_1_hint_processor/dict_manager.rs | 5 +- .../cairo_1_hint_processor/hint_processor.rs | 138 +- .../hint_processor_utils.rs | 32 +- .../hint_processor_definition.rs | 2 +- vm/src/hint_processor/hint_processor_utils.rs | 13 +- vm/src/lib.rs | 4 +- vm/src/math_utils/mod.rs | 116 +- vm/src/serde/deserialize_program.rs | 117 +- vm/src/serde/deserialize_utils.rs | 20 +- vm/src/serde/serialize_program.rs | 2 +- .../cairo_1_run_from_entrypoint_tests.rs | 8 +- vm/src/tests/cairo_pie_test.rs | 15 +- vm/src/tests/mod.rs | 4 +- ...un_deprecated_contract_class_simplified.rs | 113 +- vm/src/types/errors/math_errors.rs | 5 +- vm/src/types/errors/program_errors.rs | 4 +- vm/src/types/exec_scope.rs | 35 +- vm/src/types/instruction.rs | 10 +- vm/src/types/program.rs | 48 +- vm/src/types/relocatable.rs | 170 +- vm/src/utils.rs | 96 +- vm/src/vm/context/run_context.rs | 4 +- vm/src/vm/errors/hint_errors.rs | 13 +- vm/src/vm/errors/memory_errors.rs | 2 +- vm/src/vm/errors/runner_errors.rs | 2 +- vm/src/vm/errors/vm_errors.rs | 2 +- vm/src/vm/hooks.rs | 2 +- vm/src/vm/runners/builtin_runner/bitwise.rs | 69 +- vm/src/vm/runners/builtin_runner/ec_op.rs | 226 +-- vm/src/vm/runners/builtin_runner/hash.rs | 23 +- vm/src/vm/runners/builtin_runner/keccak.rs | 68 +- vm/src/vm/runners/builtin_runner/poseidon.rs | 17 +- .../vm/runners/builtin_runner/range_check.rs | 14 +- vm/src/vm/runners/builtin_runner/signature.rs | 28 +- vm/src/vm/runners/cairo_pie.rs | 7 +- vm/src/vm/runners/cairo_runner.rs | 117 +- vm/src/vm/security.rs | 27 +- vm/src/vm/vm_core.rs | 365 ++-- vm/src/vm/vm_memory/memory.rs | 81 +- vm/src/vm/vm_memory/memory_segments.rs | 48 +- 99 files changed, 2060 insertions(+), 7232 deletions(-) delete mode 100644 felt/Cargo.toml delete mode 100644 felt/proptest-regressions/lib.txt delete mode 100644 felt/src/arbitrary_bigint_felt.rs delete mode 100644 felt/src/arbitrary_lambdaworks.rs delete mode 100644 felt/src/bigint_felt.rs delete mode 100644 felt/src/lib.rs delete mode 100644 felt/src/lib_bigint_felt.rs delete mode 100644 felt/src/lib_lambdaworks.rs diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f8f5c9b81a..f4ea9e2193 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -14,14 +14,6 @@ jobs: uses: actions/checkout@v2 - name: Install stable toolchain uses: dtolnay/rust-toolchain@1.70.0 - - name: Publish crate cairo-felt - env: - CRATES_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} - run: cargo publish --token ${CRATES_TOKEN} --all-features --manifest-path ./felt/Cargo.toml - # FIXME: there should be a better way to make sure the index in crates.io is updated before publishing - # cairo-vm but right now the step throws timeout and fails. - - name: wait for index in crates.io - run: sleep 300 - name: Publish crate cairo-vm env: CRATES_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index a5ff5b1350..007caee4ee 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -187,12 +187,6 @@ jobs: fail-on-cache-miss: true # NOTE: we do this separately because --workspace operates in weird ways - - name: Check all features (felt) - run: | - cd felt - cargo check-all-features - cargo check-all-features --workspace --all-targets - - name: Check all features (vm) run: | cd vm @@ -218,7 +212,7 @@ jobs: strategy: fail-fast: false matrix: - special_features: ["", "lambdaworks-felt", "extensive_hints"] + special_features: ["", "extensive_hints"] target: [ test#1, test#2, test#3, test#4, test-no_std#1, test-no_std#2, test-no_std#3, test-no_std#4, test-wasm ] name: Run tests runs-on: ubuntu-22.04 @@ -445,38 +439,38 @@ jobs: path: lcov-test-no_std-.info key: codecov-cache-test-no_std--${{ github.sha }} fail-on-cache-miss: true - - - name: Fetch results for tests with stdlib (w/lambdaworks; part. 1) + - name: Fetch results for tests with stdlib (w/extensive_hints; part. 1) uses: actions/cache/restore@v3 with: - path: lcov-test#1-lambdaworks-felt.info - key: codecov-cache-test#1-lambdaworks-felt-${{ github.sha }} + path: lcov-test#1-extensive_hints.info + key: codecov-cache-test#1-extensive_hints-${{ github.sha }} fail-on-cache-miss: true - - name: Fetch results for tests with stdlib (w/lambdaworks; part. 2) + - name: Fetch results for tests with stdlib (w/extensive_hints; part. 2) uses: actions/cache/restore@v3 with: - path: lcov-test#2-lambdaworks-felt.info - key: codecov-cache-test#2-lambdaworks-felt-${{ github.sha }} + path: lcov-test#2-extensive_hints.info + key: codecov-cache-test#2-extensive_hints-${{ github.sha }} fail-on-cache-miss: true - - name: Fetch results for tests with stdlib (w/lambdaworks; part. 3) + - name: Fetch results for tests with stdlib (w/extensive_hints; part. 3) uses: actions/cache/restore@v3 with: - path: lcov-test#3-lambdaworks-felt.info - key: codecov-cache-test#3-lambdaworks-felt-${{ github.sha }} + path: lcov-test#3-extensive_hints.info + key: codecov-cache-test#3-extensive_hints-${{ github.sha }} fail-on-cache-miss: true - - name: Fetch results for tests with stdlib (w/lambdaworks; part. 4) + - name: Fetch results for tests with stdlib (w/extensive_hints; part. 4) uses: actions/cache/restore@v3 with: - path: lcov-test#4-lambdaworks-felt.info - key: codecov-cache-test#4-lambdaworks-felt-${{ github.sha }} + path: lcov-test#4-extensive_hints.info + key: codecov-cache-test#4-extensive_hints-${{ github.sha }} fail-on-cache-miss: true - - name: Fetch results for tests without stdlib (w/lambdaworks) + - name: Fetch results for tests without stdlib (w/extensive_hints) uses: actions/cache/restore@v3 with: - path: lcov-test-no_std-lambdaworks-felt.info - key: codecov-cache-test-no_std-lambdaworks-felt-${{ github.sha }} + path: lcov-no_std-extensive_hints.info + key: codecov-cache-test-no_std-extensive_hints-${{ github.sha }} fail-on-cache-miss: true + - name: Upload coverage to codecov.io uses: codecov/codecov-action@v3 with: diff --git a/CHANGELOG.md b/CHANGELOG.md index 135feac92b..b627a8f9eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,9 @@ #### Upcoming Changes -* feat/BREAKING: Add Cairo 1 proof mode compilation and execution [#1517] (https://github.com/lambdaclass/cairo-vm/pull/1517) +* feat(BREAKING): Replace `cairo-felt` crate with `starknet-types-core` [#1408](https://github.com/lambdaclass/cairo-vm/pull/1408) + +* feat(BREAKING): Add Cairo 1 proof mode compilation and execution [#1517] (https://github.com/lambdaclass/cairo-vm/pull/1517) * In the cairo1-run crate, now the Cairo 1 Programs are compiled and executed in proof-mode * BREAKING: Remove `CairoRunner.proof_mode: bool` field and replace it with `CairoRunner.runner_mode: RunnerMode` diff --git a/Cargo.lock b/Cargo.lock index 54f18a5b90..2306a67d0f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -194,15 +194,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" -[[package]] -name = "atomic-polyfill" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ff7eb3f316534d83a8a2c3d1674ace8a5a71198eba31e2e2b597833f699b28" -dependencies = [ - "critical-section", -] - [[package]] name = "autocfg" version = "1.1.0" @@ -278,12 +269,6 @@ 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" @@ -297,21 +282,6 @@ dependencies = [ "serde", ] -[[package]] -name = "cairo-felt" -version = "0.9.1" -dependencies = [ - "arbitrary", - "lambdaworks-math", - "lazy_static", - "num-bigint", - "num-integer", - "num-traits 0.2.17", - "proptest", - "rstest", - "serde", -] - [[package]] name = "cairo-lang-casm" version = "2.3.1" @@ -609,7 +579,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da74c7c4a2df66b961a982396e0f5221d6594266aed48c76d8c22d5b0d96af5d" dependencies = [ "assert_matches", - "cairo-felt 0.8.7", + "cairo-felt", "cairo-lang-casm", "cairo-lang-sierra", "cairo-lang-sierra-ap-change", @@ -640,7 +610,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9217e979f11980609d13d3a5adea8438ec9345709ddfebca975cc9cd1f85201e" dependencies = [ "anyhow", - "cairo-felt 0.8.7", + "cairo-felt", "cairo-lang-casm", "cairo-lang-compiler", "cairo-lang-defs", @@ -721,7 +691,6 @@ dependencies = [ "assert_matches", "bincode", "bitvec", - "cairo-felt 0.9.1", "cairo-lang-casm", "cairo-lang-starknet", "criterion", @@ -745,6 +714,7 @@ dependencies = [ "sha2", "sha3", "starknet-crypto", + "starknet-types-core", "thiserror-no-std", "wasm-bindgen-test", ] @@ -980,12 +950,6 @@ dependencies = [ "itertools 0.10.5", ] -[[package]] -name = "critical-section" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" - [[package]] name = "crossbeam-deque" version = "0.8.3" @@ -1027,9 +991,9 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-bigint" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28f85c3514d2a6e64160359b45a3918c3b4178bcbf4ae5d03ab2d02e521c479a" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array", "subtle", @@ -1323,15 +1287,6 @@ version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" -[[package]] -name = "hash32" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" -dependencies = [ - "byteorder", -] - [[package]] name = "hashbrown" version = "0.12.3" @@ -1352,19 +1307,6 @@ dependencies = [ "serde", ] -[[package]] -name = "heapless" -version = "0.7.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db04bc24a18b9ea980628ecf00e6c0264f3c1426dac36c00cb49b6fbad8b0743" -dependencies = [ - "atomic-polyfill", - "hash32", - "rustc_version", - "spin 0.9.8", - "stable_deref_trait", -] - [[package]] name = "heck" version = "0.3.3" @@ -1563,13 +1505,9 @@ dependencies = [ [[package]] name = "lambdaworks-math" -version = "0.1.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66ebb7299e567bbc393b50eef9de8db7728605567b7e5cc31634e34b4c8875ba" -dependencies = [ - "heapless", - "rand", -] +checksum = "540c0715d7da472edc421ceca702d3f3a716b3b9168b6211f2e3939cb14c863c" [[package]] name = "lazy_static" @@ -1577,7 +1515,7 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" dependencies = [ - "spin 0.5.2", + "spin", ] [[package]] @@ -1728,7 +1666,6 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" dependencies = [ - "arbitrary", "autocfg", "num-integer", "num-traits 0.2.17", @@ -2224,9 +2161,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.24" +version = "0.38.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ad981d6c340a49cdc40a1028d9c6084ec7e9fa33fcb839cab656a267071e234" +checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" dependencies = [ "bitflags 2.4.1", "errno", @@ -2342,18 +2279,18 @@ checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" [[package]] name = "serde" -version = "1.0.192" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.192" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", @@ -2448,15 +2385,6 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" -dependencies = [ - "lock_api", -] - [[package]] name = "sprs" version = "0.7.1" @@ -2468,12 +2396,6 @@ dependencies = [ "num-traits 0.1.43", ] -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - [[package]] name = "starknet-crypto" version = "0.6.1" @@ -2526,6 +2448,22 @@ dependencies = [ "hex", ] +[[package]] +name = "starknet-types-core" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b4af540664e3dec02f36a47b79ba4df825a7752bf0941954f69753a98a397e" +dependencies = [ + "arbitrary", + "bitvec", + "lambdaworks-math", + "lazy_static", + "num-bigint", + "num-integer", + "num-traits 0.2.17", + "serde", +] + [[package]] name = "string_cache" version = "0.8.7" @@ -2710,9 +2648,9 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unescaper" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a96a44ae11e25afb520af4534fd7b0bd8cd613e35a78def813b8cf41631fa3c8" +checksum = "d8f0f68e58d297ba8b22b8b5a96a87b863ba6bb46aaf51e19a4b02c5a6dd5b7f" dependencies = [ "thiserror", ] diff --git a/Cargo.toml b/Cargo.toml index b11e683eec..0f897a2ce7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,6 @@ [workspace] members = [ "cairo-vm-cli", - "felt", "vm", "hint_accountant", "examples/wasm-demo", @@ -9,7 +8,6 @@ members = [ ] default-members = [ "cairo-vm-cli", - "felt", "vm", "cairo1-run", ] @@ -28,9 +26,6 @@ readme = "README.md" keywords = ["starknet", "cairo", "vm", "wasm", "no_std"] [workspace.dependencies] -felt = { package = "cairo-felt", path = "./felt", version = "0.9.1", default-features = false, features = [ - "alloc", -] } cairo-vm = { path = "./vm", version = "0.9.1", default-features = false } mimalloc = { version = "0.1.37", default-features = false } num-bigint = { version = "0.4", default-features = false, features = [ diff --git a/RELEASE.md b/RELEASE.md index ef514d4f86..9490e687c6 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -12,7 +12,7 @@ `git checkout -b release-N` - [ ] Update the version field in the package entry of `Cargo.toml` files. - The versions must be the same. - - You need to update the workspace dependencies `felt` and `cairo-vm`, which + - You need to update the workspace dependency `cairo-vm`, which you can find in the root cargo manifest under the section `[workspace.dependencies]`. - [Here](https://github.com/lambdaclass/cairo-rs/pull/1301/files) is an example pull request with these changes. @@ -30,7 +30,6 @@ - [ ] Verify all the crates are available on crates.io with the correct versions. - [cairo-vm](https://crates.io/crates/cairo-vm) - - [cairo-felt](https://crates.io/crates/cairo-felt) - [ ] Create a release in Github. - Select the recently created tag. - Set the title to the version string. diff --git a/bench/criterion_benchmark.rs b/bench/criterion_benchmark.rs index 764bb42f70..d1f4029a4f 100644 --- a/bench/criterion_benchmark.rs +++ b/bench/criterion_benchmark.rs @@ -1,10 +1,8 @@ use cairo_vm::{ - felt::Felt252, types::program::Program, vm::{runners::cairo_runner::CairoRunner, vm_core::VirtualMachine}, }; -use criterion::{black_box, criterion_group, criterion_main, BatchSize, BenchmarkId, Criterion}; -use num_traits::Zero; +use criterion::{black_box, criterion_group, criterion_main, BatchSize, Criterion}; #[cfg(feature = "with_mimalloc")] use mimalloc::MiMalloc; @@ -60,39 +58,5 @@ fn load_program_data(c: &mut Criterion) { }); } -fn add_u64_with_felt252(c: &mut Criterion) { - // There are 9 possible cases: - // - The felt is `0` - // - The felt is `-1` and the result in range - // - The felt is `-1` but the result is out of range (the u64 is `0`) - // - The felt is positive and the result in range - // - The felt is positive and the result is out of range - // - The felt is `> u64::MAX` which always causes to be out of range - // - The felt is `<= -2` and the result is in range - // - The felt is `<= -2` and the result is out of range - // - The felt is `< -u64::MAX` which always causes to be out of range - // I consider all of these cases because branching is the most likely - // bottleneck here. - let cases = [ - (1u64, Felt252::zero()), - (1u64, Felt252::from(-1i128)), - (0u64, Felt252::from(-1i128)), - (0u64, Felt252::from(1i128)), - (1u64, Felt252::from(u64::MAX as i128)), - (0u64, Felt252::from(u64::MAX as i128 + 1i128)), - (2u64, Felt252::from(-2i128)), - (1u64, Felt252::from(-2i128)), - (0u64, Felt252::from(-(u64::MAX as i128) - 1i128)), - ]; - let mut group = c.benchmark_group("add_u64_with_felt"); - for (i, case) in cases.iter().enumerate() { - group.bench_with_input(BenchmarkId::from_parameter(i), case, |b, (lhs, rhs)| { - b.iter(|| *lhs + rhs); - }); - } - group.finish(); -} - -criterion_group!(felt, add_u64_with_felt252); criterion_group!(runner, build_many_runners, load_program_data, parse_program); -criterion_main!(felt, runner); +criterion_main!(runner); diff --git a/cairo-vm-cli/Cargo.toml b/cairo-vm-cli/Cargo.toml index 39509886b2..572c4db8af 100644 --- a/cairo-vm-cli/Cargo.toml +++ b/cairo-vm-cli/Cargo.toml @@ -21,5 +21,4 @@ rstest = "0.17.0" [features] default = ["with_mimalloc"] -with_mimalloc = ["cairo-vm/with_mimalloc", "mimalloc"] -lambdaworks-felt = ["cairo-vm/lambdaworks-felt"] +with_mimalloc = ["cairo-vm/with_mimalloc", "dep:mimalloc"] diff --git a/cairo1-run/Cargo.toml b/cairo1-run/Cargo.toml index 85b98e3927..34138ce983 100644 --- a/cairo1-run/Cargo.toml +++ b/cairo1-run/Cargo.toml @@ -29,5 +29,4 @@ mimalloc = { version = "0.1.37", default-features = false, optional = true } [features] default = ["with_mimalloc"] -with_mimalloc = ["cairo-vm/with_mimalloc", "mimalloc"] -lambdaworks-felt = ["cairo-vm/lambdaworks-felt"] +with_mimalloc = ["cairo-vm/with_mimalloc", "dep:mimalloc"] diff --git a/cairo1-run/src/main.rs b/cairo1-run/src/main.rs index 2100e6680e..2518d2af6e 100644 --- a/cairo1-run/src/main.rs +++ b/cairo1-run/src/main.rs @@ -40,6 +40,7 @@ use cairo_vm::serde::deserialize_program::BuiltinName; use cairo_vm::serde::deserialize_program::{ApTracking, FlowTrackingData, HintParams}; use cairo_vm::types::errors::program_errors::ProgramError; use cairo_vm::types::relocatable::Relocatable; +use cairo_vm::utils::bigint_to_felt; use cairo_vm::vm::decoding::decoder::decode_instruction; use cairo_vm::vm::errors::cairo_run_errors::CairoRunError; use cairo_vm::vm::errors::memory_errors::MemoryError; @@ -48,13 +49,13 @@ use cairo_vm::vm::errors::trace_errors::TraceError; use cairo_vm::vm::errors::vm_errors::VirtualMachineError; use cairo_vm::vm::runners::cairo_runner::RunnerMode; use cairo_vm::{ - felt::Felt252, serde::deserialize_program::ReferenceManager, types::{program::Program, relocatable::MaybeRelocatable}, vm::{ runners::cairo_runner::{CairoRunner, RunResources}, vm_core::VirtualMachine, }, + Felt252, }; use clap::{CommandFactory, Parser, ValueHint}; use itertools::{chain, Itertools}; @@ -237,7 +238,7 @@ fn run(args: impl Iterator) -> Result, Erro let data: Vec = instructions .flat_map(|inst| inst.assemble().encode()) - .map(Felt252::from) + .map(|x| bigint_to_felt(&x).unwrap_or_default()) .map(MaybeRelocatable::from) .collect(); @@ -311,7 +312,7 @@ fn run(args: impl Iterator) -> Result, Erro (panic_data_end - panic_data_start).map_err(VirtualMachineError::Math)?, )?; return Err(Error::RunPanic( - panic_data.iter().map(|c| c.as_ref().clone()).collect(), + panic_data.iter().map(|c| *c.as_ref()).collect(), )); } else { if return_values.len() < 3 { @@ -383,7 +384,7 @@ fn main() -> Result<(), Error> { .iter() .map(|m| { // Try to parse to utf8 string - let msg = String::from_utf8(m.to_be_bytes().to_vec()); + let msg = String::from_utf8(m.to_bytes_be().to_vec()); if let Ok(msg) = msg { format!("{} ('{}')", m, msg) } else { @@ -651,9 +652,13 @@ mod tests { #![allow(clippy::too_many_arguments)] use super::*; use assert_matches::assert_matches; - use cairo_vm::felt::felt_str; use rstest::rstest; + // FIXME: bit of copy-paste to avoid dealing with visibility issues + fn felt_str(x: impl AsRef) -> Felt252 { + crate::Felt252::from_dec_str(x.as_ref()).expect("Couldn't parse bytes") + } + #[rstest] #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/fibonacci.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo"].as_slice())] fn test_run_fibonacci_ok(#[case] args: &[&str]) { @@ -686,7 +691,7 @@ mod tests { #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/enum_match.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo"].as_slice())] fn test_run_enum_match_ok(#[case] args: &[&str]) { let args = args.iter().cloned().map(String::from); - assert_matches!(run(args), Ok(res) if res == vec![MaybeRelocatable::from(10), MaybeRelocatable::from(felt_str!("3618502788666131213697322783095070105623107215331596699973092056135872020471"))]); + assert_matches!(run(args), Ok(res) if res == vec![MaybeRelocatable::from(10), MaybeRelocatable::from(felt_str("3618502788666131213697322783095070105623107215331596699973092056135872020471"))]); } #[rstest] @@ -714,35 +719,35 @@ mod tests { #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/recursion.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo"].as_slice())] fn test_run_recursion_ok(#[case] args: &[&str]) { let args = args.iter().cloned().map(String::from); - assert_matches!(run(args), Ok(res) if res == vec![MaybeRelocatable::from(felt_str!("1154076154663935037074198317650845438095734251249125412074882362667803016453"))]); + assert_matches!(run(args), Ok(res) if res == vec![MaybeRelocatable::from(felt_str("1154076154663935037074198317650845438095734251249125412074882362667803016453"))]); } #[rstest] #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/sample.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo"].as_slice())] fn test_run_sample_ok(#[case] args: &[&str]) { let args = args.iter().cloned().map(String::from); - assert_matches!(run(args), Ok(res) if res == vec![MaybeRelocatable::from(felt_str!("5050"))]); + assert_matches!(run(args), Ok(res) if res == vec![MaybeRelocatable::from(felt_str("5050"))]); } #[rstest] #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/poseidon.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo"].as_slice())] fn test_run_poseidon_ok(#[case] args: &[&str]) { let args = args.iter().cloned().map(String::from); - assert_matches!(run(args), Ok(res) if res == vec![MaybeRelocatable::from(felt_str!("1099385018355113290651252669115094675591288647745213771718157553170111442461"))]); + assert_matches!(run(args), Ok(res) if res == vec![MaybeRelocatable::from(felt_str("1099385018355113290651252669115094675591288647745213771718157553170111442461"))]); } #[rstest] #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/poseidon_pedersen.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo"].as_slice())] fn test_run_poseidon_pedersen_ok(#[case] args: &[&str]) { let args = args.iter().cloned().map(String::from); - assert_matches!(run(args), Ok(res) if res == vec![MaybeRelocatable::from(felt_str!("1036257840396636296853154602823055519264738423488122322497453114874087006398"))]); + assert_matches!(run(args), Ok(res) if res == vec![MaybeRelocatable::from(felt_str("1036257840396636296853154602823055519264738423488122322497453114874087006398"))]); } #[rstest] #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/pedersen_example.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo"].as_slice())] fn test_run_pedersen_example_ok(#[case] args: &[&str]) { let args = args.iter().cloned().map(String::from); - assert_matches!(run(args), Ok(res) if res == vec![MaybeRelocatable::from(felt_str!("1089549915800264549621536909767699778745926517555586332772759280702396009108"))]); + assert_matches!(run(args), Ok(res) if res == vec![MaybeRelocatable::from(felt_str("1089549915800264549621536909767699778745926517555586332772759280702396009108"))]); } #[rstest] diff --git a/ensure-no_std/Cargo.toml b/ensure-no_std/Cargo.toml index 9232ba5e8c..fbb4f07775 100644 --- a/ensure-no_std/Cargo.toml +++ b/ensure-no_std/Cargo.toml @@ -4,20 +4,6 @@ version = "0.1.0" edition = "2021" [dependencies] -cairo-felt = { path = "../felt", default-features = false, features = [ - "alloc", -] } cairo-vm = { path = "../vm", default-features = false } esp-alloc = "0.3.0" - -[features] -default = ["lambdaworks-felt"] -lambdaworks-felt = ["cairo-felt/lambdaworks-felt"] - - -[profile.dev] -panic = "abort" - -[profile.release] -panic = "abort" diff --git a/ensure-no_std/src/main.rs b/ensure-no_std/src/main.rs index 6794b06082..b25cce251d 100644 --- a/ensure-no_std/src/main.rs +++ b/ensure-no_std/src/main.rs @@ -19,4 +19,4 @@ pub extern "C" fn _start() -> ! { static ALLOC: esp_alloc::EspHeap = esp_alloc::EspHeap::empty(); #[allow(unused_imports)] -use {cairo_felt, cairo_vm}; +use cairo_vm; diff --git a/examples/custom_hint/src/main.rs b/examples/custom_hint/src/main.rs index e6bd6e2930..1917a3268a 100644 --- a/examples/custom_hint/src/main.rs +++ b/examples/custom_hint/src/main.rs @@ -1,5 +1,4 @@ use cairo_vm::cairo_run::{cairo_run, CairoRunConfig}; -use cairo_vm::felt::Felt252; use cairo_vm::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::{ BuiltinHintProcessor, HintFunc, }; @@ -8,6 +7,7 @@ use cairo_vm::hint_processor::hint_processor_definition::HintReference; use cairo_vm::serde::deserialize_program::ApTracking; use cairo_vm::types::exec_scope::ExecutionScopes; use cairo_vm::vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}; +use cairo_vm::Felt252; use std::collections::HashMap; use std::fs::File; use std::io::{BufReader, Read}; diff --git a/felt/Cargo.toml b/felt/Cargo.toml deleted file mode 100644 index 1523749cbb..0000000000 --- a/felt/Cargo.toml +++ /dev/null @@ -1,32 +0,0 @@ -[package] -name = "cairo-felt" -description = "Field elements representation for the Cairo VM" -version.workspace = true -edition.workspace = true -license.workspace = true -repository.workspace = true -readme.workspace = true -keywords.workspace = true - -[features] -default = ["std"] -std = [] -alloc = [] -lambdaworks-felt = ["dep:lambdaworks-math"] -arbitrary = ["dep:arbitrary", "num-bigint/arbitrary", "dep:proptest"] - -[dependencies] -num-integer = { version = "0.1.45", default-features = false } -num-bigint = { version = "0.4", features = ["serde"], default-features = false } -num-traits = { version = "0.2.15", default-features = false } -lazy_static = { version = "1.4.0", default-features = false, features = [ - "spin_no_std", -] } -serde = { version = "1.0", features = ["derive"], default-features = false } -lambdaworks-math = { version = "0.1.2", default-features = false, optional = true } -arbitrary = { version = "1.3.0", features = ["derive"], optional = true } -proptest = { version = "1.2.0", optional = true } - -[dev-dependencies] -proptest = "1.2.0" -rstest = { version = "0.17.0", default-features = false } diff --git a/felt/proptest-regressions/lib.txt b/felt/proptest-regressions/lib.txt deleted file mode 100644 index d0b210cbb5..0000000000 --- a/felt/proptest-regressions/lib.txt +++ /dev/null @@ -1,9 +0,0 @@ -# Seeds for failure cases proptest has generated in the past. It is -# automatically read and these particular cases re-run before any -# novel cases are generated. -# -# It is recommended to check this file in to source control so that -# everyone who runs the test benefits from these saved cases. -cc 1bf12114a6bfc70e8f949318158595883c33bc6fb35862852bc5144547ac3557 # shrinks to ref x = "0" -cc 3a938be1bdfbb188c7c1f0dc097d8089fe8b26a98b76c013014651353d2926d0 # shrinks to ref x = "10000000000000000000000000000000" -cc 8a6f8fc921f578cc00b27655b88e73211622ec1adceab732a332fa0dfdb24547 # shrinks to ref x = 1851773111301897860446223468209874879634049222408221143747762745355066671104 diff --git a/felt/src/arbitrary_bigint_felt.rs b/felt/src/arbitrary_bigint_felt.rs deleted file mode 100644 index 3ad09040df..0000000000 --- a/felt/src/arbitrary_bigint_felt.rs +++ /dev/null @@ -1,58 +0,0 @@ -use num_bigint::BigUint; -use num_traits::Zero; -use proptest::prelude::*; - -use crate::{ - bigint_felt::{FeltBigInt, FIELD_HIGH, FIELD_LOW}, - Felt252, -}; - -fn any_felt_big_int() -> impl Strategy> { - (0..=PH) - // turn range into `impl Strategy` - .prop_map(|x| x) - // choose second 128-bit limb capped by first one - .prop_flat_map(|high| { - let low = if high == PH { - (0..PL).prop_map(|x| x).sboxed() - } else { - any::().sboxed() - }; - (Just(high), low) - }) - // turn (u128, u128) into BigUint and then into FeltBigInt - .prop_map(|(high, low)| { - let biguint = (BigUint::from(high) << 128) + low; - FeltBigInt::from(biguint) - }) -} - -/// Returns a [`Strategy`] that generates any valid Felt252 -fn any_felt252() -> impl Strategy { - any_felt_big_int::().prop_map(|value| Felt252 { value }) -} - -/// Returns a [`Strategy`] that generates any nonzero Felt252 -pub fn nonzero_felt252() -> impl Strategy { - any_felt252().prop_filter("is zero", |x| !x.is_zero()) -} - -impl Arbitrary for FeltBigInt { - type Parameters = (); - - fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy { - any_felt_big_int().sboxed() - } - - type Strategy = SBoxedStrategy; -} - -impl Arbitrary for Felt252 { - type Parameters = (); - - fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy { - any_felt252().sboxed() - } - - type Strategy = SBoxedStrategy; -} diff --git a/felt/src/arbitrary_lambdaworks.rs b/felt/src/arbitrary_lambdaworks.rs deleted file mode 100644 index 11b9df1aa4..0000000000 --- a/felt/src/arbitrary_lambdaworks.rs +++ /dev/null @@ -1,47 +0,0 @@ -use lambdaworks_math::{field::element::FieldElement, unsigned_integer::element::UnsignedInteger}; -use num_traits::Zero; -use proptest::prelude::*; - -use crate::{Felt252, FIELD_HIGH, FIELD_LOW}; - -/// Returns a [`Strategy`] that generates any valid Felt252 -fn any_felt252() -> impl Strategy { - (0..=FIELD_HIGH) - // turn range into `impl Strategy` - .prop_map(|x| x) - // choose second 128-bit limb capped by first one - .prop_flat_map(|high| { - let low = if high == FIELD_HIGH { - (0..FIELD_LOW).prop_map(|x| x).sboxed() - } else { - any::().sboxed() - }; - (Just(high), low) - }) - // turn (u128, u128) into limbs array and then into Felt252 - .prop_map(|(high, low)| { - let limbs = [ - (high >> 64) as u64, - (high & ((1 << 64) - 1)) as u64, - (low >> 64) as u64, - (low & ((1 << 64) - 1)) as u64, - ]; - FieldElement::new(UnsignedInteger::from_limbs(limbs)) - }) - .prop_map(|value| Felt252 { value }) -} - -/// Returns a [`Strategy`] that generates any nonzero Felt252 -pub fn nonzero_felt252() -> impl Strategy { - any_felt252().prop_filter("is zero", |x| !x.is_zero()) -} - -impl Arbitrary for Felt252 { - type Parameters = (); - - fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy { - any_felt252().sboxed() - } - - type Strategy = SBoxedStrategy; -} diff --git a/felt/src/bigint_felt.rs b/felt/src/bigint_felt.rs deleted file mode 100644 index c1c6505a78..0000000000 --- a/felt/src/bigint_felt.rs +++ /dev/null @@ -1,1220 +0,0 @@ -#[cfg(all(not(feature = "std"), feature = "alloc"))] -use alloc::{string::String, vec::Vec}; - -use core::{ - cmp, - convert::Into, - fmt, - iter::Sum, - ops::{ - Add, AddAssign, BitAnd, BitOr, BitXor, Div, Mul, MulAssign, Neg, Rem, Shl, Shr, ShrAssign, - Sub, SubAssign, - }, -}; - -use crate::{lib_bigint_felt::FeltOps, ParseFeltError}; - -#[cfg(all(feature = "std", feature = "arbitrary"))] -use arbitrary::Arbitrary; - -pub const FIELD_HIGH: u128 = (1 << 123) + (17 << 64); // this is equal to 10633823966279327296825105735305134080 -pub const FIELD_LOW: u128 = 1; -use lazy_static::lazy_static; -use num_bigint::{BigInt, BigUint, ToBigInt, U64Digits}; -use num_integer::Integer; -use num_traits::{Bounded, FromPrimitive, Num, One, Pow, Signed, ToPrimitive, Zero}; -use serde::{Deserialize, Serialize}; - -lazy_static! { - static ref CAIRO_PRIME_BIGUINT: BigUint = - (Into::::into(FIELD_HIGH) << 128) + Into::::into(FIELD_LOW); - pub static ref SIGNED_FELT_MAX: BigUint = (&*CAIRO_PRIME_BIGUINT).shr(1_u32); - pub static ref CAIRO_SIGNED_PRIME: BigInt = CAIRO_PRIME_BIGUINT - .to_bigint() - .expect("Conversion BigUint -> BigInt can't fail"); -} - -#[cfg_attr(all(feature = "arbitrary", feature = "std"), derive(Arbitrary))] -#[derive(Eq, Hash, PartialEq, PartialOrd, Ord, Clone, Deserialize, Default, Serialize)] -pub(crate) struct FeltBigInt { - val: BigUint, -} - -macro_rules! from_integer { - ($type:ty) => { - impl From<$type> for FeltBigInt { - fn from(value: $type) -> Self { - Self { - val: value - .try_into() - .unwrap_or_else(|_| &*CAIRO_PRIME_BIGUINT - (-value as u128)), - } - } - } - }; -} - -macro_rules! from_unsigned { - ($type:ty) => { - impl From<$type> for FeltBigInt { - fn from(value: $type) -> Self { - Self { val: value.into() } - } - } - }; -} - -from_integer!(i8); -from_integer!(i16); -from_integer!(i32); -from_integer!(i64); -from_integer!(i128); -from_integer!(isize); - -from_unsigned!(u8); -from_unsigned!(u16); -from_unsigned!(u32); -from_unsigned!(u64); -from_unsigned!(u128); -from_unsigned!(usize); - -impl From for FeltBigInt { - fn from(value: BigUint) -> Self { - Self { - val: match value { - _ if value > *CAIRO_PRIME_BIGUINT => value.mod_floor(&CAIRO_PRIME_BIGUINT), - _ if value == *CAIRO_PRIME_BIGUINT => BigUint::zero(), - _ => value, - }, - } - } -} - -impl From<&BigUint> for FeltBigInt { - fn from(value: &BigUint) -> Self { - Self { - val: match value { - _ if value > &*CAIRO_PRIME_BIGUINT => value.mod_floor(&CAIRO_PRIME_BIGUINT), - _ if value == &*CAIRO_PRIME_BIGUINT => BigUint::zero(), - _ => value.clone(), - }, - } - } -} - -/* Code used to convert from BigUint to BigInt - impl ToBigInt for BigUint { - #[inline] - fn to_bigint(&self) -> Option { - if self.is_zero() { - Some(Zero::zero()) - } else { - Some(BigInt { - sign: Plus, - data: self.clone(), - }) - } - } - } -*/ - -impl From for FeltBigInt { - fn from(value: BigInt) -> Self { - (&value).into() - } -} - -impl From<&BigInt> for FeltBigInt { - fn from(value: &BigInt) -> Self { - Self { - val: value - .mod_floor(&CAIRO_SIGNED_PRIME) - .to_biguint() - .expect("mod_floor is always positive"), - } - } -} - -impl FeltOps for FeltBigInt { - fn new>>( - value: T, - ) -> FeltBigInt { - value.into() - } - - fn modpow( - &self, - exponent: &FeltBigInt, - modulus: &FeltBigInt, - ) -> FeltBigInt { - FeltBigInt { - val: self.val.modpow(&exponent.val, &modulus.val), - } - } - - fn iter_u64_digits(&self) -> U64Digits { - self.val.iter_u64_digits() - } - - #[cfg(any(feature = "std", feature = "alloc"))] - fn to_signed_bytes_le(&self) -> Vec { - self.val.to_bytes_le() - } - - #[cfg(any(feature = "std", feature = "alloc"))] - fn to_bytes_be(&self) -> Vec { - self.val.to_bytes_be() - } - - fn parse_bytes(buf: &[u8], radix: u32) -> Option> { - match BigUint::parse_bytes(buf, radix) { - Some(parsed) => Some(FeltBigInt::new(parsed)), - None => BigInt::parse_bytes(buf, radix).map(FeltBigInt::new), - } - } - - fn from_bytes_be(bytes: &[u8]) -> FeltBigInt { - Self::from(BigUint::from_bytes_be(bytes)) - } - - fn from_bytes_le(bytes: &[u8]) -> FeltBigInt { - Self::from(BigUint::from_bytes_le(bytes)) - } - - #[cfg(any(feature = "std", feature = "alloc"))] - fn to_str_radix(&self, radix: u32) -> String { - self.val.to_str_radix(radix) - } - - fn to_signed_felt(&self) -> BigInt { - if self.val > *SIGNED_FELT_MAX { - BigInt::from_biguint(num_bigint::Sign::Minus, &*CAIRO_PRIME_BIGUINT - &self.val) - } else { - self.val.clone().into() - } - } - - fn to_bigint(&self) -> BigInt { - self.val.clone().into() - } - - fn to_biguint(&self) -> BigUint { - self.val.clone() - } - - fn bits(&self) -> u64 { - self.val.bits() - } - - fn prime() -> BigUint { - (Into::::into(FIELD_HIGH) << 128) + Into::::into(FIELD_LOW) - } -} - -impl Add for FeltBigInt { - type Output = Self; - fn add(mut self, rhs: Self) -> Self { - self.val += rhs.val; - if self.val >= *CAIRO_PRIME_BIGUINT { - self.val -= &*CAIRO_PRIME_BIGUINT; - } - self - } -} - -impl<'a, const PH: u128, const PL: u128> Add for &'a FeltBigInt { - type Output = FeltBigInt; - - fn add(self, rhs: Self) -> Self::Output { - let mut sum = &self.val + &rhs.val; - if sum >= *CAIRO_PRIME_BIGUINT { - sum -= &*CAIRO_PRIME_BIGUINT; - } - FeltBigInt { val: sum } - } -} - -impl<'a, const PH: u128, const PL: u128> Add<&'a FeltBigInt> for FeltBigInt { - type Output = FeltBigInt; - - fn add(mut self, rhs: &'a FeltBigInt) -> Self::Output { - self.val += &rhs.val; - if self.val >= *CAIRO_PRIME_BIGUINT { - self.val -= &*CAIRO_PRIME_BIGUINT; - } - self - } -} - -impl Add for FeltBigInt { - type Output = Self; - fn add(mut self, rhs: u32) -> Self { - self.val += rhs; - if self.val >= *CAIRO_PRIME_BIGUINT { - self.val -= &*CAIRO_PRIME_BIGUINT; - } - self - } -} - -impl Add for FeltBigInt { - type Output = Self; - fn add(mut self, rhs: usize) -> Self { - self.val += rhs; - if self.val >= *CAIRO_PRIME_BIGUINT { - self.val -= &*CAIRO_PRIME_BIGUINT; - } - self - } -} - -impl<'a, const PH: u128, const PL: u128> Add for &'a FeltBigInt { - type Output = FeltBigInt; - fn add(self, rhs: usize) -> Self::Output { - let mut sum = &self.val + rhs; - if sum >= *CAIRO_PRIME_BIGUINT { - sum -= &*CAIRO_PRIME_BIGUINT; - } - FeltBigInt { val: sum } - } -} - -impl Add for &FeltBigInt { - type Output = FeltBigInt; - fn add(self, rhs: u64) -> Self::Output { - let mut sum = &self.val + rhs; - if sum >= *CAIRO_PRIME_BIGUINT { - sum -= &*CAIRO_PRIME_BIGUINT; - } - FeltBigInt { val: sum } - } -} - -impl AddAssign for FeltBigInt { - fn add_assign(&mut self, rhs: Self) { - *self = &*self + &rhs; - } -} - -impl<'a, const PH: u128, const PL: u128> AddAssign<&'a FeltBigInt> for FeltBigInt { - fn add_assign(&mut self, rhs: &'a FeltBigInt) { - *self = &*self + rhs; - } -} - -impl Sum for FeltBigInt { - fn sum>(iter: I) -> Self { - iter.fold(FeltBigInt::zero(), |mut acc, x| { - acc += x; - acc - }) - } -} - -impl Neg for FeltBigInt { - type Output = FeltBigInt; - fn neg(self) -> Self::Output { - if self.is_zero() { - self - } else { - FeltBigInt { - val: &*CAIRO_PRIME_BIGUINT - self.val, - } - } - } -} - -impl<'a, const PH: u128, const PL: u128> Neg for &'a FeltBigInt { - type Output = FeltBigInt; - fn neg(self) -> Self::Output { - if self.is_zero() { - self.clone() - } else { - FeltBigInt { - val: &*CAIRO_PRIME_BIGUINT - &self.val, - } - } - } -} - -impl Sub for FeltBigInt { - type Output = Self; - fn sub(mut self, rhs: Self) -> Self::Output { - if self.val < rhs.val { - self.val += &*CAIRO_PRIME_BIGUINT; - } - self.val -= rhs.val; - self - } -} - -impl<'a, const PH: u128, const PL: u128> Sub<&'a FeltBigInt> for FeltBigInt { - type Output = FeltBigInt; - fn sub(mut self, rhs: &'a FeltBigInt) -> Self::Output { - if self.val < rhs.val { - self.val += &*CAIRO_PRIME_BIGUINT; - } - self.val -= &rhs.val; - self - } -} - -impl<'a, const PH: u128, const PL: u128> Sub for &'a FeltBigInt { - type Output = FeltBigInt; - fn sub(self, rhs: Self) -> Self::Output { - FeltBigInt { - val: if self.val < rhs.val { - &*CAIRO_PRIME_BIGUINT - (&rhs.val - &self.val) - } else { - &self.val - &rhs.val - }, - } - } -} - -impl Sub for FeltBigInt { - type Output = FeltBigInt; - fn sub(self, rhs: u32) -> Self { - match (self.val).to_u32() { - Some(num) if num < rhs => Self { - val: &*CAIRO_PRIME_BIGUINT - (rhs - self.val), - }, - _ => Self { - val: self.val - rhs, - }, - } - } -} - -impl<'a, const PH: u128, const PL: u128> Sub for &'a FeltBigInt { - type Output = FeltBigInt; - fn sub(self, rhs: u32) -> Self::Output { - match (self.val).to_u32() { - Some(num) if num < rhs => FeltBigInt { - val: &*CAIRO_PRIME_BIGUINT - (rhs - &self.val), - }, - _ => FeltBigInt { - val: &self.val - rhs, - }, - } - } -} - -impl Sub for FeltBigInt { - type Output = FeltBigInt; - fn sub(self, rhs: usize) -> Self { - match (self.val).to_usize() { - Some(num) if num < rhs => FeltBigInt { - val: &*CAIRO_PRIME_BIGUINT - (rhs - num), - }, - _ => FeltBigInt { - val: self.val - rhs, - }, - } - } -} - -impl<'a, const PH: u128, const PL: u128> Pow<&'a FeltBigInt> for &'a FeltBigInt { - type Output = FeltBigInt; - fn pow(self, rhs: Self) -> Self::Output { - FeltBigInt { - val: self.val.modpow(&rhs.val, &CAIRO_PRIME_BIGUINT), - } - } -} - -impl SubAssign for FeltBigInt { - fn sub_assign(&mut self, rhs: Self) { - *self = &*self - &rhs; - } -} - -impl<'a, const PH: u128, const PL: u128> SubAssign<&'a FeltBigInt> for FeltBigInt { - fn sub_assign(&mut self, rhs: &'a FeltBigInt) { - *self = &*self - rhs; - } -} - -impl Sub> for usize { - type Output = FeltBigInt; - fn sub(self, rhs: FeltBigInt) -> Self::Output { - self - &rhs - } -} - -impl Sub<&FeltBigInt> for usize { - type Output = FeltBigInt; - fn sub(self, rhs: &FeltBigInt) -> Self::Output { - match (rhs.val).to_usize() { - Some(num) => { - if num > self { - FeltBigInt { - val: &*CAIRO_PRIME_BIGUINT - (num - self), - } - } else { - FeltBigInt::new(self - num) - } - } - None => FeltBigInt { - val: &*CAIRO_PRIME_BIGUINT - (&rhs.val - self), - }, - } - } -} - -impl Mul for FeltBigInt { - type Output = Self; - fn mul(self, rhs: Self) -> Self::Output { - FeltBigInt { - val: (self.val * rhs.val).mod_floor(&CAIRO_PRIME_BIGUINT), - } - } -} - -impl<'a, const PH: u128, const PL: u128> Mul for &'a FeltBigInt { - type Output = FeltBigInt; - fn mul(self, rhs: Self) -> Self::Output { - FeltBigInt { - val: (&self.val * &rhs.val).mod_floor(&CAIRO_PRIME_BIGUINT), - } - } -} - -impl<'a, const PH: u128, const PL: u128> Mul<&'a FeltBigInt> for FeltBigInt { - type Output = FeltBigInt; - fn mul(self, rhs: &'a FeltBigInt) -> Self::Output { - FeltBigInt { - val: (&self.val * &rhs.val).mod_floor(&CAIRO_PRIME_BIGUINT), - } - } -} - -impl<'a, const PH: u128, const PL: u128> MulAssign<&'a FeltBigInt> for FeltBigInt { - fn mul_assign(&mut self, rhs: &'a FeltBigInt) { - *self = &*self * rhs; - } -} - -impl Pow for FeltBigInt { - type Output = Self; - fn pow(self, rhs: u32) -> Self { - FeltBigInt { - val: self.val.modpow(&BigUint::from(rhs), &CAIRO_PRIME_BIGUINT), - } - } -} - -impl<'a, const PH: u128, const PL: u128> Pow for &'a FeltBigInt { - type Output = FeltBigInt; - fn pow(self, rhs: u32) -> Self::Output { - FeltBigInt { - val: self.val.modpow(&BigUint::from(rhs), &CAIRO_PRIME_BIGUINT), - } - } -} - -impl Div for FeltBigInt { - type Output = Self; - // In Felts `x / y` needs to be expressed as `x * y^-1` - #[allow(clippy::suspicious_arithmetic_impl)] - fn div(self, rhs: Self) -> Self::Output { - if rhs.is_zero() { - panic!("Can't divide Felt by zero") - } - let x = rhs - .val - .to_bigint() // Always succeeds for BigUint -> BigInt - .unwrap() - .extended_gcd(&CAIRO_SIGNED_PRIME) - .x; - self * &FeltBigInt::from(x) - } -} - -impl<'a, const PH: u128, const PL: u128> Div for &'a FeltBigInt { - type Output = FeltBigInt; - // In Felts `x / y` needs to be expressed as `x * y^-1` - #[allow(clippy::suspicious_arithmetic_impl)] - fn div(self, rhs: Self) -> Self::Output { - if rhs.is_zero() { - panic!("Can't divide Felt by zero") - } - let x = rhs - .val - .to_bigint() // Always succeeds for BitUint -> BigInt - .unwrap() - .extended_gcd(&CAIRO_SIGNED_PRIME) - .x; - self * &FeltBigInt::from(x) - } -} - -impl<'a, const PH: u128, const PL: u128> Div> for &'a FeltBigInt { - type Output = FeltBigInt; - // In Felts `x / y` needs to be expressed as `x * y^-1` - #[allow(clippy::suspicious_arithmetic_impl)] - fn div(self, rhs: FeltBigInt) -> Self::Output { - self / &rhs - } -} - -impl Rem for FeltBigInt { - type Output = Self; - fn rem(self, _rhs: Self) -> Self { - FeltBigInt::zero() - } -} - -impl<'a, const PH: u128, const PL: u128> Rem<&'a FeltBigInt> for FeltBigInt { - type Output = Self; - fn rem(self, _rhs: &'a FeltBigInt) -> Self::Output { - FeltBigInt::zero() - } -} - -impl Zero for FeltBigInt { - fn zero() -> Self { - Self { - val: BigUint::zero(), - } - } - - fn is_zero(&self) -> bool { - self.val.is_zero() - } -} - -impl One for FeltBigInt { - fn one() -> Self { - Self { - val: BigUint::one(), - } - } - - fn is_one(&self) -> bool - where - Self: PartialEq, - { - self.val.is_one() - } -} - -impl Bounded for FeltBigInt { - fn min_value() -> Self { - Self::zero() - } - fn max_value() -> Self { - Self { - val: &*CAIRO_PRIME_BIGUINT - 1_u32, - } - } -} - -impl Num for FeltBigInt { - type FromStrRadixErr = ParseFeltError; - fn from_str_radix(string: &str, radix: u32) -> Result { - match BigUint::from_str_radix(string, radix) { - Ok(num) => Ok(FeltBigInt::::new(num)), - Err(_) => Err(ParseFeltError), - } - } -} - -impl Integer for FeltBigInt { - fn div_floor(&self, other: &Self) -> Self { - FeltBigInt { - val: &self.val / &other.val, - } - } - - fn div_rem(&self, other: &Self) -> (Self, Self) { - let (d, m) = self.val.div_mod_floor(&other.val); - (FeltBigInt { val: d }, FeltBigInt { val: m }) - } - - fn divides(&self, other: &Self) -> bool { - self.is_multiple_of(other) - } - - fn gcd(&self, other: &Self) -> Self { - Self { - val: self.val.gcd(&other.val), - } - } - - fn is_even(&self) -> bool { - self.val.is_even() - } - - fn is_multiple_of(&self, _other: &Self) -> bool { - true - } - - fn is_odd(&self) -> bool { - self.val.is_odd() - } - - fn lcm(&self, other: &Self) -> Self { - Self::new(cmp::max(&self.val, &other.val)) - } - - fn mod_floor(&self, other: &Self) -> Self { - Self { - val: self.val.mod_floor(&other.val), - } - } -} - -impl Signed for FeltBigInt { - fn abs(&self) -> Self { - self.clone() - } - - fn abs_sub(&self, other: &Self) -> Self { - if self > other { - self - other - } else { - other - self - } - } - - fn signum(&self) -> Self { - if self.is_zero() { - FeltBigInt::zero() - } else { - FeltBigInt::one() - } - } - - fn is_positive(&self) -> bool { - !self.is_zero() - } - - fn is_negative(&self) -> bool { - !(self.is_positive() || self.is_zero()) - } -} - -impl Shl for FeltBigInt { - type Output = Self; - fn shl(self, other: u32) -> Self::Output { - FeltBigInt { - val: (self.val).shl(other).mod_floor(&CAIRO_PRIME_BIGUINT), - } - } -} - -impl<'a, const PH: u128, const PL: u128> Shl for &'a FeltBigInt { - type Output = FeltBigInt; - fn shl(self, other: u32) -> Self::Output { - FeltBigInt { - val: (&self.val).shl(other).mod_floor(&CAIRO_PRIME_BIGUINT), - } - } -} - -impl Shl for FeltBigInt { - type Output = Self; - fn shl(self, other: usize) -> Self::Output { - FeltBigInt { - val: (self.val).shl(other).mod_floor(&CAIRO_PRIME_BIGUINT), - } - } -} - -impl<'a, const PH: u128, const PL: u128> Shl for &'a FeltBigInt { - type Output = FeltBigInt; - fn shl(self, other: usize) -> Self::Output { - FeltBigInt { - val: (&self.val).shl(other).mod_floor(&CAIRO_PRIME_BIGUINT), - } - } -} - -impl Shr for FeltBigInt { - type Output = Self; - fn shr(self, other: u32) -> Self::Output { - FeltBigInt { - val: self.val.shr(other), - } - } -} - -impl<'a, const PH: u128, const PL: u128> Shr for &'a FeltBigInt { - type Output = FeltBigInt; - fn shr(self, other: u32) -> Self::Output { - FeltBigInt { - val: (&self.val).shr(other).mod_floor(&CAIRO_PRIME_BIGUINT), - } - } -} - -impl ShrAssign for FeltBigInt { - fn shr_assign(&mut self, other: usize) { - self.val = (&self.val).shr(other).mod_floor(&CAIRO_PRIME_BIGUINT); - } -} - -impl<'a, const PH: u128, const PL: u128> BitAnd for &'a FeltBigInt { - type Output = FeltBigInt; - fn bitand(self, rhs: Self) -> Self::Output { - FeltBigInt { - val: &self.val & &rhs.val, - } - } -} - -impl<'a, const PH: u128, const PL: u128> BitAnd<&'a FeltBigInt> for FeltBigInt { - type Output = Self; - fn bitand(self, rhs: &'a FeltBigInt) -> Self::Output { - FeltBigInt { - val: self.val & &rhs.val, - } - } -} - -impl<'a, const PH: u128, const PL: u128> BitAnd> for &'a FeltBigInt { - type Output = FeltBigInt; - fn bitand(self, rhs: Self::Output) -> Self::Output { - FeltBigInt { - val: &self.val & rhs.val, - } - } -} - -impl<'a, const PH: u128, const PL: u128> BitOr for &'a FeltBigInt { - type Output = FeltBigInt; - fn bitor(self, rhs: Self) -> Self::Output { - FeltBigInt { - val: &self.val | &rhs.val, - } - } -} - -impl<'a, const PH: u128, const PL: u128> BitXor for &'a FeltBigInt { - type Output = FeltBigInt; - fn bitxor(self, rhs: Self) -> Self::Output { - FeltBigInt { - val: &self.val ^ &rhs.val, - } - } -} - -impl ToPrimitive for FeltBigInt { - fn to_u128(&self) -> Option { - self.val.to_u128() - } - - fn to_u64(&self) -> Option { - self.val.to_u64() - } - - fn to_i64(&self) -> Option { - self.val.to_i64() - } - - fn to_usize(&self) -> Option { - self.val.to_usize() - } -} - -impl FromPrimitive for FeltBigInt { - fn from_u64(n: u64) -> Option { - BigUint::from_u64(n).map(|n| Self { val: n }) - } - - fn from_i64(n: i64) -> Option { - BigUint::from_i64(n).map(|n| Self { val: n }) - } - - fn from_usize(n: usize) -> Option { - BigUint::from_usize(n).map(|n| Self { val: n }) - } -} - -impl fmt::Display for FeltBigInt { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.val) - } -} - -impl fmt::Debug for FeltBigInt { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.val) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use proptest::prelude::*; - - #[cfg(all(not(feature = "std"), feature = "alloc"))] - use alloc::string::ToString; - - #[cfg(target_arch = "wasm32")] - use wasm_bindgen_test::*; - - #[test] - // Tests that the result of adding two zeros is zero. - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn add_zeros() { - let a = FeltBigInt::::new(0); - let b = FeltBigInt::new(0); - let c = FeltBigInt::new(0); - - assert_eq!(a + b, c); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Tests that the result of performing add assign with two zeros is zero. - fn add_assign_zeros() { - let mut a = FeltBigInt::::new(0); - let b = FeltBigInt::new(0); - a += b; - let c = FeltBigInt::new(0); - - assert_eq!(a, c); - } - #[test] - // Tests that the result of performing a bitwise "and" operation with two zeros is zero. - fn bit_and_zeros() { - let a = FeltBigInt::::new(0); - let b = FeltBigInt::new(0); - let c = FeltBigInt::new(0); - - assert_eq!(&a & &b, c); - } - #[test] - // Tests that the result of performing a bitwise "or" operation with two zeros is zero. - - fn bit_or_zeros() { - let a = FeltBigInt::::new(0); - let b = FeltBigInt::new(0); - let c = FeltBigInt::new(0); - - assert_eq!(&a | &b, c); - } - - #[test] - // Tests that the result of performing a bitwise "xor" operation with two zeros results in zero. - fn bit_xor_zeros() { - let a = FeltBigInt::::new(0); - let b = FeltBigInt::new(0); - let c = FeltBigInt::new(0); - - assert_eq!(&a ^ &b, c); - } - - #[test] - #[should_panic] - // Tests that the result of performing a division by zero results in panic. - fn div_zeros() { - let a = FeltBigInt::::new(0); - let b = FeltBigInt::::new(0); - let _ = a / b; - } - - #[test] - #[should_panic] - // Tests that the result of performing a division by zero results in panic. - fn div_zeros_ref() { - let a = FeltBigInt::::new(0); - let b = FeltBigInt::::new(0); - let _ = &a / &b; - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Tests that the result of multiplying two zeros is zero. - fn mul_zeros() { - let a = FeltBigInt::::new(0); - let b = FeltBigInt::new(0); - let c = FeltBigInt::new(0); - - assert_eq!(a * b, c); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Tests that the result of multiplying two zeros with assignment is zero. - fn mul_assign_zeros() { - let mut a = FeltBigInt::::new(0); - let b = FeltBigInt::new(0); - a *= &b; - let c = FeltBigInt::new(0); - - assert_eq!(a, c); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Tests that the result of subtracting two zeros is zero. - fn sub_zeros() { - let a = FeltBigInt::::new(0); - let b = FeltBigInt::new(0); - let c = FeltBigInt::new(0); - - assert_eq!(a - b, c); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Tests that the result of subtracting two zeros with assignment is zero. - fn sub_assign_zeros() { - let mut a = FeltBigInt::::new(0); - let b = FeltBigInt::new(0); - a -= b; - let c = FeltBigInt::new(0); - - assert_eq!(a, c); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn sub_usize_felt() { - let a = FeltBigInt::::new(4u32); - let b = FeltBigInt::new(2u32); - - assert_eq!(6usize - &a, b); - assert_eq!(6usize - a, b); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Tests that the negative of zero is zero - fn negate_zero() { - let a = FeltBigInt::::new(0); - let b = a.neg(); - assert_eq!( - b, - FeltBigInt::from_str_radix("0", 10).expect("Couldn't parse int") - ); - - let c = FeltBigInt::::from_str_radix("0", 10) - .expect("Couldn't parse int"); - let d = c.neg(); - assert_eq!(d, FeltBigInt::new(0)); - } - - #[test] - // Tests a shift left operation performed on a felt of value zero - fn shift_left_zero() { - let a = FeltBigInt::::new(0); - let b = FeltBigInt::::new(0); - let result = &a << 10_u32; - assert_eq!(result, b) - } - - #[test] - // Tests a shift right operation performed on a felt of value zero - fn shift_right_zero() { - let a = FeltBigInt::::new(0); - let b = FeltBigInt::::new(0); - let result = &a >> 10_u32; - assert_eq!(result, b) - } - - #[test] - // Tests a shift right operation with assignment performed on a felt of value zero - fn shift_right_assign_zero() { - let mut a = FeltBigInt::::new(0); - let b = FeltBigInt::::new(0); - a >>= 10; - assert_eq!(a, b) - } - - #[test] - // Test that an iterative sum of zeros results in zero - fn sum_zeros() { - let a = FeltBigInt::::new(0); - let b = FeltBigInt::::new(0); - let c = FeltBigInt::::new(0); - let v = vec![a, b, c]; - let result: FeltBigInt = v.into_iter().sum(); - assert_eq!(result, FeltBigInt::::new(0)) - } - - #[test] - // Tests that the remainder of a division where the dividend is 0, results in 0 - fn rem_zero() { - let a = FeltBigInt::::new(0); - let b = FeltBigInt::::new(0); - let c = FeltBigInt::::new(10); - let d = FeltBigInt::::new(0); - assert_eq!(a.clone() % b, d); - assert_eq!(a % c, d) - } - - proptest! { - #[test] - // Property-based test that ensures, for 100 pairs of values that are randomly generated each time tests are run, that performing a subtraction returns a result that is inside of the range [0, p]. - fn sub_bigint_felt_within_field(ref x in "([1-9][0-9]*)", ref y in "([1-9][0-9]*)") { - let x = FeltBigInt::::parse_bytes(x.as_bytes(), 10).unwrap(); - let y = FeltBigInt::::parse_bytes(y.as_bytes(), 10).unwrap(); - let p:BigUint = BigUint::parse_bytes(CAIRO_PRIME_BIGUINT.to_string().as_bytes(), 16).unwrap(); - let result = x - y; - let as_uint = &result.to_biguint(); - prop_assert!(as_uint < &p, "{}", as_uint); - } - - #[test] - // Property-based test that ensures, for 100 pairs of values that are randomly generated each time tests are run, that performing a subtraction returns a result that is inside of the range [0, p]. - fn sub_assign_bigint_felt_within_field(ref x in "([1-9][0-9]*)", ref y in "([1-9][0-9]*)") { - let mut x = FeltBigInt::::parse_bytes(x.as_bytes(), 10).unwrap(); - let y = FeltBigInt::::parse_bytes(y.as_bytes(), 10).unwrap(); - let p:BigUint = BigUint::parse_bytes(CAIRO_PRIME_BIGUINT.to_string().as_bytes(), 16).unwrap(); - x -= y; - let as_uint = &x.to_biguint(); - prop_assert!(as_uint < &p, "{}", as_uint); - } - - #[test] - // Property-based test that ensures that the remainder of a division between two random bigint felts returns 0. The test is performed 100 times each run. - fn rem_bigint_felt_within_field(ref x in "([1-9][0-9]*)", ref y in "([1-9][0-9]*)") { - let x = FeltBigInt::::parse_bytes(x.as_bytes(), 10).unwrap(); - let y = FeltBigInt::::parse_bytes(y.as_bytes(), 10).unwrap(); - - let result = x % y; - prop_assert!(result.is_zero()); - } - // Tests that the result of adding two random large bigint felts falls within the range [0, p]. This test is performed 100 times each run. - #[test] - fn add_bigint_felts_within_field(ref x in "([1-9][0-9]*)", ref y in "([1-9][0-9]*)") { - let x = FeltBigInt::::parse_bytes(x.as_bytes(), 10).unwrap(); - let y = FeltBigInt::::parse_bytes(y.as_bytes(), 10).unwrap(); - let p = &CAIRO_PRIME_BIGUINT; - let result = x + y; - let as_uint = &result.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - - } - #[test] - // Tests that the result of performing add assign on two random large bigint felts falls within the range [0, p]. This test is performed 100 times each run. - fn add_assign_bigint_felts_within_field(ref x in "([1-9][0-9]*)", ref y in "([1-9][0-9]*)") { - let mut x = FeltBigInt::::parse_bytes(x.as_bytes(), 10).unwrap(); - let y = FeltBigInt::::parse_bytes(y.as_bytes(), 10).unwrap(); - let p = &CAIRO_PRIME_BIGUINT; - x += y; - let as_uint = &x.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - } - - #[test] - // Tests that the result of performing the bitwise "and" operation on two random large bigint felts falls within the range [0, p]. This test is performed 100 times each run. - fn bitand_bigint_felts_within_field(ref x in "([1-9][0-9]*)", ref y in "([1-9][0-9]*)") { - let x = FeltBigInt::::parse_bytes(x.as_bytes(), 10).unwrap(); - let y = FeltBigInt::::parse_bytes(y.as_bytes(), 10).unwrap(); - let p:BigUint = BigUint::parse_bytes(CAIRO_PRIME_BIGUINT.to_string().as_bytes(), 16).unwrap(); - let result = &x & &y; - let as_uint = result.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - } - #[test] - // Tests that the result of performing the bitwise "or" operation on two random large bigint felts falls within the range [0, p]. This test is performed 100 times each run. - fn bitor_bigint_felts_within_field(ref x in "([1-9][0-9]*)", ref y in "([1-9][0-9]*)") { - let x = FeltBigInt::::parse_bytes(x.as_bytes(), 10).unwrap(); - let y = FeltBigInt::::parse_bytes(y.as_bytes(), 10).unwrap(); - let p:BigUint = BigUint::parse_bytes(CAIRO_PRIME_BIGUINT.to_string().as_bytes(), 16).unwrap(); - let result = &x | &y; - let as_uint = result.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - } - #[test] - // Tests that the result of performing the bitwise "xor" operation on two random large bigint felts falls within the range [0, p]. This test is performed 100 times each run. - fn bitxor_bigint_felts_within_field(ref x in "([1-9][0-9]*)", ref y in "([1-9][0-9]*)") { - let x = FeltBigInt::::parse_bytes(x.as_bytes(), 10).unwrap(); - let y = FeltBigInt::::parse_bytes(y.as_bytes(), 10).unwrap(); - let p:BigUint = BigUint::parse_bytes(CAIRO_PRIME_BIGUINT.to_string().as_bytes(), 16).unwrap(); - let result = &x ^ &y; - let as_uint = result.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - } - #[test] - // Tests that the result dividing two random large bigint felts falls within the range [0, p]. This test is performed 100 times each run. - fn div_bigint_felts_within_field(ref x in "([1-9][0-9]*)", ref y in "([1-9][0-9]*)") { - let x = FeltBigInt::::parse_bytes(x.as_bytes(), 10).unwrap(); - let y = FeltBigInt::::parse_bytes(y.as_bytes(), 10).unwrap(); - let p:BigUint = BigUint::parse_bytes(CAIRO_PRIME_BIGUINT.to_string().as_bytes(), 16).unwrap(); - let result = &x / &y; - let as_uint = result.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - } - #[test] - // Tests that the result multiplying two random large bigint felts falls within the range [0, p]. This test is performed 100 times each run. - fn mul_bigint_felts_within_field(ref x in "([1-9][0-9]*)", ref y in "([1-9][0-9]*)") { - let x = FeltBigInt::::parse_bytes(x.as_bytes(), 10).unwrap(); - let y = FeltBigInt::::parse_bytes(y.as_bytes(), 10).unwrap(); - let p:BigUint = BigUint::parse_bytes(CAIRO_PRIME_BIGUINT.to_string().as_bytes(), 16).unwrap(); - let result = &x * &y; - let as_uint = result.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - } - #[test] - // Tests that the result of performing a multiplication with assignment between two random large bigint felts falls within the range [0, p]. This test is performed 100 times each run. - fn mul_assign_bigint_felts_within_field(ref x in "([1-9][0-9]*)", ref y in "([1-9][0-9]*)") { - let mut x = FeltBigInt::::parse_bytes(x.as_bytes(), 10).unwrap(); - let y = FeltBigInt::::parse_bytes(y.as_bytes(), 10).unwrap(); - let p:BigUint = BigUint::parse_bytes(CAIRO_PRIME_BIGUINT.to_string().as_bytes(), 16).unwrap(); - x *= &y; - let as_uint = x.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - } - #[test] - // Tests that the result of applying the negative operation to a large bigint felt falls within the range [0, p]. This test is performed 100 times each run. - fn neg_bigint_felt_within_field(ref x in "([1-9][0-9]*)") { - let x = FeltBigInt::::parse_bytes(x.as_bytes(), 10).unwrap(); - let p:BigUint = BigUint::parse_bytes(CAIRO_PRIME_BIGUINT.to_string().as_bytes(), 16).unwrap(); - let result = -x; - let as_uint = &result.to_biguint(); - prop_assert!(as_uint < &p, "{}", as_uint); - } - - #[test] - // Property-based test that ensures, for 100 {value}s that are randomly generated each time tests are run, that performing a bit shift to the left by an amount {y} of bits (between 0 and 999) returns a result that is inside of the range [0, p]. - fn shift_left_bigint_felt_within_field(ref x in "([1-9][0-9]*)", ref y in "[0-9]{1,3}") { - let x = FeltBigInt::::parse_bytes(x.as_bytes(), 10).unwrap(); - let y = y.parse::().unwrap(); - let p:BigUint = BigUint::parse_bytes(CAIRO_PRIME_BIGUINT.to_string().as_bytes(), 16).unwrap(); - let result = x << y; - let as_uint = &result.to_biguint(); - prop_assert!(as_uint < &p, "{}", as_uint); - } - - #[test] - // Property-based test that ensures, for 100 {value}s that are randomly generated each time tests are run, that performing a bit shift to the right by an amount {y} of bits (between 0 and 999) returns a result that is inside of the range [0, p]. - fn shift_right_bigint_felt_within_field(ref x in "([1-9][0-9]*)", ref y in "[0-9]{1,3}") { - let x = FeltBigInt::::parse_bytes(x.as_bytes(), 10).unwrap(); - let y = y.parse::().unwrap(); - let p:BigUint = BigUint::parse_bytes(CAIRO_PRIME_BIGUINT.to_string().as_bytes(), 16).unwrap(); - let result = x >> y; - let as_uint = &result.to_biguint(); - prop_assert!(as_uint < &p, "{}", as_uint); - } - - #[test] - // Property-based test that ensures, for 100 {value}s that are randomly generated each time tests are run, that performing a bit shift to the right with assignment by an amount {y} of bits (between 0 and 999) returns a result that is inside of the range [0, p]. - fn shift_right_assign_bigint_felt_within_field(ref x in "([1-9][0-9]*)", ref y in "[0-9]{1,3}") { - let mut x = FeltBigInt::::parse_bytes(x.as_bytes(), 10).unwrap(); - let y = y.parse::().unwrap(); - let p:BigUint = BigUint::parse_bytes(CAIRO_PRIME_BIGUINT.to_string().as_bytes(), 16).unwrap(); - x >>= y.try_into().unwrap(); - let as_uint = &x.to_biguint(); - prop_assert!(as_uint < &p, "{}", as_uint); - } - - #[test] - // Property-based test that ensures, vectors of three of values that are randomly generated each time tests are run, that performing an iterative sum returns a result that is inside of the range [0, p]. The test is performed 100 times each run. - fn sum_bigint_felt_within_field(ref x in "([1-9][0-9]*)", ref y in "([1-9][0-9]*)", ref z in "([1-9][0-9]*)") { - let x = FeltBigInt::::parse_bytes(x.as_bytes(), 10).unwrap(); - let y = FeltBigInt::::parse_bytes(y.as_bytes(), 10).unwrap(); - let z = FeltBigInt::::parse_bytes(z.as_bytes(), 10).unwrap(); - let p:BigUint = BigUint::parse_bytes(CAIRO_PRIME_BIGUINT.to_string().as_bytes(), 16).unwrap(); - let v = vec![x, y, z]; - let result: FeltBigInt = v.into_iter().sum(); - let as_uint = result.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - } - } -} diff --git a/felt/src/lib.rs b/felt/src/lib.rs deleted file mode 100644 index d79d3f2ad9..0000000000 --- a/felt/src/lib.rs +++ /dev/null @@ -1,42 +0,0 @@ -#![cfg_attr(not(feature = "std"), no_std)] - -#[allow(unused_imports)] -#[macro_use] -#[cfg(all(not(feature = "std"), feature = "alloc"))] -pub extern crate alloc; - -#[cfg(not(feature = "lambdaworks-felt"))] -mod bigint_felt; -#[cfg(not(feature = "lambdaworks-felt"))] -mod lib_bigint_felt; -#[cfg(feature = "lambdaworks-felt")] -mod lib_lambdaworks; - -use core::fmt; - -#[cfg(feature = "lambdaworks-felt")] -pub use lib_lambdaworks::Felt252; - -#[cfg(not(feature = "lambdaworks-felt"))] -pub use lib_bigint_felt::Felt252; - -pub const PRIME_STR: &str = "0x800000000000011000000000000000000000000000000000000000000000001"; // in decimal, this is equal to 3618502788666131213697322783095070105623107215331596699973092056135872020481 -pub const FIELD_HIGH: u128 = (1 << 123) + (17 << 64); // this is equal to 10633823966279327296825105735305134080 -pub const FIELD_LOW: u128 = 1; - -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct ParseFeltError; - -impl fmt::Display for ParseFeltError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{ParseFeltError:?}") - } -} - -#[cfg(any(feature = "arbitrary", test))] -#[cfg_attr(feature = "lambdaworks-felt", path = "arbitrary_lambdaworks.rs")] -#[cfg_attr(not(feature = "lambdaworks-felt"), path = "arbitrary_bigint_felt.rs")] -/// [`proptest::arbitrary::Arbitrary`] implementation for [`Felt252`], and [`Strategy`] generating functions. -/// -/// Not to be confused with [`arbitrary::Arbitrary`], which is also enabled by the _arbitrary_ feature. -pub mod arbitrary; diff --git a/felt/src/lib_bigint_felt.rs b/felt/src/lib_bigint_felt.rs deleted file mode 100644 index 1c9f3e0479..0000000000 --- a/felt/src/lib_bigint_felt.rs +++ /dev/null @@ -1,1719 +0,0 @@ -use crate::ParseFeltError; - -use crate::bigint_felt::{FeltBigInt, FIELD_HIGH, FIELD_LOW}; -use num_bigint::{BigInt, BigUint, U64Digits}; -use num_integer::Integer; -use num_traits::{Bounded, FromPrimitive, Num, One, Pow, Signed, ToPrimitive, Zero}; -use serde::{Deserialize, Serialize}; - -use core::{ - convert::Into, - fmt, - iter::Sum, - ops::{ - Add, AddAssign, BitAnd, BitOr, BitXor, Div, Mul, MulAssign, Neg, Rem, Shl, Shr, ShrAssign, - Sub, SubAssign, - }, -}; - -#[cfg(all(not(feature = "std"), feature = "alloc"))] -use alloc::{string::String, vec::Vec}; - -#[cfg(all(feature = "arbitrary", feature = "std"))] -use arbitrary::Arbitrary; - -pub(crate) trait FeltOps { - fn new>>(value: T) -> Self; - - fn modpow( - &self, - exponent: &FeltBigInt, - modulus: &FeltBigInt, - ) -> Self; - - fn iter_u64_digits(&self) -> U64Digits; - - #[cfg(any(feature = "std", feature = "alloc"))] - fn to_signed_bytes_le(&self) -> Vec; - - #[cfg(any(feature = "std", feature = "alloc"))] - fn to_bytes_be(&self) -> Vec; - - fn parse_bytes(buf: &[u8], radix: u32) -> Option>; - - fn from_bytes_be(bytes: &[u8]) -> Self; - - fn from_bytes_le(bytes: &[u8]) -> Self; - - #[cfg(any(feature = "std", feature = "alloc"))] - fn to_str_radix(&self, radix: u32) -> String; - - fn to_signed_felt(&self) -> BigInt; - - fn to_bigint(&self) -> BigInt; - - fn to_biguint(&self) -> BigUint; - - fn bits(&self) -> u64; - - fn prime() -> BigUint; -} - -#[macro_export] -macro_rules! felt_str { - ($val: expr) => { - $crate::Felt252::parse_bytes($val.as_bytes(), 10_u32).expect("Couldn't parse bytes") - }; - ($val: expr, $opt: expr) => { - $crate::Felt252::parse_bytes($val.as_bytes(), $opt as u32).expect("Couldn't parse bytes") - }; -} - -#[cfg_attr(all(feature = "arbitrary", feature = "std"), derive(Arbitrary))] -#[derive(Eq, Hash, PartialEq, PartialOrd, Ord, Clone, Deserialize, Default, Serialize)] -pub struct Felt252 { - pub(crate) value: FeltBigInt, -} - -macro_rules! from_num { - ($type:ty) => { - impl From<$type> for Felt252 { - fn from(value: $type) -> Self { - Self { - value: value.into(), - } - } - } - }; -} - -from_num!(i8); -from_num!(i16); -from_num!(i32); -from_num!(i64); -from_num!(i128); -from_num!(isize); -from_num!(u8); -from_num!(u16); -from_num!(u32); -from_num!(u64); -from_num!(u128); -from_num!(usize); -from_num!(BigInt); -from_num!(&BigInt); -from_num!(BigUint); -from_num!(&BigUint); - -impl From for Felt252 { - fn from(flag: bool) -> Self { - if flag { - Self::one() - } else { - Self::zero() - } - } -} - -impl Felt252 { - pub fn new>(value: T) -> Self { - value.into() - } - - #[deprecated] - pub fn modpow(&self, exponent: &Felt252, modulus: &Felt252) -> Self { - Self { - value: self.value.modpow(&exponent.value, &modulus.value), - } - } - - pub fn iter_u64_digits(&self) -> U64Digits { - self.value.iter_u64_digits() - } - - pub fn to_le_bytes(&self) -> [u8; 32] { - let mut res = [0u8; 32]; - let mut iter = self.iter_u64_digits(); - let (d0, d1, d2, d3) = ( - iter.next().unwrap_or_default().to_le_bytes(), - iter.next().unwrap_or_default().to_le_bytes(), - iter.next().unwrap_or_default().to_le_bytes(), - iter.next().unwrap_or_default().to_le_bytes(), - ); - res[..8].copy_from_slice(&d0); - res[8..16].copy_from_slice(&d1); - res[16..24].copy_from_slice(&d2); - res[24..].copy_from_slice(&d3); - res - } - - pub fn to_be_bytes(&self) -> [u8; 32] { - let mut bytes = self.to_le_bytes(); - bytes.reverse(); - bytes - } - - pub fn to_le_digits(&self) -> [u64; 4] { - let mut iter = self.iter_u64_digits(); - [ - iter.next().unwrap_or_default(), - iter.next().unwrap_or_default(), - iter.next().unwrap_or_default(), - iter.next().unwrap_or_default(), - ] - } - - #[cfg(any(feature = "std", feature = "alloc"))] - #[deprecated] - pub fn to_signed_bytes_le(&self) -> Vec { - // NOTE: this is unsigned - self.value.to_signed_bytes_le() - } - #[cfg(any(feature = "std", feature = "alloc"))] - pub fn to_bytes_be(&self) -> Vec { - self.value.to_bytes_be() - } - - pub fn parse_bytes(buf: &[u8], radix: u32) -> Option { - Some(Self { - value: FeltBigInt::parse_bytes(buf, radix)?, - }) - } - pub fn from_bytes_be(bytes: &[u8]) -> Self { - Self { - value: FeltBigInt::from_bytes_be(bytes), - } - } - pub fn from_bytes_le(bytes: &[u8]) -> Self { - Self { - value: FeltBigInt::from_bytes_le(bytes), - } - } - pub fn from_bytes_ne(bytes: &[u8]) -> Self { - // Call either version depending on target endianness - #[cfg(target_endian = "little")] - let res = Self::from_bytes_le(bytes); - #[cfg(target_endian = "big")] - let res = Self::from_bytes_be(bytes); - res - } - #[cfg(any(feature = "std", feature = "alloc"))] - pub fn to_str_radix(&self, radix: u32) -> String { - self.value.to_str_radix(radix) - } - - /// Converts [`Felt252`] into a [`BigInt`] number in the range: `(- FIELD / 2, FIELD / 2)`. - /// - /// # Examples - /// - /// ``` - /// # use crate::cairo_felt::Felt252; - /// # use num_bigint::BigInt; - /// # use num_traits::Bounded; - /// let positive = Felt252::new(5); - /// assert_eq!(positive.to_signed_felt(), Into::::into(5)); - /// - /// let negative = Felt252::max_value(); - /// assert_eq!(negative.to_signed_felt(), Into::::into(-1)); - /// ``` - pub fn to_signed_felt(&self) -> BigInt { - #[allow(deprecated)] - self.value.to_signed_felt() - } - - // Converts [`Felt252`]'s representation directly into a [`BigInt`]. - // Equivalent to doing felt.to_biguint().to_bigint(). - pub fn to_bigint(&self) -> BigInt { - #[allow(deprecated)] - self.value.to_bigint() - } - - /// Converts [`Felt252`] into a [`BigUint`] number. - /// - /// # Examples - /// - /// ``` - /// # use crate::cairo_felt::Felt252; - /// # use num_bigint::BigUint; - /// # use num_traits::{Num, Bounded}; - /// let positive = Felt252::new(5); - /// assert_eq!(positive.to_biguint(), Into::::into(5_u32)); - /// - /// let negative = Felt252::max_value(); - /// assert_eq!(negative.to_biguint(), BigUint::from_str_radix("800000000000011000000000000000000000000000000000000000000000000", 16).unwrap()); - /// ``` - pub fn to_biguint(&self) -> BigUint { - #[allow(deprecated)] - self.value.to_biguint() - } - pub fn sqrt(&self) -> Self { - // Based on Tonelli-Shanks' algorithm for finding square roots - // and sympy's library implementation of said algorithm. - if self.is_zero() || self.is_one() { - return self.clone(); - } - - let max_felt = Felt252::max_value(); - let trailing_prime = Felt252::max_value() >> 192; // 0x800000000000011 - - let a = self.pow(&trailing_prime); - let d = (&Felt252::new(3_i32)).pow(&trailing_prime); - let mut m = Felt252::zero(); - let mut exponent = Felt252::one() << 191_u32; - let mut adm; - for i in 0..192_u32 { - adm = &a * &(&d).pow(&m); - adm = (&adm).pow(&exponent); - exponent >>= 1; - // if adm ≡ -1 (mod CAIRO_PRIME) - if adm == max_felt { - m += Felt252::one() << i; - } - } - let root_1 = self.pow(&((trailing_prime + 1_u32) >> 1)) * (&d).pow(&(m >> 1)); - let root_2 = &max_felt - &root_1 + 1_usize; - if root_1 < root_2 { - root_1 - } else { - root_2 - } - } - - pub fn bits(&self) -> u64 { - self.value.bits() - } - - pub fn prime() -> BigUint { - FeltBigInt::prime() - } -} - -impl Add for Felt252 { - type Output = Self; - fn add(self, rhs: Self) -> Self { - Self { - value: self.value + rhs.value, - } - } -} - -impl<'a> Add for &'a Felt252 { - type Output = Felt252; - fn add(self, rhs: Self) -> Self::Output { - Self::Output { - value: &self.value + &rhs.value, - } - } -} - -impl<'a> Add<&'a Felt252> for Felt252 { - type Output = Self; - fn add(self, rhs: &Self) -> Self::Output { - Self::Output { - value: self.value + &rhs.value, - } - } -} - -impl Add for Felt252 { - type Output = Self; - fn add(self, rhs: u32) -> Self { - Self { - value: self.value + rhs, - } - } -} - -impl Add for Felt252 { - type Output = Self; - fn add(self, rhs: usize) -> Self { - Self { - value: self.value + rhs, - } - } -} - -impl<'a> Add for &'a Felt252 { - type Output = Felt252; - fn add(self, rhs: usize) -> Self::Output { - Self::Output { - value: &self.value + rhs, - } - } -} - -impl Add for &Felt252 { - type Output = Felt252; - fn add(self, rhs: u64) -> Self::Output { - Self::Output { - value: &self.value + rhs, - } - } -} - -// This is special cased and optimized compared to the obvious implementation -// due to `pc_update` relying on this, which makes it a major bottleneck for -// execution. Testing for this function is extensive, comprised of explicit -// edge and special cases testing and property tests, all comparing to the -// more intuitive `(rhs + self).to_u64()` implementation. -// This particular implementation is much more complex than a slightly more -// intuitive one based on a single match. However, this is 8-62% faster -// depending on the case being bencharked, with an average of 32%, so it's -// worth it. -impl Add<&Felt252> for u64 { - type Output = Option; - - fn add(self, rhs: &Felt252) -> Option { - const PRIME_DIGITS_LE_HI: (u64, u64, u64) = - (0x0000000000000000, 0x0000000000000000, 0x0800000000000011); - const PRIME_MINUS_U64_MAX_DIGITS_LE_HI: (u64, u64, u64) = - (0xffffffffffffffff, 0xffffffffffffffff, 0x0800000000000010); - - // Iterate through the 64 bits digits in little-endian order to - // characterize how the sum will behave. - let mut rhs_digits = rhs.iter_u64_digits(); - // No digits means `rhs` is `0`, so the sum is simply `self`. - let Some(low) = rhs_digits.next() else { - return Some(self); - }; - // A single digit means this is effectively the sum of two `u64` numbers. - let Some(h0) = rhs_digits.next() else { - return self.checked_add(low) - }; - // Now we need to compare the 3 most significant digits. - // There are two relevant cases from now on, either `rhs` behaves like a - // substraction of a `u64` or the result of the sum falls out of range. - let (h1, h2) = (rhs_digits.next()?, rhs_digits.next()?); - match (h0, h1, h2) { - // The 3 MSB only match the prime for Felt252::max_value(), which is -1 - // in the signed field, so this is equivalent to substracting 1 to `self`. - #[allow(clippy::suspicious_arithmetic_impl)] - PRIME_DIGITS_LE_HI => self.checked_sub(1), - // For the remaining values between `[-u64::MAX..0]` (where `{0, -1}` have - // already been covered) the MSB matches that of `PRIME - u64::MAX`. - // Because we're in the negative number case, we count down. Because `0` - // and `-1` correspond to different MSBs, `0` and `1` in the LSB are less - // than `-u64::MAX`, the smallest value we can add to (read, substract it's - // magnitude from) a `u64` number, meaning we exclude them from the valid - // case. - // For the remaining range, we make take the absolute value module-2 while - // correcting by substracting `1` (note we actually substract `2` because - // the absolute value itself requires substracting `1`. - #[allow(clippy::suspicious_arithmetic_impl)] - PRIME_MINUS_U64_MAX_DIGITS_LE_HI if low >= 2 => { - (self).checked_sub(u64::MAX - (low - 2)) - } - // Any other case will result in an addition that is out of bounds, so - // the addition fails, returning `None`. - _ => None, - } - } -} - -impl AddAssign for Felt252 { - fn add_assign(&mut self, rhs: Self) { - self.value += rhs.value; - } -} - -impl<'a> AddAssign<&'a Felt252> for Felt252 { - fn add_assign(&mut self, rhs: &Self) { - self.value += &rhs.value; - } -} - -impl Sum for Felt252 { - fn sum>(iter: I) -> Self { - iter.fold(Felt252::zero(), |mut acc, x| { - acc += x; - acc - }) - } -} - -impl Neg for Felt252 { - type Output = Self; - fn neg(self) -> Self { - Self { - value: self.value.neg(), - } - } -} - -impl<'a> Neg for &'a Felt252 { - type Output = Felt252; - fn neg(self) -> Self::Output { - Self::Output { - value: (&self.value).neg(), - } - } -} - -impl Sub for Felt252 { - type Output = Self; - fn sub(self, rhs: Self) -> Self { - Self { - value: self.value - rhs.value, - } - } -} - -impl<'a> Sub for &'a Felt252 { - type Output = Felt252; - fn sub(self, rhs: Self) -> Self::Output { - Self::Output { - value: &self.value - &rhs.value, - } - } -} - -impl<'a> Sub<&'a Felt252> for Felt252 { - type Output = Self; - fn sub(self, rhs: &Self) -> Self { - Self { - value: self.value - &rhs.value, - } - } -} - -impl Sub<&Felt252> for usize { - type Output = Felt252; - fn sub(self, rhs: &Self::Output) -> Self::Output { - Self::Output { - value: self - &rhs.value, - } - } -} - -impl SubAssign for Felt252 { - fn sub_assign(&mut self, rhs: Self) { - self.value -= rhs.value - } -} - -impl<'a> SubAssign<&'a Felt252> for Felt252 { - fn sub_assign(&mut self, rhs: &Self) { - self.value -= &rhs.value; - } -} - -impl Sub for Felt252 { - type Output = Self; - fn sub(self, rhs: u32) -> Self { - Self { - value: self.value - rhs, - } - } -} - -impl<'a> Sub for &'a Felt252 { - type Output = Felt252; - fn sub(self, rhs: u32) -> Self::Output { - Self::Output { - value: &self.value - rhs, - } - } -} - -impl Sub for Felt252 { - type Output = Self; - fn sub(self, rhs: usize) -> Self { - Self { - value: self.value - rhs, - } - } -} - -impl Mul for Felt252 { - type Output = Self; - fn mul(self, rhs: Self) -> Self { - Self { - value: self.value * rhs.value, - } - } -} - -impl<'a> Mul for &'a Felt252 { - type Output = Felt252; - fn mul(self, rhs: Self) -> Self::Output { - Self::Output { - value: &self.value * &rhs.value, - } - } -} - -impl<'a> Mul<&'a Felt252> for Felt252 { - type Output = Self; - fn mul(self, rhs: &Self) -> Self { - Self { - value: self.value * &rhs.value, - } - } -} - -impl<'a> MulAssign<&'a Felt252> for Felt252 { - fn mul_assign(&mut self, rhs: &Self) { - self.value *= &rhs.value; - } -} - -impl Pow for Felt252 { - type Output = Self; - fn pow(self, rhs: u32) -> Self { - Self { - value: self.value.pow(rhs), - } - } -} - -impl<'a> Pow for &'a Felt252 { - type Output = Felt252; - fn pow(self, rhs: u32) -> Self::Output { - Self::Output { - value: (&self.value).pow(rhs), - } - } -} - -impl<'a> Pow<&'a Felt252> for &'a Felt252 { - type Output = Felt252; - fn pow(self, rhs: &'a Felt252) -> Self::Output { - Self::Output { - value: (&self.value).pow(&rhs.value), - } - } -} - -impl Div for Felt252 { - type Output = Self; - fn div(self, rhs: Self) -> Self { - Self { - value: self.value / rhs.value, - } - } -} - -impl<'a> Div for &'a Felt252 { - type Output = Felt252; - fn div(self, rhs: Self) -> Self::Output { - Self::Output { - value: &self.value / &rhs.value, - } - } -} - -impl<'a> Div for &'a Felt252 { - type Output = Felt252; - fn div(self, rhs: Self::Output) -> Self::Output { - Self::Output { - value: &self.value / rhs.value, - } - } -} - -impl Rem for Felt252 { - type Output = Self; - fn rem(self, rhs: Self) -> Self { - Self { - value: self.value % rhs.value, - } - } -} - -impl<'a> Rem<&'a Felt252> for Felt252 { - type Output = Self; - fn rem(self, rhs: &Self) -> Self { - Self { - value: self.value % &rhs.value, - } - } -} - -impl Zero for Felt252 { - fn zero() -> Self { - Self { - value: FeltBigInt::zero(), - } - } - - fn is_zero(&self) -> bool { - self.value.is_zero() - } -} - -impl One for Felt252 { - fn one() -> Self { - Self { - value: FeltBigInt::one(), - } - } - - fn is_one(&self) -> bool { - self.value.is_one() - } -} - -impl Bounded for Felt252 { - fn min_value() -> Self { - Self { - value: FeltBigInt::min_value(), - } - } - - fn max_value() -> Self { - Self { - value: FeltBigInt::max_value(), - } - } -} - -impl Num for Felt252 { - type FromStrRadixErr = ParseFeltError; - fn from_str_radix(string: &str, radix: u32) -> Result { - Ok(Self { - value: FeltBigInt::from_str_radix(string, radix)?, - }) - } -} - -impl Integer for Felt252 { - fn div_floor(&self, rhs: &Self) -> Self { - Self { - value: self.value.div_floor(&rhs.value), - } - } - - fn div_rem(&self, other: &Self) -> (Self, Self) { - let (div, rem) = self.value.div_rem(&other.value); - (Self { value: div }, Self { value: rem }) - } - - fn divides(&self, other: &Self) -> bool { - self.value.divides(&other.value) - } - - fn gcd(&self, other: &Self) -> Self { - Self { - value: self.value.gcd(&other.value), - } - } - - fn is_even(&self) -> bool { - self.value.is_even() - } - - fn is_multiple_of(&self, other: &Self) -> bool { - self.value.is_multiple_of(&other.value) - } - - fn is_odd(&self) -> bool { - self.value.is_odd() - } - - fn lcm(&self, other: &Self) -> Self { - Self { - value: self.value.lcm(&other.value), - } - } - - fn mod_floor(&self, rhs: &Self) -> Self { - Self { - value: self.value.mod_floor(&rhs.value), - } - } -} - -impl Signed for Felt252 { - fn abs(&self) -> Self { - Self { - value: self.value.abs(), - } - } - - fn abs_sub(&self, other: &Self) -> Self { - Self { - value: self.value.abs_sub(&other.value), - } - } - - fn signum(&self) -> Self { - Self { - value: self.value.signum(), - } - } - - fn is_positive(&self) -> bool { - self.value.is_positive() - } - - fn is_negative(&self) -> bool { - self.value.is_negative() - } -} - -impl Shl for Felt252 { - type Output = Self; - fn shl(self, rhs: u32) -> Self { - Self { - value: self.value << rhs, - } - } -} - -impl<'a> Shl for &'a Felt252 { - type Output = Felt252; - fn shl(self, rhs: u32) -> Self::Output { - Self::Output { - value: &self.value << rhs, - } - } -} - -impl Shl for Felt252 { - type Output = Self; - fn shl(self, rhs: usize) -> Self { - Self { - value: self.value << rhs, - } - } -} - -impl<'a> Shl for &'a Felt252 { - type Output = Felt252; - fn shl(self, rhs: usize) -> Self::Output { - Self::Output { - value: &self.value << rhs, - } - } -} - -impl Shr for Felt252 { - type Output = Self; - fn shr(self, rhs: u32) -> Self { - Self { - value: self.value >> rhs, - } - } -} - -impl<'a> Shr for &'a Felt252 { - type Output = Felt252; - fn shr(self, rhs: u32) -> Self::Output { - Self::Output { - value: &self.value >> rhs, - } - } -} - -impl ShrAssign for Felt252 { - fn shr_assign(&mut self, rhs: usize) { - self.value >>= rhs - } -} - -impl<'a> BitAnd for &'a Felt252 { - type Output = Felt252; - fn bitand(self, rhs: Self) -> Self::Output { - Self::Output { - value: &self.value & &rhs.value, - } - } -} - -impl<'a> BitAnd<&'a Felt252> for Felt252 { - type Output = Self; - fn bitand(self, rhs: &Self) -> Self { - Self { - value: self.value & &rhs.value, - } - } -} - -impl<'a> BitAnd for &'a Felt252 { - type Output = Felt252; - fn bitand(self, rhs: Self::Output) -> Self::Output { - Self::Output { - value: &self.value & rhs.value, - } - } -} - -impl<'a> BitOr for &'a Felt252 { - type Output = Felt252; - fn bitor(self, rhs: Self) -> Self::Output { - Self::Output { - value: &self.value | &rhs.value, - } - } -} - -impl<'a> BitXor for &'a Felt252 { - type Output = Felt252; - fn bitxor(self, rhs: Self) -> Self::Output { - Self::Output { - value: &self.value ^ &rhs.value, - } - } -} - -impl ToPrimitive for Felt252 { - fn to_u128(&self) -> Option { - self.value.to_u128() - } - - fn to_u64(&self) -> Option { - self.value.to_u64() - } - - fn to_i64(&self) -> Option { - self.value.to_i64() - } -} - -impl FromPrimitive for Felt252 { - fn from_u64(n: u64) -> Option { - FeltBigInt::from_u64(n).map(|n| Self { value: n }) - } - - fn from_i64(n: i64) -> Option { - FeltBigInt::from_i64(n).map(|n| Self { value: n }) - } -} - -impl fmt::Display for Felt252 { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.value) - } -} - -impl fmt::Debug for Felt252 { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.value) - } -} - -macro_rules! assert_felt_methods { - ($type:ty) => { - const _: () = { - fn assert_felt_ops() {} - fn assertion() { - assert_felt_ops::<$type>(); - } - }; - }; -} - -macro_rules! assert_felt_impl { - ($type:ty) => { - const _: () = { - fn assert_add() {} - fn assert_add_ref<'a, T: Add<&'a $type>>() {} - fn assert_add_u32>() {} - fn assert_add_usize>() {} - fn assert_add_assign() {} - fn assert_add_assign_ref<'a, T: AddAssign<&'a $type>>() {} - fn assert_sum>() {} - fn assert_neg() {} - fn assert_sub() {} - fn assert_sub_ref<'a, T: Sub<&'a $type>>() {} - fn assert_sub_assign() {} - fn assert_sub_assign_ref<'a, T: SubAssign<&'a $type>>() {} - fn assert_sub_u32>() {} - fn assert_sub_usize>() {} - fn assert_mul() {} - fn assert_mul_ref<'a, T: Mul<&'a $type>>() {} - fn assert_mul_assign_ref<'a, T: MulAssign<&'a $type>>() {} - fn assert_pow_u32>() {} - fn assert_pow_felt<'a, T: Pow<&'a $type>>() {} - fn assert_div() {} - fn assert_ref_div>() {} - fn assert_rem() {} - fn assert_rem_ref<'a, T: Rem<&'a $type>>() {} - fn assert_zero() {} - fn assert_one() {} - fn assert_bounded() {} - fn assert_num() {} - fn assert_integer() {} - fn assert_signed() {} - fn assert_shl_u32>() {} - fn assert_shl_usize>() {} - fn assert_shr_u32>() {} - fn assert_shr_assign_usize>() {} - fn assert_bitand() {} - fn assert_bitand_ref<'a, T: BitAnd<&'a $type>>() {} - fn assert_ref_bitand>() {} - fn assert_bitor() {} - fn assert_bitxor() {} - fn assert_from_primitive() {} - fn assert_to_primitive() {} - fn assert_display() {} - fn assert_debug() {} - - #[allow(dead_code)] - fn assert_all() { - assert_add::<$type>(); - assert_add::<&$type>(); - assert_add_ref::<$type>(); - assert_add_u32::<$type>(); - assert_add_usize::<$type>(); - assert_add_usize::<&$type>(); - assert_add_assign::<$type>(); - assert_add_assign_ref::<$type>(); - assert_sum::<$type>(); - assert_neg::<$type>(); - assert_neg::<&$type>(); - assert_sub::<$type>(); - assert_sub::<&$type>(); - assert_sub_ref::<$type>(); - assert_sub_assign::<$type>(); - assert_sub_assign_ref::<$type>(); - assert_sub_u32::<$type>(); - assert_sub_u32::<&$type>(); - assert_sub_usize::<$type>(); - assert_mul::<$type>(); - assert_mul::<&$type>(); - assert_mul_ref::<$type>(); - assert_mul_assign_ref::<$type>(); - assert_pow_u32::<$type>(); - assert_pow_felt::<&$type>(); - assert_div::<$type>(); - assert_div::<&$type>(); - assert_ref_div::<&$type>(); - assert_rem::<$type>(); - assert_rem_ref::<$type>(); - assert_zero::<$type>(); - assert_one::<$type>(); - assert_bounded::<$type>(); - assert_num::<$type>(); - assert_integer::<$type>(); - assert_signed::<$type>(); - assert_shl_u32::<$type>(); - assert_shl_u32::<&$type>(); - assert_shl_usize::<$type>(); - assert_shl_usize::<&$type>(); - assert_shr_u32::<$type>(); - assert_shr_u32::<&$type>(); - assert_shr_assign_usize::<$type>(); - assert_bitand::<&$type>(); - assert_bitand_ref::<$type>(); - assert_ref_bitand::<&$type>(); - assert_bitor::<&$type>(); - assert_bitxor::<&$type>(); - assert_from_primitive::<$type>(); - assert_to_primitive::<$type>(); - assert_display::<$type>(); - assert_debug::<$type>(); - } - }; - }; -} - -assert_felt_methods!(FeltBigInt); -assert_felt_impl!(FeltBigInt); -assert_felt_impl!(Felt252); - -#[cfg(test)] -mod test { - use super::*; - use crate::{arbitrary::nonzero_felt252, PRIME_STR}; - use core::cmp; - use rstest::rstest; - - use proptest::prelude::*; - - proptest! { - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property-based test that ensures, for 100 felt values that are randomly generated - // each time tests are run, that a new felt doesn't fall outside the range [0, p]. - // In this and some of the following tests, The value of {x} can be either [0] or a - // very large number, in order to try to overflow the value of {p} and thus ensure the - // modular arithmetic is working correctly. - fn new_in_range(ref x in any::<[u8; 40]>()) { - let x = Felt252::from_bytes_be(x); - let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - prop_assert!(&x.to_biguint() < p); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn from_bytes_be(high: u128, low: u128) { - let expected = (Felt252::from(high) << 128_usize) + Felt252::from(low); - let mut bytes = [0; 32]; - // big-endian order: [ high, low ] - bytes[..16].copy_from_slice(&high.to_be_bytes()); - bytes[16..].copy_from_slice(&low.to_be_bytes()); - let got = Felt252::from_bytes_be(&bytes); - prop_assert_eq!(got, expected); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn from_bytes_le(high: u128, low: u128) { - let expected = (Felt252::from(high) << 128_usize) + Felt252::from(low); - let mut bytes = [0; 32]; - // little-endian order: [ low, high ] - bytes[..16].copy_from_slice(&low.to_le_bytes()); - bytes[16..].copy_from_slice(&high.to_le_bytes()); - let got = Felt252::from_bytes_le(&bytes); - prop_assert_eq!(got, expected); - } - - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn to_be_bytes(ref x in any::()) { - let bytes = x.to_be_bytes(); - let y = &Felt252::from_bytes_be(&bytes); - prop_assert_eq!(x, y); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn to_le_bytes(ref x in any::()) { - let mut bytes = x.to_le_bytes(); - // Convert to big endian for test - bytes.reverse(); - let y = &Felt252::from_bytes_be(&bytes); - prop_assert_eq!(x, y); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn to_le_digits(ref x in any::()) { - let digits: [u64; 4] = x.to_le_digits(); - let mut bytes: Vec<_> = digits - .into_iter() - .flat_map(|x| x.to_le_bytes()) - .collect(); - // Convert to big endian for test - bytes.reverse(); - let y = &Felt252::from_bytes_be(&bytes); - prop_assert_eq!(x, y); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn to_u128_ok(x in any::()) { - let y = Felt252::from(x); - let y = y.to_u128(); - prop_assert_eq!(Some(x), y); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn to_u128_out_of_range(x in nonzero_felt252()) { - let y = x + Felt252::from(u128::MAX); - let y = y.to_u128(); - prop_assert_eq!(None, y); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property-based test that ensures, for 100 felt values that are randomly - // generated each time tests are run, that a felt created using Felt252::from_bytes_be doesn't - // fall outside the range [0, p]. - // In this and some of the following tests, The value of {x} can be either [0] or a very large number, - // in order to try to overflow the value of {p} and thus ensure the modular arithmetic is working correctly. - fn from_bytes_be_in_range(ref x in any::<[u8; 40]>()) { - let x = Felt252::from_bytes_be(x); - let max_felt = Felt252::max_value(); - prop_assert!(x <= max_felt); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property-based test that ensures, for 100 felt values that are randomly generated each time - // tests are run, that the negative of a felt doesn't fall outside the range [0, p]. - fn neg_in_range(x in any::()) { - let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - - let neg = -x.clone(); - let as_uint = &neg.to_biguint(); - prop_assert!(as_uint < p); - - // test reference variant - let neg = -&x; - let as_uint = &neg.to_biguint(); - prop_assert!(as_uint < p); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property-based test that ensures, for 100 {x} and {y} values that are randomly generated - // each time tests are run, that a subtraction between two felts {x} and {y} and doesn't fall - // outside the range [0, p]. The values of {x} and {y} can be either [0] or a very large number. - fn sub(ref x in any::(), ref y in any::()) { - let (x_int, y_int) = (&x.to_biguint(), &y.to_biguint()); - let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - - let sub_xy = x - y; - prop_assert!(&sub_xy.to_biguint() < p); - prop_assert_eq!(Felt252::from(p + x_int - y_int), sub_xy); - - let sub_yx = y - x; - prop_assert!(&sub_yx.to_biguint() < p); - prop_assert_eq!(Felt252::from(p + y_int - x_int), sub_yx); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property-based test that ensures, for 100 {x} and {y} values that are randomly generated - // each time tests are run, that a subtraction with assignment between two felts {x} and {y} - // and doesn't fall outside the range [0, p]. The values of {x} and {y} can be either [0] or a very large number. - fn sub_assign_in_range(mut x in any::(), y in any::()) { - let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - - x -= y.clone(); - let as_uint = &x.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - - // test reference variant - x -= &y; - let as_uint = &x.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property-based test that ensures, for 100 {x} and {y} values that are randomly - // generated each time tests are run, that a multiplication between two felts {x} - // and {y} and doesn't fall outside the range [0, p]. The values of {x} and {y} - // can be either [0] or a very large number. - fn mul(ref x in any::(), ref y in any::()) { - let xy_int = x.to_biguint() * y.to_biguint(); - - let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - - let (xy, yx) = (x * y, y * x); - prop_assert_eq!(&xy, &yx); - prop_assert_eq!(xy.to_biguint(), xy_int.mod_floor(p)); - prop_assert!(&xy.to_biguint() < p); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property-based test that ensures, for 100 pairs of {x} and {y} values that - // are randomly generated each time tests are run, that a multiplication with - // assignment between two felts {x} and {y} and doesn't fall outside the range [0, p]. - // The values of {x} and {y} can be either [0] or a very large number. - fn mul_assign_in_range(mut x in any::(), y in any::()) { - let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - - x *= &y; - let as_uint = &x.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property-based test that ensures, for 100 pairs of {x} and {y} values that are - // randomly generated each time tests are run, that the result of the division of - // {x} by {y} is the inverse multiplicative of {x} --that is, multiplying the result - // by {y} returns the original number {x}. The values of {x} and {y} can be either - // [0] or a very large number. - fn div_is_mul_inv(ref x in any::(), ref y in nonzero_felt252()) { - let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - prop_assume!(!y.is_zero()); - - let q = x / y; - let as_uint = &q.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - prop_assert_eq!(&(q * y), x); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property-based test that ensures, for 100 {value}s that are randomly generated - // each time tests are run, that performing a bit shift to the left by {shift_amount} - // of bits (between 0 and 999) returns a result that is inside of the range [0, p]. - fn shift_left_in_range(value in any::(), shift_amount in 0..1000_u32){ - let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - - let result = (value.clone() << shift_amount).to_biguint(); - prop_assert!(&result < p); - - let result = (&value << shift_amount).to_biguint(); - prop_assert!(&result < p); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property-based test that ensures, for 100 {value}s that are randomly - // generated each time tests are run, that performing a bit shift to the right - // by {shift_amount} of bits (between 0 and 999) returns a result that is inside of the range [0, p]. - fn shift_right_in_range(value in any::(), shift_amount in 0..1000_u32){ - let result = (value >> shift_amount).to_biguint(); - let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - prop_assert!(&result < p); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property-based test that ensures, for 100 {value}s that are randomly generated - // each time tests are run, that performing a bit shift to the right by {shift_amount} - // of bits (between 0 and 999), with assignment, returns a result that is inside of the range [0, p]. - // "With assignment" means that the result of the operation is autommatically assigned - // to the variable value, replacing its previous content. - fn shift_right_assign_in_range(mut value in any::(), shift_amount in 0..1000_usize){ - let p = BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - value >>= shift_amount; - prop_assert!(value.to_biguint() < p); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property based test that ensures, for 100 pairs of values {x} and {y} - // generated at random each time tests are run, that performing a BitAnd - // operation between them returns a result that is inside of the range [0, p]. - fn bitand_in_range(x in any::(), y in any::()){ - let p = BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - let result = x & &y; - result.to_biguint(); - prop_assert!(result.to_biguint() < p); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property based test that ensures, for 100 pairs of values {x} and {y} - // generated at random each time tests are run, that performing a BitOr - // operation between them returns a result that is inside of the range [0, p]. - fn bitor_in_range(x in any::(), y in any::()){ - let p = BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - let result = &x | &y; - prop_assert!(result.to_biguint() < p); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property based test that ensures, for 100 pairs of values {x} and {y} - // generated at random each time tests are run, that performing a BitXor - // operation between them returns a result that is inside of the range [0, p]. - fn bitxor_in_range(x in any::(), y in any::()){ - let p = BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - let result = &x ^ &y; - prop_assert!(result.to_biguint() < p); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property-based test that ensures, for 100 values {x} that are randomly - // generated each time tests are run, that raising {x} to the {y}th power - // returns a result that is inside of the range [0, p]. - fn pow_in_range(base in any::(), exp in 0..100_u32){ - let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - - let result = Pow::pow(base.clone(), exp); - let as_uint = &result.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - - // test reference variant - let result = Pow::pow(&base, exp); - let as_uint = &result.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property-based test that ensures, for 100 values {x} that are randomly - // generated each time tests are run, that raising {x} to the {y}th power - // returns a result that is inside of the range [0, p]. - fn pow_felt_in_range(base in any::(), exponent in any::()){ - let p = BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - - let result = Pow::pow(&base, &exponent); - let as_uint = result.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - - // test reference variant - let result: Felt252 = Pow::pow(&base, &exponent); - let as_uint = result.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property based test that ensures, for 100 pairs of values {x} and {y} - // generated at random each time tests are run, that performing a Sum operation - // between them returns a result that is inside of the range [0, p]. - fn sum_in_range(x in any::(), y in any::()){ - let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - - let result = x + y; - let as_uint = &result.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property test to check that the remainder of a division between 100 pairs of - // values {x} and {y},generated at random each time tests are run, falls in the - // range [0, p]. x and y can either take the value of 0 or a large integer. - // In Cairo, the result of x / y is defined to always satisfy the equation - // (x / y) * y == x, so the remainder is 0 most of the time. - fn rem_in_range(x in any::(), y in nonzero_felt252()) { - let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - - let result = x.clone() % y.clone(); - let as_uint = &result.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - - // test reference variant - let result = x % &y; - let as_uint = &result.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property based test that ensures, for 100 Felt252s {x} generated at - // random each time tests are run, that converting them into the u64 type - // returns a result that is inside of the range [0, p]. - fn from_u64_and_to_u64_primitive(x in any::()) { - let x_felt:Felt252 = Felt252::from_u64(x).unwrap(); - let x_u64:u64 = Felt252::to_u64(&x_felt).unwrap(); - - prop_assert_eq!(x, x_u64); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn from_i64_and_to_i64_primitive(x in any::()) { - let x: i64 = x as i64; - let x_felt:Felt252 = Felt252::from_i64(x).unwrap(); - let x_i64:i64 = Felt252::to_i64(&x_felt).unwrap(); - prop_assert_eq!(x, x_i64); - } - - #[test] - // Property test to check that lcm(x, y) works. Since we're operating in a prime field, lcm - // will just be the smaller number. - fn lcm_doesnt_panic(x in any::(), y in any::()) { - let lcm = x.lcm(&y); - prop_assert!(lcm == cmp::max(x, y)); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property test to check that is_multiple_of(x, y) works. Since we're operating in a prime field, is_multiple_of - // will always be true - fn is_multiple_of_doesnt_panic(x in any::(), y in any::()) { - prop_assert!(x.is_multiple_of(&y)); - } - - #[test] - fn divides_doesnt_panic(x in any::(), y in any::()) { - prop_assert!(x.divides(&y)); - } - - #[test] - fn gcd_doesnt_panic(x in any::(), y in any::()) { - let gcd1 = x.gcd(&y); - let gcd2 = y.gcd(&x); - prop_assert_eq!(gcd1, gcd2); - } - - #[test] - fn is_even(x in any::()) { - prop_assert_eq!(x.is_even(), x.to_biguint().is_even()); - } - - #[test] - fn is_odd(x in any::()) { - prop_assert_eq!(x.is_odd(), x.to_biguint().is_odd()); - } - - /// Tests the additive identity of the implementation of Zero trait for felts - /// - /// ```{.text} - /// x + 0 = x ∀ x - /// 0 + x = x ∀ x - /// ``` - #[test] - fn zero_additive_identity(ref x in any::()) { - let zero = Felt252::zero(); - prop_assert_eq!(x, &(x + &zero)); - prop_assert_eq!(x, &(&zero + x)); - } - - /// Tests the multiplicative identity of the implementation of One trait for felts - /// - /// ```{.text} - /// x * 1 = x ∀ x - /// 1 * x = x ∀ x - /// ``` - #[test] - fn one_multiplicative_identity(ref x in any::()) { - let one = Felt252::one(); - prop_assert_eq!(x, &(x * &one)); - prop_assert_eq!(x, &(&one * x)); - } - - #[test] - fn felt_is_always_positive(x in any::()) { - prop_assert!(x.is_positive()) - } - - #[test] - fn felt_is_never_negative(x in any::()) { - prop_assert!(!x.is_negative()) - } - - #[test] - fn non_zero_felt_signum_is_always_one(ref x in nonzero_felt252()) { - let one = Felt252::one(); - prop_assert_eq!(x.signum(), one) - } - - #[test] - fn sub_abs(x in any::(), y in any::()) { - let expected_abs_sub = if x > y {&x - &y} else {&y - &x}; - - prop_assert_eq!(x.abs_sub(&y), expected_abs_sub) - } - - #[test] - fn abs(x in any::()) { - prop_assert_eq!(&x, &x.abs()) - } - - #[test] - fn modpow_in_range(x in any::(), y in any::()) { - let p = BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - - let p_felt = Felt252::max_value(); - - #[allow(deprecated)] - let modpow = x.modpow(&y, &p_felt).to_biguint(); - prop_assert!(modpow < p, "{}", modpow); - } - - #[test] - fn sqrt_in_range(x in any::()) { - let p = BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - - let sqrt = x.sqrt().to_biguint(); - prop_assert!(sqrt < p, "{}", sqrt); - } - - #[test] - fn sqrt_is_inv_square(x in any::()) { - let x_sq = &x * &x; - let sqrt = x_sq.sqrt(); - - if sqrt != x { - prop_assert_eq!(Felt252::max_value() - sqrt + 1_usize, x); - } else { - prop_assert_eq!(sqrt, x); - } - } - - #[test] - fn add_to_u64(x in any::(), ref felt in any::()) { - let sum = (felt + x).to_u64(); - prop_assert_eq!(x + felt, sum); - } - - #[test] - fn add_to_u64_extremes(x in any::()) { - let big_zero = &Felt252::zero(); - let big_max = &Felt252::max_value(); - let big_min = &(big_zero + (i64::MIN as usize)); - - let sum_max = (big_max + x).to_u64(); - prop_assert_eq!(x + big_max, sum_max); - let sum_min = (big_min + x).to_u64(); - prop_assert_eq!(x + big_min, sum_min); - let sum_zero = (big_zero + x).to_u64(); - prop_assert_eq!(x + big_zero, sum_zero); - } - - #[test] - fn add_u32_in_range(x in any::(), y in any::()) { - let p = BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - let x_add_y = (x + y).to_biguint(); - prop_assert!(x_add_y < p, "{}", x_add_y); - } - - #[test] - fn add_u32_is_inv_sub(x in any::(), y in any::()) { - let expected_y = (x.clone() + y - x).to_u32().unwrap(); - prop_assert_eq!(expected_y, y, "{}", expected_y); - } - - #[test] - fn sub_u32_in_range(x in any::(), y in any::()) { - let p = BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - let x_sub_y = (x - y).to_biguint(); - prop_assert!(x_sub_y < p, "{}", x_sub_y); - } - - #[test] - fn sub_u32_is_inv_add(x in any::(), y in any::()) { - prop_assert_eq!(x.clone() - y + y, x) - } - - #[test] - fn sub_usize_in_range(x in any::(), y in any::()) { - let p = BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - let x_sub_y = (x - y).to_biguint(); - prop_assert!(x_sub_y < p, "{}", x_sub_y); - } - - #[test] - fn sub_usize_is_inv_add(x in any::(), y in any::()) { - prop_assert_eq!(x.clone() - y + y, x) - } - - #[test] - fn add_in_range(x in any::(), y in any::()) { - let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - - let sub = x + y; - let as_uint = &sub.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - } - - #[test] - fn add_is_inv_sub(ref x in any::(), ref y in any::()) { - let expected_y = x + y - x; - prop_assert_eq!(&expected_y, y, "{}", y); - } - - #[test] - fn add_assign_in_range(mut x in any::(), y in any::()) { - let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - - x += y.clone(); - let as_uint = &x.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - - // test reference variant - x += &y; - let as_uint = &x.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - } - } - - #[rstest] - fn add_to_u64_edge_cases( - #[values(0, 1, u64::MAX)] x: u64, - #[values(-2, -1, 0, 1, 1i128.neg(), i64::MIN as i128, u64::MAX as i128, u64::MAX as i128 + 1, (u64::MAX as i128).neg())] - y: i128, - ) { - let y = Felt252::from(y); - assert_eq!(x + &y, (&y + x).to_u64()); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Checks that the result of adding two zeroes is zero - fn sum_zeros_in_range() { - let x = Felt252::new(0); - let y = Felt252::new(0); - let z = Felt252::new(0); - assert_eq!(x + y, z) - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Checks that the result of multiplying two zeroes is zero - fn mul_zeros_in_range() { - let x = Felt252::new(0); - let y = Felt252::new(0); - let z = Felt252::new(0); - assert_eq!(x * y, z) - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Checks that the result of performing a bit and operation between zeroes is zero - fn bit_and_zeros_in_range() { - let x = Felt252::new(0); - let y = Felt252::new(0); - let z = Felt252::new(0); - assert_eq!(&x & &y, z) - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Checks that the result of perfforming a bit or operation between zeroes is zero - fn bit_or_zeros_in_range() { - let x = Felt252::new(0); - let y = Felt252::new(0); - let z = Felt252::new(0); - assert_eq!(&x | &y, z) - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Checks that the result of perfforming a bit xor operation between zeroes is zero - fn bit_xor_zeros_in_range() { - let x = Felt252::new(0); - let y = Felt252::new(0); - let z = Felt252::new(0); - assert_eq!(&x ^ &y, z) - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Tests that the maximum value a Felt252 can take is equal to (prime - 1) - fn upper_bound() { - let prime = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - let unit = BigUint::one(); - let felt_max_value = Felt252::max_value().to_biguint(); - assert_eq!(prime - unit, felt_max_value) - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Tests that the minimum value a Felt252 can take is equal to zero. - fn lower_bound() { - let zero = BigUint::zero(); - let felt_min_value = Felt252::min_value().to_biguint(); - assert_eq!(zero, felt_min_value) - } - - #[test] - fn zero_value() { - let zero = BigUint::zero(); - let felt_zero = Felt252::zero().to_biguint(); - assert_eq!(zero, felt_zero) - } - - #[test] - fn is_zero() { - let felt_zero = Felt252::zero(); - let felt_non_zero = Felt252::new(3); - assert!(felt_zero.is_zero()); - assert!(!felt_non_zero.is_zero()) - } - - #[test] - fn one_value() { - let one = BigUint::one(); - let felt_one = Felt252::one().to_biguint(); - assert_eq!(one, felt_one) - } - - #[test] - fn is_one() { - let felt_one = Felt252::one(); - let felt_non_one = Felt252::new(8); - assert!(felt_one.is_one()); - assert!(!felt_non_one.is_one()) - } - - #[test] - fn signum_of_zero_is_zero() { - let zero = Felt252::zero(); - assert_eq!(&zero.signum(), &zero) - } - - #[test] - fn from_bytes_ne() { - let expected = Felt252::zero(); - let bytes = [0; 32]; - let got = Felt252::from_bytes_ne(&bytes); - assert_eq!(got, expected); - } -} diff --git a/felt/src/lib_lambdaworks.rs b/felt/src/lib_lambdaworks.rs deleted file mode 100644 index 4fd06b38d8..0000000000 --- a/felt/src/lib_lambdaworks.rs +++ /dev/null @@ -1,1770 +0,0 @@ -use core::{ - convert::Into, - fmt, - iter::Sum, - ops::{ - Add, AddAssign, BitAnd, BitOr, BitXor, Div, Mul, MulAssign, Neg, Rem, Shl, Shr, ShrAssign, - Sub, SubAssign, - }, -}; -use lambdaworks_math::{ - field::{ - element::FieldElement, fields::fft_friendly::stark_252_prime_field::Stark252PrimeField, - }, - unsigned_integer::element::UnsignedInteger, -}; -use lazy_static::lazy_static; -use num_bigint::{BigInt, BigUint, Sign, ToBigInt}; -use num_integer::Integer; -use num_traits::{Bounded, FromPrimitive, Num, One, Pow, Signed, ToPrimitive, Zero}; -use serde::{Deserialize, Serialize}; - -#[cfg(all(not(feature = "std"), feature = "alloc"))] -use alloc::{string::String, vec::Vec}; - -#[cfg(feature = "arbitrary")] -use arbitrary::{Arbitrary, Unstructured}; - -use crate::{ParseFeltError, FIELD_HIGH, FIELD_LOW}; - -#[cfg(feature = "arbitrary")] -impl<'a> Arbitrary<'a> for Felt252 { - fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { - let num: BigUint = BigUint::arbitrary(u)?; - Ok(Felt252::from(num)) - } -} - -lazy_static! { - pub static ref CAIRO_PRIME_BIGUINT: BigUint = - (Into::::into(FIELD_HIGH) << 128) + Into::::into(FIELD_LOW); - pub static ref SIGNED_FELT_MAX: BigUint = (&*CAIRO_PRIME_BIGUINT).shr(1_u32); - pub static ref CAIRO_SIGNED_PRIME: BigInt = CAIRO_PRIME_BIGUINT - .to_bigint() - .expect("Conversion BigUint -> BigInt can't fail"); -} - -#[macro_export] -macro_rules! felt_str { - ($val: expr) => { - $crate::Felt252::parse_bytes($val.as_bytes(), 10_u32).expect("Couldn't parse bytes") - }; - ($val: expr, $opt: expr) => { - $crate::Felt252::parse_bytes($val.as_bytes(), $opt as u32).expect("Couldn't parse bytes") - }; -} - -#[derive(Eq, Hash, PartialEq, Clone, Deserialize, Serialize)] -#[serde(from = "BigInt")] -#[serde(into = "BigInt")] -pub struct Felt252 { - pub(crate) value: FieldElement, -} - -// TODO: remove and change for transformation + compare -impl PartialOrd for Felt252 { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -// TODO: remove and change for transformation + compare -// Also, maybe this could be changed to compare against zero without changing montgomeryness -impl Ord for Felt252 { - fn cmp(&self, other: &Self) -> core::cmp::Ordering { - self.value - .representative() - .cmp(&other.value.representative()) - } -} - -impl Default for Felt252 { - fn default() -> Self { - Self { - value: FieldElement::zero(), - } - } -} - -macro_rules! from_num { - ($type:ty, $cast:ty) => { - impl From<$type> for Felt252 { - fn from(value: $type) -> Self { - let uplifted: $cast = value as $cast; - uplifted.into() - } - } - }; -} - -from_num!(isize, i64); -from_num!(i8, i64); -from_num!(i16, i64); -from_num!(i32, i64); - -// TODO: move to upstream? -impl From for Felt252 { - fn from(value: i64) -> Self { - let value = if !value.is_negative() { - FieldElement::new(UnsignedInteger::from_u64(value as u64)) - } else { - let abs_minus_one = UnsignedInteger::from_u64(-(value + 1) as u64); - FieldElement::zero() - FieldElement::one() - FieldElement::new(abs_minus_one) - }; - Self { value } - } -} - -// TODO: move to upstream? -impl From for Felt252 { - fn from(value: i128) -> Self { - let value = if !value.is_negative() { - FieldElement::new(UnsignedInteger::from_u128(value as u128)) - } else { - let abs_minus_one = UnsignedInteger::from_u128(-(value + 1) as u128); - FieldElement::zero() - FieldElement::one() - FieldElement::new(abs_minus_one) - }; - Self { value } - } -} - -from_num!(usize, u64); -from_num!(u8, u64); -from_num!(u16, u64); -from_num!(u32, u64); - -// TODO: move to upstream? -impl From for Felt252 { - fn from(value: u64) -> Self { - let value = FieldElement::new(UnsignedInteger::from_u64(value)); - Self { value } - } -} - -// TODO: move to upstream? -impl From for Felt252 { - fn from(value: u128) -> Self { - let value = FieldElement::new(UnsignedInteger::from_u128(value)); - Self { value } - } -} - -impl From for Felt252 { - fn from(flag: bool) -> Self { - if flag { - Self::one() - } else { - Self::zero() - } - } -} - -impl From for Felt252 { - fn from(mut value: BigUint) -> Self { - if value >= *CAIRO_PRIME_BIGUINT { - value = value.mod_floor(&CAIRO_PRIME_BIGUINT); - } - let mut limbs = [0; 4]; - for (i, l) in (0..4).rev().zip(value.iter_u64_digits()) { - limbs[i] = l; - } - let value = FieldElement::new(UnsignedInteger::from_limbs(limbs)); - Self { value } - } -} - -impl From<&BigUint> for Felt252 { - fn from(value: &BigUint) -> Self { - if value >= &CAIRO_PRIME_BIGUINT { - Self::from(value.clone()) - } else { - let mut limbs = [0; 4]; - for (i, l) in (0..4).rev().zip(value.iter_u64_digits()) { - limbs[i] = l; - } - let value = FieldElement::new(UnsignedInteger::from_limbs(limbs)); - Self { value } - } - } -} - -// NOTE: used for deserialization -impl From for Felt252 { - fn from(value: BigInt) -> Self { - let val = value.mod_floor(&CAIRO_PRIME_BIGUINT.to_bigint().expect("cannot fail")); - let mut limbs = [0; 4]; - for (i, l) in (0..4).rev().zip(val.iter_u64_digits()) { - limbs[i] = l; - } - let value = FieldElement::new(UnsignedInteger::from_limbs(limbs)); - Self { value } - } -} - -// NOTE: used for serialization -impl From for BigInt { - fn from(value: Felt252) -> Self { - value.to_bigint() - } -} - -impl Felt252 { - pub fn new>(value: T) -> Self { - value.into() - } - - pub fn iter_u64_digits(&self) -> impl Iterator { - self.value.representative().limbs.into_iter().rev() - } - - #[cfg(any(feature = "std", feature = "alloc"))] - pub fn to_bytes_be(&self) -> Vec { - self.to_be_bytes().to_vec() - } - - pub fn to_le_bytes(&self) -> [u8; 32] { - // TODO: upstream should return array - let mut bytes = [0; 32]; - let digits = self.to_le_digits(); - for (i, d) in digits.into_iter().enumerate() { - let idx = i * 8; - bytes[idx..(idx + 8)].copy_from_slice(&d.to_le_bytes()); - } - bytes - } - - pub fn to_be_bytes(&self) -> [u8; 32] { - // TODO: upstream should return array - let mut bytes = [0; 32]; - let digits = self.to_be_digits(); - for (i, d) in digits.into_iter().enumerate() { - let idx = i * 8; - bytes[idx..(idx + 8)].copy_from_slice(&d.to_be_bytes()); - } - bytes - } - - pub fn to_le_digits(&self) -> [u64; 4] { - let mut rep = self.value.representative(); - rep.limbs.reverse(); - rep.limbs - } - - pub fn to_be_digits(&self) -> [u64; 4] { - self.value.representative().limbs - } - - pub fn parse_bytes(bytes: &[u8], radix: u32) -> Option { - Some(BigInt::parse_bytes(bytes, radix)?.into()) - } - - pub fn from_bytes_be(bytes: &[u8]) -> Self { - // TODO: use upstream's version when it's more lenient - Self::from(BigUint::from_bytes_be(bytes)) - } - - pub fn from_bytes_le(bytes: &[u8]) -> Self { - // TODO: use upstream's version when it's more lenient - Self::from(BigUint::from_bytes_le(bytes)) - } - - pub fn from_bytes_ne(bytes: &[u8]) -> Self { - // Call either version depending on target endianness - #[cfg(target_endian = "little")] - let res = Self::from_bytes_le(bytes); - #[cfg(target_endian = "big")] - let res = Self::from_bytes_be(bytes); - res - } - - #[cfg(any(feature = "std", feature = "alloc"))] - pub fn to_str_radix(&self, radix: u32) -> String { - if radix == 16 { - let mut res = format!("{}", self.value); - res.replace_range(..2, ""); - res - } else { - self.to_biguint().to_str_radix(radix) - } - } - - /// Converts [`Felt252`] into a [`BigInt`] number in the range: `(- FIELD / 2, FIELD / 2)`. - /// - /// # Examples - /// - /// ``` - /// # use crate::cairo_felt::Felt252; - /// # use num_bigint::BigInt; - /// # use num_traits::Bounded; - /// let positive = Felt252::new(5); - /// assert_eq!(positive.to_signed_felt(), Into::::into(5)); - /// - /// let negative = Felt252::max_value(); - /// assert_eq!(negative.to_signed_felt(), Into::::into(-1)); - /// ``` - pub fn to_signed_felt(&self) -> BigInt { - let biguint = self.to_biguint(); - if biguint > *SIGNED_FELT_MAX { - BigInt::from_biguint(num_bigint::Sign::Minus, &*CAIRO_PRIME_BIGUINT - &biguint) - } else { - biguint.to_bigint().expect("cannot fail") - } - } - - // Converts [`Felt252`]'s representation directly into a [`BigInt`]. - // Equivalent to doing felt.to_biguint().to_bigint(). - pub fn to_bigint(&self) -> BigInt { - BigInt::from_biguint(Sign::Plus, self.to_biguint()) - } - - /// Converts [`Felt252`] into a [`BigUint`] number. - /// - /// # Examples - /// - /// ``` - /// # use crate::cairo_felt::Felt252; - /// # use num_bigint::BigUint; - /// # use num_traits::{Num, Bounded}; - /// let positive = Felt252::new(5); - /// assert_eq!(positive.to_biguint(), Into::::into(5_u32)); - /// - /// let negative = Felt252::max_value(); - /// assert_eq!(negative.to_biguint(), BigUint::from_str_radix("800000000000011000000000000000000000000000000000000000000000000", 16).unwrap()); - /// ``` - pub fn to_biguint(&self) -> BigUint { - let big_digits = self - .iter_u64_digits() - .flat_map(|limb| [limb as u32, (limb >> 32) as u32]) - .collect(); - BigUint::new(big_digits) - } - - pub fn sqrt(&self) -> Self { - // Safety: must be called with residual - let (root_1, root_2) = self.value.sqrt().unwrap(); - let value = FieldElement::new(root_1.representative().min(root_2.representative())); - Self { value } - } - - pub fn bits(&self) -> u64 { - // TODO: move upstream - let rep = self.value.representative(); - match rep.limbs { - [0, 0, 0, 0] => 0, - [0, 0, 0, l0] => u64::BITS - l0.leading_zeros(), - [0, 0, l1, _] => 2 * u64::BITS - l1.leading_zeros(), - [0, l2, _, _] => 3 * u64::BITS - l2.leading_zeros(), - [l3, _, _, _] => 4 * u64::BITS - l3.leading_zeros(), - } - .into() - } - - pub fn prime() -> BigUint { - CAIRO_PRIME_BIGUINT.clone() - } -} - -impl Add for Felt252 { - type Output = Self; - fn add(self, rhs: Self) -> Self { - Self { - value: self.value + rhs.value, - } - } -} - -impl<'a> Add for &'a Felt252 { - type Output = Felt252; - fn add(self, rhs: Self) -> Self::Output { - Self::Output { - value: self.value + rhs.value, - } - } -} - -impl<'a> Add<&'a Felt252> for Felt252 { - type Output = Self; - fn add(self, rhs: &Self) -> Self::Output { - Self::Output { - value: self.value + rhs.value, - } - } -} - -impl Add for Felt252 { - type Output = Self; - fn add(self, rhs: u32) -> Self { - let rhs = UnsignedInteger::from_u64(rhs.into()); - Self { - value: self.value + FieldElement::new(rhs), - } - } -} - -impl Add for Felt252 { - type Output = Self; - fn add(self, rhs: usize) -> Self { - let rhs = UnsignedInteger::from_u64(rhs as u64); - Self { - value: self.value + FieldElement::new(rhs), - } - } -} - -impl<'a> Add for &'a Felt252 { - type Output = Felt252; - fn add(self, rhs: usize) -> Self::Output { - let rhs = UnsignedInteger::from_u64(rhs as u64); - Self::Output { - value: self.value + FieldElement::new(rhs), - } - } -} - -impl Add for &Felt252 { - type Output = Felt252; - fn add(self, rhs: u64) -> Self::Output { - let rhs = UnsignedInteger::from_u64(rhs); - Self::Output { - value: self.value + FieldElement::new(rhs), - } - } -} - -// TODO: verify if this optimization causes a speed-up in the current implementation. -// This is special cased and optimized compared to the obvious implementation -// due to `pc_update` relying on this, which makes it a major bottleneck for -// execution. Testing for this function is extensive, comprised of explicit -// edge and special cases testing and property tests, all comparing to the -// more intuitive `(rhs + self).to_u64()` implementation. -impl Add<&Felt252> for u64 { - type Output = Option; - - fn add(self, rhs: &Felt252) -> Option { - const PRIME_DIGITS_BE_HI: [u64; 3] = - [0x0800000000000011, 0x0000000000000000, 0x0000000000000000]; - const PRIME_MINUS_U64_MAX_DIGITS_BE_HI: [u64; 3] = - [0x0800000000000010, 0xffffffffffffffff, 0xffffffffffffffff]; - - // Match with the 64 bits digits in big-endian order to - // characterize how the sum will behave. - match rhs.to_be_digits() { - // All digits are `0`, so the sum is simply `self`. - [0, 0, 0, 0] => Some(self), - // A single digit means this is effectively the sum of two `u64` numbers. - [0, 0, 0, low] => self.checked_add(low), - // Now we need to compare the 3 most significant digits. - // There are two relevant cases from now on, either `rhs` behaves like a - // substraction of a `u64` or the result of the sum falls out of range. - - // The 3 MSB only match the prime for Felt252::max_value(), which is -1 - // in the signed field, so this is equivalent to substracting 1 to `self`. - [hi @ .., _] if hi == PRIME_DIGITS_BE_HI => self.checked_sub(1), - - // For the remaining values between `[-u64::MAX..0]` (where `{0, -1}` have - // already been covered) the MSB matches that of `PRIME - u64::MAX`. - // Because we're in the negative number case, we count down. Because `0` - // and `-1` correspond to different MSBs, `0` and `1` in the LSB are less - // than `-u64::MAX`, the smallest value we can add to (read, substract its - // magnitude from) a `u64` number, meaning we exclude them from the valid - // case. - // For the remaining range, we take the absolute value module-2 while - // correcting by substracting `1` (note we actually substract `2` because - // the absolute value itself requires substracting `1`. - [hi @ .., low] if hi == PRIME_MINUS_U64_MAX_DIGITS_BE_HI && low >= 2 => { - (self).checked_sub(u64::MAX - (low - 2)) - } - // Any other case will result in an addition that is out of bounds, so - // the addition fails, returning `None`. - _ => None, - } - } -} - -impl AddAssign for Felt252 { - fn add_assign(&mut self, rhs: Self) { - self.value += rhs.value; - } -} - -impl<'a> AddAssign<&'a Felt252> for Felt252 { - fn add_assign(&mut self, rhs: &Self) { - // TODO: optimize and move upstream - self.value += rhs.value; - } -} - -impl Sum for Felt252 { - fn sum>(iter: I) -> Self { - iter.fold(Felt252::zero(), |mut acc, x| { - acc += x; - acc - }) - } -} - -impl Neg for Felt252 { - type Output = Self; - fn neg(self) -> Self { - Self { - value: self.value.neg(), - } - } -} - -impl<'a> Neg for &'a Felt252 { - type Output = Felt252; - fn neg(self) -> Self::Output { - Self::Output { - value: (&self.value).neg(), - } - } -} - -impl Sub for Felt252 { - type Output = Self; - fn sub(self, rhs: Self) -> Self { - Self { - value: self.value - rhs.value, - } - } -} - -impl<'a> Sub for &'a Felt252 { - type Output = Felt252; - fn sub(self, rhs: Self) -> Self::Output { - Self::Output { - value: self.value - rhs.value, - } - } -} - -impl<'a> Sub<&'a Felt252> for Felt252 { - type Output = Self; - fn sub(self, rhs: &Self) -> Self { - Self { - value: self.value - rhs.value, - } - } -} - -// a - b = a + (-b), but clippy doesn't know that -#[allow(clippy::suspicious_arithmetic_impl)] -impl Sub<&Felt252> for usize { - type Output = Felt252; - fn sub(self, rhs: &Self::Output) -> Self::Output { - let neg = Self::Output { - value: (&rhs.value).neg(), - }; - neg + self - } -} - -impl SubAssign for Felt252 { - fn sub_assign(&mut self, rhs: Self) { - // TODO: optimize and move to upstream - self.value = self.value - rhs.value - } -} - -impl<'a> SubAssign<&'a Felt252> for Felt252 { - fn sub_assign(&mut self, rhs: &Self) { - // TODO: optimize and move to upstream - self.value = self.value - rhs.value - } -} - -impl Sub for Felt252 { - type Output = Self; - fn sub(self, rhs: u32) -> Self { - let value = self.value - FieldElement::new(UnsignedInteger::from_u64(rhs as u64)); - Self { value } - } -} - -impl<'a> Sub for &'a Felt252 { - type Output = Felt252; - fn sub(self, rhs: u32) -> Self::Output { - self.clone() - rhs - } -} - -impl Sub for Felt252 { - type Output = Self; - fn sub(self, rhs: usize) -> Self { - let value = self.value - FieldElement::new(UnsignedInteger::from_u64(rhs as u64)); - Self { value } - } -} - -impl Mul for Felt252 { - type Output = Self; - fn mul(self, rhs: Self) -> Self { - Self { - value: self.value * rhs.value, - } - } -} - -impl<'a> Mul for &'a Felt252 { - type Output = Felt252; - fn mul(self, rhs: Self) -> Self::Output { - Self::Output { - value: self.value * rhs.value, - } - } -} - -impl<'a> Mul<&'a Felt252> for Felt252 { - type Output = Self; - fn mul(self, rhs: &Self) -> Self { - Self { - value: self.value * rhs.value, - } - } -} - -impl<'a> MulAssign<&'a Felt252> for Felt252 { - fn mul_assign(&mut self, rhs: &Self) { - self.value = self.value * rhs.value; - } -} - -impl Pow for Felt252 { - type Output = Self; - fn pow(self, rhs: u32) -> Self { - Self { - value: self.value.pow(rhs), - } - } -} - -impl<'a> Pow for &'a Felt252 { - type Output = Felt252; - fn pow(self, rhs: u32) -> Self::Output { - Self::Output { - value: self.value.pow(rhs), - } - } -} - -impl<'a> Pow<&'a Felt252> for &'a Felt252 { - type Output = Felt252; - fn pow(self, rhs: &'a Felt252) -> Self::Output { - Self::Output { - value: self.value.pow(rhs.value.representative()), - } - } -} - -impl Div for Felt252 { - type Output = Self; - fn div(self, rhs: Self) -> Self { - Self { - value: self.value / rhs.value, - } - } -} - -impl<'a> Div for &'a Felt252 { - type Output = Felt252; - fn div(self, rhs: Self) -> Self::Output { - Self::Output { - value: self.value / rhs.value, - } - } -} - -impl<'a> Div for &'a Felt252 { - type Output = Felt252; - fn div(self, rhs: Self::Output) -> Self::Output { - Self::Output { - value: self.value / rhs.value, - } - } -} - -impl Rem for Felt252 { - type Output = Self; - fn rem(self, _rhs: Self) -> Self { - Self::zero() - } -} - -impl<'a> Rem<&'a Felt252> for Felt252 { - type Output = Self; - fn rem(self, _rhs: &Self) -> Self { - Self::zero() - } -} - -impl Zero for Felt252 { - fn zero() -> Self { - Self { - value: FieldElement::from_raw(&Stark252PrimeField::ZERO), - } - } - - fn is_zero(&self) -> bool { - self.value == FieldElement::from_raw(&Stark252PrimeField::ZERO) - } -} - -impl One for Felt252 { - fn one() -> Self { - let value = FieldElement::from_raw(&Stark252PrimeField::ONE); - Self { value } - } - - fn is_one(&self) -> bool { - self.value == FieldElement::from_raw(&Stark252PrimeField::ONE) - } -} - -impl Bounded for Felt252 { - fn min_value() -> Self { - Self { - value: FieldElement::zero(), - } - } - - fn max_value() -> Self { - Self { - value: FieldElement::zero() - FieldElement::one(), - } - } -} - -impl Num for Felt252 { - type FromStrRadixErr = ParseFeltError; - fn from_str_radix(string: &str, radix: u32) -> Result { - let res = if radix == 16 { - let value = FieldElement::from_hex(string).map_err(|_| ParseFeltError)?; - Self { value } - } else { - let biguint = BigInt::from_str_radix(string, radix).map_err(|_| ParseFeltError)?; - biguint.into() - }; - Ok(res) - } -} - -impl Integer for Felt252 { - fn div_floor(&self, rhs: &Self) -> Self { - let (d, _) = self.div_rem(rhs); - d - } - - fn mod_floor(&self, rhs: &Self) -> Self { - let (_, m) = self.div_rem(rhs); - m - } - - fn div_rem(&self, other: &Self) -> (Self, Self) { - let (div, rem) = self - .value - .representative() - .div_rem(&other.value.representative()); - ( - Self { - value: FieldElement::from(&div), - }, - Self { - value: FieldElement::from(&rem), - }, - ) - } - - // NOTE: we overload because the default impl calls div_floor AND mod_floor. - fn div_mod_floor(&self, rhs: &Self) -> (Self, Self) { - // NOTE: for positive integers, to floor and truncate is the same, so div_rem == div_mod_floor. - self.div_rem(rhs) - } - - fn divides(&self, _other: &Self) -> bool { - !self.is_zero() - } - - fn gcd(&self, other: &Self) -> Self { - Self::from(self.to_biguint().gcd(&other.to_biguint())) - } - - fn is_even(&self) -> bool { - self.value.representative().limbs[3] & 1 == 0 - } - - fn is_multiple_of(&self, other: &Self) -> bool { - !other.is_zero() - } - - fn is_odd(&self) -> bool { - !self.is_even() - } - - fn lcm(&self, other: &Self) -> Self { - self.max(other).clone() - } -} - -impl Signed for Felt252 { - fn abs(&self) -> Self { - self.clone() - } - - fn abs_sub(&self, other: &Self) -> Self { - self.max(other) - self.min(other) - } - - fn signum(&self) -> Self { - if self.is_zero() { - Self::zero() - } else { - Self::one() - } - } - - fn is_positive(&self) -> bool { - !self.is_zero() - } - - fn is_negative(&self) -> bool { - false - } -} - -// ------------------- -// Bit-wise operations -// NOTE: these do bit shifting on the representative - -impl Shl for Felt252 { - type Output = Self; - fn shl(self, rhs: u32) -> Self { - &self << rhs - } -} - -impl<'a> Shl for &'a Felt252 { - type Output = Felt252; - #[allow(clippy::suspicious_arithmetic_impl)] - fn shl(self, rhs: u32) -> Self::Output { - // TODO: upstream should be able to receive usize - Felt252::from(2).pow(rhs) * self - } -} - -impl Shl for Felt252 { - type Output = Self; - fn shl(self, rhs: usize) -> Self { - &self << rhs - } -} - -impl<'a> Shl for &'a Felt252 { - type Output = Felt252; - fn shl(self, rhs: usize) -> Self::Output { - self << (rhs as u32) - } -} - -impl Shr for Felt252 { - type Output = Self; - fn shr(self, rhs: u32) -> Self { - &self >> rhs - } -} - -impl<'a> Shr for &'a Felt252 { - type Output = Felt252; - fn shr(self, rhs: u32) -> Self::Output { - self >> (rhs as usize) - } -} - -impl Shr for Felt252 { - type Output = Felt252; - fn shr(self, rhs: usize) -> Self::Output { - &self >> rhs - } -} - -impl<'a> Shr for &'a Felt252 { - type Output = Felt252; - fn shr(self, rhs: usize) -> Self::Output { - // TODO: upstream should do this check - if rhs >= 64 * 4 { - Felt252::zero() - } else { - let value = FieldElement::new(self.value.representative() >> rhs); - Self::Output { value } - } - } -} - -impl ShrAssign for Felt252 { - fn shr_assign(&mut self, rhs: usize) { - // TODO: optimize and move upstream - *self = self.clone() >> rhs; - } -} - -impl<'a> BitAnd for &'a Felt252 { - type Output = Felt252; - fn bitand(self, rhs: Self) -> Self::Output { - self.clone() & rhs - } -} - -impl<'a> BitAnd<&'a Felt252> for Felt252 { - type Output = Self; - fn bitand(self, rhs: &Self) -> Self { - rhs & self - } -} - -impl<'a> BitAnd for &'a Felt252 { - type Output = Felt252; - fn bitand(self, rhs: Self::Output) -> Self::Output { - let a = self.value.representative(); - let b = rhs.value.representative(); - - let value = FieldElement::new(a & b); - Self::Output { value } - } -} - -impl<'a> BitOr for &'a Felt252 { - type Output = Felt252; - fn bitor(self, rhs: Self) -> Self::Output { - let a = self.value.representative(); - let b = rhs.value.representative(); - - let value = FieldElement::new(a | b); - Self::Output { value } - } -} - -impl<'a> BitXor for &'a Felt252 { - type Output = Felt252; - fn bitxor(self, rhs: Self) -> Self::Output { - let a = self.value.representative(); - let b = rhs.value.representative(); - - let value = FieldElement::new(a ^ b); - Self::Output { value } - } -} - -// TODO: move to upstream -impl ToPrimitive for Felt252 { - fn to_u128(&self) -> Option { - match self.value.representative().limbs { - [0, 0, high, low] => Some(((high as u128) << 64) | low as u128), - _ => None, - } - } - - fn to_u64(&self) -> Option { - match self.value.representative().limbs { - [0, 0, 0, val] => Some(val), - _ => None, - } - } - - fn to_i64(&self) -> Option { - // NOTE: result can't be negative - self.to_u64().as_ref().and_then(u64::to_i64) - } -} - -impl FromPrimitive for Felt252 { - fn from_u64(n: u64) -> Option { - Some(Felt252 { - value: FieldElement::from(n), - }) - } - - fn from_i64(n: i64) -> Option { - let res = (!n.is_negative()).then(|| FieldElement::from(n as u64)); - res.map(|value| Felt252 { value }) - } -} - -impl fmt::Display for Felt252 { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.to_biguint().to_str_radix(10)) - } -} - -impl fmt::Debug for Felt252 { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.to_biguint().to_str_radix(10)) - } -} - -#[cfg(test)] -mod test { - use core::cmp; - - use super::*; - use crate::{arbitrary::nonzero_felt252, PRIME_STR}; - use num_integer::Integer; - use rstest::rstest; - - use proptest::prelude::*; - - proptest! { - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property-based test that ensures, for 100 felt values that are randomly generated - // each time tests are run, that a new felt doesn't fall outside the range [0, p]. - // In this and some of the following tests, The value of {x} can be either [0] or a - // very large number, in order to try to overflow the value of {p} and thus ensure the - // modular arithmetic is working correctly. - fn new_in_range_be(ref x in any::<[u8; 40]>()) { - let x = Felt252::from_bytes_be(x); - let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - prop_assert!(&x.to_biguint() < p); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn new_in_range_le(ref x in any::<[u8; 40]>()) { - let x = Felt252::from_bytes_le(x); - let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - prop_assert!(&x.to_biguint() < p); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn from_bytes_be(high: u128, low: u128) { - let expected = (Felt252::from(high) << 128_usize) + Felt252::from(low); - let mut bytes = [0; 32]; - // big-endian order: [ high, low ] - bytes[..16].copy_from_slice(&high.to_be_bytes()); - bytes[16..].copy_from_slice(&low.to_be_bytes()); - let got = Felt252::from_bytes_be(&bytes); - prop_assert_eq!(got, expected); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn from_bytes_le(high: u128, low: u128) { - let expected = (Felt252::from(high) << 128_usize) + Felt252::from(low); - let mut bytes = [0; 32]; - // little-endian order: [ low, high ] - bytes[..16].copy_from_slice(&low.to_le_bytes()); - bytes[16..].copy_from_slice(&high.to_le_bytes()); - let got = Felt252::from_bytes_le(&bytes); - prop_assert_eq!(got, expected); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn to_be_bytes(ref x in any::()) { - let bytes = x.to_be_bytes(); - let y = &Felt252::from_bytes_be(&bytes); - prop_assert_eq!(x, y); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn to_le_bytes(ref x in any::()) { - let mut bytes = x.to_le_bytes(); - // Convert to big endian for test - bytes.reverse(); - let y = &Felt252::from_bytes_be(&bytes); - prop_assert_eq!(x, y); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn to_le_digits(ref x in any::()) { - let digits: [u64; 4] = x.to_le_digits(); - let mut bytes: Vec<_> = digits - .into_iter() - .flat_map(|x| x.to_le_bytes()) - .collect(); - // Convert to big endian for test - bytes.reverse(); - let y = &Felt252::from_bytes_be(&bytes); - prop_assert_eq!(x, y); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn to_u128_ok(x in any::()) { - let y = Felt252::from(x); - let y = y.to_u128(); - prop_assert_eq!(Some(x), y); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn to_u128_out_of_range(x in nonzero_felt252()) { - let y = x + Felt252::from(u128::MAX); - let y = y.to_u128(); - prop_assert_eq!(None, y); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property-based test that ensures, for 100 felt values that are randomly - // generated each time tests are run, that a felt created using Felt252::from_bytes_be doesn't - // fall outside the range [0, p]. - // In this and some of the following tests, The value of {x} can be either [0] or a very large number, - // in order to try to overflow the value of {p} and thus ensure the modular arithmetic is working correctly. - fn from_bytes_be_in_range(ref x in any::<[u8; 40]>()) { - let x = Felt252::from_bytes_be(x); - let max_felt = Felt252::max_value(); - prop_assert!(x <= max_felt); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property-based test that ensures, for 100 felt values that are randomly generated each time - // tests are run, that the negative of a felt doesn't fall outside the range [0, p]. - fn neg_in_range(x in any::()) { - let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - - let neg = -x.clone(); - let as_uint = &neg.to_biguint(); - prop_assert!(as_uint < p); - - // test reference variant - let neg = -&x; - let as_uint = &neg.to_biguint(); - prop_assert!(as_uint < p); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property-based test that ensures, for 100 {x} and {y} values that are randomly generated - // each time tests are run, that a subtraction between two felts {x} and {y} and doesn't fall - // outside the range [0, p]. The values of {x} and {y} can be either [0] or a very large number. - fn sub(ref x in any::(), ref y in any::()) { - let (x_int, y_int) = (&x.to_biguint(), &y.to_biguint()); - let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - - let sub_xy = x - y; - prop_assert!(&sub_xy.to_biguint() < p); - prop_assert_eq!(Felt252::from(p + x_int - y_int), sub_xy); - - let sub_yx = y - x; - prop_assert!(&sub_yx.to_biguint() < p); - prop_assert_eq!(Felt252::from(p + y_int - x_int), sub_yx); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property-based test that ensures, for 100 {x} and {y} values that are randomly generated - // each time tests are run, that a subtraction with assignment between two felts {x} and {y} - // and doesn't fall outside the range [0, p]. The values of {x} and {y} can be either [0] or a very large number. - fn sub_assign_in_range(mut x in any::(), y in any::()) { - let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - - x -= y.clone(); - let as_uint = &x.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - - // test reference variant - x -= &y; - let as_uint = &x.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property-based test that ensures, for 100 {x} and {y} values that are randomly - // generated each time tests are run, that a multiplication between two felts {x} - // and {y} and doesn't fall outside the range [0, p]. The values of {x} and {y} - // can be either [0] or a very large number. - fn mul(ref x in any::(), ref y in any::()) { - let xy_int = x.to_biguint() * y.to_biguint(); - - let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - - let (xy, yx) = (x * y, y * x); - prop_assert_eq!(&xy, &yx); - prop_assert_eq!(xy.to_biguint(), xy_int.mod_floor(p)); - prop_assert!(&xy.to_biguint() < p); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property-based test that ensures, for 100 pairs of {x} and {y} values that - // are randomly generated each time tests are run, that a multiplication with - // assignment between two felts {x} and {y} and doesn't fall outside the range [0, p]. - // The values of {x} and {y} can be either [0] or a very large number. - fn mul_assign_in_range(mut x in any::(), y in any::()) { - let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - - x *= &y; - let as_uint = &x.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property-based test that ensures, for 100 pairs of {x} and {y} values that are - // randomly generated each time tests are run, that the result of the division of - // {x} by {y} is the inverse multiplicative of {x} --that is, multiplying the result - // by {y} returns the original number {x}. The values of {x} and {y} can be either - // [0] or a very large number. - fn div_is_mul_inv(ref x in any::(), ref y in nonzero_felt252()) { - let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - prop_assume!(!y.is_zero()); - - let q = x / y; - let as_uint = &q.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - prop_assert_eq!(&(q * y), x); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property-based test that ensures, for 100 {value}s that are randomly generated - // each time tests are run, that performing a bit shift to the left by {shift_amount} - // of bits (between 0 and 999) returns a result that is inside of the range [0, p]. - fn shift_left_in_range(value in any::(), shift_amount in 0..1000_u32) { - let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - - let result = (value.clone() << shift_amount).to_biguint(); - prop_assert!(&result < p); - - let result = (&value << shift_amount).to_biguint(); - prop_assert!(&result < p); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn shift_left_equals_old_shl(value in any::(), shift_amount in 0..1000_u32) { - let expected = (value.to_biguint() << shift_amount).mod_floor(&Felt252::prime()); - - let result = (&value << shift_amount).to_biguint(); - prop_assert_eq!(&result, &expected); - - let result = (value << shift_amount).to_biguint(); - prop_assert_eq!(&result, &expected); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property-based test that ensures, for 100 {value}s that are randomly - // generated each time tests are run, that performing a bit shift to the right - // by {shift_amount} of bits (between 0 and 999) returns a result that is inside of the range [0, p]. - fn shift_right_in_range(value in any::(), shift_amount in 0..1000_u32){ - let result = (value >> shift_amount).to_biguint(); - let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - prop_assert!(&result < p); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property-based test that ensures, for 100 {value}s that are randomly generated - // each time tests are run, that performing a bit shift to the right by {shift_amount} - // of bits (between 0 and 999), with assignment, returns a result that is inside of the range [0, p]. - // "With assignment" means that the result of the operation is autommatically assigned - // to the variable value, replacing its previous content. - fn shift_right_assign_in_range(mut value in any::(), shift_amount in 0..1000_usize) { - let p = BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - value >>= shift_amount; - prop_assert!(value.to_biguint() < p); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn shift_right_equals_old_shr(value in any::(), shift_amount in 0..1000_u32) { - let expected = (value.to_biguint() >> shift_amount).mod_floor(&Felt252::prime()); - - let result = (&value >> shift_amount).to_biguint(); - prop_assert_eq!(&result, &expected); - - let result = (value >> shift_amount).to_biguint(); - prop_assert_eq!(&result, &expected); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property based test that ensures, for 100 pairs of values {x} and {y} - // generated at random each time tests are run, that performing a BitAnd - // operation between them returns a result that is inside of the range [0, p]. - fn bitand_in_range(x in any::(), y in any::()){ - let p = BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - let result = x & &y; - result.to_biguint(); - prop_assert!(result.to_biguint() < p); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property based test that ensures, for 100 pairs of values {x} and {y} - // generated at random each time tests are run, that performing a BitOr - // operation between them returns a result that is inside of the range [0, p]. - fn bitor_in_range(x in any::(), y in any::()){ - let p = BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - let result = &x | &y; - prop_assert!(result.to_biguint() < p); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property based test that ensures, for 100 pairs of values {x} and {y} - // generated at random each time tests are run, that performing a BitXor - // operation between them returns a result that is inside of the range [0, p]. - fn bitxor_in_range(x in any::(), y in any::()){ - let p = BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - let result = &x ^ &y; - prop_assert!(result.to_biguint() < p); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property-based test that ensures, for 100 values {x} that are randomly - // generated each time tests are run, that raising {x} to the {y}th power - // returns a result that is inside of the range [0, p]. - fn pow_in_range(base in any::(), exp in 0..100_u32){ - let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - - let result = Pow::pow(base.clone(), exp); - let as_uint = &result.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - - // test reference variant - let result = Pow::pow(&base, exp); - let as_uint = &result.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property-based test that ensures, for 100 values {x} that are randomly - // generated each time tests are run, that raising {x} to the {y}th power - // returns a result that is inside of the range [0, p]. - fn pow_felt_in_range(base in any::(), exponent in any::()){ - let p = BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - - let result = Pow::pow(&base, &exponent); - let as_uint = result.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - - // test reference variant - let result: Felt252 = Pow::pow(&base, &exponent); - let as_uint = result.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property based test that ensures, for 100 pairs of values {x} and {y} - // generated at random each time tests are run, that performing a Sum operation - // between them returns a result that is inside of the range [0, p]. - fn sum_in_range(x in any::(), y in any::()){ - let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - - let result = x + y; - let as_uint = &result.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property test to check that the remainder of a division between 100 pairs of - // values {x} and {y},generated at random each time tests are run, falls in the - // range [0, p]. x and y can either take the value of 0 or a large integer. - // In Cairo, the result of x / y is defined to always satisfy the equation - // (x / y) * y == x, so the remainder is 0 most of the time. - fn rem_in_range(x in any::(), y in nonzero_felt252()) { - let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - - let result = x.clone() % y.clone(); - let as_uint = &result.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - - // test reference variant - let result = x % &y; - let as_uint = &result.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property based test that ensures, for 100 Felt252s {x} generated at - // random each time tests are run, that converting them into the u64 type - // returns a result that is inside of the range [0, p]. - fn from_u64_and_to_u64_primitive(x in any::()) { - let x_felt:Felt252 = Felt252::from_u64(x).unwrap(); - let x_u64:u64 = Felt252::to_u64(&x_felt).unwrap(); - - prop_assert_eq!(x, x_u64); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn from_i64_and_to_i64_primitive(x in any::()) { - let x = x.checked_abs().unwrap_or(0); - let x_felt: Felt252 = Felt252::from_i64(x).unwrap(); - let x_i64: i64 = Felt252::to_i64(&x_felt).unwrap(); - prop_assert_eq!(x, x_i64); - } - - #[test] - // Property test to check that lcm(x, y) works. Since we're operating in a prime field, lcm - // will just be the smaller number. - fn lcm_doesnt_panic(x in any::(), y in any::()) { - let lcm = x.lcm(&y); - prop_assert!(lcm == cmp::max(x, y)); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Property test to check that is_multiple_of(x, y) works. Since we're operating in a prime field, is_multiple_of - // will always be true - fn is_multiple_of_doesnt_panic(x in any::(), y in any::()) { - prop_assert!(x.is_multiple_of(&y)); - } - - #[test] - fn divides_doesnt_panic(x in any::(), y in any::()) { - prop_assert!(x.divides(&y)); - } - - #[test] - fn gcd_doesnt_panic(x in any::(), y in any::()) { - let gcd1 = x.gcd(&y); - let gcd2 = y.gcd(&x); - prop_assert_eq!(gcd1, gcd2); - } - - #[test] - fn is_even(x in any::()) { - prop_assert_eq!(x.is_even(), x.to_biguint().is_even()); - } - - #[test] - fn is_odd(x in any::()) { - prop_assert_eq!(x.is_odd(), x.to_biguint().is_odd()); - } - - /// Tests the additive identity of the implementation of Zero trait for felts - /// - /// ```{.text} - /// x + 0 = x ∀ x - /// 0 + x = x ∀ x - /// ``` - #[test] - fn zero_additive_identity(ref x in any::()) { - let zero = Felt252::zero(); - prop_assert_eq!(x, &(x + &zero)); - prop_assert_eq!(x, &(&zero + x)); - } - - /// Tests the multiplicative identity of the implementation of One trait for felts - /// - /// ```{.text} - /// x * 1 = x ∀ x - /// 1 * x = x ∀ x - /// ``` - #[test] - fn one_multiplicative_identity(ref x in any::()) { - let one = Felt252::one(); - prop_assert_eq!(x, &(x * &one)); - prop_assert_eq!(x, &(&one * x)); - } - - #[test] - fn felt_is_always_positive(x in any::()) { - prop_assume!(!x.is_zero()); - prop_assert!(x.is_positive()) - } - - #[test] - fn felt_is_never_negative(x in any::()) { - prop_assert!(!x.is_negative()) - } - - #[test] - fn non_zero_felt_signum_is_always_one(ref x in nonzero_felt252()) { - let one = Felt252::one(); - prop_assert_eq!(x.signum(), one) - } - - #[test] - fn sub_abs(x in any::(), y in any::()) { - let expected_abs_sub = if x > y {&x - &y} else {&y - &x}; - - prop_assert_eq!(x.abs_sub(&y), expected_abs_sub) - } - - #[test] - fn abs(x in any::()) { - prop_assert_eq!(&x, &x.abs()) - } - - #[test] - fn sqrt_in_range(x in any::()) { - // we use x = x' * x' so x has a square root - let x = &x * &x; - let p = Felt252::prime(); - - let sqrt = x.sqrt().to_biguint(); - prop_assert!(sqrt < p, "{}", sqrt); - } - - #[test] - fn sqrt_is_inv_square(x in any::()) { - // we use x = x' * x' so x has a square root - let x = &x * &x; - let x_sq = &x * &x; - let sqrt = x_sq.sqrt(); - - if sqrt != x { - prop_assert_eq!(Felt252::max_value() - sqrt + 1_usize, x); - } else { - prop_assert_eq!(sqrt, x); - } - } - - #[test] - fn add_to_u64(x in any::(), ref felt in any::()) { - let sum = (felt + x).to_u64(); - prop_assert_eq!(x + felt, sum); - } - - #[test] - fn add_to_u64_extremes(x in any::()) { - let big_zero = &Felt252::zero(); - let big_max = &Felt252::max_value(); - let big_min = &(big_zero + (i64::MIN as usize)); - - let sum_max = (big_max + x).to_u64(); - prop_assert_eq!(x + big_max, sum_max); - let sum_min = (big_min + x).to_u64(); - prop_assert_eq!(x + big_min, sum_min); - let sum_zero = (big_zero + x).to_u64(); - prop_assert_eq!(x + big_zero, sum_zero); - } - - #[test] - fn add_u32_in_range(x in any::(), y in any::()) { - let p = BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - let x_add_y = (x + y).to_biguint(); - prop_assert!(x_add_y < p, "{}", x_add_y); - } - - #[test] - fn add_u32_is_inv_sub(x in any::(), y in any::()) { - let expected_y = (x.clone() + y - x).to_u32().unwrap(); - prop_assert_eq!(expected_y, y, "{}", expected_y); - } - - #[test] - fn sub_u32_in_range(x in any::(), y in any::()) { - let p = BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - let x_sub_y = (x - y).to_biguint(); - prop_assert!(x_sub_y < p, "{}", x_sub_y); - } - - #[test] - fn sub_u32_is_inv_add(x in any::(), y in any::()) { - prop_assert_eq!(x.clone() - y + y, x) - } - - #[test] - fn sub_usize_in_range(x in any::(), y in any::()) { - let p = BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - let x_sub_y = (x - y).to_biguint(); - prop_assert!(x_sub_y < p, "{}", x_sub_y); - } - - #[test] - fn sub_usize_is_inv_add(x in any::(), y in any::()) { - prop_assert_eq!(x.clone() - y + y, x) - } - - #[test] - fn add_in_range(x in any::(), y in any::()) { - let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - - let sub = x + y; - let as_uint = &sub.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - } - - #[test] - fn add_is_inv_sub(ref x in any::(), ref y in any::()) { - let expected_y = x + y - x; - prop_assert_eq!(&expected_y, y, "{}", y); - } - - #[test] - fn add_assign_in_range(mut x in any::(), y in any::()) { - let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - - x += y.clone(); - let as_uint = &x.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - - // test reference variant - x += &y; - let as_uint = &x.to_biguint(); - prop_assert!(as_uint < p, "{}", as_uint); - } - - #[test] - fn felt_to_str(x in any::(), radix in 2_u32..37) { - let str_x = x.to_str_radix(radix); - let int_x = x.to_biguint(); - let expected = int_x.to_str_radix(radix); - prop_assert_eq!(str_x, expected); - } - - #[test] - fn bigint_from_felt(x in any::()) { - prop_assert_eq!(BigInt::from(x.clone()), x.to_bigint()); - } - - #[test] - fn to_signed_felt_is_negative(x in any::()) { - let int = BigInt::from(x); - let felt = Felt252::from(x); - prop_assert_eq!(felt.to_signed_felt(), int); - } - } - - #[rstest] - fn add_to_u64_edge_cases( - #[values(0, 1, u64::MAX)] x: u64, - #[values(-2, -1, 0, 1, 1i128.neg(), i64::MIN as i128, u64::MAX as i128, u64::MAX as i128 + 1, (u64::MAX as i128).neg())] - y: i128, - ) { - let y = Felt252::from(y); - assert_eq!(x + &y, (&y + x).to_u64()); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Checks that the result of adding two zeroes is zero - fn sum_zeros_in_range() { - let x = Felt252::zero(); - let y = Felt252::zero(); - let z = Felt252::zero(); - assert_eq!(x + y, z) - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Checks that the result of multiplying two zeroes is zero - fn mul_zeros_in_range() { - let x = Felt252::zero(); - let y = Felt252::zero(); - let z = Felt252::zero(); - assert_eq!(x * y, z) - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Checks that the result of performing a bit and operation between zeroes is zero - fn bit_and_zeros_in_range() { - let x = Felt252::zero(); - let y = Felt252::zero(); - let z = Felt252::zero(); - assert_eq!(&x & &y, z) - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Checks that the result of perfforming a bit or operation between zeroes is zero - fn bit_or_zeros_in_range() { - let x = Felt252::zero(); - let y = Felt252::zero(); - let z = Felt252::zero(); - assert_eq!(&x | &y, z) - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Checks that the result of perfforming a bit xor operation between zeroes is zero - fn bit_xor_zeros_in_range() { - let x = Felt252::zero(); - let y = Felt252::zero(); - let z = Felt252::zero(); - assert_eq!(&x ^ &y, z) - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Tests that the maximum value a Felt252 can take is equal to (prime - 1) - fn upper_bound() { - let prime = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap(); - let unit = BigUint::one(); - let felt_max_value = Felt252::max_value().to_biguint(); - assert_eq!(prime - unit, felt_max_value) - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - // Tests that the minimum value a Felt252 can take is equal to zero. - fn lower_bound() { - let zero = BigUint::zero(); - let felt_min_value = Felt252::min_value().to_biguint(); - assert_eq!(zero, felt_min_value) - } - - #[test] - fn zero_value() { - let zero = BigUint::zero(); - let felt_zero = Felt252::zero().to_biguint(); - assert_eq!(zero, felt_zero) - } - - #[test] - fn is_zero() { - let felt_zero = Felt252::zero(); - let felt_non_zero = Felt252::new(3_u32); - assert!(felt_zero.is_zero()); - assert!(!felt_non_zero.is_zero()) - } - - #[test] - fn one_value() { - let one = BigUint::one(); - let felt_one = Felt252::one().to_biguint(); - assert_eq!(one, felt_one) - } - - #[test] - fn is_one() { - let felt_one = Felt252::one(); - let felt_non_one = Felt252::new(8_u32); - assert!(felt_one.is_one()); - assert!(!felt_non_one.is_one()) - } - - #[test] - fn signum_of_zero_is_zero() { - let zero = Felt252::zero(); - assert_eq!(&zero.signum(), &zero) - } - - #[test] - fn felt_from_str_radix_failed() { - let x = Felt252::from_str_radix("abcdefghijk", 16); - assert!(x.is_err()); - let res = x.unwrap_err().to_string(); - let expected = "ParseFeltError"; - assert_eq!(res, expected) - } - - #[test] - fn default_is_zero() { - assert_eq!(Felt252::default(), Felt252::zero()) - } - - #[test] - fn from_bytes_ne() { - let expected = Felt252::zero(); - let bytes = [0; 32]; - let got = Felt252::from_bytes_ne(&bytes); - assert_eq!(got, expected); - } -} diff --git a/fuzzer/Cargo.lock b/fuzzer/Cargo.lock index 5c99acc4da..321c4ad2e1 100644 --- a/fuzzer/Cargo.lock +++ b/fuzzer/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "ahash" -version = "0.7.6" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" dependencies = [ "getrandom", "once_cell", @@ -15,13 +15,14 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" dependencies = [ "cfg-if", "once_cell", "version_check", + "zerocopy", ] [[package]] @@ -32,15 +33,15 @@ checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" [[package]] name = "anyhow" -version = "1.0.72" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "arbitrary" -version = "1.3.0" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d098ff73c1ca148721f37baad5ea6a465a13f9573aba8641fbbbae8164a54e" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" dependencies = [ "derive_arbitrary", ] @@ -124,33 +125,12 @@ dependencies = [ "serde", ] -[[package]] -name = "bit-set" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" - [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "bitflags" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" - [[package]] name = "bitvec" version = "1.0.1" @@ -174,28 +154,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "cairo-felt" -version = "0.9.1" -dependencies = [ - "arbitrary", - "lazy_static", - "num-bigint", - "num-integer", - "num-traits", - "proptest", - "serde", -] +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "cairo-vm" @@ -205,9 +166,8 @@ dependencies = [ "arbitrary", "bincode", "bitvec", - "cairo-felt", "generic-array", - "hashbrown 0.14.0", + "hashbrown 0.14.3", "hex", "keccak", "lazy_static", @@ -223,14 +183,15 @@ dependencies = [ "sha2", "sha3", "starknet-crypto", + "starknet-types-core", "thiserror-no-std", ] [[package]] name = "cc" -version = "1.0.82" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ "jobserver", "libc", @@ -244,18 +205,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cpufeatures" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" dependencies = [ "libc", ] [[package]] name = "crypto-bigint" -version = "0.5.2" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4c2f4e1afd912bc40bfd6fed5d9dc1f288e0ba01bfcc835cc5bc3eb13efe15" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array", "subtle", @@ -285,13 +246,13 @@ dependencies = [ [[package]] name = "derive_arbitrary" -version = "1.3.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e0efad4403bfc52dc201159c4b842a246a14b98c64b55dfd0f2d89729dfeb8" +checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn 2.0.39", ] [[package]] @@ -311,39 +272,6 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" -[[package]] -name = "errno" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" -dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "fastrand" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - [[package]] name = "funty" version = "2.0.0" @@ -355,10 +283,10 @@ name = "fuzzer" version = "0.1.1" dependencies = [ "arbitrary", - "cairo-felt", "cairo-vm", "honggfuzz", "libfuzzer-sys", + "num-bigint", "pyo3", "serde", "serde_json", @@ -376,9 +304,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" dependencies = [ "cfg-if", "js-sys", @@ -393,16 +321,16 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ - "ahash 0.7.6", + "ahash 0.7.7", ] [[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 0.8.3", + "ahash 0.8.6", "allocator-api2", "serde", ] @@ -457,18 +385,18 @@ checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "jobserver" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" +checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" dependencies = [ "wasm-bindgen", ] @@ -482,6 +410,12 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "lambdaworks-math" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "540c0715d7da472edc421ceca702d3f3a716b3b9168b6211f2e3939cb14c863c" + [[package]] name = "lazy_static" version = "1.4.0" @@ -493,9 +427,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.147" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" [[package]] name = "libfuzzer-sys" @@ -508,33 +442,21 @@ dependencies = [ "once_cell", ] -[[package]] -name = "libm" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" - [[package]] name = "libmimalloc-sys" -version = "0.1.33" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4ac0e912c8ef1b735e92369695618dc5b1819f5a7bf3f167301a3ba1cea515e" +checksum = "3979b5c37ece694f1f5e51e7ecc871fdb0f517ed04ee45f88d15d6d553cb9664" dependencies = [ "cc", "libc", ] -[[package]] -name = "linux-raw-sys" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" - [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", @@ -542,9 +464,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.19" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "lru" @@ -557,9 +479,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "memmap2" @@ -581,9 +503,9 @@ dependencies = [ [[package]] name = "mimalloc" -version = "0.1.37" +version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e2894987a3459f3ffb755608bd82188f8ed00d0ae077f1edea29c068d639d98" +checksum = "fa01922b5ea280a911e323e4d2fd24b7fe5cc4042e0d2cda3c40775cdc4bdc9c" dependencies = [ "libmimalloc-sys", ] @@ -606,11 +528,10 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" dependencies = [ - "arbitrary", "autocfg", "num-integer", "num-traits", @@ -657,12 +578,11 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ "autocfg", - "libm", ] [[package]] @@ -683,9 +603,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", @@ -708,33 +628,13 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" dependencies = [ "unicode-ident", ] -[[package]] -name = "proptest" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e35c06b98bf36aba164cc17cb25f7e232f5c4aeea73baa14b8a9f0d92dbfa65" -dependencies = [ - "bit-set", - "bitflags 1.3.2", - "byteorder", - "lazy_static", - "num-traits", - "rand", - "rand_chacha", - "rand_xorshift", - "regex-syntax", - "rusty-fork", - "tempfile", - "unarray", -] - [[package]] name = "pyo3" version = "0.19.2" @@ -795,17 +695,11 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - [[package]] name = "quote" -version = "1.0.32" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -846,30 +740,15 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_xorshift" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" -dependencies = [ - "rand_core", -] - [[package]] name = "redox_syscall" -version = "0.3.5" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ - "bitflags 1.3.2", + "bitflags", ] -[[package]] -name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - [[package]] name = "rfc6979" version = "0.4.0" @@ -889,31 +768,6 @@ dependencies = [ "semver", ] -[[package]] -name = "rustix" -version = "0.38.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f" -dependencies = [ - "bitflags 2.4.0", - "errno", - "libc", - "linux-raw-sys", - "windows-sys", -] - -[[package]] -name = "rusty-fork" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" -dependencies = [ - "fnv", - "quick-error", - "tempfile", - "wait-timeout", -] - [[package]] name = "ryu" version = "1.0.15" @@ -928,35 +782,35 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.18" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" +checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" [[package]] name = "serde" -version = "1.0.183" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.183" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn 2.0.39", ] [[package]] name = "serde_json" -version = "1.0.104" +version = "1.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" dependencies = [ "itoa", "ryu", @@ -965,9 +819,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.7" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", @@ -986,9 +840,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.0" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" [[package]] name = "spin" @@ -1024,7 +878,7 @@ checksum = "af6527b845423542c8a16e060ea1bc43f67229848e7cd4c4d80be994a84220ce" dependencies = [ "starknet-curve", "starknet-ff", - "syn 2.0.28", + "syn 2.0.39", ] [[package]] @@ -1038,9 +892,9 @@ dependencies = [ [[package]] name = "starknet-ff" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2cb1d9c0a50380cddab99cb202c6bfb3332728a2769bd0ca2ee80b0b390dd4" +checksum = "7584bc732e4d2a8ccebdd1dda8236f7940a79a339e30ebf338d45c329659e36c" dependencies = [ "ark-ff", "crypto-bigint", @@ -1048,6 +902,22 @@ dependencies = [ "hex", ] +[[package]] +name = "starknet-types-core" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b4af540664e3dec02f36a47b79ba4df825a7752bf0941954f69753a98a397e" +dependencies = [ + "arbitrary", + "bitvec", + "lambdaworks-math", + "lazy_static", + "num-bigint", + "num-integer", + "num-traits", + "serde", +] + [[package]] name = "subtle" version = "2.5.0" @@ -1067,9 +937,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.28" +version = "2.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" dependencies = [ "proc-macro2", "quote", @@ -1084,22 +954,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "target-lexicon" -version = "0.12.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d0e916b1148c8e263850e1ebcbd046f333e0683c724876bb0da63ea4373dc8a" - -[[package]] -name = "tempfile" -version = "3.7.1" +version = "0.12.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651" -dependencies = [ - "cfg-if", - "fastrand", - "redox_syscall", - "rustix", - "windows-sys", -] +checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" [[package]] name = "thiserror-impl-no-std" @@ -1123,21 +980,15 @@ dependencies = [ [[package]] name = "typenum" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" - -[[package]] -name = "unarray" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-ident" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unindent" @@ -1151,15 +1002,6 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "wait-timeout" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" -dependencies = [ - "libc", -] - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -1168,9 +1010,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1178,24 +1020,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.28", + "syn 2.0.39", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1203,37 +1045,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn 2.0.39", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets", -] +checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" [[package]] name = "windows-targets" -version = "0.48.1" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -1246,45 +1079,45 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "wyz" @@ -1295,11 +1128,31 @@ dependencies = [ "tap", ] +[[package]] +name = "zerocopy" +version = "0.7.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d075cf85bbb114e933343e087b92f2146bac0d55b534cbb8188becf0039948e" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86cd5ca076997b97ef09d3ad65efe811fa68c9e874cb636ccb211223a813b0c2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + [[package]] name = "zeroize" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" dependencies = [ "zeroize_derive", ] @@ -1312,5 +1165,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn 2.0.39", ] diff --git a/fuzzer/Cargo.toml b/fuzzer/Cargo.toml index 1c53db1811..ea7f163360 100644 --- a/fuzzer/Cargo.toml +++ b/fuzzer/Cargo.toml @@ -13,10 +13,10 @@ members = ["."] [dependencies] arbitrary = { version = "1.3.0", features = ["derive"] } +cairo-vm = { path = "../vm", features = ["arbitrary"] } honggfuzz = "0.5.55" libfuzzer-sys = "0.4" -cairo-vm = { path = "../vm", features = ["arbitrary"] } -cairo-felt = { path = "../felt", features = ["arbitrary"] } +num-bigint = "0.4" pyo3 = { version = "0.19.2", features = ["extension-module"] } serde = { version = "1.0.180", features = ["derive"] } serde_json = "1.0.104" diff --git a/fuzzer/src/cairo_compiled_programs_fuzzer.rs b/fuzzer/src/cairo_compiled_programs_fuzzer.rs index e16220cdaa..4fa61de7dc 100644 --- a/fuzzer/src/cairo_compiled_programs_fuzzer.rs +++ b/fuzzer/src/cairo_compiled_programs_fuzzer.rs @@ -1,7 +1,9 @@ #![no_main] -use cairo_felt::Felt252; -use cairo_vm::cairo_run::{self, CairoRunConfig}; use cairo_vm::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::BuiltinHintProcessor; +use cairo_vm::{ + cairo_run::{self, CairoRunConfig}, + Felt252, +}; use libfuzzer_sys::{ arbitrary::{Arbitrary, Unstructured}, fuzz_target, @@ -197,9 +199,14 @@ fn program_bitwise( cairo_run_config: &CairoRunConfig, hint_executor: &mut BuiltinHintProcessor, ) { - let and = num1 & num2; - let xor = num1 ^ num2; - let or = num1 | num2; + use num_bigint::BigUint; + + let bnum1 = &BigUint::from_bytes_be(&num1.to_bytes_be()); + let bnum2 = &BigUint::from_bytes_be(&num2.to_bytes_be()); + + let and = bnum1 & bnum2; + let xor = bnum1 ^ bnum2; + let or = bnum1 | bnum2; let file_content = format!(" %builtins bitwise from starkware.cairo.common.bitwise import bitwise_and, bitwise_xor, bitwise_or, bitwise_operations diff --git a/fuzzer/src/fuzz_json.rs b/fuzzer/src/fuzz_json.rs index 57361a0bbc..09193c512b 100644 --- a/fuzzer/src/fuzz_json.rs +++ b/fuzzer/src/fuzz_json.rs @@ -1,5 +1,4 @@ use arbitrary::{self, Arbitrary, Unstructured}; -use cairo_felt::Felt252; use cairo_vm::{ cairo_run::{cairo_run, CairoRunConfig}, hint_processor::builtin_hint_processor::{ @@ -8,6 +7,7 @@ use cairo_vm::{ serde::deserialize_program::{ Attribute, DebugInfo, FlowTrackingData, Member, ReferenceManager, }, + Felt252, }; use honggfuzz::fuzz; use serde::{Deserialize, Serialize, Serializer}; @@ -292,9 +292,9 @@ fn arbitrary_builtins(u: &mut Unstructured) -> arbitrary::Result> { let builtin_total = u.choose_index(BUILTIN_NAMES.len())?; let mut selected_builtins = Vec::new(); - for i in 0..=builtin_total { + for builtin_name in BUILTIN_NAMES.iter().take(builtin_total + 1) { if u.ratio(2, 3)? { - selected_builtins.push(BUILTIN_NAMES[i].to_string()) + selected_builtins.push(builtin_name.to_string()) } } @@ -335,20 +335,17 @@ fn main() { loop { fuzz!(|data: (CairoRunConfig, ProgramJson)| { let (cairo_run_config, program_json) = data; - match serde_json::to_string_pretty(&program_json) { - Ok(program_raw) => { - let _ = cairo_run( - program_raw.as_bytes(), - &CairoRunConfig::default(), - &mut BuiltinHintProcessor::new_empty(), - ); - let _ = cairo_run( - program_raw.as_bytes(), - &cairo_run_config, - &mut BuiltinHintProcessor::new_empty(), - ); - } - Err(_) => {} + if let Ok(program_raw) = serde_json::to_string_pretty(&program_json) { + let _ = cairo_run( + program_raw.as_bytes(), + &CairoRunConfig::default(), + &mut BuiltinHintProcessor::new_empty(), + ); + let _ = cairo_run( + program_raw.as_bytes(), + &cairo_run_config, + &mut BuiltinHintProcessor::new_empty(), + ); } }); } diff --git a/fuzzer/src/py_export.rs b/fuzzer/src/py_export.rs index 070b233de7..332035c009 100644 --- a/fuzzer/src/py_export.rs +++ b/fuzzer/src/py_export.rs @@ -31,7 +31,7 @@ fn cairo_run_dump_mem(json: String) -> PyResult> { let result_no_panic = panic::catch_unwind(|| { cairo_run( - &json.as_bytes(), + json.as_bytes(), &config, &mut BuiltinHintProcessor::new_empty(), ) @@ -49,7 +49,7 @@ fn cairo_run_dump_mem(json: String) -> PyResult> { None => continue, Some(unwrapped_memory_cell) => { memory_dump.extend_from_slice(&(i as u64).to_le_bytes()); - memory_dump.extend_from_slice(&unwrapped_memory_cell.to_le_bytes()); + memory_dump.extend_from_slice(&unwrapped_memory_cell.to_bytes_le()); } } } diff --git a/vm/Cargo.toml b/vm/Cargo.toml index 9d42795907..67634489eb 100644 --- a/vm/Cargo.toml +++ b/vm/Cargo.toml @@ -10,13 +10,13 @@ keywords.workspace = true [features] default = ["std", "with_mimalloc"] -with_mimalloc = ["mimalloc"] +with_mimalloc = ["dep:mimalloc"] std = [ "serde_json/std", "bincode/std", "anyhow/std", + "starknet-types-core/std", "starknet-crypto/std", - "felt/std", "dep:num-prime", "thiserror-no-std/std", ] @@ -26,11 +26,6 @@ cairo-1-hints = [ "dep:ark-ff", "dep:ark-std", ] -arbitrary = ["dep:arbitrary", "felt/arbitrary", "felt/std", "std"] -lambdaworks-felt = ["felt/lambdaworks-felt"] -# Allows extending the set of hints for the current vm run from within a hint. -# For a usage example checkout vm/src/tests/run_deprecated_contract_class_simplified.rs -extensive_hints = [] # Note that these features are not retro-compatible with the cairo Python VM. test_utils = [ @@ -40,6 +35,10 @@ test_utils = [ ] # This feature will reference every test-oriented feature skip_next_instruction_hint = [] hooks = [] +arbitrary = ["dep:arbitrary", "std", "starknet-types-core/arbitrary", "starknet-types-core/std"] +# Allows extending the set of hints for the current vm run from within a hint. +# For a usage example checkout vm/src/tests/run_deprecated_contract_class_simplified.rs +extensive_hints = [] print = ["std"] [dependencies] @@ -62,10 +61,10 @@ keccak = { workspace = true } hashbrown = { workspace = true } anyhow = { workspace = true } thiserror-no-std = { workspace = true } +starknet-types-core = { version = "0.0.4", default-features = false, features = ["serde"] } # only for std num-prime = { version = "0.4.3", features = ["big-int"], optional = true } -felt = { workspace = true } bitvec = { workspace = true } # Dependencies for cairo-1-hints feature diff --git a/vm/src/air_public_input.rs b/vm/src/air_public_input.rs index fa752e94fb..692f391f2a 100644 --- a/vm/src/air_public_input.rs +++ b/vm/src/air_public_input.rs @@ -1,4 +1,4 @@ -use felt::Felt252; +use crate::Felt252; use serde::Serialize; use thiserror_no_std::Error; @@ -24,6 +24,7 @@ pub struct PublicMemoryEntry { mod mem_value_serde { use super::*; + use serde::Serializer; pub(crate) fn serialize( @@ -31,7 +32,7 @@ mod mem_value_serde { serializer: S, ) -> Result { if let Some(value) = value { - serializer.serialize_str(&format!("0x{}", value.to_str_radix(16))) + serializer.serialize_str(&format!("{:x}", value)) } else { serializer.serialize_none() } @@ -82,10 +83,9 @@ impl<'a> PublicInput<'a> { Ok(PublicMemoryEntry { address: *address, page: *page, - value: memory + value: *memory .get(*address) - .ok_or(PublicInputError::MemoryNotFound(*address))? - .clone(), + .ok_or(PublicInputError::MemoryNotFound(*address))?, }) }; let public_memory = public_memory_addresses diff --git a/vm/src/cairo_run.rs b/vm/src/cairo_run.rs index ff9cc3bc4e..2ddb1c0de2 100644 --- a/vm/src/cairo_run.rs +++ b/vm/src/cairo_run.rs @@ -9,8 +9,8 @@ use crate::{ }, }; +use crate::Felt252; use bincode::enc::write::Writer; -use felt::Felt252; use thiserror_no_std::Error; @@ -196,7 +196,7 @@ pub fn write_encoded_memory( Some(unwrapped_memory_cell) => { dest.write(&(i as u64).to_le_bytes()) .map_err(|e| EncodeTraceError(i, e))?; - dest.write(&unwrapped_memory_cell.to_le_bytes()) + dest.write(&unwrapped_memory_cell.to_bytes_le()) .map_err(|e| EncodeTraceError(i, e))?; } } @@ -209,6 +209,7 @@ pub fn write_encoded_memory( mod tests { use super::*; use crate::stdlib::prelude::*; + use crate::Felt252; use crate::{ hint_processor::{ builtin_hint_processor::builtin_hint_processor_definition::BuiltinHintProcessor, @@ -217,7 +218,6 @@ mod tests { utils::test_utils::*, }; use bincode::enc::write::SliceWriter; - use felt::Felt252; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; @@ -259,7 +259,7 @@ mod tests { assert!(cairo_runner.relocate(&mut vm, true).is_ok()); // `main` returns without doing nothing, but `not_main` sets `[ap]` to `1` // Memory location was found empirically and simply hardcoded - assert_eq!(cairo_runner.relocated_memory[2], Some(Felt252::new(123))); + assert_eq!(cairo_runner.relocated_memory[2], Some(Felt252::from(123))); } #[test] diff --git a/vm/src/hint_processor/builtin_hint_processor/bigint.rs b/vm/src/hint_processor/builtin_hint_processor/bigint.rs index ef0e8abb04..2069446fb7 100644 --- a/vm/src/hint_processor/builtin_hint_processor/bigint.rs +++ b/vm/src/hint_processor/builtin_hint_processor/bigint.rs @@ -1,9 +1,10 @@ use crate::hint_processor::builtin_hint_processor::secp::bigint_utils::BigInt5; use crate::hint_processor::builtin_hint_processor::secp::secp_utils::BASE; -use crate::math_utils::{div_mod, safe_div_bigint}; +use crate::math_utils::{div_mod, safe_div_bigint, signed_felt}; use crate::stdlib::collections::HashMap; use crate::stdlib::prelude::String; use crate::types::exec_scope::ExecutionScopes; +use crate::Felt252; use crate::{ hint_processor::{ builtin_hint_processor::secp::bigint_utils::BigInt3, @@ -12,9 +13,8 @@ use crate::{ serde::deserialize_program::ApTracking, vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, }; -use felt::Felt252; use num_bigint::BigInt; -use num_traits::{One, Signed, Zero}; +use num_traits::Signed; use super::hint_utils::insert_value_from_var_name; @@ -49,8 +49,8 @@ pub fn bigint_pack_div_mod_hint( ], }; let x_lower = x_lower.pack86(); - let d3 = x_bigint5.limbs[3].as_ref().to_signed_felt(); - let d4 = x_bigint5.limbs[4].as_ref().to_signed_felt(); + let d3 = signed_felt(*x_bigint5.limbs[3].as_ref()); + let d4 = signed_felt(*x_bigint5.limbs[4].as_ref()); x_lower + d3 * BigInt::from(BASE.pow(3)) + d4 * BigInt::from(BASE.pow(4)) }; let y: BigInt = BigInt3::from_var_name("y", vm, ids_data, ap_tracking)?.pack86(); @@ -84,9 +84,9 @@ pub fn bigint_safe_div_hint( let k = safe_div_bigint(&(res * y - x), &p)?; let (value, flag) = if k.is_positive() { - (k.clone(), Felt252::one()) + (k.clone(), Felt252::ONE) } else { - (-k.clone(), Felt252::zero()) + (-k.clone(), Felt252::ZERO) }; exec_scopes.insert_value("k", k); @@ -219,6 +219,6 @@ mod test { check_memory![vm.segments.memory, ((1, 0), 1)]; // let flag_result = get_integer_from_var_name("flag", vm, ids_data, ap_tracking); // assert!(flag_result.is_ok()); - // assert_eq!(flag_result.unwrap().as_ref(), Felt252::one()); + // assert_eq!(flag_result.unwrap().as_ref(), Felt252::ONE); } } diff --git a/vm/src/hint_processor/builtin_hint_processor/blake2s_utils.rs b/vm/src/hint_processor/builtin_hint_processor/blake2s_utils.rs index 34b5677dfe..5f5fe2ef83 100644 --- a/vm/src/hint_processor/builtin_hint_processor/blake2s_utils.rs +++ b/vm/src/hint_processor/builtin_hint_processor/blake2s_utils.rs @@ -1,6 +1,7 @@ use crate::stdlib::{borrow::Cow, collections::HashMap, prelude::*}; use crate::types::errors::math_errors::MathError; +use crate::Felt252; use crate::{ hint_processor::{ builtin_hint_processor::{ @@ -10,11 +11,12 @@ use crate::{ hint_processor_definition::HintReference, hint_processor_utils::felt_to_u32, }, + math_utils::pow2_const_nz, serde::deserialize_program::ApTracking, types::relocatable::{MaybeRelocatable, Relocatable}, vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, }; -use felt::Felt252; + use num_traits::ToPrimitive; use super::hint_utils::get_integer_from_var_name; @@ -34,14 +36,11 @@ fn get_fixed_size_u32_array( fn get_maybe_relocatable_array_from_u32(array: &Vec) -> Vec { let mut new_array = Vec::::with_capacity(array.len()); for element in array { - new_array.push(MaybeRelocatable::from(Felt252::new(*element))); + new_array.push(MaybeRelocatable::from(Felt252::from(*element))); } new_array } -fn get_maybe_relocatable_array_from_felt(array: &[Felt252]) -> Vec { - array.iter().map(MaybeRelocatable::from).collect() -} /*Helper function for the Cairo blake2s() implementation. Computes the blake2s compress function and fills the value in the right position. output_ptr should point to the middle of an instance, right after initial_state, message, t, f, @@ -183,31 +182,24 @@ pub fn blake2s_add_uint256( let data_ptr = get_ptr_from_var_name("data", vm, ids_data, ap_tracking)?; let low_addr = get_relocatable_from_var_name("low", vm, ids_data, ap_tracking)?; let high_addr = get_relocatable_from_var_name("high", vm, ids_data, ap_tracking)?; - let low = vm.get_integer(low_addr)?.into_owned(); - let high = vm.get_integer(high_addr)?.into_owned(); + let mut low = vm.get_integer(low_addr)?.into_owned(); + let mut high = vm.get_integer(high_addr)?.into_owned(); //Main logic - //Declare constant - const MASK: u32 = u32::MAX; - const B: u32 = 32; - //Convert MASK to felt - let mask = Felt252::new(MASK); //Build first batch of data - let mut inner_data = Vec::::new(); - for i in 0..4 { - inner_data.push((&low >> (B * i)) & &mask); + let b = pow2_const_nz(32); + let mut data = Vec::::with_capacity(8); + for _ in 0..4 { + let (q, r) = low.div_rem(b); + data.push(r.into()); + low = q; } - //Insert first batch of data - let data = get_maybe_relocatable_array_from_felt(&inner_data); - vm.load_data(data_ptr, &data).map_err(HintError::Memory)?; - //Build second batch of data - let mut inner_data = Vec::::new(); - for i in 0..4 { - inner_data.push((&high >> (B * i)) & &mask); + for _ in 0..4 { + let (q, r) = high.div_rem(b); + data.push(r.into()); + high = q; } //Insert second batch of data - let data = get_maybe_relocatable_array_from_felt(&inner_data); - vm.load_data((data_ptr + 4)?, &data) - .map_err(HintError::Memory)?; + vm.load_data(data_ptr, &data).map_err(HintError::Memory)?; Ok(()) } @@ -226,31 +218,27 @@ pub fn blake2s_add_uint256_bigend( let data_ptr = get_ptr_from_var_name("data", vm, ids_data, ap_tracking)?; let low_addr = get_relocatable_from_var_name("low", vm, ids_data, ap_tracking)?; let high_addr = get_relocatable_from_var_name("high", vm, ids_data, ap_tracking)?; - let low = vm.get_integer(low_addr)?.into_owned(); - let high = vm.get_integer(high_addr)?.into_owned(); + let mut low = vm.get_integer(low_addr)?.into_owned(); + let mut high = vm.get_integer(high_addr)?.into_owned(); //Main logic - //Declare constant - const MASK: u32 = u32::MAX; - const B: u32 = 32; - //Convert MASK to felt - let mask = Felt252::new(MASK); + let b = pow2_const_nz(32); + let mut data = Vec::::with_capacity(8); //Build first batch of data - let mut inner_data = Vec::::new(); - for i in 0..4 { - inner_data.push((&high >> (B * (3 - i))) & &mask); + for _ in 0..4 { + let (q, r) = low.div_rem(b); + data.push(r.into()); + low = q; } - //Insert first batch of data - let data = get_maybe_relocatable_array_from_felt(&inner_data); - vm.load_data(data_ptr, &data).map_err(HintError::Memory)?; //Build second batch of data - let mut inner_data = Vec::::new(); - for i in 0..4 { - inner_data.push((&low >> (B * (3 - i))) & &mask); + for _ in 0..4 { + let (q, r) = high.div_rem(b); + data.push(r.into()); + high = q; } + //Reverse to make big-endian + data.reverse(); //Insert second batch of data - let data = get_maybe_relocatable_array_from_felt(&inner_data); - vm.load_data((data_ptr + 4)?, &data) - .map_err(HintError::Memory)?; + vm.load_data(data_ptr, &data).map_err(HintError::Memory)?; Ok(()) } @@ -500,7 +488,7 @@ mod tests { MemoryError::InconsistentMemory(bx) )) if *bx == (Relocatable::from((2, 0)), MaybeRelocatable::from((2, 0)), - MaybeRelocatable::from(Felt252::new(1795745351))) + MaybeRelocatable::from(Felt252::from(1795745351))) ); } diff --git a/vm/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs b/vm/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs index 0b367e3edd..b23f58635b 100644 --- a/vm/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs +++ b/vm/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs @@ -20,6 +20,7 @@ use super::{ pack::*, }, }; +use crate::Felt252; use crate::{ hint_processor::{ builtin_hint_processor::secp::ec_utils::{ @@ -111,7 +112,6 @@ use crate::{ types::exec_scope::ExecutionScopes, vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, }; -use felt::Felt252; #[cfg(feature = "skip_next_instruction_hint")] use crate::hint_processor::builtin_hint_processor::skip_next_instruction::skip_next_instruction; @@ -865,7 +865,6 @@ mod tests { }, }; use assert_matches::assert_matches; - use num_traits::{One, Zero}; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; @@ -978,7 +977,7 @@ mod tests { // initialize fp vm.run_context.fp = 2; // initialize vm scope with variable `n` - let mut exec_scopes = scope![("n", Felt252::one())]; + let mut exec_scopes = scope![("n", Felt252::ONE)]; // initialize ids.continue_copying // we create a memory gap so that there is None in (1, 0), the actual addr of continue_copying vm.segments = segments![((1, 2), 5)]; @@ -1015,7 +1014,7 @@ mod tests { // initialize fp vm.run_context.fp = 2; // initialize with variable `n` - let mut exec_scopes = scope![("n", Felt252::one())]; + let mut exec_scopes = scope![("n", Felt252::ONE)]; // initialize ids.continue_copying // a value is written in the address so the hint cant insert value there vm.segments = segments![((1, 1), 5)]; @@ -1027,8 +1026,8 @@ mod tests { MemoryError::InconsistentMemory(bx) )) if *bx == (Relocatable::from((1, 1)), - MaybeRelocatable::from(Felt252::new(5)), - MaybeRelocatable::from(Felt252::zero())) + MaybeRelocatable::from(Felt252::from(5)), + MaybeRelocatable::from(Felt252::ZERO)) ); } @@ -1039,7 +1038,7 @@ mod tests { let mut vm = vm!(); // Create new vm scope with dummy variable let mut exec_scopes = ExecutionScopes::new(); - let a_value: Box = Box::new(Felt252::one()); + let a_value: Box = Box::new(Felt252::ONE); exec_scopes.enter_scope(HashMap::from([(String::from("a"), a_value)])); // Initialize memory segments add_segments!(vm, 1); @@ -1099,7 +1098,7 @@ mod tests { ((1, 5), 0) ]; let ids_data = ids_data!["length", "data", "high", "low"]; - let mut exec_scopes = scope![("__keccak_max_size", Felt252::new(500))]; + let mut exec_scopes = scope![("__keccak_max_size", Felt252::from(500))]; assert!(run_hint!(vm, ids_data, hint_code, &mut exec_scopes).is_ok()); } @@ -1121,10 +1120,10 @@ mod tests { ((1, 2), (2, 0)) ]; let ids_data = ids_data!["length", "data", "high", "low"]; - let mut exec_scopes = scope![("__keccak_max_size", Felt252::new(2))]; + let mut exec_scopes = scope![("__keccak_max_size", Felt252::from(2))]; assert_matches!( run_hint!(vm, ids_data, hint_code, &mut exec_scopes), - Err(HintError::KeccakMaxSize(bx)) if *bx == (Felt252::new(5), Felt252::new(2)) + Err(HintError::KeccakMaxSize(bx)) if *bx == (Felt252::from(5), Felt252::from(2)) ); } @@ -1169,10 +1168,10 @@ mod tests { ((1, 2), (2, 0)) ]; let ids_data = ids_data!["length", "data", "high", "low"]; - let mut exec_scopes = scope![("__keccak_max_size", Felt252::new(10))]; + let mut exec_scopes = scope![("__keccak_max_size", Felt252::from(10))]; assert_matches!( run_hint!(vm, ids_data, hint_code, &mut exec_scopes), - Err(HintError::InvalidWordSize(bx)) if *bx == Felt252::new(-1) + Err(HintError::InvalidWordSize(bx)) if *bx == Felt252::from(-1) ); } diff --git a/vm/src/hint_processor/builtin_hint_processor/cairo_keccak/keccak_hints.rs b/vm/src/hint_processor/builtin_hint_processor/cairo_keccak/keccak_hints.rs index a73a85c8b4..0beea39ee9 100644 --- a/vm/src/hint_processor/builtin_hint_processor/cairo_keccak/keccak_hints.rs +++ b/vm/src/hint_processor/builtin_hint_processor/cairo_keccak/keccak_hints.rs @@ -5,7 +5,6 @@ use crate::stdlib::{ prelude::*, }; use crate::{ - felt::Felt252, hint_processor::{ builtin_hint_processor::hint_utils::{ get_integer_from_var_name, get_ptr_from_var_name, insert_value_from_var_name, @@ -13,14 +12,16 @@ use crate::{ }, hint_processor_definition::HintReference, }, + math_utils::pow2_const_nz, serde::deserialize_program::ApTracking, types::{errors::math_errors::MathError, relocatable::MaybeRelocatable}, vm::{ errors::{hint_errors::HintError, vm_errors::VirtualMachineError}, vm_core::VirtualMachine, }, + Felt252, }; -use num_traits::{ToPrimitive, Zero}; +use num_traits::ToPrimitive; // Constants in package "starkware.cairo.common.cairo_keccak.keccak". const BYTES_IN_WORD: &str = "starkware.cairo.common.cairo_keccak.keccak.BYTES_IN_WORD"; @@ -53,19 +54,16 @@ pub fn keccak_write_args( let low = get_integer_from_var_name("low", vm, ids_data, ap_tracking)?; let high = get_integer_from_var_name("high", vm, ids_data, ap_tracking)?; - let low = low.as_ref(); - let high = high.as_ref(); - let low_args = [low & Felt252::new(u64::MAX), low >> 64_u32]; - let high_args = [high & Felt252::new(u64::MAX), high >> 64_u32]; + let bound = pow2_const_nz(64); + let (d1, d0) = low.div_rem(bound); + let (d3, d2) = high.div_rem(bound); + let args: Vec<_> = [d0, d1, d2, d3] + .into_iter() + .map(MaybeRelocatable::from) + .collect(); - let low_args: Vec<_> = low_args.into_iter().map(MaybeRelocatable::from).collect(); - vm.write_arg(inputs_ptr, &low_args) - .map_err(HintError::Memory)?; - - let high_args: Vec<_> = high_args.into_iter().map(MaybeRelocatable::from).collect(); - vm.write_arg((inputs_ptr + 2_i32)?, &high_args) - .map_err(HintError::Memory)?; + vm.write_arg(inputs_ptr, &args)?; Ok(()) } @@ -91,11 +89,11 @@ pub fn compare_bytes_in_word_nondet( // One option is to try to convert n_bytes into usize, with failure to do so simply // making value be 0 (if it can't convert then it's either negative, which can't be in Cairo memory // or too big, which also means n_bytes > BYTES_IN_WORD). The other option is to exctract - // Felt252::new(BYTES_INTO_WORD) into a lazy_static! + // Felt252::from(BYTES_INTO_WORD) into a lazy_static! let bytes_in_word = constants .get(BYTES_IN_WORD) .ok_or_else(|| HintError::MissingConstant(Box::new(BYTES_IN_WORD)))?; - let value = Felt252::new((n_bytes < bytes_in_word) as usize); + let value = Felt252::from((n_bytes < bytes_in_word) as usize); insert_value_into_ap(vm, value) } @@ -120,7 +118,7 @@ pub fn compare_keccak_full_rate_in_bytes_nondet( .get(KECCAK_FULL_RATE_IN_BYTES_CAIRO_KECCAK) .or_else(|| constants.get(KECCAK_FULL_RATE_IN_BYTES_BUILTIN_KECCAK)) .ok_or_else(|| HintError::MissingConstant(Box::new(KECCAK_FULL_RATE_IN_BYTES)))?; - let value = Felt252::new((n_bytes >= keccak_full_rate_in_bytes) as usize); + let value = Felt252::from((n_bytes >= keccak_full_rate_in_bytes) as usize); insert_value_into_ap(vm, value) } @@ -154,9 +152,9 @@ pub(crate) fn block_permutation_v1( let keccak_state_size_felts = constants .get(KECCAK_STATE_SIZE_FELTS) .ok_or_else(|| HintError::MissingConstant(Box::new(KECCAK_STATE_SIZE_FELTS)))?; - if keccak_state_size_felts >= &Felt252::new(100_i32) { + if keccak_state_size_felts >= &Felt252::from(100_i32) { return Err(HintError::InvalidKeccakStateSizeFelt252s(Box::new( - keccak_state_size_felts.clone(), + *keccak_state_size_felts, ))); } @@ -198,7 +196,7 @@ pub(crate) fn cairo_keccak_is_full_word( .to_usize() .unwrap_or(8); // Hack: if it doesn't fit `usize` then it's >= 8 let full_word = Felt252::from((n_bytes >= 8) as usize); - insert_value_from_var_name("full_word", &full_word, vm, ids_data, ap_tracking) + insert_value_from_var_name("full_word", full_word, vm, ids_data, ap_tracking) } /* @@ -223,7 +221,7 @@ pub(crate) fn block_permutation_v2( .ok_or_else(|| HintError::MissingConstant(Box::new(KECCAK_STATE_SIZE_FELTS)))?; if keccak_state_size_felts >= &Felt252::from(100_i32) { return Err(HintError::InvalidKeccakStateSizeFelt252s(Box::new( - keccak_state_size_felts.clone(), + *keccak_state_size_felts, ))); } @@ -262,14 +260,14 @@ fn cairo_keccak_finalize( .get(BLOCK_SIZE) .ok_or_else(|| HintError::MissingConstant(Box::new(BLOCK_SIZE)))?; - if keccak_state_size_felts >= &Felt252::new(100_i32) { + if keccak_state_size_felts >= &Felt252::from(100_i32) { return Err(HintError::InvalidKeccakStateSizeFelt252s(Box::new( - keccak_state_size_felts.clone(), + *keccak_state_size_felts, ))); } - if block_size >= &Felt252::new(block_size_limit) { - return Err(HintError::InvalidBlockSize(Box::new(block_size.clone()))); + if block_size >= &Felt252::from(block_size_limit) { + return Err(HintError::InvalidBlockSize(Box::new(*block_size))); }; let keccak_state_size_felts = keccak_state_size_felts.to_usize().unwrap(); @@ -280,7 +278,7 @@ fn cairo_keccak_finalize( .map_err(|_| VirtualMachineError::SliceToArrayError)?; keccak::f1600(&mut inp); - let mut padding = vec![Felt252::zero().into(); keccak_state_size_felts]; + let mut padding = vec![Felt252::ZERO.into(); keccak_state_size_felts]; padding.extend(u64_array_to_mayberelocatable_vec(&inp)); let base_padding = padding.clone(); @@ -350,7 +348,7 @@ pub(crate) fn maybe_reloc_vec_to_u64_array( Some(Cow::Owned(MaybeRelocatable::Int(ref num))) | Some(Cow::Borrowed(MaybeRelocatable::Int(ref num))) => num .to_u64() - .ok_or_else(|| MathError::Felt252ToU64Conversion(Box::new(num.clone())).into()), + .ok_or_else(|| MathError::Felt252ToU64Conversion(Box::new(*num)).into()), _ => Err(VirtualMachineError::ExpectedIntAtRange(Box::new( n.as_ref().map(|x| x.as_ref().to_owned()), ))), @@ -361,7 +359,7 @@ pub(crate) fn maybe_reloc_vec_to_u64_array( } pub fn u64_array_to_mayberelocatable_vec(array: &[u64]) -> Vec { - array.iter().map(|n| Felt252::new(*n).into()).collect() + array.iter().map(|n| Felt252::from(*n).into()).collect() } #[cfg(test)] @@ -456,7 +454,7 @@ mod tests { ids_data, hint_code, exec_scopes_ref!(), - &[(KECCAK_FULL_RATE_IN_BYTES_CAIRO_KECCAK, Felt252::new(136))] + &[(KECCAK_FULL_RATE_IN_BYTES_CAIRO_KECCAK, Felt252::from(136))] .into_iter() .map(|(k, v)| (k.to_string(), v)) .collect() @@ -485,7 +483,7 @@ mod tests { ids_data, hint_code, exec_scopes_ref!(), - &[(KECCAK_FULL_RATE_IN_BYTES_CAIRO_KECCAK, Felt252::new(136))] + &[(KECCAK_FULL_RATE_IN_BYTES_CAIRO_KECCAK, Felt252::from(136))] .into_iter() .map(|(k, v)| (k.to_string(), v)) .collect() @@ -513,7 +511,7 @@ mod tests { ids_data, hint_code, exec_scopes_ref!(), - &[(KECCAK_FULL_RATE_IN_BYTES_CAIRO_KECCAK, Felt252::new(136))] + &[(KECCAK_FULL_RATE_IN_BYTES_CAIRO_KECCAK, Felt252::from(136))] .into_iter() .map(|(k, v)| (k.to_string(), v)) .collect() diff --git a/vm/src/hint_processor/builtin_hint_processor/ec_utils.rs b/vm/src/hint_processor/builtin_hint_processor/ec_utils.rs index 5ea381e0f9..08f211b5a8 100644 --- a/vm/src/hint_processor/builtin_hint_processor/ec_utils.rs +++ b/vm/src/hint_processor/builtin_hint_processor/ec_utils.rs @@ -1,5 +1,6 @@ use crate::stdlib::{borrow::Cow, boxed::Box, collections::HashMap, prelude::*}; -use crate::utils::CAIRO_PRIME; +use crate::utils::{bigint_to_felt, biguint_to_felt, felt_to_biguint, CAIRO_PRIME}; +use crate::Felt252; use crate::{ hint_processor::{ builtin_hint_processor::hint_utils::{ @@ -10,11 +11,10 @@ use crate::{ serde::deserialize_program::ApTracking, vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, }; -use felt::Felt252; use lazy_static::lazy_static; use num_bigint::BigUint; use num_bigint::ToBigInt; -use num_traits::{Bounded, Num, One, Pow, ToPrimitive, Zero}; +use num_traits::{Num, One, Pow, ToPrimitive, Zero}; use sha2::{Digest, Sha256}; use super::hint_utils::get_ptr_from_var_name; @@ -65,7 +65,7 @@ pub fn random_ec_point_hint( let m = get_integer_from_var_name("m", vm, ids_data, ap_tracking)?; let bytes: Vec = [p.x, p.y, m, q.x, q.y] .iter() - .flat_map(|x| x.to_be_bytes()) + .flat_map(|x| x.to_bytes_be()) .collect(); let (x, y) = random_ec_point_seeded(bytes)?; let s_addr = get_relocatable_from_var_name("s", vm, ids_data, ap_tracking)?; @@ -121,7 +121,7 @@ pub fn chained_ec_op_random_ec_point_hint( .iter() .chain(m_range.iter()) .chain(q_range.iter()) - .flat_map(|x| x.to_be_bytes()) + .flat_map(|x| x.to_bytes_be()) .collect(); let (x, y) = random_ec_point_seeded(bytes)?; let s_addr = get_relocatable_from_var_name("s", vm, ids_data, ap_tracking)?; @@ -143,11 +143,11 @@ pub fn recover_y_hint( ) -> Result<(), HintError> { let p_x = get_integer_from_var_name("x", vm, ids_data, ap_tracking)?.into_owned(); let p_addr = get_relocatable_from_var_name("p", vm, ids_data, ap_tracking)?; - vm.insert_value(p_addr, &p_x)?; - let p_y = Felt252::from( - recover_y(&p_x.to_biguint()) + vm.insert_value(p_addr, p_x)?; + let p_y = biguint_to_felt( + &recover_y(&felt_to_biguint(p_x)) .ok_or_else(|| HintError::RecoverYPointNotOnCurve(Box::new(p_x)))?, - ); + )?; vm.insert_value((p_addr + 1)?, p_y)?; Ok(()) } @@ -174,8 +174,8 @@ fn random_ec_point_seeded(seed_bytes: Vec) -> Result<(Felt252, Felt252), Hin if let Some(y) = y { // Conversion from BigUint to BigInt doesnt fail return Ok(( - Felt252::from(x), - Felt252::from(y.to_bigint().unwrap() * y_coef), + biguint_to_felt(&x)?, + bigint_to_felt(&(y.to_bigint().unwrap() * y_coef))?, )); } } @@ -188,7 +188,7 @@ lazy_static! { 10 ) .unwrap(); - static ref FELT_MAX_HALVED: BigUint = Felt252::max_value().to_biguint() / 2_u32; + static ref FELT_MAX_HALVED: BigUint = felt_to_biguint(Felt252::MAX) / 2_u32; } // Recovers the corresponding y coordinate on the elliptic curve @@ -198,7 +198,7 @@ lazy_static! { fn recover_y(x: &BigUint) -> Option { let y_squared: BigUint = x.modpow(&BigUint::from(3_u32), &CAIRO_PRIME) + ALPHA * x + &*BETA; if is_quad_residue(&y_squared) { - Some(Felt252::from(y_squared).sqrt().to_biguint()) + Some(felt_to_biguint(biguint_to_felt(&y_squared).ok()?.sqrt()?)) } else { None } @@ -215,6 +215,7 @@ fn is_quad_residue(a: &BigUint) -> bool { #[cfg(test)] mod tests { use crate::any_box; + use crate::felt_str; use crate::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::BuiltinHintProcessor; use crate::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::HintProcessorData; use crate::hint_processor::hint_processor_definition::HintProcessorLogic; @@ -297,16 +298,12 @@ mod tests { 102, 152, 72, 44, 4, 250, 210, 105, 203, 248, 96, 152, 14, 56, 118, 143, 233, 203, 107, 11, 154, 176, 62, 227, 254, 132, 207, 222, 46, 204, 206, 89, 124, 135, 79, 216, ]; - let x = Felt252::from_str_radix( - "2497468900767850684421727063357792717599762502387246235265616708902555305129", - 10, - ) - .unwrap(); - let y = Felt252::from_str_radix( - "3412645436898503501401619513420382337734846074629040678138428701431530606439", - 10, - ) - .unwrap(); + let x = felt_str!( + "2497468900767850684421727063357792717599762502387246235265616708902555305129" + ); + let y = felt_str!( + "3412645436898503501401619513420382337734846074629040678138428701431530606439" + ); assert_eq!(random_ec_point_seeded(seed).unwrap(), (x, y)); } @@ -328,39 +325,31 @@ mod tests { add_segments!(vm, 2); vm.insert_value( (1, 0).into(), - Felt252::from_str_radix( - "3004956058830981475544150447242655232275382685012344776588097793621230049020", - 10, - ) - .unwrap(), + felt_str!( + "3004956058830981475544150447242655232275382685012344776588097793621230049020" + ), ) .unwrap(); vm.insert_value( (1, 1).into(), - Felt252::from_str_radix( - "3232266734070744637901977159303149980795588196503166389060831401046564401743", - 10, - ) - .unwrap(), + felt_str!( + "3232266734070744637901977159303149980795588196503166389060831401046564401743" + ), ) .unwrap(); vm.insert_value((1, 2).into(), Felt252::from(34)).unwrap(); vm.insert_value( (1, 3).into(), - Felt252::from_str_radix( - "2864041794633455918387139831609347757720597354645583729611044800117714995244", - 10, - ) - .unwrap(), + felt_str!( + "2864041794633455918387139831609347757720597354645583729611044800117714995244" + ), ) .unwrap(); vm.insert_value( (1, 4).into(), - Felt252::from_str_radix( - "2252415379535459416893084165764951913426528160630388985542241241048300343256", - 10, - ) - .unwrap(), + felt_str!( + "2252415379535459416893084165764951913426528160630388985542241241048300343256" + ), ) .unwrap(); //Execute the hint @@ -370,19 +359,15 @@ mod tests { // s.y = 3412645436898503501401619513420382337734846074629040678138428701431530606439 assert_eq!( vm.get_integer((1, 5).into()).unwrap().as_ref(), - &Felt252::from_str_radix( - "96578541406087262240552119423829615463800550101008760434566010168435227837635", - 10 + &felt_str!( + "96578541406087262240552119423829615463800550101008760434566010168435227837635" ) - .unwrap() ); assert_eq!( vm.get_integer((1, 6).into()).unwrap().as_ref(), - &Felt252::from_str_radix( - "3412645436898503501401619513420382337734846074629040678138428701431530606439", - 10 + &felt_str!( + "3412645436898503501401619513420382337734846074629040678138428701431530606439" ) - .unwrap() ); } @@ -410,20 +395,16 @@ mod tests { //p vm.insert_value( (1, 0).into(), - Felt252::from_str_radix( - "3004956058830981475544150447242655232275382685012344776588097793621230049020", - 10, - ) - .unwrap(), + felt_str!( + "3004956058830981475544150447242655232275382685012344776588097793621230049020" + ), ) .unwrap(); vm.insert_value( (1, 1).into(), - Felt252::from_str_radix( - "3232266734070744637901977159303149980795588196503166389060831401046564401743", - 10, - ) - .unwrap(), + felt_str!( + "3232266734070744637901977159303149980795588196503166389060831401046564401743" + ), ) .unwrap(); //m @@ -435,56 +416,44 @@ mod tests { vm.insert_value((1, 3).into(), relocatable!(3, 0)).unwrap(); vm.insert_value( (3, 0).into(), - Felt252::from_str_radix( - "2864041794633455918387139831609347757720597354645583729611044800117714995244", - 10, - ) - .unwrap(), + felt_str!( + "2864041794633455918387139831609347757720597354645583729611044800117714995244" + ), ) .unwrap(); vm.insert_value( (3, 1).into(), - Felt252::from_str_radix( - "2252415379535459416893084165764951913426528160630388985542241241048300343256", - 10, - ) - .unwrap(), + felt_str!( + "2252415379535459416893084165764951913426528160630388985542241241048300343256" + ), ) .unwrap(); vm.insert_value( (3, 2).into(), - Felt252::from_str_radix( - "2864041794633455918387139831609347757720597354645583729611044800117714995244", - 10, - ) - .unwrap(), + felt_str!( + "2864041794633455918387139831609347757720597354645583729611044800117714995244" + ), ) .unwrap(); vm.insert_value( (3, 3).into(), - Felt252::from_str_radix( - "2252415379535459416893084165764951913426528160630388985542241241048300343256", - 10, - ) - .unwrap(), + felt_str!( + "2252415379535459416893084165764951913426528160630388985542241241048300343256" + ), ) .unwrap(); vm.insert_value( (3, 4).into(), - Felt252::from_str_radix( - "2864041794633455918387139831609347757720597354645583729611044800117714995244", - 10, - ) - .unwrap(), + felt_str!( + "2864041794633455918387139831609347757720597354645583729611044800117714995244" + ), ) .unwrap(); vm.insert_value( (3, 5).into(), - Felt252::from_str_radix( - "2252415379535459416893084165764951913426528160630388985542241241048300343256", - 10, - ) - .unwrap(), + felt_str!( + "2252415379535459416893084165764951913426528160630388985542241241048300343256" + ), ) .unwrap(); //len @@ -496,19 +465,15 @@ mod tests { // s.y = 907662328694455187848008017177970257426839229889571025406355869359245158736 assert_eq!( vm.get_integer((1, 5).into()).unwrap().as_ref(), - &Felt252::from_str_radix( - "1354562415074475070179359167082942891834423311678180448592849484844152837347", - 10 + &felt_str!( + "1354562415074475070179359167082942891834423311678180448592849484844152837347" ) - .unwrap() ); assert_eq!( vm.get_integer((1, 6).into()).unwrap().as_ref(), - &Felt252::from_str_radix( - "907662328694455187848008017177970257426839229889571025406355869359245158736", - 10 + &felt_str!( + "907662328694455187848008017177970257426839229889571025406355869359245158736" ) - .unwrap() ); } @@ -525,11 +490,9 @@ mod tests { add_segments!(vm, 2); vm.insert_value( (1, 0).into(), - Felt252::from_str_radix( - "3004956058830981475544150447242655232275382685012344776588097793621230049020", - 10, - ) - .unwrap(), + felt_str!( + "3004956058830981475544150447242655232275382685012344776588097793621230049020" + ), ) .unwrap(); //Execute the hint @@ -539,19 +502,15 @@ mod tests { // p.y = 386236054595386575795345623791920124827519018828430310912260655089307618738 assert_eq!( vm.get_integer((1, 2).into()).unwrap().as_ref(), - &Felt252::from_str_radix( - "3004956058830981475544150447242655232275382685012344776588097793621230049020", - 10 + &felt_str!( + "3004956058830981475544150447242655232275382685012344776588097793621230049020" ) - .unwrap() ); assert_eq!( vm.get_integer((1, 3).into()).unwrap().as_ref(), - &Felt252::from_str_radix( - "386236054595386575795345623791920124827519018828430310912260655089307618738", - 10 + &felt_str!( + "386236054595386575795345623791920124827519018828430310912260655089307618738" ) - .unwrap() ); } } diff --git a/vm/src/hint_processor/builtin_hint_processor/field_arithmetic.rs b/vm/src/hint_processor/builtin_hint_processor/field_arithmetic.rs index e74dffa370..6f5430a387 100644 --- a/vm/src/hint_processor/builtin_hint_processor/field_arithmetic.rs +++ b/vm/src/hint_processor/builtin_hint_processor/field_arithmetic.rs @@ -1,4 +1,4 @@ -use felt::Felt252; +use crate::Felt252; use num_bigint::{BigUint, ToBigInt}; use num_integer::Integer; use num_traits::Zero; diff --git a/vm/src/hint_processor/builtin_hint_processor/find_element_hint.rs b/vm/src/hint_processor/builtin_hint_processor/find_element_hint.rs index d9d7a56600..7837a7ea91 100644 --- a/vm/src/hint_processor/builtin_hint_processor/find_element_hint.rs +++ b/vm/src/hint_processor/builtin_hint_processor/find_element_hint.rs @@ -1,4 +1,5 @@ use crate::stdlib::{boxed::Box, collections::HashMap, prelude::*}; +use crate::Felt252; use crate::{ hint_processor::{ builtin_hint_processor::hint_utils::{ @@ -12,8 +13,6 @@ use crate::{ types::{errors::math_errors::MathError, exec_scope::ExecutionScopes}, vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, }; -use felt::Felt252; -use num_traits::Signed; use num_traits::ToPrimitive; pub fn find_element( @@ -29,7 +28,7 @@ pub fn find_element( let find_element_index = exec_scopes.get::("find_element_index").ok(); let elm_size = elm_size_bigint .to_usize() - .ok_or_else(|| HintError::ValueOutOfRange(Box::new(elm_size_bigint.as_ref().clone())))?; + .ok_or_else(|| HintError::ValueOutOfRange(Box::new(*elm_size_bigint.as_ref())))?; if elm_size == 0 { return Err(HintError::ValueOutOfRange(Box::new( elm_size_bigint.into_owned(), @@ -56,13 +55,13 @@ pub fn find_element( if let Ok(find_element_max_size) = exec_scopes.get_ref::("find_element_max_size") { if n_elms.as_ref() > find_element_max_size { return Err(HintError::FindElemMaxSize(Box::new(( - find_element_max_size.clone(), + *find_element_max_size, n_elms.into_owned(), )))); } } - let n_elms_iter: i32 = n_elms - .to_i32() + let n_elms_iter: u32 = n_elms + .to_u32() .ok_or_else(|| MathError::Felt252ToI32Conversion(Box::new(n_elms.into_owned())))?; for i in 0..n_elms_iter { @@ -73,7 +72,7 @@ pub fn find_element( if iter_key.as_ref() == key.as_ref() { return insert_value_from_var_name( "index", - Felt252::new(i), + Felt252::from(i), vm, ids_data, ap_tracking, @@ -94,20 +93,20 @@ pub fn search_sorted_lower( ap_tracking: &ApTracking, ) -> Result<(), HintError> { let find_element_max_size = exec_scopes.get::("find_element_max_size"); - let n_elms = get_integer_from_var_name("n_elms", vm, ids_data, ap_tracking)?; + let n_elms = *get_integer_from_var_name("n_elms", vm, ids_data, ap_tracking)?; let rel_array_ptr = get_relocatable_from_var_name("array_ptr", vm, ids_data, ap_tracking)?; - let elm_size = get_integer_from_var_name("elm_size", vm, ids_data, ap_tracking)?; - let key = get_integer_from_var_name("key", vm, ids_data, ap_tracking)?; + let elm_size = *get_integer_from_var_name("elm_size", vm, ids_data, ap_tracking)?; + let key = *get_integer_from_var_name("key", vm, ids_data, ap_tracking)?; - if !elm_size.is_positive() { - return Err(HintError::ValueOutOfRange(Box::new(elm_size.into_owned()))); + if elm_size == Felt252::ZERO { + return Err(HintError::ValueOutOfRange(Box::new(elm_size))); } if let Ok(find_element_max_size) = find_element_max_size { - if n_elms.as_ref() > &find_element_max_size { + if n_elms > find_element_max_size { return Err(HintError::FindElemMaxSize(Box::new(( find_element_max_size, - n_elms.into_owned(), + n_elms, )))); } } @@ -119,11 +118,17 @@ pub fn search_sorted_lower( for i in 0..n_elms_usize { let value = vm.get_integer(array_iter)?; if value.as_ref() >= key.as_ref() { - return insert_value_from_var_name("index", Felt252::new(i), vm, ids_data, ap_tracking); + return insert_value_from_var_name( + "index", + Felt252::from(i), + vm, + ids_data, + ap_tracking, + ); } array_iter.offset += elm_size_usize; } - insert_value_from_var_name("index", n_elms.into_owned(), vm, ids_data, ap_tracking) + insert_value_from_var_name("index", n_elms, vm, ids_data, ap_tracking) } #[cfg(test)] @@ -145,7 +150,7 @@ mod tests { vm::vm_core::VirtualMachine, }; use assert_matches::assert_matches; - use num_traits::{One, Zero}; + use num_traits::Zero; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; @@ -175,13 +180,13 @@ mod tests { let default_values = vec![ ("array_ptr", MaybeRelocatable::from((2, 0))), - ("elm_size", MaybeRelocatable::from(Felt252::new(2_i32))), - ("n_elms", MaybeRelocatable::from(Felt252::new(2_i32))), - ("key", MaybeRelocatable::from(Felt252::new(3_i32))), - ("arr[0].a", MaybeRelocatable::from(Felt252::one())), - ("arr[0].b", MaybeRelocatable::from(Felt252::new(2_i32))), - ("arr[1].a", MaybeRelocatable::from(Felt252::new(3_i32))), - ("arr[1].b", MaybeRelocatable::from(Felt252::new(4_i32))), + ("elm_size", MaybeRelocatable::from(Felt252::from(2_i32))), + ("n_elms", MaybeRelocatable::from(Felt252::from(2_i32))), + ("key", MaybeRelocatable::from(Felt252::from(3_i32))), + ("arr[0].a", MaybeRelocatable::from(Felt252::ONE)), + ("arr[0].b", MaybeRelocatable::from(Felt252::from(2_i32))), + ("arr[1].a", MaybeRelocatable::from(Felt252::from(3_i32))), + ("arr[1].b", MaybeRelocatable::from(Felt252::from(4_i32))), ]; /* array_ptr = (1,0) -> [Struct{1, 2}, Struct{3, 4}] @@ -229,7 +234,7 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn element_found_by_oracle() { let (mut vm, ids_data) = init_vm_ids_data(HashMap::new()); - let mut exec_scopes = scope![("find_element_index", Felt252::one())]; + let mut exec_scopes = scope![("find_element_index", Felt252::ONE)]; assert_matches!( run_hint!(vm, ids_data, hint_code::FIND_ELEMENT, &mut exec_scopes), Ok(()) @@ -242,11 +247,11 @@ mod tests { fn element_not_found_search() { let (mut vm, ids_data) = init_vm_ids_data(HashMap::from([( "key".to_string(), - MaybeRelocatable::from(Felt252::new(7)), + MaybeRelocatable::from(Felt252::from(7)), )])); assert_matches!( run_hint!(vm, ids_data, hint_code::FIND_ELEMENT), - Err(HintError::NoValueForKeyFindElement(bx)) if *bx == Felt252::new(7) + Err(HintError::NoValueForKeyFindElement(bx)) if *bx == Felt252::from(7) ); } @@ -254,7 +259,7 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn element_not_found_oracle() { let (mut vm, ids_data) = init_vm_ids_data(HashMap::new()); - let mut exec_scopes = scope![("find_element_index", Felt252::new(2))]; + let mut exec_scopes = scope![("find_element_index", Felt252::from(2))]; assert_matches!( run_hint!(vm, ids_data, hint_code::FIND_ELEMENT, &mut exec_scopes), Err(HintError::KeyNotFound) @@ -291,11 +296,11 @@ mod tests { fn find_elm_zero_elm_size() { let (mut vm, ids_data) = init_vm_ids_data(HashMap::from([( "elm_size".to_string(), - MaybeRelocatable::Int(Felt252::zero()), + MaybeRelocatable::Int(Felt252::ZERO), )])); assert_matches!( run_hint!(vm, ids_data, hint_code::FIND_ELEMENT), - Err(HintError::ValueOutOfRange(bx)) if *bx == Felt252::zero() + Err(HintError::ValueOutOfRange(bx)) if *bx == Felt252::ZERO ); } @@ -304,11 +309,11 @@ mod tests { fn find_elm_negative_elm_size() { let (mut vm, ids_data) = init_vm_ids_data(HashMap::from([( "elm_size".to_string(), - MaybeRelocatable::Int(Felt252::new(-1)), + MaybeRelocatable::Int(Felt252::from(-1)), )])); assert_matches!( run_hint!(vm, ids_data, hint_code::FIND_ELEMENT), - Err(HintError::ValueOutOfRange(bx)) if *bx == Felt252::new(-1) + Err(HintError::ValueOutOfRange(bx)) if *bx == Felt252::from(-1) ); } @@ -329,11 +334,11 @@ mod tests { fn find_elm_negative_n_elms() { let (mut vm, ids_data) = init_vm_ids_data(HashMap::from([( "n_elms".to_string(), - MaybeRelocatable::Int(Felt252::new(-1)), + MaybeRelocatable::Int(Felt252::from(-1)), )])); assert_matches!( run_hint!(vm, ids_data, hint_code::FIND_ELEMENT), - Err(HintError::Math(MathError::Felt252ToI32Conversion(bx))) if *bx == Felt252::new(-1) + Err(HintError::Math(MathError::Felt252ToI32Conversion(bx))) if *bx == Felt252::from(-1) ); } @@ -348,10 +353,10 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn find_elm_n_elms_gt_max_size() { let (mut vm, ids_data) = init_vm_ids_data(HashMap::new()); - let mut exec_scopes = scope![("find_element_max_size", Felt252::one())]; + let mut exec_scopes = scope![("find_element_max_size", Felt252::ONE)]; assert_matches!( run_hint!(vm, ids_data, hint_code::FIND_ELEMENT, &mut exec_scopes), - Err(HintError::FindElemMaxSize(bx)) if *bx == (Felt252::one(), Felt252::new(2)) + Err(HintError::FindElemMaxSize(bx)) if *bx == (Felt252::ONE, Felt252::from(2)) ); } @@ -384,7 +389,7 @@ mod tests { fn search_sorted_lower_no_matches() { let (mut vm, ids_data) = init_vm_ids_data(HashMap::from([( "key".to_string(), - MaybeRelocatable::Int(Felt252::new(7)), + MaybeRelocatable::Int(Felt252::from(7)), )])); assert_matches!( run_hint!(vm, ids_data, hint_code::SEARCH_SORTED_LOWER), @@ -411,7 +416,7 @@ mod tests { fn search_sorted_lower_zero_elm_size() { let (mut vm, ids_data) = init_vm_ids_data(HashMap::from([( "elm_size".to_string(), - MaybeRelocatable::Int(Felt252::zero()), + MaybeRelocatable::Int(Felt252::ZERO), )])); assert_matches!( run_hint!(vm, ids_data, hint_code::SEARCH_SORTED_LOWER), @@ -446,7 +451,7 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn search_sorted_lower_n_elms_gt_max_size() { let (mut vm, ids_data) = init_vm_ids_data(HashMap::new()); - let mut exec_scopes = scope![("find_element_max_size", Felt252::one())]; + let mut exec_scopes = scope![("find_element_max_size", Felt252::ONE)]; assert_matches!( run_hint!( vm, @@ -454,7 +459,7 @@ mod tests { hint_code::SEARCH_SORTED_LOWER, &mut exec_scopes ), - Err(HintError::FindElemMaxSize(bx)) if *bx == (Felt252::one(), Felt252::new(2)) + Err(HintError::FindElemMaxSize(bx)) if *bx == (Felt252::ONE, Felt252::from(2)) ); } } diff --git a/vm/src/hint_processor/builtin_hint_processor/garaga.rs b/vm/src/hint_processor/builtin_hint_processor/garaga.rs index 94e90464ac..37f5a33025 100644 --- a/vm/src/hint_processor/builtin_hint_processor/garaga.rs +++ b/vm/src/hint_processor/builtin_hint_processor/garaga.rs @@ -20,8 +20,7 @@ pub fn get_felt_bitlenght( ap_tracking: &ApTracking, ) -> Result<(), HintError> { let x = get_integer_from_var_name("x", vm, ids_data, ap_tracking)?; - let bit_length = x.bits() as usize; - insert_value_from_var_name("bit_length", bit_length, vm, ids_data, ap_tracking) + insert_value_from_var_name("bit_length", x.bits(), vm, ids_data, ap_tracking) } #[cfg(test)] @@ -31,9 +30,8 @@ mod tests { use crate::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::HintProcessorData; use crate::hint_processor::hint_processor_definition::HintProcessorLogic; use crate::types::exec_scope::ExecutionScopes; + use crate::Felt252; use crate::{hint_processor::builtin_hint_processor::hint_code, utils::test_utils::*}; - use felt::Felt252; - use num_traits::{Bounded, One, Zero}; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; @@ -58,7 +56,7 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn test_simple() { - let bit_length_result = run_hint(Felt252::new(7)); + let bit_length_result = run_hint(Felt252::from(7)); assert!(bit_length_result.is_ok()); assert_eq!(bit_length_result.unwrap(), Felt252::from(3)); } @@ -66,8 +64,8 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn test_in_range() { - for i in 0..252_usize { - let x: Felt252 = Felt252::one() << i; + for i in 0..252_u32 { + let x: Felt252 = Felt252::TWO.pow(i); let bit_length_result = run_hint(x); assert!(bit_length_result.is_ok()); @@ -78,9 +76,9 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn test_wraparound() { - let x = Felt252::max_value() + Felt252::one(); + let x = Felt252::MAX + Felt252::ONE; let bit_length_result = run_hint(x); assert!(bit_length_result.is_ok()); - assert_eq!(bit_length_result.unwrap(), Felt252::zero()); + assert_eq!(bit_length_result.unwrap(), Felt252::ZERO); } } diff --git a/vm/src/hint_processor/builtin_hint_processor/hint_utils.rs b/vm/src/hint_processor/builtin_hint_processor/hint_utils.rs index d8b53f25d7..3a1808b5a0 100644 --- a/vm/src/hint_processor/builtin_hint_processor/hint_utils.rs +++ b/vm/src/hint_processor/builtin_hint_processor/hint_utils.rs @@ -1,6 +1,6 @@ use crate::stdlib::{borrow::Cow, boxed::Box, collections::HashMap, prelude::*}; -use felt::Felt252; +use crate::Felt252; use crate::hint_processor::hint_processor_definition::HintReference; use crate::hint_processor::hint_processor_utils::{ @@ -260,7 +260,7 @@ mod tests { assert_matches!( get_integer_from_var_name("value", &vm, &ids_data, &ApTracking::new()), - Ok(Cow::Borrowed(x)) if x == &Felt252::new(1) + Ok(Cow::Borrowed(x)) if x == &Felt252::from(1) ); } diff --git a/vm/src/hint_processor/builtin_hint_processor/keccak_utils.rs b/vm/src/hint_processor/builtin_hint_processor/keccak_utils.rs index 01a88b3151..8a22530f9b 100644 --- a/vm/src/hint_processor/builtin_hint_processor/keccak_utils.rs +++ b/vm/src/hint_processor/builtin_hint_processor/keccak_utils.rs @@ -1,6 +1,7 @@ use crate::stdlib::{boxed::Box, cmp, collections::HashMap, prelude::*}; use crate::types::errors::math_errors::MathError; +use crate::Felt252; use crate::{ hint_processor::{ builtin_hint_processor::hint_utils::{ @@ -8,13 +9,13 @@ use crate::{ }, hint_processor_definition::HintReference, }, + math_utils::pow2_const_nz, serde::deserialize_program::ApTracking, types::{exec_scope::ExecutionScopes, relocatable::Relocatable}, vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, }; -use felt::Felt252; use num_integer::Integer; -use num_traits::{One, Signed, ToPrimitive}; +use num_traits::ToPrimitive; use sha3::{Digest, Keccak256}; use super::hint_utils::insert_value_from_var_name; @@ -72,6 +73,7 @@ pub fn unsafe_keccak( .to_u64() .ok_or_else(|| HintError::InvalidKeccakInputLength(Box::new(length.into_owned())))?; + const ZEROES: [u8; 32] = [0u8; 32]; let mut keccak_input = Vec::new(); for (word_i, byte_i) in (0..u64_length).step_by(16).enumerate() { let word_addr = Relocatable { @@ -80,14 +82,16 @@ pub fn unsafe_keccak( }; let word = vm.get_integer(word_addr)?; + let bytes = word.to_bytes_be(); let n_bytes = cmp::min(16, u64_length - byte_i); + let start = 32 - n_bytes as usize; - if word.is_negative() || word.bits() > 8 * n_bytes { + // word <= 2^(8 * n_bytes) <=> `start` leading zeroes + if !ZEROES.starts_with(&bytes[..start]) { return Err(HintError::InvalidWordSize(Box::new(word.into_owned()))); } - let start = 32 - n_bytes as usize; - keccak_input.extend_from_slice(&word.to_be_bytes()[start..]); + keccak_input.extend_from_slice(&bytes[start..]); } let mut hasher = Keccak256::new(); @@ -95,11 +99,16 @@ pub fn unsafe_keccak( let hashed = hasher.finalize(); - let high = Felt252::from_bytes_be(&hashed[..16]); - let low = Felt252::from_bytes_be(&hashed[16..32]); + let mut high_bytes = [0; 16].to_vec(); + let mut low_bytes = [0; 16].to_vec(); + high_bytes.extend_from_slice(&hashed[0..16]); + low_bytes.extend_from_slice(&hashed[16..32]); - vm.insert_value(high_addr, &high)?; - vm.insert_value(low_addr, &low)?; + let high = Felt252::from_bytes_be_slice(&high_bytes); + let low = Felt252::from_bytes_be_slice(&low_bytes); + + vm.insert_value(high_addr, high)?; + vm.insert_value(low_addr, low)?; Ok(()) } @@ -152,7 +161,7 @@ pub fn unsafe_keccak_finalize( let range = vm.get_integer_range(start_ptr, n_elems)?; for word in range.into_iter() { - keccak_input.extend_from_slice(&word.to_be_bytes()[16..]); + keccak_input.extend_from_slice(&word.to_bytes_be()[16..]); } let mut hasher = Keccak256::new(); @@ -160,14 +169,19 @@ pub fn unsafe_keccak_finalize( let hashed = hasher.finalize(); + let mut high_bytes = [0; 16].to_vec(); + let mut low_bytes = [0; 16].to_vec(); + high_bytes.extend_from_slice(&hashed[0..16]); + low_bytes.extend_from_slice(&hashed[16..32]); + let high_addr = get_relocatable_from_var_name("high", vm, ids_data, ap_tracking)?; let low_addr = get_relocatable_from_var_name("low", vm, ids_data, ap_tracking)?; - let high = Felt252::from_bytes_be(&hashed[..16]); - let low = Felt252::from_bytes_be(&hashed[16..32]); + let high = Felt252::from_bytes_be_slice(&high_bytes); + let low = Felt252::from_bytes_be_slice(&low_bytes); - vm.insert_value(high_addr, &high)?; - vm.insert_value(low_addr, &low)?; + vm.insert_value(high_addr, high)?; + vm.insert_value(low_addr, low)?; Ok(()) } @@ -180,10 +194,8 @@ pub fn split_output( num: u32, ) -> Result<(), HintError> { let output_name = format!("output{}", num); - let output_cow = get_integer_from_var_name(&output_name, vm, ids_data, ap_tracking)?; - let output = output_cow.as_ref(); - let low = output & Felt252::from(u128::MAX); - let high = output >> 128_u32; + let output = get_integer_from_var_name(&output_name, vm, ids_data, ap_tracking)?; + let (high, low) = output.div_rem(pow2_const_nz(128)); insert_value_from_var_name( &format!("output{}_high", num), high, @@ -210,9 +222,8 @@ pub fn split_input( ) -> Result<(), HintError> { let inputs_ptr = get_ptr_from_var_name("inputs", vm, ids_data, ap_tracking)?; let binding = vm.get_integer((inputs_ptr + input_key)?)?; - let input = binding.as_ref(); - let low = input & ((Felt252::one() << (8 * exponent)) - 1u32); - let high = input >> (8 * exponent); + let split = pow2_const_nz(8 * exponent); + let (high, low) = binding.div_rem(split); insert_value_from_var_name( &format!("high{}", input_key), high, @@ -267,10 +278,8 @@ pub fn split_output_mid_low_high( ) -> Result<(), HintError> { let binding = get_integer_from_var_name("output1", vm, ids_data, ap_tracking)?; let output1 = binding.as_ref(); - let output1_low = output1 & Felt252::from((1u64 << (8 * 7)) - 1u64); - let tmp = output1 >> (8_u32 * 7); - let output1_high = &tmp >> 128_u32; - let output1_mid = tmp & &Felt252::from(u128::MAX); + let (tmp, output1_low) = output1.div_rem(pow2_const_nz(8 * 7)); + let (output1_high, output1_mid) = tmp.div_rem(pow2_const_nz(128)); insert_value_from_var_name("output1_high", output1_high, vm, ids_data, ap_tracking)?; insert_value_from_var_name("output1_mid", output1_mid, vm, ids_data, ap_tracking)?; insert_value_from_var_name("output1_low", output1_low, vm, ids_data, ap_tracking) diff --git a/vm/src/hint_processor/builtin_hint_processor/math_utils.rs b/vm/src/hint_processor/builtin_hint_processor/math_utils.rs index 1b62962f3d..1265c8ed8f 100644 --- a/vm/src/hint_processor/builtin_hint_processor/math_utils.rs +++ b/vm/src/hint_processor/builtin_hint_processor/math_utils.rs @@ -1,17 +1,16 @@ use crate::{ hint_processor::builtin_hint_processor::hint_utils::get_constant_from_var_name, - stdlib::{ - boxed::Box, - collections::HashMap, - ops::{Shl, Shr}, - prelude::*, - }, + math_utils::signed_felt, + stdlib::{boxed::Box, collections::HashMap, prelude::*}, + types::errors::math_errors::MathError, + utils::{bigint_to_felt, biguint_to_felt, felt_to_bigint, felt_to_biguint}, }; use lazy_static::lazy_static; -use num_traits::{Bounded, Pow}; +use num_traits::{Signed, Zero}; use crate::utils::CAIRO_PRIME; +use crate::Felt252; use crate::{ any_box, hint_processor::{ @@ -21,7 +20,7 @@ use crate::{ }, hint_processor_definition::HintReference, }, - math_utils::isqrt, + math_utils::{isqrt, pow2_const}, serde::deserialize_program::ApTracking, types::{exec_scope::ExecutionScopes, relocatable::MaybeRelocatable}, vm::{ @@ -29,11 +28,9 @@ use crate::{ vm_core::VirtualMachine, }, }; -use felt::Felt252; use num_bigint::{BigUint, Sign}; use num_integer::Integer; use num_traits::One; -use num_traits::{Signed, Zero}; use super::{ hint_utils::{get_maybe_relocatable_from_var_name, get_relocatable_from_var_name}, @@ -52,8 +49,8 @@ pub fn is_nn( let range_check_builtin = vm.get_range_check_builtin()?; //Main logic (assert a is not negative and within the expected range) let value = match &range_check_builtin._bound { - Some(bound) if a.as_ref() >= bound => Felt252::one(), - _ => Felt252::zero(), + Some(bound) if a.as_ref() >= bound => Felt252::ONE, + _ => Felt252::ZERO, }; insert_value_into_ap(vm, value) } @@ -70,9 +67,9 @@ pub fn is_nn_out_of_range( //Main logic (assert a is not negative and within the expected range) //let value = if (-a - 1usize).mod_floor(vm.get_prime()) < range_check_builtin._bound { let value = match &range_check_builtin._bound { - Some(bound) if Felt252::zero() - (a + 1usize) < *bound => Felt252::zero(), - None => Felt252::zero(), - _ => Felt252::one(), + Some(bound) if Felt252::ZERO - (a + 1u64) < *bound => Felt252::ZERO, + None => Felt252::ZERO, + _ => Felt252::ONE, }; insert_value_into_ap(vm, value) } @@ -115,8 +112,8 @@ pub fn assert_le_felt( let prime_over_2_high = constants .get(PRIME_OVER_2_HIGH) .ok_or_else(|| HintError::MissingConstant(Box::new(PRIME_OVER_2_HIGH)))?; - let a = get_integer_from_var_name("a", vm, ids_data, ap_tracking)?.to_biguint(); - let b = get_integer_from_var_name("b", vm, ids_data, ap_tracking)?.to_biguint(); + let a = felt_to_biguint(*get_integer_from_var_name("a", vm, ids_data, ap_tracking)?); + let b = felt_to_biguint(*get_integer_from_var_name("b", vm, ids_data, ap_tracking)?); let range_check_ptr = get_ptr_from_var_name("range_check_ptr", vm, ids_data, ap_tracking)?; // TODO: use UnsignedInteger for this @@ -125,35 +122,35 @@ pub fn assert_le_felt( if a > b { return Err(HintError::NonLeFelt252(Box::new(( - Felt252::from(a), - Felt252::from(b), + biguint_to_felt(&a)?, + biguint_to_felt(&b)?, )))); } let arc1 = &b - &a; - let arc2 = Felt252::prime() - 1_u32 - &b; + let arc2 = &*CAIRO_PRIME - 1_u32 - &b; let mut lengths_and_indices = [(&a, 0_i32), (&arc1, 1_i32), (&arc2, 2_i32)]; lengths_and_indices.sort(); // TODO: I believe this check can be removed if lengths_and_indices[0].0 > &prime_div3 || lengths_and_indices[1].0 > &prime_div2 { return Err(HintError::ArcTooBig(Box::new(( - Felt252::from(lengths_and_indices[0].0.clone()), - Felt252::from(prime_div2), - Felt252::from(lengths_and_indices[1].0.clone()), - Felt252::from(prime_div3), + biguint_to_felt(&lengths_and_indices[0].0.clone())?, + biguint_to_felt(&prime_div2)?, + biguint_to_felt(&lengths_and_indices[1].0.clone())?, + biguint_to_felt(&prime_div3)?, )))); } let excluded = lengths_and_indices[2].1; - exec_scopes.assign_or_update_variable("excluded", any_box!(Felt252::new(excluded))); + exec_scopes.assign_or_update_variable("excluded", any_box!(Felt252::from(excluded))); - let (q_0, r_0) = (lengths_and_indices[0].0).div_mod_floor(&prime_over_3_high.to_biguint()); - let (q_1, r_1) = (lengths_and_indices[1].0).div_mod_floor(&prime_over_2_high.to_biguint()); + let (q_0, r_0) = (lengths_and_indices[0].0).div_mod_floor(&felt_to_biguint(*prime_over_3_high)); + let (q_1, r_1) = (lengths_and_indices[1].0).div_mod_floor(&felt_to_biguint(*prime_over_2_high)); - vm.insert_value(range_check_ptr, Felt252::from(r_0))?; - vm.insert_value((range_check_ptr + 1_i32)?, Felt252::from(q_0))?; - vm.insert_value((range_check_ptr + 2_i32)?, Felt252::from(r_1))?; - vm.insert_value((range_check_ptr + 3_i32)?, Felt252::from(q_1))?; + vm.insert_value(range_check_ptr, biguint_to_felt(&r_0)?)?; + vm.insert_value((range_check_ptr + 1_i32)?, biguint_to_felt(&q_0)?)?; + vm.insert_value((range_check_ptr + 2_i32)?, biguint_to_felt(&r_1)?)?; + vm.insert_value((range_check_ptr + 3_i32)?, biguint_to_felt(&q_1)?)?; Ok(()) } @@ -188,11 +185,7 @@ pub fn assert_le_felt_v_0_8( b.clone().into_owned(), )))); } - let bound = vm - .get_range_check_builtin()? - ._bound - .clone() - .unwrap_or_default(); + let bound = vm.get_range_check_builtin()?._bound.unwrap_or_default(); let small_inputs = Felt252::from((a.as_ref() < &bound && b.as_ref() - a.as_ref() < bound) as u8); insert_value_from_var_name("small_inputs", small_inputs, vm, ids_data, ap_tracking) @@ -201,7 +194,7 @@ pub fn assert_le_felt_v_0_8( pub fn assert_le_felt_excluded_2(exec_scopes: &mut ExecutionScopes) -> Result<(), HintError> { let excluded: Felt252 = exec_scopes.get("excluded")?; - if excluded != Felt252::new(2_i32) { + if excluded != Felt252::from(2_i32) { Err(HintError::ExcludedNot2(Box::new(excluded))) } else { Ok(()) @@ -214,10 +207,10 @@ pub fn assert_le_felt_excluded_1( ) -> Result<(), HintError> { let excluded: Felt252 = exec_scopes.get("excluded")?; - if excluded != Felt252::one() { - insert_value_into_ap(vm, &Felt252::one()) + if excluded != Felt252::ONE { + insert_value_into_ap(vm, Felt252::ONE) } else { - insert_value_into_ap(vm, &Felt252::zero()) + insert_value_into_ap(vm, Felt252::ZERO) } } @@ -228,9 +221,9 @@ pub fn assert_le_felt_excluded_0( let excluded: Felt252 = exec_scopes.get("excluded")?; if !excluded.is_zero() { - insert_value_into_ap(vm, Felt252::one()) + insert_value_into_ap(vm, Felt252::ONE) } else { - insert_value_into_ap(vm, Felt252::zero()) + insert_value_into_ap(vm, Felt252::ZERO) } } @@ -244,9 +237,9 @@ pub fn is_le_felt( let a_mod = get_integer_from_var_name("a", vm, ids_data, ap_tracking)?; let b_mod = get_integer_from_var_name("b", vm, ids_data, ap_tracking)?; let value = if a_mod > b_mod { - Felt252::one() + Felt252::ONE } else { - Felt252::zero() + Felt252::ZERO }; insert_value_into_ap(vm, value) } @@ -268,7 +261,7 @@ pub fn assert_not_equal( let maybe_rel_b = get_maybe_relocatable_from_var_name("b", vm, ids_data, ap_tracking)?; match (maybe_rel_a, maybe_rel_b) { (MaybeRelocatable::Int(a), MaybeRelocatable::Int(b)) => { - if (&a - &b).is_zero() { + if (a - b).is_zero() { return Err(HintError::AssertNotEqualFail(Box::new(( MaybeRelocatable::Int(a), MaybeRelocatable::Int(b), @@ -330,7 +323,7 @@ pub fn assert_not_zero( if value.is_zero() { return Err(HintError::AssertNotZero(Box::new(( value.into_owned(), - felt::PRIME_STR.to_string(), + crate::utils::PRIME_STR.to_string(), )))); }; Ok(()) @@ -360,7 +353,10 @@ pub fn split_int( let value = get_integer_from_var_name("value", vm, ids_data, ap_tracking)?; let base = get_integer_from_var_name("base", vm, ids_data, ap_tracking)?; let bound = get_integer_from_var_name("bound", vm, ids_data, ap_tracking)?; - let base = base.as_ref(); + let base = &base + .as_ref() + .try_into() + .map_err(|_| MathError::DividedByZero)?; let bound = bound.as_ref(); let output = get_ptr_from_var_name("output", vm, ids_data, ap_tracking)?; //Main Logic @@ -380,14 +376,14 @@ pub fn is_positive( ap_tracking: &ApTracking, ) -> Result<(), HintError> { let value = get_integer_from_var_name("value", vm, ids_data, ap_tracking)?; - let value_as_int = value.to_signed_felt(); + let value_as_int = signed_felt(*value); let range_check_builtin = vm.get_range_check_builtin()?; // Avoid using abs so we don't allocate a new BigInt let (sign, abs_value) = value_as_int.into_parts(); //Main logic (assert a is positive) match &range_check_builtin._bound { - Some(bound) if abs_value > bound.to_biguint() => { + Some(bound) if abs_value > felt_to_biguint(*bound) => { return Err(HintError::ValueOutsideValidRange(Box::new( value.into_owned(), ))) @@ -414,30 +410,28 @@ pub fn split_felt( ap_tracking: &ApTracking, constants: &HashMap, ) -> Result<(), HintError> { + let assert = |b: bool, msg: &str| { + b.then_some(()) + .ok_or_else(|| HintError::AssertionFailed(msg.to_string().into_boxed_str())) + }; + let bound = pow2_const(128); let max_high = get_constant_from_var_name("MAX_HIGH", constants)?; let max_low = get_constant_from_var_name("MAX_LOW", constants)?; - if max_high.bits() > 128 || max_low.bits() > 128 { - return Err(HintError::AssertionFailed( - "assert ids.MAX_HIGH < 2**128 and ids.MAX_LOW < 2**128" - .to_string() - .into_boxed_str(), - )); - } - if Felt252::from(-1) != max_high * &Felt252::one().shl(128_u32) + max_low { - return Err(HintError::AssertionFailed( - "assert PRIME - 1 == ids.MAX_HIGH * 2**128 + ids.MAX_LOW" - .to_string() - .into_boxed_str(), - )); - } + assert( + max_high < &bound && max_low < &bound, + "assert ids.MAX_HIGH < 2**128 and ids.MAX_LOW < 2**128", + )?; + assert( + Felt252::MAX == max_high * bound + max_low, + "assert PRIME - 1 == ids.MAX_HIGH * 2**128 + ids.MAX_LOW", + )?; let value = get_integer_from_var_name("value", vm, ids_data, ap_tracking)?; let value = value.as_ref(); //Main logic //assert_integer(ids.value) (done by match) // ids.low = ids.value & ((1 << 128) - 1) // ids.high = ids.value >> 128 - let low: Felt252 = value & ((Felt252::one().shl(128_u32)) - Felt252::one()); - let high: Felt252 = value.shr(128_u32); + let (high, low) = value.div_rem(&bound.try_into().unwrap()); insert_value_from_var_name("high", high, vm, ids_data, ap_tracking)?; insert_value_from_var_name("low", low, vm, ids_data, ap_tracking) } @@ -453,8 +447,8 @@ pub fn sqrt( ap_tracking: &ApTracking, ) -> Result<(), HintError> { let mod_value = get_integer_from_var_name("value", vm, ids_data, ap_tracking)?; - //This is equal to mod_value > Felt252::new(2).pow(250) - if mod_value.as_ref().shr(250_u32).is_positive() { + //This is equal to mod_value > Felt252::from(2).pow(250) + if *mod_value > pow2_const(250) { return Err(HintError::ValueOutside250BitRange(Box::new( mod_value.into_owned(), ))); @@ -463,7 +457,7 @@ pub fn sqrt( #[allow(deprecated)] insert_value_from_var_name( "root", - Felt252::new(isqrt(&mod_value.to_biguint())?), + biguint_to_felt(&isqrt(&felt_to_biguint(*mod_value))?)?, vm, ids_data, ap_tracking, @@ -481,47 +475,38 @@ pub fn signed_div_rem( let bound = get_integer_from_var_name("bound", vm, ids_data, ap_tracking)?; let builtin = vm.get_range_check_builtin()?; - match &builtin._bound { - Some(builtin_bound) - if div.is_zero() || div.as_ref() > &div_prime_by_bound(builtin_bound.clone())? => - { - return Err(HintError::OutOfValidRange(Box::new(( - div.into_owned(), - builtin_bound.clone(), - )))); - } - Some(builtin_bound) if bound.as_ref() > &(builtin_bound >> 1_u32) => { - return Err(HintError::OutOfValidRange(Box::new(( - bound.into_owned(), - builtin_bound >> 1_u32, - )))); - } - None if div.is_zero() => { - return Err(HintError::OutOfValidRange(Box::new(( - div.into_owned(), - Felt252::zero() - Felt252::one(), - )))); - } - _ => {} + let builtin_bound = &builtin._bound.unwrap_or(Felt252::MAX); + if div.is_zero() || div.as_ref() > &div_prime_by_bound(*builtin_bound)? { + return Err(HintError::OutOfValidRange(Box::new(( + div.into_owned(), + *builtin_bound, + )))); + } + let builtin_bound_div_2 = builtin_bound.field_div(&Felt252::TWO.try_into().unwrap()); + if *bound > builtin_bound_div_2 { + return Err(HintError::OutOfValidRange(Box::new(( + bound.into_owned(), + builtin_bound_div_2, + )))); } - let int_value = value.to_signed_felt(); - let int_div = div.to_bigint(); - let int_bound = bound.to_bigint(); + let int_value = signed_felt(*value); + let int_div = felt_to_bigint(*div); + let int_bound = felt_to_bigint(*bound); let (q, r) = int_value.div_mod_floor(&int_div); if int_bound.abs() < q.abs() { return Err(HintError::OutOfValidRange(Box::new(( - Felt252::new(q), + bigint_to_felt(&q)?, bound.into_owned(), )))); } let biased_q = q + int_bound; - insert_value_from_var_name("r", Felt252::new(r), vm, ids_data, ap_tracking)?; + insert_value_from_var_name("r", bigint_to_felt(&r)?, vm, ids_data, ap_tracking)?; insert_value_from_var_name( "biased_q", - Felt252::new(biased_q), + bigint_to_felt(&biased_q)?, vm, ids_data, ap_tracking, @@ -549,23 +534,23 @@ pub fn unsigned_div_rem( // Main logic match &builtin._bound { Some(builtin_bound) - if div.is_zero() || div.as_ref() > &div_prime_by_bound(builtin_bound.clone())? => + if div.is_zero() || div.as_ref() > &div_prime_by_bound(*builtin_bound)? => { return Err(HintError::OutOfValidRange(Box::new(( div.into_owned(), - builtin_bound.clone(), + *builtin_bound, )))); } None if div.is_zero() => { return Err(HintError::OutOfValidRange(Box::new(( div.into_owned(), - Felt252::zero() - Felt252::one(), + Felt252::ZERO - Felt252::ONE, )))); } _ => {} } - let (q, r) = value.div_mod_floor(div.as_ref()); + let (q, r) = value.div_rem(&(*div).try_into().map_err(|_| MathError::DividedByZero)?); insert_value_from_var_name("r", r, vm, ids_data, ap_tracking)?; insert_value_from_var_name("q", q, vm, ids_data, ap_tracking) } @@ -591,14 +576,17 @@ pub fn assert_250_bit( let shift = constants .get(SHIFT) .map_or_else(|| get_constant_from_var_name("SHIFT", constants), Ok)?; - let value = Felt252::from( - get_integer_from_var_name("value", vm, ids_data, ap_tracking)?.to_signed_felt(), - ); + let value = bigint_to_felt(&signed_felt(*get_integer_from_var_name( + "value", + vm, + ids_data, + ap_tracking, + )?))?; //Main logic if &value > upper_bound { return Err(HintError::ValueOutside250BitRange(Box::new(value))); } - let (high, low) = value.div_rem(shift); + let (high, low) = value.div_rem(&shift.try_into().map_err(|_| MathError::DividedByZero)?); insert_value_from_var_name("high", high, vm, ids_data, ap_tracking)?; insert_value_from_var_name("low", low, vm, ids_data, ap_tracking) } @@ -636,21 +624,24 @@ pub fn is_addr_bounded( constants: &HashMap, ) -> Result<(), HintError> { let addr = get_integer_from_var_name("addr", vm, ids_data, ap_tracking)?; - let prime = Felt252::prime(); - let addr_bound = constants - .get(ADDR_BOUND) - .ok_or_else(|| HintError::MissingConstant(Box::new(ADDR_BOUND)))? - .to_biguint(); + let addr_bound = felt_to_biguint( + *constants + .get(ADDR_BOUND) + .ok_or_else(|| HintError::MissingConstant(Box::new(ADDR_BOUND)))?, + ); - let lower_bound = BigUint::one() << 250_u32; - let upper_bound = BigUint::one() << 251_u32; + let lower_bound = BigUint::one() << 250_usize; + let upper_bound = BigUint::one() << 251_usize; // assert (2**250 < ADDR_BOUND <= 2**251) and (2 * 2**250 < PRIME) and ( // ADDR_BOUND * 2 > PRIME), \ // 'normalize_address() cannot be used with the current constants.' // The second check is not needed, as it's true for the CAIRO_PRIME - if !(lower_bound < addr_bound && addr_bound <= upper_bound && (&addr_bound << 1_u32) > prime) { + if !(lower_bound < addr_bound + && addr_bound <= upper_bound + && (&addr_bound << 1_usize) > *CAIRO_PRIME) + { return Err(HintError::AssertionFailed( "normalize_address() cannot be used with the current constants." .to_string() @@ -659,7 +650,7 @@ pub fn is_addr_bounded( } // Main logic: ids.is_small = 1 if ids.addr < ADDR_BOUND else 0 - let is_small = Felt252::from((addr.as_ref() < &Felt252::from(addr_bound)) as u8); + let is_small = Felt252::from((addr.as_ref() < &biguint_to_felt(&addr_bound)?) as u8); insert_value_from_var_name("is_small", is_small, vm, ids_data, ap_tracking) } @@ -700,16 +691,20 @@ pub fn is_quad_residue( ids_data: &HashMap, ap_tracking: &ApTracking, ) -> Result<(), HintError> { - let x = get_integer_from_var_name("x", vm, ids_data, ap_tracking)?; - - if x.is_zero() || x.is_one() { - insert_value_from_var_name("y", x.as_ref().clone(), vm, ids_data, ap_tracking) - } else if Pow::pow(x.as_ref(), &(Felt252::max_value() >> 1_u32)).is_one() { - insert_value_from_var_name("y", &x.sqrt(), vm, ids_data, ap_tracking) + let x = *get_integer_from_var_name("x", vm, ids_data, ap_tracking)?; + + if x.is_zero() || x == Felt252::ONE { + insert_value_from_var_name("y", *x.as_ref(), vm, ids_data, ap_tracking) + // } else if Pow::pow(felt_to_biguint(x), &(&*CAIRO_PRIME >> 1_u32)).is_one() { + } else if x.pow_felt(&Felt252::MAX.div_rem(&Felt252::TWO.try_into().unwrap()).0) == Felt252::ONE + { + insert_value_from_var_name("y", x.sqrt().unwrap_or_default(), vm, ids_data, ap_tracking) } else { insert_value_from_var_name( "y", - (x.as_ref() / Felt252::new(3_i32)).sqrt(), + (x.field_div(&Felt252::THREE.try_into().unwrap())) + .sqrt() + .unwrap_or_default(), vm, ids_data, ap_tracking, @@ -720,8 +715,8 @@ pub fn is_quad_residue( fn div_prime_by_bound(bound: Felt252) -> Result { let prime: &BigUint = &CAIRO_PRIME; #[allow(deprecated)] - let limit = prime / bound.to_biguint(); - Ok(Felt252::new(limit)) + let limit = prime / felt_to_biguint(bound); + Ok(biguint_to_felt(&limit)?) } fn prime_div_constant(bound: u32) -> Result { @@ -743,8 +738,9 @@ pub fn a_b_bitand_1( ) -> Result<(), HintError> { let a = get_integer_from_var_name("a", vm, ids_data, ap_tracking)?; let b = get_integer_from_var_name("b", vm, ids_data, ap_tracking)?; - let a_lsb = a.as_ref() & Felt252::one(); - let b_lsb = b.as_ref() & Felt252::one(); + let two = Felt252::TWO.try_into().unwrap(); + let a_lsb = a.mod_floor(&two); + let b_lsb = b.mod_floor(&two); insert_value_from_var_name("a_lsb", a_lsb, vm, ids_data, ap_tracking)?; insert_value_from_var_name("b_lsb", b_lsb, vm, ids_data, ap_tracking) } @@ -784,7 +780,7 @@ pub fn split_xx( ) -> Result<(), HintError> { let xx = Uint256::from_var_name("xx", vm, ids_data, ap_tracking)?; let x_addr = get_relocatable_from_var_name("x", vm, ids_data, ap_tracking)?; - let xx = xx.low.to_biguint() + (xx.high.to_biguint() << 128_u32); + let xx: BigUint = felt_to_biguint(*xx.low) + felt_to_biguint(*xx.high * pow2_const(128)); let mut x = xx.modpow( &(&*SPLIT_XX_PRIME + 3_u32).div_floor(&BigUint::from(8_u32)), &SPLIT_XX_PRIME, @@ -798,9 +794,9 @@ pub fn split_xx( vm.insert_value( x_addr, - Felt252::from(&x & &BigUint::from(u128::max_value())), + biguint_to_felt(&(&x & &BigUint::from(u128::max_value())))?, )?; - vm.insert_value((x_addr + 1)?, Felt252::from(x >> 128_u32))?; + vm.insert_value((x_addr + 1)?, biguint_to_felt(&(x >> 128_u32))?)?; Ok(()) } @@ -808,7 +804,8 @@ pub fn split_xx( #[cfg(test)] mod tests { use super::*; - use crate::stdlib::ops::Shl; + use crate::{felt_hex, felt_str}; + use core::ops::Neg; use crate::{ any_box, @@ -826,8 +823,6 @@ mod tests { vm::{errors::memory_errors::MemoryError, vm_core::VirtualMachine}, }; use assert_matches::assert_matches; - use felt::felt_str; - use num_traits::Zero; #[cfg(not(target_arch = "wasm32"))] use proptest::prelude::*; @@ -881,13 +876,15 @@ mod tests { //Initialize fp vm.run_context.fp = 5; //Insert ids into memory - vm.segments = segments![( - (1, 4), - ( - "-3618502788666131213697322783095070105623107215331596699973092056135872020480", - 10 + add_segments!(vm, 2); + vm.insert_value( + (1, 4).into(), + felt_str!( + "3618502788666131213697322783095070105623107215331596699973092056135872020480" ) - )]; + .neg(), + ) + .unwrap(); //Create ids_data let ids_data = ids_data!["a"]; //Execute the hint @@ -974,11 +971,11 @@ mod tests { let mut constants = HashMap::new(); constants.insert( "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_3_HIGH".to_string(), - felt_str!("4000000000000088000000000000001", 16), + felt_hex!("4000000000000088000000000000001"), ); constants.insert( "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_2_HIGH".to_string(), - felt_str!("2AAAAAAAAAAAAB05555555555555556", 16), + felt_hex!("2AAAAAAAAAAAAB05555555555555556"), ); let mut vm = vm_with_range_check!(); let mut exec_scopes = scope![("excluded", 1)]; @@ -1036,8 +1033,8 @@ mod tests { Err(HintError::Memory( MemoryError::InconsistentMemory(bx) )) if *bx == (Relocatable::from((1, 0)), - MaybeRelocatable::Int(Felt252::one()), - MaybeRelocatable::Int(Felt252::zero())) + MaybeRelocatable::Int(Felt252::ONE), + MaybeRelocatable::Int(Felt252::ZERO)) ); } @@ -1086,7 +1083,7 @@ mod tests { //Execute the hint assert_matches!( run_hint!(vm, ids_data, hint_code), - Err(HintError::AssertNNValueOutOfRange(bx)) if *bx == Felt252::new(-1) + Err(HintError::AssertNNValueOutOfRange(bx)) if *bx == Felt252::from(-1) ); } @@ -1166,13 +1163,13 @@ mod tests { let mut constants = HashMap::new(); constants.insert( "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_3_HIGH".to_string(), - felt_str!("4000000000000088000000000000001", 16), + felt_hex!("4000000000000088000000000000001"), ); constants.insert( "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_2_HIGH".to_string(), - felt_str!("2AAAAAAAAAAAAB05555555555555556", 16), + felt_hex!("2AAAAAAAAAAAAB05555555555555556"), ); - let mut exec_scopes = scope![("excluded", Felt252::one())]; + let mut exec_scopes = scope![("excluded", Felt252::ONE)]; //Initialize fp vm.run_context.fp = 3; //Insert ids into memory @@ -1182,7 +1179,7 @@ mod tests { //Execute the hint assert_matches!( run_hint!(vm, ids_data, hint_code::ASSERT_LE_FELT, &mut exec_scopes, &constants), - Err(HintError::NonLeFelt252(bx)) if *bx == (Felt252::new(2), Felt252::one()) + Err(HintError::NonLeFelt252(bx)) if *bx == (Felt252::from(2), Felt252::ONE) ); } @@ -1193,11 +1190,11 @@ mod tests { let mut constants = HashMap::new(); constants.insert( "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_3_HIGH".to_string(), - felt_str!("4000000000000088000000000000001", 16), + felt_hex!("4000000000000088000000000000001"), ); constants.insert( "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_2_HIGH".to_string(), - felt_str!("2AAAAAAAAAAAAB05555555555555556", 16), + felt_hex!("2AAAAAAAAAAAAB05555555555555556"), ); let mut exec_scopes = scope![("excluded", 1)]; //Initialize fp @@ -1219,11 +1216,11 @@ mod tests { let mut constants = HashMap::new(); constants.insert( "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_3_HIGH".to_string(), - felt_str!("4000000000000088000000000000001", 16), + felt_hex!("4000000000000088000000000000001"), ); constants.insert( "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_2_HIGH".to_string(), - felt_str!("2AAAAAAAAAAAAB05555555555555556", 16), + felt_hex!("2AAAAAAAAAAAAB05555555555555556"), ); let mut exec_scopes = scope![("excluded", 1)]; //Initialize fp @@ -1287,7 +1284,7 @@ mod tests { assert_matches!( run_hint!(vm, ids_data, hint_code), Err(HintError::AssertNotEqualFail(bx)) - if *bx == (MaybeRelocatable::from(Felt252::one()), MaybeRelocatable::from(Felt252::one())) + if *bx == (MaybeRelocatable::from(Felt252::ONE), MaybeRelocatable::from(Felt252::ONE)) ); } @@ -1394,7 +1391,7 @@ mod tests { run_hint!(vm, ids_data, hint_code), Err(HintError::Internal( VirtualMachineError::DiffTypeComparison(bx) - )) if *bx == (MaybeRelocatable::from((1, 0)), MaybeRelocatable::from(Felt252::one())) + )) if *bx == (MaybeRelocatable::from((1, 0)), MaybeRelocatable::from(Felt252::ONE)) ); } @@ -1428,7 +1425,7 @@ mod tests { let ids_data = ids_data!["value"]; assert_matches!( run_hint!(vm, ids_data, hint_code), - Err(HintError::AssertNotZero(bx)) if *bx == (Felt252::zero(), felt::PRIME_STR.to_string()) + Err(HintError::AssertNotZero(bx)) if *bx == (Felt252::ZERO, crate::utils::PRIME_STR.to_string()) ); } @@ -1534,7 +1531,7 @@ mod tests { //Execute the hint assert_matches!( run_hint!(vm, ids_data, hint_code), - Err(HintError::SplitIntLimbOutOfRange(bx)) if *bx == Felt252::new(100) + Err(HintError::SplitIntLimbOutOfRange(bx)) if *bx == Felt252::from(100) ); } @@ -1619,8 +1616,8 @@ mod tests { Err(HintError::Memory( MemoryError::InconsistentMemory(bx) )) if *bx == (Relocatable::from((1, 1)), - MaybeRelocatable::from(Felt252::new(4)), - MaybeRelocatable::from(Felt252::one())) + MaybeRelocatable::from(Felt252::from(4)), + MaybeRelocatable::from(Felt252::ONE)) ); } @@ -1678,8 +1675,8 @@ mod tests { Err(HintError::Memory( MemoryError::InconsistentMemory(bx) )) if *bx == (Relocatable::from((1, 1)), - MaybeRelocatable::from(Felt252::new(7)), - MaybeRelocatable::from(Felt252::new(9))) + MaybeRelocatable::from(Felt252::from(7)), + MaybeRelocatable::from(Felt252::from(9))) ); } @@ -1714,7 +1711,7 @@ mod tests { assert_matches!( run_hint!(vm, ids_data, hint_code), Err(HintError::OutOfValidRange(bx)) - if *bx == (Felt252::new(-5), felt_str!("340282366920938463463374607431768211456")) + if *bx == (Felt252::from(-5), felt_str!("340282366920938463463374607431768211456")) ) } @@ -1754,8 +1751,8 @@ mod tests { Err(HintError::Memory( MemoryError::InconsistentMemory(bx) )) if *bx == (Relocatable::from((1, 0)), - MaybeRelocatable::Int(Felt252::new(5)), - MaybeRelocatable::Int(Felt252::new(2))) + MaybeRelocatable::Int(Felt252::from(5)), + MaybeRelocatable::Int(Felt252::from(2))) ); } @@ -1824,7 +1821,7 @@ mod tests { assert_matches!( run_hint!(vm, ids_data, hint_code), Err(HintError::OutOfValidRange(bx)) - if *bx == (Felt252::new(-5), felt_str!("340282366920938463463374607431768211456")) + if *bx == (Felt252::from(-5), felt_str!("340282366920938463463374607431768211456")) ) } @@ -1836,10 +1833,9 @@ mod tests { //Initialize fp vm.run_context.fp = 6; //Insert ids into memory - let bound = vm.get_range_check_builtin().unwrap()._bound.clone(); + let bound = vm.get_range_check_builtin().unwrap()._bound; vm.segments = segments![((1, 3), (5)), ((1, 4), 10)]; - vm.insert_value((1, 5).into(), bound.clone().unwrap()) - .unwrap(); + vm.insert_value((1, 5).into(), bound.unwrap()).unwrap(); //Create ids let ids_data = ids_data!["r", "biased_q", "range_check_ptr", "div", "value", "bound"]; //Execute the hint @@ -1847,7 +1843,7 @@ mod tests { assert_matches!( run_hint!(vm, ids_data, hint_code), Err(HintError::OutOfValidRange(bx)) - if *bx == (bound.unwrap(), builtin_bound >> 1_u32) + if *bx == (bound.unwrap(), builtin_bound.field_div(&Felt252::TWO.try_into().unwrap())) ) } @@ -1887,8 +1883,8 @@ mod tests { Err(HintError::Memory( MemoryError::InconsistentMemory(bx) )) if *bx == (Relocatable::from((1, 1)), - MaybeRelocatable::Int(Felt252::new(10)), - MaybeRelocatable::Int(Felt252::new(31))) + MaybeRelocatable::Int(Felt252::from(10)), + MaybeRelocatable::Int(Felt252::from(31))) ); } @@ -1960,7 +1956,7 @@ mod tests { //Execute the hint assert_matches!( run_hint!(vm, ids_data, hint_code, &mut exec_scopes_ref!(), &constants), - Err(HintError::ValueOutside250BitRange(bx)) if *bx == Felt252::one().shl(251_u32) + Err(HintError::ValueOutside250BitRange(bx)) if *bx == pow2_const(251) ); } @@ -2048,7 +2044,7 @@ mod tests { fn run_is_addr_bounded_assert_fail() { let hint_code = hint_code::IS_ADDR_BOUNDED; let mut vm = vm!(); - let addr_bound = Felt252::one(); + let addr_bound = Felt252::ONE; //Initialize fp vm.run_context.fp = 2; //Insert ids into memory @@ -2120,7 +2116,7 @@ mod tests { hint_code, exec_scopes_ref!(), &HashMap::from([ - ("MAX_LOW".to_string(), Felt252::zero()), + ("MAX_LOW".to_string(), Felt252::ZERO), ( "MAX_HIGH".to_string(), felt_str!("10633823966279327296825105735305134080") @@ -2160,7 +2156,7 @@ mod tests { hint_code, exec_scopes_ref!(), &HashMap::from([ - ("MAX_LOW".to_string(), Felt252::zero()), + ("MAX_LOW".to_string(), Felt252::ZERO), ( "MAX_HIGH".to_string(), felt_str!("10633823966279327296825105735305134080") @@ -2199,7 +2195,7 @@ mod tests { hint_code, exec_scopes_ref!(), &HashMap::from([ - ("MAX_LOW".to_string(), Felt252::zero()), + ("MAX_LOW".to_string(), Felt252::ZERO), ( "MAX_HIGH".to_string(), felt_str!("10633823966279327296825105735305134080") @@ -2209,7 +2205,7 @@ mod tests { Err(HintError::Memory( MemoryError::InconsistentMemory(bx) )) if *bx == (Relocatable::from((2, 0)), - MaybeRelocatable::from(Felt252::new(99)), + MaybeRelocatable::from(Felt252::from(99)), MaybeRelocatable::from(felt_str!("335438970432432812899076431678123043273"))) ); } @@ -2242,7 +2238,7 @@ mod tests { hint_code, exec_scopes_ref!(), &HashMap::from([ - ("MAX_LOW".to_string(), Felt252::zero()), + ("MAX_LOW".to_string(), Felt252::ZERO), ( "MAX_HIGH".to_string(), felt_str!("10633823966279327296825105735305134080") @@ -2252,8 +2248,8 @@ mod tests { Err(HintError::Memory( MemoryError::InconsistentMemory(bx) )) if *bx == (Relocatable::from((2, 1)), - MaybeRelocatable::from(Felt252::new(99)), - MaybeRelocatable::from(Felt252::new(0))) + MaybeRelocatable::from(Felt252::from(99)), + MaybeRelocatable::from(Felt252::from(0))) ); } @@ -2280,7 +2276,7 @@ mod tests { hint_code, exec_scopes_ref!(), &HashMap::from([ - ("MAX_LOW".to_string(), Felt252::zero()), + ("MAX_LOW".to_string(), Felt252::ZERO), ( "MAX_HIGH".to_string(), felt_str!("10633823966279327296825105735305134080") @@ -2382,10 +2378,10 @@ mod tests { hint_code, exec_scopes_ref!(), &HashMap::from([ - ("MAX_LOW".to_string(), Felt252::zero()), + ("MAX_LOW".to_string(), Felt252::ZERO), ( "MAX_HIGH".to_string(), - Felt252::zero(), + Felt252::ZERO, ) ]) ), @@ -2422,7 +2418,7 @@ mod tests { //Execute the hint assert_matches!( run_hint!(vm, ids_data, hint_code), - Err(HintError::AssertLtFelt252(bx)) if *bx == (Felt252::new(3), Felt252::new(2)) + Err(HintError::AssertLtFelt252(bx)) if *bx == (Felt252::from(3), Felt252::from(2)) ); } @@ -2540,14 +2536,14 @@ mod tests { assert_matches!(run_hint!(vm, ids_data, hint_code::IS_QUAD_RESIDUE), Ok(())); - let x = &Felt252::parse_bytes(x.as_bytes(), 10).unwrap(); + let x = felt_str!(x); - if x.is_zero() || x.is_one() { - assert_eq!(vm.get_integer(Relocatable::from((1, 0))).unwrap().as_ref(), x); - } else if x.pow(&(Felt252::max_value() >> 1_u32)).is_one() { - assert_eq!(vm.get_integer(Relocatable::from((1, 0))).unwrap().into_owned(), x.sqrt()); + if x.is_zero() || x == Felt252::ONE { + assert_eq!(vm.get_integer(Relocatable::from((1, 0))).unwrap().as_ref(), &x); + } else if x.pow_felt(&Felt252::MAX.field_div(&Felt252::TWO.try_into().unwrap())) == Felt252::ONE { + assert_eq!(vm.get_integer(Relocatable::from((1, 0))).unwrap().into_owned(), x.sqrt().unwrap()); } else { - assert_eq!(vm.get_integer(Relocatable::from((1, 0))).unwrap().into_owned(), (x / Felt252::new(3)).sqrt()); + assert_eq!(vm.get_integer(Relocatable::from((1, 0))).unwrap().into_owned(), (x.field_div(&(Felt252::from(3).try_into().unwrap())).sqrt().unwrap())); } } } diff --git a/vm/src/hint_processor/builtin_hint_processor/memcpy_hint_utils.rs b/vm/src/hint_processor/builtin_hint_processor/memcpy_hint_utils.rs index 150b712242..4709545bbc 100644 --- a/vm/src/hint_processor/builtin_hint_processor/memcpy_hint_utils.rs +++ b/vm/src/hint_processor/builtin_hint_processor/memcpy_hint_utils.rs @@ -49,7 +49,7 @@ mod tests { use crate::utils::test_utils::*; use assert_matches::assert_matches; - use felt::Felt252; + use crate::Felt252; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; @@ -75,7 +75,7 @@ mod tests { get_integer_from_var_name(var_name, &vm, &ids_data, &ApTracking::default()) .unwrap() .as_ref(), - &Felt252::new(10) + &Felt252::from(10) ); } diff --git a/vm/src/hint_processor/builtin_hint_processor/memset_utils.rs b/vm/src/hint_processor/builtin_hint_processor/memset_utils.rs index b5182522e9..4ad693968c 100644 --- a/vm/src/hint_processor/builtin_hint_processor/memset_utils.rs +++ b/vm/src/hint_processor/builtin_hint_processor/memset_utils.rs @@ -1,5 +1,6 @@ use crate::stdlib::{any::Any, collections::HashMap, prelude::*}; +use crate::Felt252; use crate::{ hint_processor::{ builtin_hint_processor::hint_utils::{ @@ -11,8 +12,6 @@ use crate::{ types::exec_scope::ExecutionScopes, vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, }; -use felt::Felt252; -use num_traits::{One, Signed}; // Implements hint: // %{ vm_enter_scope({'n': ids.n}) %} @@ -44,10 +43,10 @@ pub fn memset_step_loop( // get `n` variable from vm scope let n = exec_scopes.get_mut_ref::("n")?; // this variable will hold the value of `n - 1` - *n -= Felt252::one(); + *n -= Felt252::ONE; // if `new_n` is positive, insert 1 in the address of `continue_loop` // else, insert 0 - let flag = Felt252::new(n.is_positive()); + let flag = Felt252::from((*n > Felt252::ZERO) as u8); insert_value_from_var_name(i_name, flag, vm, ids_data, ap_tracking)?; // Reassign `n` with `n - 1` // we do it at the end of the function so that the borrow checker doesn't complain @@ -72,7 +71,6 @@ mod tests { vm::errors::memory_errors::MemoryError, }; use assert_matches::assert_matches; - use num_traits::{One, Zero}; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; @@ -115,7 +113,7 @@ mod tests { // initialize fp vm.run_context.fp = 1; // initialize vm scope with variable `n` = 1 - let mut exec_scopes = scope![("n", Felt252::one())]; + let mut exec_scopes = scope![("n", Felt252::ONE)]; // initialize ids.continue_loop // we create a memory gap so that there is None in (1, 0), the actual addr of continue_loop vm.segments = segments![((1, 1), 5)]; @@ -133,7 +131,7 @@ mod tests { // initialize fp vm.run_context.fp = 1; // initialize vm scope with variable `n` = 5 - let mut exec_scopes = scope![("n", Felt252::new(5))]; + let mut exec_scopes = scope![("n", Felt252::from(5))]; // initialize ids.continue_loop // we create a memory gap so that there is None in (0, 0), the actual addr of continue_loop vm.segments = segments![((1, 2), 5)]; @@ -154,7 +152,7 @@ mod tests { // we don't initialize `n` now: /* vm.exec_scopes - .assign_or_update_variable("n", Felt252::one())); */ + .assign_or_update_variable("n", Felt252::ONE)); */ // initialize ids.continue_loop // we create a memory gap so that there is None in (0, 1), the actual addr of continue_loop @@ -174,7 +172,7 @@ mod tests { // initialize fp vm.run_context.fp = 1; // initialize with variable `n` - let mut exec_scopes = scope![("n", Felt252::one())]; + let mut exec_scopes = scope![("n", Felt252::ONE)]; // initialize ids.continue_loop // a value is written in the address so the hint cant insert value there vm.segments = segments![((1, 0), 5)]; @@ -184,8 +182,8 @@ mod tests { Err(HintError::Memory( MemoryError::InconsistentMemory(bx) )) if *bx == (Relocatable::from((1, 0)), - MaybeRelocatable::from(Felt252::new(5)), - MaybeRelocatable::from(Felt252::zero())) + MaybeRelocatable::from(Felt252::from(5)), + MaybeRelocatable::from(Felt252::ZERO)) ); } } diff --git a/vm/src/hint_processor/builtin_hint_processor/poseidon_utils.rs b/vm/src/hint_processor/builtin_hint_processor/poseidon_utils.rs index 0beefc2b66..7ba388fa7b 100644 --- a/vm/src/hint_processor/builtin_hint_processor/poseidon_utils.rs +++ b/vm/src/hint_processor/builtin_hint_processor/poseidon_utils.rs @@ -1,7 +1,6 @@ use crate::stdlib::{collections::HashMap, string::String}; -use felt::Felt252; -use num_traits::ToPrimitive; +use crate::Felt252; use crate::{ hint_processor::hint_processor_definition::HintReference, @@ -10,6 +9,7 @@ use crate::{ }; use super::hint_utils::{get_integer_from_var_name, insert_value_into_ap}; +use num_traits::ToPrimitive; // Implements hint: "memory[ap] = to_felt_or_relocatable(ids.n >= 10)" pub fn n_greater_than_10( diff --git a/vm/src/hint_processor/builtin_hint_processor/pow_utils.rs b/vm/src/hint_processor/builtin_hint_processor/pow_utils.rs index 0ef880b41d..a749f4b896 100644 --- a/vm/src/hint_processor/builtin_hint_processor/pow_utils.rs +++ b/vm/src/hint_processor/builtin_hint_processor/pow_utils.rs @@ -1,5 +1,6 @@ use crate::stdlib::{boxed::Box, collections::HashMap, prelude::*}; +use crate::Felt252; use crate::{ hint_processor::{ builtin_hint_processor::hint_utils::{ @@ -10,8 +11,6 @@ use crate::{ serde::deserialize_program::ApTracking, vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, }; -use felt::Felt252; -use num_integer::Integer; /* Implements hint: @@ -29,14 +28,8 @@ pub fn pow( .map_err(|_| { HintError::IdentifierHasNoMember(Box::new(("prev_locs".to_string(), "exp".to_string()))) })?; - let locs_bit = prev_locs_exp.is_odd(); - insert_value_from_var_name( - "locs", - Felt252::new(locs_bit as u8), - vm, - ids_data, - ap_tracking, - )?; + let locs_bit = prev_locs_exp.mod_floor(&Felt252::TWO.try_into().unwrap()); + insert_value_from_var_name("locs", locs_bit, vm, ids_data, ap_tracking)?; Ok(()) } @@ -57,7 +50,6 @@ mod tests { vm::{errors::memory_errors::MemoryError, vm_core::VirtualMachine}, }; use assert_matches::assert_matches; - use num_traits::One; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; @@ -146,8 +138,8 @@ mod tests { Err(HintError::Memory( MemoryError::InconsistentMemory(bx) )) if *bx == (Relocatable::from((1, 11)), - MaybeRelocatable::from(Felt252::new(3)), - MaybeRelocatable::from(Felt252::one())) + MaybeRelocatable::from(Felt252::from(3)), + MaybeRelocatable::from(Felt252::ONE)) ); } } diff --git a/vm/src/hint_processor/builtin_hint_processor/print.rs b/vm/src/hint_processor/builtin_hint_processor/print.rs index 10ce39c504..a73f8e8950 100644 --- a/vm/src/hint_processor/builtin_hint_processor/print.rs +++ b/vm/src/hint_processor/builtin_hint_processor/print.rs @@ -1,6 +1,6 @@ use core::fmt::{Debug, Formatter}; -use felt::Felt252; +use crate::Felt252; use num_traits::ToPrimitive; use crate::hint_processor::builtin_hint_processor::dict_manager::Dictionary; @@ -12,6 +12,7 @@ use crate::stdlib::collections::HashMap; use crate::types::exec_scope::ExecutionScopes; use crate::types::relocatable::MaybeRelocatable; +use crate::utils::felt_to_bigint; use crate::vm::errors::hint_errors::HintError; use crate::{ hint_processor::hint_processor_definition::HintReference, vm::vm_core::VirtualMachine, @@ -33,7 +34,7 @@ fn print_name( ap_tracking: &ApTracking, ) -> Result<(), HintError> { let name = get_integer_from_var_name("name", vm, ids_data, ap_tracking)?; - let name = String::from_utf8(name.to_bigint().to_signed_bytes_be()) + let name = String::from_utf8(felt_to_bigint(*name.as_ref()).to_signed_bytes_be()) .map_err(|err| HintError::CustomHint(err.to_string().into_boxed_str()))?; println!("{name}"); Ok(()) @@ -106,12 +107,12 @@ pub fn print_dict( })?; match v { MaybeRelocatable::Int(value) => { - acc.insert(key, DictValue::Int(value.clone())); + acc.insert(key, DictValue::Int(*value)); } MaybeRelocatable::RelocatableValue(val) => { let mut structure = Vec::new(); for i in 0..pointer_size { - let val = vm.get_integer((*val + i)?)?.as_ref().clone(); + let val = *vm.get_integer((*val + i)?)?.as_ref(); structure.push(val); } acc.insert(key, DictValue::Relocatable(structure)); diff --git a/vm/src/hint_processor/builtin_hint_processor/secp/bigint_utils.rs b/vm/src/hint_processor/builtin_hint_processor/secp/bigint_utils.rs index 2be1ac58a2..c0e4a6d07a 100644 --- a/vm/src/hint_processor/builtin_hint_processor/secp/bigint_utils.rs +++ b/vm/src/hint_processor/builtin_hint_processor/secp/bigint_utils.rs @@ -1,7 +1,11 @@ use core::ops::Shl; use crate::hint_processor::builtin_hint_processor::uint_utils::{pack, split}; +use crate::math_utils::signed_felt; use crate::stdlib::{borrow::Cow, boxed::Box, collections::HashMap, prelude::*}; +use crate::types::errors::math_errors::MathError; +use crate::utils::biguint_to_felt; +use crate::Felt252; use crate::{ hint_processor::{ builtin_hint_processor::{ @@ -10,6 +14,7 @@ use crate::{ }, hint_processor_definition::HintReference, }, + math_utils::pow2_const_nz, serde::deserialize_program::ApTracking, types::{ exec_scope::ExecutionScopes, @@ -17,9 +22,7 @@ use crate::{ }, vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, }; -use felt::Felt252; use num_bigint::{BigInt, BigUint}; -use num_traits::Bounded; pub(crate) type BigInt3<'a> = BigIntN<'a, 3>; pub(crate) type Uint384<'a> = BigIntN<'a, 3>; @@ -76,7 +79,7 @@ impl BigIntN<'_, NUM_LIMBS> { ) -> Result<(), HintError> { let addr = get_relocatable_from_var_name(var_name, vm, ids_data, ap_tracking)?; for i in 0..NUM_LIMBS { - vm.insert_value((addr + i)?, self.limbs[i].as_ref().clone())?; + vm.insert_value((addr + i)?, *self.limbs[i].as_ref())?; } Ok(()) } @@ -90,7 +93,7 @@ impl BigIntN<'_, NUM_LIMBS> { .into_iter() .take(3) .enumerate() - .map(|(idx, value)| value.to_signed_felt().shl(idx * 86)) + .map(|(idx, value)| signed_felt(*value).shl(idx * 86)) .sum() } @@ -127,8 +130,8 @@ pub fn nondet_bigint3( .ok_or(HintError::BigIntToBigUintFail)?; let arg: Vec = bigint3_split(&value)? .into_iter() - .map(|n| MaybeRelocatable::from(Felt252::new(n))) - .collect(); + .map(|ref n| biguint_to_felt(n).map(MaybeRelocatable::from)) + .collect::, MathError>>()?; vm.write_arg(res_reloc, &arg).map_err(HintError::Memory)?; Ok(()) } @@ -149,7 +152,8 @@ pub fn bigint_to_uint256( let base_86 = constants .get(BASE_86) .ok_or_else(|| HintError::MissingConstant(Box::new(BASE_86)))?; - let low = (d0 + &(d1 * base_86)) & &Felt252::new(u128::MAX); + let mask = pow2_const_nz(128); + let low = (d0 + (d1 * base_86)).mod_floor(mask); insert_value_from_var_name("low", low, vm, ids_data, ap_tracking) } @@ -170,7 +174,7 @@ pub fn hi_max_bitlen( // equal to `len_hi.wrapping_sub(1)` let res = if len_hi == 0 { - Felt252::max_value() + Felt252::MAX } else { (len_hi - 1).into() }; @@ -181,14 +185,13 @@ pub fn hi_max_bitlen( #[cfg(test)] mod tests { use super::*; - use crate::any_box; use crate::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::{ BuiltinHintProcessor, HintProcessorData, }; use crate::hint_processor::hint_processor_definition::HintProcessorLogic; - use crate::stdlib::ops::Shl; use crate::stdlib::string::ToString; use crate::types::exec_scope::ExecutionScopes; + use crate::{any_box, felt_str}; use crate::types::relocatable::Relocatable; use crate::utils::test_utils::*; @@ -196,8 +199,6 @@ mod tests { use crate::vm::vm_core::VirtualMachine; use assert_matches::assert_matches; - use felt::felt_str; - use num_traits::One; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; @@ -223,7 +224,7 @@ mod tests { ids_data, hint_code, &mut exec_scopes, - &[(BASE_86, Felt252::one().shl(86_u32))] + &[(BASE_86, crate::math_utils::pow2_const(86))] .into_iter() .map(|(k, v)| (k.to_string(), v)) .collect() @@ -277,7 +278,7 @@ mod tests { let mut vm = vm!(); vm.segments = segments![((0, 0), 1), ((0, 1), 2), ((0, 2), 3)]; let x = BigInt3::from_base_addr((0, 0).into(), "x", &vm).unwrap(); - assert_eq!(x.limbs[0].as_ref(), &Felt252::one()); + assert_eq!(x.limbs[0].as_ref(), &Felt252::ONE); assert_eq!(x.limbs[1].as_ref(), &Felt252::from(2)); assert_eq!(x.limbs[2].as_ref(), &Felt252::from(3)); } @@ -294,7 +295,7 @@ mod tests { ((0, 4), 5) ]; let x = BigInt5::from_base_addr((0, 0).into(), "x", &vm).unwrap(); - assert_eq!(x.limbs[0].as_ref(), &Felt252::one()); + assert_eq!(x.limbs[0].as_ref(), &Felt252::ONE); assert_eq!(x.limbs[1].as_ref(), &Felt252::from(2)); assert_eq!(x.limbs[2].as_ref(), &Felt252::from(3)); assert_eq!(x.limbs[3].as_ref(), &Felt252::from(4)); @@ -332,7 +333,7 @@ mod tests { vm.segments = segments![((1, 0), 1), ((1, 1), 2), ((1, 2), 3)]; let ids_data = ids_data!["x"]; let x = BigInt3::from_var_name("x", &vm, &ids_data, &ApTracking::default()).unwrap(); - assert_eq!(x.limbs[0].as_ref(), &Felt252::one()); + assert_eq!(x.limbs[0].as_ref(), &Felt252::ONE); assert_eq!(x.limbs[1].as_ref(), &Felt252::from(2)); assert_eq!(x.limbs[2].as_ref(), &Felt252::from(3)); } @@ -351,7 +352,7 @@ mod tests { ]; let ids_data = ids_data!["x"]; let x = BigInt5::from_var_name("x", &vm, &ids_data, &ApTracking::default()).unwrap(); - assert_eq!(x.limbs[0].as_ref(), &Felt252::one()); + assert_eq!(x.limbs[0].as_ref(), &Felt252::ONE); assert_eq!(x.limbs[1].as_ref(), &Felt252::from(2)); assert_eq!(x.limbs[2].as_ref(), &Felt252::from(3)); assert_eq!(x.limbs[3].as_ref(), &Felt252::from(4)); @@ -441,9 +442,9 @@ mod tests { fn u384_pack86() { let pack_1 = Uint384 { limbs: [ - Cow::Borrowed(&Felt252::new(10_i32)), - Cow::Borrowed(&Felt252::new(10_i32)), - Cow::Borrowed(&Felt252::new(10_i32)), + Cow::Borrowed(&Felt252::from(10_i32)), + Cow::Borrowed(&Felt252::from(10_i32)), + Cow::Borrowed(&Felt252::from(10_i32)), ], } .pack86(); diff --git a/vm/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs b/vm/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs index ffeb87472f..700c5778ea 100644 --- a/vm/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs +++ b/vm/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs @@ -1,3 +1,5 @@ +use crate::utils::{biguint_to_felt, felt_to_biguint}; +use crate::Felt252; use crate::{ hint_processor::{ builtin_hint_processor::{ @@ -14,11 +16,10 @@ use crate::{ }, math_utils::{ec_double_slope, line_slope}, serde::deserialize_program::ApTracking, - stdlib::{collections::HashMap, ops::BitAnd, prelude::*}, + stdlib::{collections::HashMap, prelude::*}, types::exec_scope::ExecutionScopes, vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, }; -use felt::Felt252; use num_bigint::{BigInt, BigUint}; use num_integer::Integer; @@ -416,7 +417,7 @@ pub fn ec_mul_inner( //(ids.scalar % PRIME) % 2 let scalar = get_integer_from_var_name("scalar", vm, ids_data, ap_tracking)? .as_ref() - .bitand(&Felt252::one()); + .mod_floor(&Felt252::TWO.try_into().expect("nonzero by construction")); insert_value_into_ap(vm, scalar) } @@ -502,7 +503,7 @@ pub fn n_pair_bits( return Err(HintError::NPairBitsTooLowM); } - let (scalar_v, scalar_u) = (scalar_v.to_biguint(), scalar_u.to_biguint()); + let (scalar_v, scalar_u) = (felt_to_biguint(*scalar_v), felt_to_biguint(*scalar_u)); // Each step, fetches the bits in mth position for v and u, // and appends them to the accumulator. i.e: @@ -511,21 +512,22 @@ pub fn n_pair_bits( // 1010101__ -> 101010110 let get_bit = |x: &BigUint, i| m.checked_sub(i).map(|i| x.bit(i.into())).unwrap_or(false) as u32; - let res: Felt252 = (0..number_of_pairs) - .map(|i| { - // This code is definitely verbose, but it's the only way I found to avoid a `panic` - // when `m < number_of_pairs` while still being correct and hopefully fast. - let bit_1 = get_bit(&scalar_v, i); - // 1 * ((ids.scalar_u >> ids.m) & 1) - let bit_0 = get_bit(&scalar_u, i); - bit_0 | (bit_1 << 1) - }) - .fold(BigUint::zero(), |mut acc, x| { - acc <<= 2_u32; - acc += x; - acc - }) - .into(); + let res: Felt252 = biguint_to_felt( + &(0..number_of_pairs) + .map(|i| { + // This code is definitely verbose, but it's the only way I found to avoid a `panic` + // when `m < number_of_pairs` while still being correct and hopefully fast. + let bit_1 = get_bit(&scalar_v, i); + // 1 * ((ids.scalar_u >> ids.m) & 1) + let bit_0 = get_bit(&scalar_u, i); + bit_0 | (bit_1 << 1) + }) + .fold(BigUint::zero(), |mut acc, x| { + acc <<= 2_u32; + acc += x; + acc + }), + )?; /* ids.quad_bit = ( 8 * ((ids.scalar_v >> ids.m) & 1) @@ -1272,7 +1274,7 @@ mod tests { let ids_data = ids_data!["e"]; let ap_tracking = ApTracking::default(); let e = EcPoint::from_var_name("e", &vm, &ids_data, &ap_tracking).unwrap(); - assert_eq!(e.x.limbs[0].as_ref(), &Felt252::one()); + assert_eq!(e.x.limbs[0].as_ref(), &Felt252::ONE); assert_eq!(e.x.limbs[1].as_ref(), &Felt252::from(2)); assert_eq!(e.x.limbs[2].as_ref(), &Felt252::from(3)); assert_eq!(e.y.limbs[0].as_ref(), &Felt252::from(4)); diff --git a/vm/src/hint_processor/builtin_hint_processor/secp/field_utils.rs b/vm/src/hint_processor/builtin_hint_processor/secp/field_utils.rs index ea4448c5ad..8f34b1bead 100644 --- a/vm/src/hint_processor/builtin_hint_processor/secp/field_utils.rs +++ b/vm/src/hint_processor/builtin_hint_processor/secp/field_utils.rs @@ -1,3 +1,5 @@ +use crate::utils::bigint_to_felt; +use crate::Felt252; use crate::{ hint_processor::{ builtin_hint_processor::{ @@ -12,7 +14,6 @@ use crate::{ types::exec_scope::ExecutionScopes, vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, }; -use felt::Felt252; use num_bigint::BigInt; use num_integer::Integer; use num_traits::{One, Zero}; @@ -41,7 +42,7 @@ pub fn verify_zero( return Err(HintError::SecpVerifyZero(Box::new(val))); } - insert_value_from_var_name("q", Felt252::new(q), vm, ids_data, ap_tracking) + insert_value_from_var_name("q", bigint_to_felt(&q)?, vm, ids_data, ap_tracking) } /* @@ -67,7 +68,7 @@ pub fn verify_zero_with_external_const( return Err(HintError::SecpVerifyZero(Box::new(val))); } - insert_value_from_var_name("q", Felt252::new(q), vm, ids_data, ap_tracking) + insert_value_from_var_name("q", bigint_to_felt(&q)?, vm, ids_data, ap_tracking) } /* @@ -159,9 +160,9 @@ pub fn is_zero_nondet( let x = exec_scopes.get::("x")?; let value = if x.is_zero() { - Felt252::one() + Felt252::ONE } else { - Felt252::zero() + Felt252::ZERO }; insert_value_into_ap(vm, value) } @@ -351,8 +352,8 @@ mod tests { Err(HintError::Memory( MemoryError::InconsistentMemory(bx) )) if *bx == (Relocatable::from((1, 9)), - MaybeRelocatable::from(Felt252::new(55_i32)), - MaybeRelocatable::from(Felt252::zero())) + MaybeRelocatable::from(Felt252::from(55_i32)), + MaybeRelocatable::from(Felt252::ZERO)) ); } @@ -638,8 +639,8 @@ mod tests { Err(HintError::Memory( MemoryError::InconsistentMemory(bx) )) if *bx == (vm.run_context.get_ap(), - MaybeRelocatable::from(Felt252::new(55i32)), - MaybeRelocatable::from(Felt252::new(1i32))) + MaybeRelocatable::from(Felt252::from(55i32)), + MaybeRelocatable::from(Felt252::from(1i32))) ); } diff --git a/vm/src/hint_processor/builtin_hint_processor/secp/secp_utils.rs b/vm/src/hint_processor/builtin_hint_processor/secp/secp_utils.rs index c2ea6f8c36..7f34ea4436 100644 --- a/vm/src/hint_processor/builtin_hint_processor/secp/secp_utils.rs +++ b/vm/src/hint_processor/builtin_hint_processor/secp/secp_utils.rs @@ -90,13 +90,12 @@ pub fn bigint3_split(integer: &num_bigint::BigUint) -> Result<[num_bigint::BigUi #[cfg(test)] mod tests { use super::*; + use crate::stdlib::{collections::HashMap, string::ToString}; use crate::utils::test_utils::*; use assert_matches::assert_matches; - use felt::Felt252; use num_bigint::BigUint; - use num_traits::One; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; @@ -104,7 +103,7 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn secp_split() { let mut constants = HashMap::new(); - constants.insert(BASE_86.to_string(), Felt252::one() << 86_usize); + constants.insert(BASE_86.to_string(), crate::math_utils::pow2_const(86)); let array_1 = bigint3_split(&BigUint::zero()); #[allow(deprecated)] diff --git a/vm/src/hint_processor/builtin_hint_processor/secp/signature.rs b/vm/src/hint_processor/builtin_hint_processor/secp/signature.rs index 833226c87c..f8000d465b 100644 --- a/vm/src/hint_processor/builtin_hint_processor/secp/signature.rs +++ b/vm/src/hint_processor/builtin_hint_processor/secp/signature.rs @@ -1,3 +1,5 @@ +use crate::utils::{felt_to_bigint, felt_to_biguint}; +use crate::Felt252; use crate::{ any_box, hint_processor::{ @@ -11,7 +13,6 @@ use crate::{ vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, }; use core::ops::Add; -use felt::Felt252; use num_bigint::BigInt; use num_integer::Integer; @@ -110,10 +111,11 @@ pub fn get_point_from_x( ) -> Result<(), HintError> { exec_scopes.insert_value("SECP_P", SECP_P.clone()); #[allow(deprecated)] - let beta = constants - .get(BETA) - .ok_or_else(|| HintError::MissingConstant(Box::new(BETA)))? - .to_bigint(); + let beta = felt_to_bigint( + *constants + .get(BETA) + .ok_or_else(|| HintError::MissingConstant(Box::new(BETA)))?, + ); let x_cube_int = Uint384::from_var_name("x_cube", vm, ids_data, ap_tracking)? .pack86() @@ -123,7 +125,7 @@ pub fn get_point_from_x( let mut y = y_cube_int.modpow(&(&*SECP_P + 1_u32).shr(2_u32), &SECP_P); #[allow(deprecated)] - let v = get_integer_from_var_name("v", vm, ids_data, ap_tracking)?.to_biguint(); + let v = felt_to_biguint(*get_integer_from_var_name("v", vm, ids_data, ap_tracking)?); if v.is_even() != y.is_even() { y = &*SECP_P - y; } @@ -258,7 +260,7 @@ mod tests { ids_data, hint_code, exec_scopes_ref!(), - &[(BETA, Felt252::new(7)),] + &[(BETA, Felt252::from(7)),] .into_iter() .map(|(k, v)| (k.to_string(), v)) .collect() @@ -288,7 +290,7 @@ mod tests { ids_data, hint_code, &mut exec_scopes, - &[(BETA, Felt252::new(7)),] + &[(BETA, Felt252::from(7)),] .into_iter() .map(|(k, v)| (k.to_string(), v)) .collect() diff --git a/vm/src/hint_processor/builtin_hint_processor/set.rs b/vm/src/hint_processor/builtin_hint_processor/set.rs index a3feda7485..9d93590c87 100644 --- a/vm/src/hint_processor/builtin_hint_processor/set.rs +++ b/vm/src/hint_processor/builtin_hint_processor/set.rs @@ -1,5 +1,6 @@ use crate::stdlib::{boxed::Box, collections::HashMap, prelude::*}; +use crate::Felt252; use crate::{ hint_processor::{ builtin_hint_processor::hint_utils::{ @@ -11,8 +12,7 @@ use crate::{ types::errors::math_errors::MathError, vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, }; -use felt::Felt252; -use num_traits::{One, ToPrimitive, Zero}; +use num_traits::{ToPrimitive, Zero}; pub fn set_add( vm: &mut VirtualMachine, @@ -41,17 +41,17 @@ pub fn set_add( for i in 0..range_limit { if vm.mem_eq(elm_ptr, (set_ptr + elm_size * i)?, elm_size) { - insert_value_from_var_name("index", Felt252::new(i), vm, ids_data, ap_tracking)?; + insert_value_from_var_name("index", Felt252::from(i), vm, ids_data, ap_tracking)?; return insert_value_from_var_name( "is_elm_in_set", - Felt252::one(), + Felt252::ONE, vm, ids_data, ap_tracking, ); } } - insert_value_from_var_name("is_elm_in_set", Felt252::zero(), vm, ids_data, ap_tracking) + insert_value_from_var_name("is_elm_in_set", Felt252::ZERO, vm, ids_data, ap_tracking) } #[cfg(test)] @@ -127,7 +127,7 @@ mod tests { .get(&MaybeRelocatable::from((1, 0))) .unwrap() .as_ref(), - &MaybeRelocatable::Int(Felt252::zero()) + &MaybeRelocatable::Int(Felt252::ZERO) ) } diff --git a/vm/src/hint_processor/builtin_hint_processor/sha256_utils.rs b/vm/src/hint_processor/builtin_hint_processor/sha256_utils.rs index 89120574e5..659c752036 100644 --- a/vm/src/hint_processor/builtin_hint_processor/sha256_utils.rs +++ b/vm/src/hint_processor/builtin_hint_processor/sha256_utils.rs @@ -1,5 +1,6 @@ use crate::stdlib::{boxed::Box, collections::HashMap, prelude::*}; +use crate::Felt252; use crate::{ hint_processor::{ builtin_hint_processor::hint_utils::{ @@ -12,9 +13,8 @@ use crate::{ vm::errors::{hint_errors::HintError, vm_errors::VirtualMachineError}, vm::vm_core::VirtualMachine, }; -use felt::Felt252; use generic_array::GenericArray; -use num_traits::{One, ToPrimitive, Zero}; +use num_traits::ToPrimitive; use sha2::compress256; use crate::hint_processor::hint_processor_definition::HintReference; @@ -37,10 +37,10 @@ pub fn sha256_input( insert_value_from_var_name( "full_word", - if n_bytes >= &Felt252::new(4_i32) { - Felt252::one() + if n_bytes >= &Felt252::from(4_i32) { + Felt252::ONE } else { - Felt252::zero() + Felt252::ZERO }, vm, ids_data, @@ -87,7 +87,7 @@ fn sha256_main( let mut output: Vec = Vec::with_capacity(iv.len()); for new_state in iv { - output.push(Felt252::new(*new_state).into()); + output.push(Felt252::from(*new_state).into()); } let output_base = get_ptr_from_var_name("output", vm, ids_data, ap_tracking)?; @@ -149,7 +149,7 @@ pub fn sha256_main_arbitrary_input_length( Some(size) if size < 100 => { return Err(HintError::InvalidValue(Box::new(( "SHA256_STATE_SIZE_FELTS", - state_size_felt.clone(), + *state_size_felt, Felt252::from(SHA256_STATE_SIZE_FELTS), )))) } @@ -183,7 +183,7 @@ pub fn sha256_finalize( let mut iv = IV; - let iv_static: Vec = iv.iter().map(|n| Felt252::new(*n).into()).collect(); + let iv_static: Vec = iv.iter().map(|n| Felt252::from(*n).into()).collect(); let new_message = GenericArray::clone_from_slice(&message); compress256(&mut iv, &[new_message]); @@ -191,13 +191,13 @@ pub fn sha256_finalize( let mut output: Vec = Vec::with_capacity(SHA256_STATE_SIZE_FELTS); for new_state in iv { - output.push(Felt252::new(new_state).into()); + output.push(Felt252::from(new_state).into()); } let sha256_ptr_end = get_ptr_from_var_name("sha256_ptr_end", vm, ids_data, ap_tracking)?; let mut padding: Vec = Vec::new(); - let zero_vector_message: Vec = vec![Felt252::zero().into(); 16]; + let zero_vector_message: Vec = vec![Felt252::ZERO.into(); 16]; for _ in 0..BLOCK_SIZE - 1 { padding.extend_from_slice(zero_vector_message.as_slice()); @@ -474,7 +474,7 @@ mod tests { "SHA256_INPUT_CHUNK_SIZE_FELTS".to_string(), Felt252::from(SHA256_INPUT_CHUNK_SIZE_FELTS), ), - ("SHA256_STATE_SIZE_FELTS".to_string(), state_size.clone()), + ("SHA256_STATE_SIZE_FELTS".to_string(), state_size), ]); let expected_size = Felt252::from(SHA256_STATE_SIZE_FELTS); assert_matches!( diff --git a/vm/src/hint_processor/builtin_hint_processor/squash_dict_utils.rs b/vm/src/hint_processor/builtin_hint_processor/squash_dict_utils.rs index 3ef80e10e4..32ea9cb253 100644 --- a/vm/src/hint_processor/builtin_hint_processor/squash_dict_utils.rs +++ b/vm/src/hint_processor/builtin_hint_processor/squash_dict_utils.rs @@ -1,5 +1,6 @@ use crate::stdlib::{boxed::Box, collections::HashMap, prelude::*}; +use crate::Felt252; use crate::{ hint_processor::{ builtin_hint_processor::{ @@ -18,9 +19,7 @@ use crate::{ vm_core::VirtualMachine, }, }; -use felt::Felt252; -use num_integer::Integer; -use num_traits::{One, ToPrimitive, Zero}; +use num_traits::ToPrimitive; fn get_access_indices( exec_scopes: &mut ExecutionScopes, @@ -57,7 +56,7 @@ pub fn squash_dict_inner_first_iteration( //Get current_indices from access_indices let mut current_access_indices = access_indices .get(&key) - .ok_or_else(|| HintError::NoKeyInAccessIndices(Box::new(key.clone())))? + .ok_or_else(|| HintError::NoKeyInAccessIndices(Box::new(key)))? .clone(); current_access_indices.sort(); current_access_indices.reverse(); @@ -67,7 +66,7 @@ pub fn squash_dict_inner_first_iteration( .ok_or(HintError::EmptyCurrentAccessIndices)?; //Store variables in scope exec_scopes.insert_value("current_access_indices", current_access_indices); - exec_scopes.insert_value("current_access_index", first_val.clone()); + exec_scopes.insert_value("current_access_index", first_val); //Insert current_accesss_index into range_check_ptr vm.insert_value(range_check_ptr, first_val) .map_err(HintError::Memory) @@ -84,9 +83,9 @@ pub fn squash_dict_inner_skip_loop( let current_access_indices = exec_scopes.get_list_ref::("current_access_indices")?; //Main Logic let should_skip_loop = if current_access_indices.is_empty() { - Felt252::one() + Felt252::ONE } else { - Felt252::zero() + Felt252::ZERO }; insert_value_from_var_name( "should_skip_loop", @@ -116,11 +115,11 @@ pub fn squash_dict_inner_check_access_index( let new_access_index = current_access_indices .pop() .ok_or(HintError::EmptyCurrentAccessIndices)?; - let index_delta_minus1 = new_access_index.clone() - current_access_index - Felt252::one(); + let index_delta_minus1 = new_access_index - current_access_index - Felt252::ONE; //loop_temps.delta_minus1 = loop_temps + 0 as it is the first field of the struct //Insert loop_temps.delta_minus1 into memory insert_value_from_var_name("loop_temps", index_delta_minus1, vm, ids_data, ap_tracking)?; - exec_scopes.insert_value("new_access_index", new_access_index.clone()); + exec_scopes.insert_value("new_access_index", new_access_index); exec_scopes.insert_value("current_access_index", new_access_index); Ok(()) } @@ -139,9 +138,9 @@ pub fn squash_dict_inner_continue_loop( let current_access_indices = exec_scopes.get_list_ref::("current_access_indices")?; //Main Logic let should_continue = if current_access_indices.is_empty() { - Felt252::zero() + Felt252::ZERO } else { - Felt252::one() + Felt252::ONE }; //loop_temps.delta_minus1 = loop_temps + 3 as it is the fourth field of the struct //Insert loop_temps.delta_minus1 into memory @@ -173,9 +172,9 @@ pub fn squash_dict_inner_used_accesses_assert( //Main Logic let access_indices_at_key = access_indices .get(&key) - .ok_or_else(|| HintError::NoKeyInAccessIndices(Box::new(key.clone())))?; + .ok_or_else(|| HintError::NoKeyInAccessIndices(Box::new(key)))?; - if n_used_accesses.as_ref() != &Felt252::new(access_indices_at_key.len()) { + if n_used_accesses.as_ref() != &Felt252::from(access_indices_at_key.len()) { return Err(HintError::NumUsedAccessesAssertFail(Box::new(( n_used_accesses.into_owned(), access_indices_at_key.len(), @@ -210,7 +209,7 @@ pub fn squash_dict_inner_next_key( let keys = exec_scopes.get_mut_list_ref::("keys")?; let next_key = keys.pop().ok_or(HintError::EmptyKeys)?; //Insert next_key into ids.next_keys - insert_value_from_var_name("next_key", next_key.clone(), vm, ids_data, ap_tracking)?; + insert_value_from_var_name("next_key", next_key, vm, ids_data, ap_tracking)?; //Update local variables exec_scopes.insert_value("key", next_key); Ok(()) @@ -249,9 +248,12 @@ pub fn squash_dict( let n_accesses = get_integer_from_var_name("n_accesses", vm, ids_data, ap_tracking)?; //Get range_check_builtin let range_check_builtin = vm.get_range_check_builtin()?; - let range_check_bound = range_check_builtin._bound.clone(); + let range_check_bound = range_check_builtin._bound; //Main Logic - if ptr_diff.mod_floor(&Felt252::new(DICT_ACCESS_SIZE)) != Felt252::zero() { + let ptr_diff = ptr_diff + .to_usize() + .ok_or(HintError::PtrDiffNotDivisibleByDictAccessSize)?; + if ptr_diff % DICT_ACCESS_SIZE != 0 { return Err(HintError::PtrDiffNotDivisibleByDictAccessSize); } let squash_dict_max_size = exec_scopes.get::("__squash_dict_max_size"); @@ -276,7 +278,7 @@ pub fn squash_dict( access_indices .entry(key.into_owned()) .or_default() - .push(Felt252::new(i)); + .push(Felt252::from(i)); } //Descending list of keys. let mut keys: Vec = access_indices.keys().cloned().collect(); @@ -284,13 +286,13 @@ pub fn squash_dict( keys.reverse(); //Are the keys used bigger than the range_check bound. let big_keys = if keys[0] >= range_check_bound.unwrap() { - Felt252::one() + Felt252::ONE } else { - Felt252::zero() + Felt252::ZERO }; insert_value_from_var_name("big_keys", big_keys, vm, ids_data, ap_tracking)?; let key = keys.pop().ok_or(HintError::EmptyKeys)?; - insert_value_from_var_name("first_key", key.clone(), vm, ids_data, ap_tracking)?; + insert_value_from_var_name("first_key", key, vm, ids_data, ap_tracking)?; //Insert local variables into scope exec_scopes.insert_value("access_indices", access_indices); exec_scopes.insert_value("keys", keys); @@ -301,6 +303,7 @@ pub fn squash_dict( #[cfg(test)] mod tests { use super::*; + use crate::felt_str; use crate::{ any_box, hint_processor::{ @@ -314,7 +317,6 @@ mod tests { vm::vm_core::VirtualMachine, }; use assert_matches::assert_matches; - use felt::felt_str; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; @@ -339,16 +341,19 @@ mod tests { //Prepare scope variables let mut access_indices = HashMap::>::new(); let current_accessed_indices = vec![ - Felt252::new(9), - Felt252::new(3), - Felt252::new(10), - Felt252::new(7), + Felt252::from(9), + Felt252::from(3), + Felt252::from(10), + Felt252::from(7), ]; - access_indices.insert(Felt252::new(5), current_accessed_indices); + access_indices.insert(Felt252::from(5), current_accessed_indices); //Create vm let mut vm = vm!(); //Store scope variables - let mut exec_scopes = scope![("access_indices", access_indices), ("key", Felt252::new(5))]; + let mut exec_scopes = scope![ + ("access_indices", access_indices), + ("key", Felt252::from(5)) + ]; //Initialize fp vm.run_context.fp = 1; //Insert ids into memory (range_check_ptr) @@ -364,9 +369,9 @@ mod tests { [ ( "current_access_indices", - vec![Felt252::new(10), Felt252::new(9), Felt252::new(7)] + vec![Felt252::from(10), Felt252::from(9), Felt252::from(7)] ), - ("current_access_index", Felt252::new(3)) + ("current_access_index", Felt252::from(3)) ] ); //Check that current_access_index is now at range_check_ptr @@ -381,11 +386,14 @@ mod tests { let mut access_indices = HashMap::>::new(); //Leave current_accessed_indices empty let current_accessed_indices = Vec::::new(); - access_indices.insert(Felt252::new(5), current_accessed_indices); + access_indices.insert(Felt252::from(5), current_accessed_indices); //Create vm let mut vm = vm!(); //Store scope variables - let mut exec_scopes = scope![("access_indices", access_indices), ("key", Felt252::new(5))]; + let mut exec_scopes = scope![ + ("access_indices", access_indices), + ("key", Felt252::from(5)) + ]; //Initialize fp vm.run_context.fp = 1; //Insert ids into memory (range_check_ptr) @@ -448,7 +456,7 @@ mod tests { //Store scope variables let mut exec_scopes = scope![( "current_access_indices", - vec![Felt252::new(4), Felt252::new(7)] + vec![Felt252::from(4), Felt252::from(7)] )]; //Initialize fp vm.run_context.fp = 1; @@ -472,13 +480,13 @@ mod tests { ( "current_access_indices", vec![ - Felt252::new(10), - Felt252::new(9), - Felt252::new(7), - Felt252::new(5) + Felt252::from(10), + Felt252::from(9), + Felt252::from(7), + Felt252::from(5) ] ), - ("current_access_index", Felt252::one()) + ("current_access_index", Felt252::ONE) ]; //Initialize fp vm.run_context.fp = 1; @@ -492,10 +500,10 @@ mod tests { [ ( "current_access_indices", - vec![Felt252::new(10), Felt252::new(9), Felt252::new(7)] + vec![Felt252::from(10), Felt252::from(9), Felt252::from(7)] ), - ("new_access_index", Felt252::new(5)), - ("current_access_index", Felt252::new(5)) + ("new_access_index", Felt252::from(5)), + ("current_access_index", Felt252::from(5)) ] ); //Check the value of loop_temps.index_delta_minus_1 @@ -513,7 +521,7 @@ mod tests { //Store scope variables let mut exec_scopes = scope![ ("current_access_indices", Vec::::new()), - ("current_access_index", Felt252::one()) + ("current_access_index", Felt252::ONE) ]; //Initialize fp vm.run_context.fp = 1; @@ -538,7 +546,7 @@ mod tests { //Store scope variables let mut exec_scopes = scope![( "current_access_indices", - vec![Felt252::new(4), Felt252::new(7)] + vec![Felt252::from(4), Felt252::from(7)] )]; //Initialize fp vm.run_context.fp = 1; @@ -592,7 +600,7 @@ mod tests { //Create vm let mut vm = vm!(); //Store scope variables - let mut exec_scopes = scope![("current_access_indices", vec![Felt252::new(29)])]; + let mut exec_scopes = scope![("current_access_indices", vec![Felt252::from(29)])]; //Execute the hint //Hint should produce an error if assertion fails assert_matches!( @@ -608,16 +616,19 @@ mod tests { //Prepare scope variables let mut access_indices = HashMap::>::new(); let current_accessed_indices = vec![ - Felt252::new(9), - Felt252::new(3), - Felt252::new(10), - Felt252::new(7), + Felt252::from(9), + Felt252::from(3), + Felt252::from(10), + Felt252::from(7), ]; - access_indices.insert(Felt252::new(5), current_accessed_indices); + access_indices.insert(Felt252::from(5), current_accessed_indices); //Create vm let mut vm = vm!(); //Store scope variables - let mut exec_scopes = scope![("access_indices", access_indices), ("key", Felt252::new(5))]; + let mut exec_scopes = scope![ + ("access_indices", access_indices), + ("key", Felt252::from(5)) + ]; //Initialize fp vm.run_context.fp = 1; //Insert ids into memory (n_used_accesses) @@ -636,16 +647,19 @@ mod tests { //Prepare scope variables let mut access_indices = HashMap::>::new(); let current_accessed_indices = vec![ - Felt252::new(9), - Felt252::new(3), - Felt252::new(10), - Felt252::new(7), + Felt252::from(9), + Felt252::from(3), + Felt252::from(10), + Felt252::from(7), ]; - access_indices.insert(Felt252::new(5), current_accessed_indices); + access_indices.insert(Felt252::from(5), current_accessed_indices); //Create vm let mut vm = vm!(); //Store scope variables - let mut exec_scopes = scope![("access_indices", access_indices), ("key", Felt252::new(5))]; + let mut exec_scopes = scope![ + ("access_indices", access_indices), + ("key", Felt252::from(5)) + ]; //Initialize fp vm.run_context.fp = 1; //Insert ids into memory (n_used_accesses) @@ -655,7 +669,7 @@ mod tests { //Execute the hint assert_matches!( run_hint!(vm, ids_data, hint_code, &mut exec_scopes), - Err(HintError::NumUsedAccessesAssertFail(bx)) if *bx == (Felt252::new(5), 4, Felt252::new(5)) + Err(HintError::NumUsedAccessesAssertFail(bx)) if *bx == (Felt252::from(5), 4, Felt252::from(5)) ); } @@ -666,16 +680,19 @@ mod tests { //Prepare scope variables let mut access_indices = HashMap::>::new(); let current_accessed_indices = vec![ - Felt252::new(9), - Felt252::new(3), - Felt252::new(10), - Felt252::new(7), + Felt252::from(9), + Felt252::from(3), + Felt252::from(10), + Felt252::from(7), ]; - access_indices.insert(Felt252::new(5), current_accessed_indices); + access_indices.insert(Felt252::from(5), current_accessed_indices); //Create vm let mut vm = vm!(); //Store scope variables - let mut exec_scopes = scope![("access_indices", access_indices), ("key", Felt252::new(5))]; + let mut exec_scopes = scope![ + ("access_indices", access_indices), + ("key", Felt252::from(5)) + ]; //Initialize fp vm.run_context.fp = 1; //Insert ids into memory (n_used_accesses) @@ -711,7 +728,7 @@ mod tests { //Create vm let mut vm = vm!(); //Store scope variables - let mut exec_scopes = scope![("keys", vec![Felt252::new(3)])]; + let mut exec_scopes = scope![("keys", vec![Felt252::from(3)])]; //Execute the hint assert_matches!( run_hint!(vm, HashMap::new(), hint_code, &mut exec_scopes), @@ -740,7 +757,7 @@ mod tests { let mut vm = vm!(); add_segments!(vm, 2); //Store scope variables - let mut exec_scopes = scope![("keys", vec![Felt252::one(), Felt252::new(3)])]; + let mut exec_scopes = scope![("keys", vec![Felt252::ONE, Felt252::from(3)])]; //Initialize fp vm.run_context.fp = 1; //Create hint_data @@ -752,7 +769,7 @@ mod tests { //Check local variables check_scope!( &exec_scopes, - [("keys", vec![Felt252::one()]), ("key", Felt252::new(3))] + [("keys", vec![Felt252::ONE]), ("key", Felt252::from(3))] ); } @@ -809,13 +826,13 @@ mod tests { assert_matches!(run_hint!(vm, ids_data, hint_code, &mut exec_scopes), Ok(())); //Check scope variables let access_indices_scope_value: HashMap> = - HashMap::from([(Felt252::one(), vec![Felt252::zero(), Felt252::one()])]); + HashMap::from([(Felt252::ONE, vec![Felt252::ZERO, Felt252::ONE])]); check_scope!( &exec_scopes, [ ("access_indices", access_indices_scope_value), ("keys", Vec::::new()), - ("key", Felt252::one()) + ("key", Felt252::ONE) ] ); //Check ids variables @@ -862,19 +879,19 @@ mod tests { assert_matches!(run_hint!(vm, ids_data, hint_code, &mut exec_scopes), Ok(())); //Check scope variables let access_indices_scope_value: HashMap> = HashMap::from([ - (Felt252::one(), vec![Felt252::zero(), Felt252::one()]), - (Felt252::new(2), vec![Felt252::new(2), Felt252::new(3)]), + (Felt252::ONE, vec![Felt252::ZERO, Felt252::ONE]), + (Felt252::from(2), vec![Felt252::from(2), Felt252::from(3)]), ]); check_scope!( &exec_scopes, [ ("access_indices", access_indices_scope_value), - ("keys", vec![Felt252::new(2)]), - ("key", Felt252::one()) + ("keys", vec![Felt252::from(2)]), + ("key", Felt252::ONE) ] ); let keys = exec_scopes.get_list_ref::("keys").unwrap(); - assert_eq!(*keys, vec![Felt252::new(2)]); + assert_eq!(*keys, vec![Felt252::from(2)]); //Check ids variables check_memory![vm.segments.memory, ((1, 1), 0), ((1, 2), 1)]; } @@ -887,7 +904,7 @@ mod tests { //Create vm let mut vm = vm_with_range_check!(); //Create scope variables - let mut exec_scopes = scope![("__squash_dict_max_size", Felt252::new(12))]; + let mut exec_scopes = scope![("__squash_dict_max_size", Felt252::from(12))]; //Initialize fp vm.run_context.fp = 5; //Insert ids into memory @@ -914,13 +931,13 @@ mod tests { assert_matches!(run_hint!(vm, ids_data, hint_code, &mut exec_scopes), Ok(())); //Check scope variables let access_indices_scope_value: HashMap> = - HashMap::from([(Felt252::one(), vec![Felt252::zero(), Felt252::one()])]); + HashMap::from([(Felt252::ONE, vec![Felt252::ZERO, Felt252::ONE])]); check_scope!( &exec_scopes, [ ("access_indices", access_indices_scope_value), ("keys", Vec::::new()), - ("key", Felt252::one()) + ("key", Felt252::ONE) ] ); //Check ids variables @@ -935,7 +952,7 @@ mod tests { //Create vm let mut vm = vm_with_range_check!(); //Create scope variables - let mut exec_scopes = scope![("__squash_dict_max_size", Felt252::one())]; + let mut exec_scopes = scope![("__squash_dict_max_size", Felt252::ONE)]; //Initialize fp vm.run_context.fp = 5; //Insert ids into memory @@ -961,7 +978,7 @@ mod tests { //Execute the hint assert_matches!( run_hint!(vm, ids_data, hint_code, &mut exec_scopes), - Err(HintError::SquashDictMaxSizeExceeded(bx)) if *bx == (Felt252::one(), Felt252::new(2)) + Err(HintError::SquashDictMaxSizeExceeded(bx)) if *bx == (Felt252::ONE, Felt252::from(2)) ); } @@ -1093,7 +1110,7 @@ mod tests { felt_str!( "3618502761706184546546682988428055018603476541694452277432519575032261771265" ), - vec![Felt252::zero(), Felt252::one()], + vec![Felt252::ZERO, Felt252::ONE], )]); check_scope!(&exec_scopes, [("access_indices", access_indices_scope_value), ("keys", Vec::::new()), ("key", felt_str!("3618502761706184546546682988428055018603476541694452277432519575032261771265"))]); //Check ids variables diff --git a/vm/src/hint_processor/builtin_hint_processor/uint256_utils.rs b/vm/src/hint_processor/builtin_hint_processor/uint256_utils.rs index 67b5dcec8c..1416fec21d 100644 --- a/vm/src/hint_processor/builtin_hint_processor/uint256_utils.rs +++ b/vm/src/hint_processor/builtin_hint_processor/uint256_utils.rs @@ -1,10 +1,12 @@ +use crate::utils::{biguint_to_felt, felt_to_biguint}; +use crate::Felt252; use crate::{ hint_processor::builtin_hint_processor::hint_utils::{ get_integer_from_var_name, get_relocatable_from_var_name, insert_value_from_var_name, insert_value_into_ap, }, hint_processor::hint_processor_definition::HintReference, - math_utils::isqrt, + math_utils::{isqrt, pow2_const, pow2_const_nz}, serde::deserialize_program::ApTracking, stdlib::{ borrow::Cow, @@ -16,10 +18,9 @@ use crate::{ types::{errors::math_errors::MathError, relocatable::Relocatable}, vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, }; -use felt::Felt252; use num_bigint::BigUint; use num_integer::{div_rem, Integer}; -use num_traits::{One, Signed, Zero}; +use num_traits::{One, Zero}; // TODO: use this type in all uint256 functions pub(crate) struct Uint256<'a> { @@ -75,13 +76,13 @@ impl<'a> Uint256<'a> { } pub(crate) fn pack(self) -> BigUint { - (self.high.to_biguint() << 128) + self.low.to_biguint() + (felt_to_biguint(*self.high) << 128) + felt_to_biguint(*self.low) } pub(crate) fn split(num: &BigUint) -> Self { let mask_low: BigUint = u128::MAX.into(); - let low = Felt252::from(num & mask_low); - let high = Felt252::from(num >> 128); + let low = biguint_to_felt(&(num & mask_low)).unwrap(); + let high = biguint_to_felt(&(num >> 128)).unwrap(); Self::from_values(low, high) } } @@ -94,8 +95,7 @@ impl<'a> From<&BigUint> for Uint256<'a> { impl<'a> From for Uint256<'a> { fn from(value: Felt252) -> Self { - let low = Felt252::new(u128::MAX) & &value; - let high = value >> 128_u32; + let (high, low) = value.div_rem(pow2_const_nz(128)); Self::from_values(low, high) } } @@ -119,7 +119,7 @@ pub fn uint256_add( ap_tracking: &ApTracking, low_only: bool, ) -> Result<(), HintError> { - let shift = Felt252::new(1_u32) << 128_u32; + let shift = pow2_const(128); let a = Uint256::from_var_name("a", vm, ids_data, ap_tracking)?; let b = Uint256::from_var_name("b", vm, ids_data, ap_tracking)?; @@ -138,7 +138,7 @@ pub fn uint256_add( // Main logic // sum_high = ids.a.high + ids.b.high + ids.carry_low // ids.carry_high = 1 if sum_high >= ids.SHIFT else 0 - let carry_high = Felt252::from((a_high + b_high + &carry_low >= shift) as u8); + let carry_high = Felt252::from((a_high + b_high + carry_low >= shift) as u8); insert_value_from_var_name("carry_high", carry_high, vm, ids_data, ap_tracking)?; } @@ -158,7 +158,7 @@ pub fn uint128_add( ids_data: &HashMap, ap_tracking: &ApTracking, ) -> Result<(), HintError> { - let shift = Felt252::new(1_u32) << 128_u32; + let shift = pow2_const(128); let a = get_integer_from_var_name("a", vm, ids_data, ap_tracking)?; let b = get_integer_from_var_name("b", vm, ids_data, ap_tracking)?; let a = a.as_ref(); @@ -245,9 +245,14 @@ pub fn split_64( ap_tracking: &ApTracking, ) -> Result<(), HintError> { let a = get_integer_from_var_name("a", vm, ids_data, ap_tracking)?; - let mut digits = a.iter_u64_digits(); - let low = Felt252::new(digits.next().unwrap_or(0u64)); - let high = a.as_ref() >> 64_u32; + let digits = a.to_le_digits(); + let mut bytes = [0u8; 32]; + bytes[..8].copy_from_slice(digits[1].to_le_bytes().as_slice()); + bytes[8..16].copy_from_slice(digits[2].to_le_bytes().as_slice()); + bytes[16..24].copy_from_slice(digits[3].to_le_bytes().as_slice()); + + let low = Felt252::from(digits[0]); + let high = Felt252::from_bytes_le(&bytes); insert_value_from_var_name("high", high, vm, ids_data, ap_tracking)?; insert_value_from_var_name("low", low, vm, ids_data, ap_tracking) } @@ -287,12 +292,12 @@ pub fn uint256_sqrt( )); } - let root = Felt252::new(root); + let root = biguint_to_felt(&root)?; if only_low { insert_value_from_var_name("root", root, vm, ids_data, ap_tracking)?; } else { - let root_u256 = Uint256::from_values(root, Felt252::zero()); + let root_u256 = Uint256::from_values(root, Felt252::ZERO); root_u256.insert_from_var_name("root", vm, ids_data, ap_tracking)?; } Ok(()) @@ -311,11 +316,12 @@ pub fn uint256_signed_nn( let a_high = vm.get_integer((a_addr + 1_usize)?)?; //Main logic //memory[ap] = 1 if 0 <= (ids.a.high % PRIME) < 2 ** 127 else 0 - let result: Felt252 = if !a_high.is_negative() && a_high.as_ref() <= &Felt252::new(i128::MAX) { - Felt252::one() - } else { - Felt252::zero() - }; + let result: Felt252 = + if *a_high >= Felt252::ZERO && a_high.as_ref() <= &Felt252::from(i128::MAX) { + Felt252::ONE + } else { + Felt252::ZERO + }; insert_value_into_ap(vm, result) } @@ -388,8 +394,8 @@ pub fn uint256_offseted_unsigned_div_rem( //ids.remainder.low = remainder & ((1 << 128) - 1) //ids.remainder.high = remainder >> 128 - let a = (a_high.to_biguint() << 128_u32) + a_low.to_biguint(); - let div = (div_high.to_biguint() << 128_u32) + div_low.to_biguint(); + let a = (felt_to_biguint(*a_high) << 128_u32) + felt_to_biguint(*a_low); + let div = (felt_to_biguint(*div_high) << 128_u32) + felt_to_biguint(*div_low); //a and div will always be positive numbers //Then, Rust div_rem equals Python divmod let (quotient, remainder) = div_rem(a, div); @@ -447,9 +453,9 @@ pub fn uint256_mul_div_mod( let div_high = div_high.as_ref(); // Main Logic - let a = a_high.to_biguint().shl(128_usize) + a_low.to_biguint(); - let b = b_high.to_biguint().shl(128_usize) + b_low.to_biguint(); - let div = div_high.to_biguint().shl(128_usize) + div_low.to_biguint(); + let a = felt_to_biguint(*a_high).shl(128_usize) + felt_to_biguint(*a_low); + let b = felt_to_biguint(*b_high).shl(128_usize) + felt_to_biguint(*b_low); + let div = felt_to_biguint(*div_high).shl(128_usize) + felt_to_biguint(*div_low); if div.is_zero() { return Err(MathError::DividedByZero.into()); } @@ -458,30 +464,33 @@ pub fn uint256_mul_div_mod( // ids.quotient_low.low vm.insert_value( quotient_low_addr, - Felt252::from("ient & &BigUint::from(u128::MAX)), + biguint_to_felt(&("ient & &BigUint::from(u128::MAX)))?, )?; // ids.quotient_low.high vm.insert_value( (quotient_low_addr + 1)?, - Felt252::from(("ient).shr(128_u32) & &BigUint::from(u128::MAX)), + biguint_to_felt(&(("ient).shr(128_u32) & &BigUint::from(u128::MAX)))?, )?; // ids.quotient_high.low vm.insert_value( quotient_high_addr, - Felt252::from(("ient).shr(256_u32) & &BigUint::from(u128::MAX)), + biguint_to_felt(&(("ient).shr(256_u32) & &BigUint::from(u128::MAX)))?, )?; // ids.quotient_high.high vm.insert_value( (quotient_high_addr + 1)?, - Felt252::from(("ient).shr(384_u32)), + biguint_to_felt(&(("ient).shr(384_u32)))?, )?; //ids.remainder.low vm.insert_value( remainder_addr, - Felt252::from(&remainder & &BigUint::from(u128::MAX)), + biguint_to_felt(&(&remainder & &BigUint::from(u128::MAX)))?, )?; //ids.remainder.high - vm.insert_value((remainder_addr + 1)?, Felt252::from(remainder.shr(128_u32)))?; + vm.insert_value( + (remainder_addr + 1)?, + biguint_to_felt(&remainder.shr(128_u32))?, + )?; Ok(()) } @@ -489,6 +498,7 @@ pub fn uint256_mul_div_mod( #[cfg(test)] mod tests { use super::*; + use crate::felt_str; use crate::{ any_box, hint_processor::{ @@ -506,7 +516,6 @@ mod tests { vm::{errors::memory_errors::MemoryError, vm_core::VirtualMachine}, }; use assert_matches::assert_matches; - use felt::felt_str; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; @@ -598,8 +607,8 @@ mod tests { Err(HintError::Memory( MemoryError::InconsistentMemory(bx) )) if *bx == (Relocatable::from((1, 12)), - MaybeRelocatable::from(Felt252::new(2)), - MaybeRelocatable::from(Felt252::zero())) + MaybeRelocatable::from(Felt252::from(2)), + MaybeRelocatable::from(Felt252::ZERO)) ); } @@ -780,7 +789,7 @@ mod tests { Err(HintError::Memory( MemoryError::InconsistentMemory(bx) )) if *bx == (Relocatable::from((1, 10)), - MaybeRelocatable::from(Felt252::zero()), + MaybeRelocatable::from(Felt252::ZERO), MaybeRelocatable::from(felt_str!("7249717543555297151"))) ); } @@ -860,7 +869,7 @@ mod tests { Err(HintError::Memory( MemoryError::InconsistentMemory(bx) )) if *bx == (Relocatable::from((1, 5)), - MaybeRelocatable::from(Felt252::one()), + MaybeRelocatable::from(Felt252::ONE), MaybeRelocatable::from(felt_str!("48805497317890012913"))) ); } @@ -929,8 +938,8 @@ mod tests { Err(HintError::Memory( MemoryError::InconsistentMemory(bx) )) if *bx == (Relocatable::from((1, 5)), - MaybeRelocatable::from(Felt252::new(55)), - MaybeRelocatable::from(Felt252::one())) + MaybeRelocatable::from(Felt252::from(55)), + MaybeRelocatable::from(Felt252::ONE)) ); } @@ -1018,8 +1027,8 @@ mod tests { Err(HintError::Memory( MemoryError::InconsistentMemory(bx) )) if *bx == (Relocatable::from((1, 10)), - MaybeRelocatable::from(Felt252::zero()), - MaybeRelocatable::from(Felt252::new(10))) + MaybeRelocatable::from(Felt252::ZERO), + MaybeRelocatable::from(Felt252::from(10))) ); } @@ -1047,8 +1056,8 @@ mod tests { Err(HintError::Memory( MemoryError::InconsistentMemory(bx) )) if *bx == (Relocatable::from((1, 11)), - MaybeRelocatable::from(Felt252::one()), - MaybeRelocatable::from(Felt252::zero())) + MaybeRelocatable::from(Felt252::ONE), + MaybeRelocatable::from(Felt252::ZERO)) ); } diff --git a/vm/src/hint_processor/builtin_hint_processor/uint384.rs b/vm/src/hint_processor/builtin_hint_processor/uint384.rs index 9eb25240bd..c7d6ba3465 100644 --- a/vm/src/hint_processor/builtin_hint_processor/uint384.rs +++ b/vm/src/hint_processor/builtin_hint_processor/uint384.rs @@ -1,4 +1,5 @@ -use felt::Felt252; +use crate::utils::felt_to_biguint; +use crate::Felt252; use num_integer::Integer; use num_traits::Zero; @@ -7,6 +8,7 @@ use crate::stdlib::{boxed::Box, collections::HashMap, prelude::*}; use crate::types::errors::math_errors::MathError; use crate::{ hint_processor::hint_processor_definition::HintReference, + math_utils::pow2_const_nz, serde::deserialize_program::ApTracking, vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, }; @@ -79,15 +81,11 @@ pub fn uint384_split_128( ids_data: &HashMap, ap_tracking: &ApTracking, ) -> Result<(), HintError> { - let a = get_integer_from_var_name("a", vm, ids_data, ap_tracking)?.into_owned(); - insert_value_from_var_name( - "low", - &a & &Felt252::from(u128::MAX), - vm, - ids_data, - ap_tracking, - )?; - insert_value_from_var_name("high", a >> 128_u32, vm, ids_data, ap_tracking) + let bound = pow2_const_nz(128); + let a = get_integer_from_var_name("a", vm, ids_data, ap_tracking)?; + let (high, low) = a.div_rem(bound); + insert_value_from_var_name("low", low, vm, ids_data, ap_tracking)?; + insert_value_from_var_name("high", high, vm, ids_data, ap_tracking) } /* Implements Hint: @@ -109,13 +107,17 @@ pub fn add_no_uint384_check( let a = Uint384::from_var_name("a", vm, ids_data, ap_tracking)?; let b = Uint384::from_var_name("b", vm, ids_data, ap_tracking)?; // This hint is not from the cairo commonlib, and its lib can be found under different paths, so we cant rely on a full path name - let shift = get_constant_from_var_name("SHIFT", constants)?.to_biguint(); + let shift = felt_to_biguint(*get_constant_from_var_name("SHIFT", constants)?); - let sum_d0 = a.limbs[0].to_biguint() + b.limbs[0].to_biguint(); + let sum_d0 = felt_to_biguint(*a.limbs[0].as_ref()) + felt_to_biguint(*b.limbs[0].as_ref()); let carry_d0 = Felt252::from((sum_d0 >= shift) as usize); - let sum_d1 = a.limbs[1].to_biguint() + b.limbs[1].to_biguint() + carry_d0.to_biguint(); + let sum_d1 = felt_to_biguint(*a.limbs[1].as_ref()) + + felt_to_biguint(*b.limbs[1].as_ref()) + + felt_to_biguint(carry_d0); let carry_d1 = Felt252::from((sum_d1 >= shift) as usize); - let sum_d2 = a.limbs[2].to_biguint() + b.limbs[2].to_biguint() + carry_d1.to_biguint(); + let sum_d2 = felt_to_biguint(*a.limbs[2].as_ref()) + + felt_to_biguint(*b.limbs[2].as_ref()) + + felt_to_biguint(carry_d1); let carry_d2 = Felt252::from((sum_d2 >= shift) as usize); insert_value_from_var_name("carry_d0", carry_d0, vm, ids_data, ap_tracking)?; @@ -230,8 +232,8 @@ pub fn sub_reduced_a_and_reduced_b( mod tests { use super::*; use crate::hint_processor::builtin_hint_processor::hint_code; - use core::ops::Shl; + use crate::felt_str; use crate::{ any_box, hint_processor::{ @@ -248,9 +250,7 @@ mod tests { vm::{errors::memory_errors::MemoryError, vm_core::VirtualMachine}, }; use assert_matches::assert_matches; - use felt::felt_str; - use num_traits::One; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; @@ -364,8 +364,8 @@ mod tests { Err(HintError::Memory( MemoryError::InconsistentMemory(bx) )) if *bx == (Relocatable::from((1, 7)), - MaybeRelocatable::from(Felt252::new(2)), - MaybeRelocatable::from(Felt252::new(221))) + MaybeRelocatable::from(Felt252::from(2)), + MaybeRelocatable::from(Felt252::from(221))) ); } @@ -451,8 +451,8 @@ mod tests { Err(HintError::Memory( MemoryError::InconsistentMemory(bx) )) if *bx == (Relocatable::from((1, 1)), - MaybeRelocatable::from(Felt252::new(2)), - MaybeRelocatable::from(Felt252::new(34895349583295832495320945304_i128))) + MaybeRelocatable::from(Felt252::from(2)), + MaybeRelocatable::from(Felt252::from(34895349583295832495320945304_i128))) ); } @@ -488,7 +488,7 @@ mod tests { ids_data, hint_code::ADD_NO_UINT384_CHECK, &mut exec_scopes_ref!(), - &[("path.path.path.SHIFT", Felt252::one().shl(128_u32))] + &[("path.path.path.SHIFT", crate::math_utils::pow2_const(128))] .into_iter() .map(|(k, v)| (k.to_string(), v)) .collect() diff --git a/vm/src/hint_processor/builtin_hint_processor/uint384_extension.rs b/vm/src/hint_processor/builtin_hint_processor/uint384_extension.rs index 27bada5acf..85c3cf6af8 100644 --- a/vm/src/hint_processor/builtin_hint_processor/uint384_extension.rs +++ b/vm/src/hint_processor/builtin_hint_processor/uint384_extension.rs @@ -78,9 +78,8 @@ mod tests { use assert_matches::assert_matches; - use felt::felt_str; - use felt::Felt252; - use num_traits::One; + use crate::felt_str; + use crate::Felt252; use rstest::rstest; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; @@ -98,7 +97,7 @@ mod tests { ((1, 5), 6) ]; let x = Uint768::from_base_addr((1, 0).into(), "x", &vm).unwrap(); - assert_eq!(x.limbs[0].as_ref(), &Felt252::one()); + assert_eq!(x.limbs[0].as_ref(), &Felt252::ONE); assert_eq!(x.limbs[1].as_ref(), &Felt252::from(2)); assert_eq!(x.limbs[2].as_ref(), &Felt252::from(3)); } @@ -186,7 +185,7 @@ mod tests { ]; let ids_data = ids_data!["x"]; let x = Uint768::from_var_name("x", &vm, &ids_data, &ApTracking::default()).unwrap(); - assert_eq!(x.limbs[0].as_ref(), &Felt252::one()); + assert_eq!(x.limbs[0].as_ref(), &Felt252::ONE); assert_eq!(x.limbs[1].as_ref(), &Felt252::from(2)); assert_eq!(x.limbs[2].as_ref(), &Felt252::from(3)); } diff --git a/vm/src/hint_processor/builtin_hint_processor/uint_utils.rs b/vm/src/hint_processor/builtin_hint_processor/uint_utils.rs index bdbf131da4..7db0b95593 100644 --- a/vm/src/hint_processor/builtin_hint_processor/uint_utils.rs +++ b/vm/src/hint_processor/builtin_hint_processor/uint_utils.rs @@ -1,4 +1,7 @@ -use felt::Felt252; +use crate::{ + utils::{biguint_to_felt, felt_to_biguint}, + Felt252, +}; use num_bigint::BigUint; use num_traits::One; @@ -8,7 +11,7 @@ pub(crate) fn split(num: &BigUint, num_bits_shift: u32) -> [Felt [0; N].map(|_| { let a = &num & bitmask; num >>= num_bits_shift; - Felt252::from(a) + biguint_to_felt(&a).unwrap() }) } @@ -19,6 +22,6 @@ pub(crate) fn pack( limbs .into_iter() .enumerate() - .map(|(i, limb)| limb.as_ref().to_biguint() << (i * num_bits_shift)) + .map(|(i, limb)| felt_to_biguint(*limb.as_ref()) << (i * num_bits_shift)) .sum() } diff --git a/vm/src/hint_processor/builtin_hint_processor/usort.rs b/vm/src/hint_processor/builtin_hint_processor/usort.rs index 319e394c74..f553866fe6 100644 --- a/vm/src/hint_processor/builtin_hint_processor/usort.rs +++ b/vm/src/hint_processor/builtin_hint_processor/usort.rs @@ -1,5 +1,6 @@ use crate::stdlib::{any::Any, boxed::Box, collections::HashMap, prelude::*}; +use crate::Felt252; use crate::{ hint_processor::{ builtin_hint_processor::hint_utils::{ @@ -11,8 +12,8 @@ use crate::{ types::exec_scope::ExecutionScopes, vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, }; -use felt::Felt252; -use num_traits::{ToPrimitive, Zero}; + +use num_traits::ToPrimitive; pub fn usort_enter_scope(exec_scopes: &mut ExecutionScopes) -> Result<(), HintError> { if let Ok(usort_max_size) = exec_scopes.get::("usort_max_size") { @@ -51,7 +52,7 @@ pub fn usort_body( for i in 0..input_len_u64 { let val = vm.get_integer((input_ptr + i as usize)?)?.into_owned(); if let Err(output_index) = output.binary_search(&val) { - output.insert(output_index, val.clone()); + output.insert(output_index, val); } positions_dict.entry(val).or_default().push(i); } @@ -70,12 +71,12 @@ pub fn usort_body( } for (i, repetition_amount) in multiplicities.into_iter().enumerate() { - vm.insert_value((multiplicities_base + i)?, Felt252::new(repetition_amount))?; + vm.insert_value((multiplicities_base + i)?, Felt252::from(repetition_amount))?; } insert_value_from_var_name( "output_len", - Felt252::new(output_len), + Felt252::from(output_len), vm, ids_data, ap_tracking, @@ -104,7 +105,7 @@ pub fn verify_usort( .ok_or(HintError::UnexpectedPositionsDictFail)?; positions.reverse(); exec_scopes.insert_value("positions", positions); - exec_scopes.insert_value("last_pos", Felt252::zero()); + exec_scopes.insert_value("last_pos", Felt252::ZERO); Ok(()) } @@ -127,9 +128,9 @@ pub fn verify_multiplicity_body( .get_mut_list_ref::("positions")? .pop() .ok_or(HintError::CouldntPopPositions)?; - let pos_diff = Felt252::new(current_pos) - exec_scopes.get::("last_pos")?; + let pos_diff = Felt252::from(current_pos) - exec_scopes.get::("last_pos")?; insert_value_from_var_name("next_item_index", pos_diff, vm, ids_data, ap_tracking)?; - exec_scopes.insert_value("last_pos", Felt252::new(current_pos + 1)); + exec_scopes.insert_value("last_pos", Felt252::from(current_pos + 1)); Ok(()) } @@ -173,7 +174,7 @@ mod tests { let mut exec_scopes = scope![("usort_max_size", 1_u64)]; assert_matches!( run_hint!(vm, ids_data, USORT_BODY, &mut exec_scopes), - Err(HintError::UsortOutOfRange(bx)) if *bx == (1, Felt252::new(5_i32)) + Err(HintError::UsortOutOfRange(bx)) if *bx == (1, Felt252::from(5_i32)) ); } } diff --git a/vm/src/hint_processor/builtin_hint_processor/vrf/inv_mod_p_uint512.rs b/vm/src/hint_processor/builtin_hint_processor/vrf/inv_mod_p_uint512.rs index accd67c193..8854c15a34 100644 --- a/vm/src/hint_processor/builtin_hint_processor/vrf/inv_mod_p_uint512.rs +++ b/vm/src/hint_processor/builtin_hint_processor/vrf/inv_mod_p_uint512.rs @@ -1,12 +1,12 @@ use crate::hint_processor::builtin_hint_processor::secp::bigint_utils::Uint512; use crate::hint_processor::builtin_hint_processor::uint256_utils::Uint256; use crate::stdlib::prelude::String; +use crate::utils::bigint_to_felt; use crate::{ hint_processor::hint_processor_definition::HintReference, math_utils::div_mod, serde::deserialize_program::ApTracking, stdlib::collections::HashMap, vm::errors::hint_errors::HintError, }; -use felt::Felt252; use num_bigint::BigInt; use num_traits::One; @@ -38,8 +38,11 @@ pub fn inv_mod_p_uint512( let p = Uint256::from_var_name("p", vm, ids_data, ap_tracking)?.pack(); - let x_inverse_mod_p = - Felt252::from(div_mod(&BigInt::one(), &BigInt::from(x), &BigInt::from(p))?); + let x_inverse_mod_p = bigint_to_felt(&div_mod( + &BigInt::one(), + &BigInt::from(x), + &BigInt::from(p), + )?)?; let x_inverse_mod_p = Uint256::from(x_inverse_mod_p); x_inverse_mod_p.insert_from_var_name("x_inverse_mod_p", vm, ids_data, ap_tracking)?; @@ -51,6 +54,7 @@ pub fn inv_mod_p_uint512( mod tests { use super::*; use crate::any_box; + use crate::felt_str; use crate::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::BuiltinHintProcessor; use crate::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::HintProcessorData; use crate::hint_processor::hint_processor_definition::HintProcessorLogic; @@ -59,6 +63,7 @@ mod tests { use crate::utils::test_utils::memory; use crate::utils::test_utils::memory_from_memory; use crate::utils::test_utils::memory_inner; + use crate::Felt252; use crate::{ hint_processor::builtin_hint_processor::hint_code::INV_MOD_P_UINT512, types::exec_scope::ExecutionScopes, @@ -67,7 +72,7 @@ mod tests { }, }; use num_bigint::BigUint; - use num_traits::{FromPrimitive, Num}; + use num_traits::Num; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; @@ -75,10 +80,10 @@ mod tests { fn test_pack_512() { assert_eq!( Uint512::from_values([ - Felt252::new(13123), - Felt252::new(534354), - Felt252::new(9901823), - Felt252::new(7812371) + Felt252::from(13123), + Felt252::from(534354), + Felt252::from(9901823), + Felt252::from(7812371) ]).pack(), BigUint::from_str_radix( "307823090550532533958111616786199064327151160536573522012843486812312234767517005952120863393832102810613083123402814796611", @@ -87,10 +92,10 @@ mod tests { ); assert_eq!( Uint512::from_values([ - Felt252::new(13123), - Felt252::new(534354), - Felt252::new(9901823), - Felt252::new(7812371) + Felt252::from(13123), + Felt252::from(534354), + Felt252::from(9901823), + Felt252::from(7812371) ]).pack(), BigUint::from_str_radix( "307823090550532533958111616786199064327151160536573522012843486812312234767517005952120863393832102810613083123402814796611", @@ -101,10 +106,10 @@ mod tests { assert_eq!( Uint512::from_values([ - Felt252::new(90812398), - Felt252::new(55), - Felt252::new(83127), - Felt252::from_i128(45312309123).unwrap() + Felt252::from(90812398), + Felt252::from(55), + Felt252::from(83127), + Felt252::from(45312309123_u64) ]).pack(), BigUint::from_str_radix("1785395884837388090117385402351420305430103423113021825538726783888669416377532493875431795584456624829488631993250169127284718", 10).unwrap() ); @@ -131,12 +136,12 @@ mod tests { ]; vm.insert_value( Relocatable::from((1, 15)), - Felt252::from_str_radix("201385395114098847380338600778089168199", 10).unwrap(), + felt_str!("201385395114098847380338600778089168199"), ) .expect("error setting ids.p"); vm.insert_value( Relocatable::from((1, 16)), - Felt252::from_str_radix("64323764613183177041862057485226039389", 10).unwrap(), + felt_str!("64323764613183177041862057485226039389"), ) .expect("error setting ids.p"); @@ -149,13 +154,13 @@ mod tests { vm.get_integer(Relocatable::from((1, 5))) .unwrap() .into_owned(), - Felt252::from_str_radix("80275402838848031859800366538378848249", 10).unwrap() + felt_str!("80275402838848031859800366538378848249") ); assert_eq!( vm.get_integer(Relocatable::from((1, 6))) .unwrap() .into_owned(), - Felt252::from_str_radix("5810892639608724280512701676461676039", 10).unwrap() + felt_str!("5810892639608724280512701676461676039") ); } } diff --git a/vm/src/hint_processor/cairo_1_hint_processor/dict_manager.rs b/vm/src/hint_processor/cairo_1_hint_processor/dict_manager.rs index 4a29c66726..69a8e77b36 100644 --- a/vm/src/hint_processor/cairo_1_hint_processor/dict_manager.rs +++ b/vm/src/hint_processor/cairo_1_hint_processor/dict_manager.rs @@ -1,9 +1,10 @@ +use num_traits::One; + use crate::stdlib::collections::HashMap; use crate::stdlib::prelude::*; -use num_traits::One; -use crate::felt::Felt252; use crate::vm::errors::hint_errors::HintError; +use crate::Felt252; use crate::{types::relocatable::Relocatable, vm::vm_core::VirtualMachine}; /// Stores the data of a specific dictionary. diff --git a/vm/src/hint_processor/cairo_1_hint_processor/hint_processor.rs b/vm/src/hint_processor/cairo_1_hint_processor/hint_processor.rs index 8fa775a125..b97107f865 100644 --- a/vm/src/hint_processor/cairo_1_hint_processor/hint_processor.rs +++ b/vm/src/hint_processor/cairo_1_hint_processor/hint_processor.rs @@ -1,13 +1,15 @@ use super::dict_manager::DictManagerExecScope; use super::hint_processor_utils::*; use crate::any_box; -use crate::felt::{felt_str, Felt252}; use crate::hint_processor::cairo_1_hint_processor::dict_manager::DictSquashExecScope; use crate::hint_processor::hint_processor_definition::HintReference; use crate::stdlib::{boxed::Box, collections::HashMap, prelude::*}; use crate::types::relocatable::Relocatable; +use crate::utils::biguint_to_felt; +use crate::utils::felt_to_biguint; use crate::vm::runners::cairo_runner::ResourceTracker; use crate::vm::runners::cairo_runner::RunResources; +use crate::Felt252; use crate::{ hint_processor::hint_processor_definition::HintProcessorLogic, types::exec_scope::ExecutionScopes, @@ -27,7 +29,7 @@ use core::ops::Shl; use num_bigint::BigUint; use num_integer::Integer; -use num_traits::cast::ToPrimitive; +use num_traits::ToPrimitive; /// Execution scope for constant memory allocation. struct MemoryExecScope { @@ -44,7 +46,10 @@ struct FqConfig; type Fq = Fp256>; fn get_beta() -> Felt252 { - felt_str!("3141592653589793238462643383279502884197169399375105820974944592307816406665") + Felt252::from_dec_str( + "3141592653589793238462643383279502884197169399375105820974944592307816406665", + ) + .unwrap() } /// HintProcessor for Cairo 1 compiler hints. @@ -273,9 +278,9 @@ impl Cairo1HintProcessor { value: &ResOperand, dst: &CellRef, ) -> Result<(), HintError> { - let value = res_operand_get_val(vm, value)?.to_biguint(); + let value = felt_to_biguint(res_operand_get_val(vm, value)?); let result = value.sqrt(); - vm.insert_value(cell_ref_to_relocatable(dst, vm)?, Felt252::from(result)) + vm.insert_value(cell_ref_to_relocatable(dst, vm)?, biguint_to_felt(&result)?) .map_err(HintError::from) } @@ -305,8 +310,8 @@ impl Cairo1HintProcessor { let a_val = res_operand_get_val(vm, a)?; let b_val = res_operand_get_val(vm, b)?; let mut lengths_and_indices = vec![ - (a_val.clone(), 0), - (b_val.clone() - a_val, 1), + (a_val, 0), + (b_val - a_val, 1), (Felt252::from(-1) - b_val, 2), ]; lengths_and_indices.sort(); @@ -319,19 +324,19 @@ impl Cairo1HintProcessor { let range_check_ptr = get_ptr(vm, range_check_base, &range_check_offset)?; vm.insert_value( range_check_ptr, - Felt252::from(lengths_and_indices[0].0.to_biguint() % prime_over_3_high), + biguint_to_felt(&(felt_to_biguint(lengths_and_indices[0].0) % prime_over_3_high))?, )?; vm.insert_value( (range_check_ptr + 1)?, - Felt252::from(lengths_and_indices[0].0.to_biguint() / prime_over_3_high), + biguint_to_felt(&(felt_to_biguint(lengths_and_indices[0].0) / prime_over_3_high))?, )?; vm.insert_value( (range_check_ptr + 2)?, - Felt252::from(lengths_and_indices[1].0.to_biguint() % prime_over_2_high), + biguint_to_felt(&(felt_to_biguint(lengths_and_indices[1].0) % prime_over_2_high))?, )?; vm.insert_value( (range_check_ptr + 3)?, - Felt252::from(lengths_and_indices[1].0.to_biguint() / prime_over_2_high), + biguint_to_felt(&(felt_to_biguint(lengths_and_indices[1].0) / prime_over_2_high))?, ) .map_err(HintError::from) } @@ -366,10 +371,10 @@ impl Cairo1HintProcessor { quotient: &CellRef, remainder: &CellRef, ) -> Result<(), HintError> { - let lhs_value = res_operand_get_val(vm, lhs)?.to_biguint(); - let rhs_value = res_operand_get_val(vm, rhs)?.to_biguint(); - let quotient_value = Felt252::new(&lhs_value / &rhs_value); - let remainder_value = Felt252::new(lhs_value % rhs_value); + let lhs_value = felt_to_biguint(res_operand_get_val(vm, lhs)?); + let rhs_value = felt_to_biguint(res_operand_get_val(vm, rhs)?); + let quotient_value = biguint_to_felt(&(&lhs_value / &rhs_value))?; + let remainder_value = biguint_to_felt(&(lhs_value % rhs_value))?; vm.insert_value(cell_ref_to_relocatable(quotient, vm)?, quotient_value)?; vm.insert_value(cell_ref_to_relocatable(remainder, vm)?, remainder_value) .map_err(HintError::from) @@ -392,6 +397,7 @@ impl Cairo1HintProcessor { .map_err(HintError::from) } + #[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)] fn uint256_div_mod( &self, @@ -406,30 +412,30 @@ impl Cairo1HintProcessor { remainder1: &CellRef, ) -> Result<(), HintError> { let pow_2_128 = BigUint::from(u128::MAX) + 1u32; - let dividend0 = get_val(vm, dividend0)?.to_biguint(); - let dividend1 = get_val(vm, dividend1)?.to_biguint(); - let divisor0 = get_val(vm, divisor0)?.to_biguint(); - let divisor1 = get_val(vm, divisor1)?.to_biguint(); + let dividend0 = felt_to_biguint(get_val(vm, dividend0)?); + let dividend1 = felt_to_biguint(get_val(vm, dividend1)?); + let divisor0 = felt_to_biguint(get_val(vm, divisor0)?); + let divisor1 = felt_to_biguint(get_val(vm, divisor1)?); let dividend: BigUint = dividend0 + dividend1.shl(128); let divisor = divisor0 + divisor1.shl(128); let (quotient, remainder) = dividend.div_rem(&divisor); let (limb1, limb0) = quotient.div_rem(&pow_2_128); vm.insert_value( cell_ref_to_relocatable(quotient0, vm)?, - Felt252::from(limb0), + biguint_to_felt(&limb0)?, )?; vm.insert_value( cell_ref_to_relocatable(quotient1, vm)?, - Felt252::from(limb1), + biguint_to_felt(&limb1)?, )?; let (limb1, limb0) = remainder.div_rem(&pow_2_128); vm.insert_value( cell_ref_to_relocatable(remainder0, vm)?, - Felt252::from(limb0), + biguint_to_felt(&limb0)?, )?; vm.insert_value( cell_ref_to_relocatable(remainder1, vm)?, - Felt252::from(limb1), + biguint_to_felt(&limb1)?, )?; Ok(()) @@ -456,15 +462,15 @@ impl Cairo1HintProcessor { x: &CellRef, y: &CellRef, ) -> Result<(), HintError> { - let value = res_operand_get_val(vm, value)?.to_biguint(); - let scalar = res_operand_get_val(vm, scalar)?.to_biguint(); - let max_x = res_operand_get_val(vm, max_x)?.to_biguint(); + let value = felt_to_biguint(res_operand_get_val(vm, value)?); + let scalar = felt_to_biguint(res_operand_get_val(vm, scalar)?); + let max_x = felt_to_biguint(res_operand_get_val(vm, max_x)?); let x_value = (&value / &scalar).min(max_x); let y_value = value - &x_value * &scalar; - vm.insert_value(cell_ref_to_relocatable(x, vm)?, Felt252::from(x_value)) + vm.insert_value(cell_ref_to_relocatable(x, vm)?, biguint_to_felt(&x_value)?) .map_err(HintError::from)?; - vm.insert_value(cell_ref_to_relocatable(y, vm)?, Felt252::from(y_value)) + vm.insert_value(cell_ref_to_relocatable(y, vm)?, biguint_to_felt(&y_value)?) .map_err(HintError::from)?; Ok(()) @@ -476,7 +482,7 @@ impl Cairo1HintProcessor { x: &CellRef, y: &CellRef, ) -> Result<(), HintError> { - let beta = Fq::from(get_beta().to_biguint()); + let beta = Fq::from(felt_to_biguint(get_beta())); let mut rng = ark_std::test_rng(); let (random_x, random_y_squared) = loop { @@ -496,8 +502,8 @@ impl Cairo1HintProcessor { .into_bigint() .into(); - vm.insert_value(cell_ref_to_relocatable(x, vm)?, Felt252::from(x_bigint))?; - vm.insert_value(cell_ref_to_relocatable(y, vm)?, Felt252::from(y_bigint))?; + vm.insert_value(cell_ref_to_relocatable(x, vm)?, biguint_to_felt(&x_bigint)?)?; + vm.insert_value(cell_ref_to_relocatable(y, vm)?, biguint_to_felt(&y_bigint)?)?; Ok(()) } @@ -615,12 +621,12 @@ impl Cairo1HintProcessor { remainder1: &CellRef, ) -> Result<(), HintError> { let pow_2_128 = BigUint::from(u128::MAX) + 1u32; - let dividend0 = res_operand_get_val(vm, dividend0)?.to_biguint(); - let dividend1 = res_operand_get_val(vm, dividend1)?.to_biguint(); - let dividend2 = res_operand_get_val(vm, dividend2)?.to_biguint(); - let dividend3 = res_operand_get_val(vm, dividend3)?.to_biguint(); - let divisor0 = res_operand_get_val(vm, divisor0)?.to_biguint(); - let divisor1 = res_operand_get_val(vm, divisor1)?.to_biguint(); + let dividend0 = felt_to_biguint(res_operand_get_val(vm, dividend0)?); + let dividend1 = felt_to_biguint(res_operand_get_val(vm, dividend1)?); + let dividend2 = felt_to_biguint(res_operand_get_val(vm, dividend2)?); + let dividend3 = felt_to_biguint(res_operand_get_val(vm, dividend3)?); + let divisor0 = felt_to_biguint(res_operand_get_val(vm, divisor0)?); + let divisor1 = felt_to_biguint(res_operand_get_val(vm, divisor1)?); let dividend: BigUint = dividend0 + dividend1.shl(128) + dividend2.shl(256) + dividend3.shl(384); let divisor = divisor0 + divisor1.shl(128); @@ -629,33 +635,33 @@ impl Cairo1HintProcessor { vm.insert_value( cell_ref_to_relocatable(quotient0, vm)?, - Felt252::from(limb0), + biguint_to_felt(&limb0)?, )?; let (quotient, limb1) = quotient.div_rem(&pow_2_128); vm.insert_value( cell_ref_to_relocatable(quotient1, vm)?, - Felt252::from(limb1), + biguint_to_felt(&limb1)?, )?; let (limb3, limb2) = quotient.div_rem(&pow_2_128); vm.insert_value( cell_ref_to_relocatable(quotient2, vm)?, - Felt252::from(limb2), + biguint_to_felt(&limb2)?, )?; vm.insert_value( cell_ref_to_relocatable(quotient3, vm)?, - Felt252::from(limb3), + biguint_to_felt(&limb3)?, )?; let (limb1, limb0) = remainder.div_rem(&pow_2_128); vm.insert_value( cell_ref_to_relocatable(remainder0, vm)?, - Felt252::from(limb0), + biguint_to_felt(&limb0)?, )?; vm.insert_value( cell_ref_to_relocatable(remainder1, vm)?, - Felt252::from(limb1), + biguint_to_felt(&limb1)?, )?; Ok(()) @@ -675,8 +681,8 @@ impl Cairo1HintProcessor { ) -> Result<(), HintError> { let pow_2_128 = BigUint::from(u128::MAX) + 1u32; let pow_2_64 = BigUint::from(u64::MAX) + 1u32; - let value_low = res_operand_get_val(vm, value_low)?.to_biguint(); - let value_high = res_operand_get_val(vm, value_high)?.to_biguint(); + let value_low = felt_to_biguint(res_operand_get_val(vm, value_low)?); + let value_high = felt_to_biguint(res_operand_get_val(vm, value_high)?); let value = value_low + value_high * pow_2_128.clone(); let sqrt = value.sqrt(); let remainder = value - sqrt.clone() * sqrt.clone(); @@ -687,22 +693,22 @@ impl Cairo1HintProcessor { let (sqrt1_val, sqrt0_val) = sqrt.div_rem(&pow_2_64); vm.insert_value( cell_ref_to_relocatable(sqrt0, vm)?, - Felt252::from(sqrt0_val), + biguint_to_felt(&sqrt0_val)?, )?; vm.insert_value( cell_ref_to_relocatable(sqrt1, vm)?, - Felt252::from(sqrt1_val), + biguint_to_felt(&sqrt1_val)?, )?; let (remainder_high_val, remainder_low_val) = remainder.div_rem(&pow_2_128); vm.insert_value( cell_ref_to_relocatable(remainder_low, vm)?, - Felt252::from(remainder_low_val), + biguint_to_felt(&remainder_low_val)?, )?; vm.insert_value( cell_ref_to_relocatable(remainder_high, vm)?, - Felt252::from(remainder_high_val), + biguint_to_felt(&remainder_high_val)?, )?; vm.insert_value( cell_ref_to_relocatable(sqrt_mul_2_minus_remainder_ge_u128, vm)?, @@ -773,9 +779,9 @@ impl Cairo1HintProcessor { let access_indices_at_key = dict_squash_exec_scope .access_indices .get(&key.clone()) - .ok_or_else(|| HintError::NoKeyInAccessIndices(Box::new(key.clone())))?; + .ok_or_else(|| HintError::NoKeyInAccessIndices(Box::new(key)))?; - if n != Felt252::new(access_indices_at_key.len()) { + if n != Felt252::from(access_indices_at_key.len()) { return Err(HintError::NumUsedAccessesAssertFail(Box::new(( n, access_indices_at_key.len(), @@ -853,12 +859,14 @@ impl Cairo1HintProcessor { .ok_or_else(|| { HintError::CustomHint("no accessed index".to_string().into_boxed_str()) })?; - let index_delta_minus_1_val = dict_squash_exec_scope - .current_access_index() - .ok_or_else(|| HintError::CustomHint("no index accessed".to_string().into_boxed_str()))? - .clone() - - prev_access_index - - 1_u32; + let index_delta_minus_1_val = + *dict_squash_exec_scope + .current_access_index() + .ok_or_else(|| { + HintError::CustomHint("no index accessed".to_string().into_boxed_str()) + })? + - prev_access_index + - 1_u64; vm.insert_value( cell_ref_to_relocatable(index_delta_minus1, vm)?, @@ -878,7 +886,7 @@ impl Cairo1HintProcessor { first_key: &CellRef, ) -> Result<(), HintError> { let dict_access_size = 3; - let rangecheck_bound = Felt252::from(u128::MAX) + 1u32; + let rangecheck_bound = Felt252::from(u128::MAX) + 1u64; exec_scopes.assign_or_update_variable( "dict_squash_exec_scope", @@ -1016,9 +1024,9 @@ impl Cairo1HintProcessor { val: &ResOperand, sqrt: &CellRef, ) -> Result<(), HintError> { - let value = Fq::from(res_operand_get_val(vm, val)?.to_biguint()); + let value = Fq::from(felt_to_biguint(res_operand_get_val(vm, val)?)); - let three_fq = Fq::from(Felt252::new(3).to_biguint()); + let three_fq = Fq::from(BigUint::from(3_u32)); let res = if value.legendre().is_qr() { value } else { @@ -1028,7 +1036,7 @@ impl Cairo1HintProcessor { if let Some(root) = res.sqrt() { let root0: BigUint = root.into_bigint().into(); let root1: BigUint = (-root).into_bigint().into(); - let root = Felt252::from(core::cmp::min(root0, root1)); + let root = biguint_to_felt(&core::cmp::min(root0, root1))?; vm.insert_value(cell_ref_to_relocatable(sqrt, vm)?, root) .map_err(HintError::from) } else { @@ -1047,16 +1055,16 @@ impl Cairo1HintProcessor { low: &CellRef, ) -> Result<(), HintError> { let mask128 = BigUint::from(u128::MAX); - let lhs_val = res_operand_get_val(vm, lhs)?.to_biguint(); - let rhs_val = res_operand_get_val(vm, rhs)?.to_biguint(); + let lhs_val = felt_to_biguint(res_operand_get_val(vm, lhs)?); + let rhs_val = felt_to_biguint(res_operand_get_val(vm, rhs)?); let prod = lhs_val * rhs_val; vm.insert_value( cell_ref_to_relocatable(high, vm)?, - Felt252::from(prod.clone() >> 128), + biguint_to_felt(&(prod.clone() >> 128))?, )?; vm.insert_value( cell_ref_to_relocatable(low, vm)?, - Felt252::from(prod & mask128), + biguint_to_felt(&(prod & mask128))?, ) .map_err(HintError::from) } diff --git a/vm/src/hint_processor/cairo_1_hint_processor/hint_processor_utils.rs b/vm/src/hint_processor/cairo_1_hint_processor/hint_processor_utils.rs index 615f65ed99..f549fc23a3 100644 --- a/vm/src/hint_processor/cairo_1_hint_processor/hint_processor_utils.rs +++ b/vm/src/hint_processor/cairo_1_hint_processor/hint_processor_utils.rs @@ -1,9 +1,10 @@ use crate::stdlib::prelude::*; use crate::types::{errors::math_errors::MathError, relocatable::Relocatable}; +use crate::utils::bigint_to_felt; use crate::vm::errors::{hint_errors::HintError, vm_errors::VirtualMachineError}; use crate::vm::vm_core::VirtualMachine; +use crate::Felt252; use cairo_lang_casm::operand::{CellRef, DerefOrImmediate, Operation, Register, ResOperand}; -use felt::Felt252; /// Extracts a parameter assumed to be a buffer. pub(crate) fn extract_buffer(buffer: &ResOperand) -> Result<(&CellRef, Felt252), HintError> { @@ -11,7 +12,7 @@ pub(crate) fn extract_buffer(buffer: &ResOperand) -> Result<(&CellRef, Felt252), ResOperand::Deref(cell) => (cell, 0.into()), ResOperand::BinOp(bin_op) => { if let DerefOrImmediate::Immediate(val) = &bin_op.b { - (&bin_op.a, val.clone().value.into()) + (&bin_op.a, bigint_to_felt(&val.value)?) } else { return Err(HintError::CustomHint( "Failed to extract buffer, expected ResOperand of BinOp type to have Inmediate b value".to_owned().into_boxed_str() @@ -36,13 +37,15 @@ pub(crate) fn get_val( ) -> Result { match res_operand { ResOperand::Deref(cell) => get_cell_val(vm, cell), - ResOperand::DoubleDeref(cell, offset) => get_double_deref_val(vm, cell, &(*offset).into()), - ResOperand::Immediate(x) => Ok(Felt252::from(x.value.clone())), + ResOperand::DoubleDeref(cell, offset) => { + get_double_deref_val(vm, cell, &Felt252::from(*offset as i32)) + } + ResOperand::Immediate(x) => Ok(bigint_to_felt(&x.value)?), ResOperand::BinOp(op) => { let a = get_cell_val(vm, &op.a)?; let b = match &op.b { DerefOrImmediate::Deref(cell) => get_cell_val(vm, cell)?, - DerefOrImmediate::Immediate(x) => Felt252::from(x.value.clone()), + DerefOrImmediate::Immediate(x) => bigint_to_felt(&x.value)?, }; match op.op { Operation::Add => Ok(a + b), @@ -67,10 +70,7 @@ pub(crate) fn get_cell_val( vm: &VirtualMachine, cell: &CellRef, ) -> Result { - Ok(vm - .get_integer(cell_ref_to_relocatable(cell, vm)?)? - .as_ref() - .clone()) + Ok(*vm.get_integer(cell_ref_to_relocatable(cell, vm)?)?.as_ref()) } pub(crate) fn get_ptr( @@ -95,7 +95,7 @@ pub(crate) fn get_double_deref_val( cell: &CellRef, offset: &Felt252, ) -> Result { - Ok(vm.get_integer(get_ptr(vm, cell, offset)?)?.as_ref().clone()) + Ok(*vm.get_integer(get_ptr(vm, cell, offset)?)?.as_ref()) } /// Fetches the value of `res_operand` from the vm. @@ -105,13 +105,15 @@ pub(crate) fn res_operand_get_val( ) -> Result { match res_operand { ResOperand::Deref(cell) => get_cell_val(vm, cell), - ResOperand::DoubleDeref(cell, offset) => get_double_deref_val(vm, cell, &(*offset).into()), - ResOperand::Immediate(x) => Ok(Felt252::from(x.value.clone())), + ResOperand::DoubleDeref(cell, offset) => { + get_double_deref_val(vm, cell, &Felt252::from(*offset as i32)) + } + ResOperand::Immediate(x) => Ok(bigint_to_felt(&x.value)?), ResOperand::BinOp(op) => { let a = get_cell_val(vm, &op.a)?; let b = match &op.b { DerefOrImmediate::Deref(cell) => get_cell_val(vm, cell)?, - DerefOrImmediate::Immediate(x) => Felt252::from(x.value.clone()), + DerefOrImmediate::Immediate(x) => bigint_to_felt(&x.value)?, }; match op.op { Operation::Add => Ok(a + b), @@ -126,7 +128,7 @@ pub(crate) fn as_cairo_short_string(value: &Felt252) -> Option { let mut as_string = String::default(); let mut is_end = false; for byte in value - .to_be_bytes() + .to_bytes_be() .into_iter() .skip_while(num_traits::Zero::is_zero) { @@ -148,7 +150,7 @@ mod tests { fn simple_as_cairo_short_string() { // Values extracted from cairo book example let s = "Hello, Scarb!"; - let x = Felt252::new(5735816763073854913753904210465_u128); + let x = Felt252::from(5735816763073854913753904210465_u128); assert!(s.is_ascii()); let cairo_string = as_cairo_short_string(&x).expect("call to as_cairo_short_string failed"); assert_eq!(cairo_string, s); diff --git a/vm/src/hint_processor/hint_processor_definition.rs b/vm/src/hint_processor/hint_processor_definition.rs index 6b9b892574..a096d45521 100644 --- a/vm/src/hint_processor/hint_processor_definition.rs +++ b/vm/src/hint_processor/hint_processor_definition.rs @@ -13,7 +13,7 @@ use crate::vm::runners::cairo_runner::ResourceTracker; use crate::vm::vm_core::VirtualMachine; use super::builtin_hint_processor::builtin_hint_processor_definition::HintProcessorData; -use felt::Felt252; +use crate::Felt252; #[cfg(feature = "arbitrary")] use arbitrary::Arbitrary; diff --git a/vm/src/hint_processor/hint_processor_utils.rs b/vm/src/hint_processor/hint_processor_utils.rs index 558a631bf9..b78c7c9a79 100644 --- a/vm/src/hint_processor/hint_processor_utils.rs +++ b/vm/src/hint_processor/hint_processor_utils.rs @@ -11,7 +11,8 @@ use crate::{ }; use super::hint_processor_definition::HintReference; -use felt::Felt252; +use crate::Felt252; + use num_traits::ToPrimitive; ///Inserts value into the address of the given ids variable @@ -136,13 +137,13 @@ fn apply_ap_tracking_correction( //Tries to convert a Felt252 value to usize pub fn felt_to_usize(felt: &Felt252) -> Result { felt.to_usize() - .ok_or_else(|| MathError::Felt252ToUsizeConversion(Box::new(felt.clone()))) + .ok_or_else(|| MathError::Felt252ToUsizeConversion(Box::new(*felt))) } ///Tries to convert a Felt252 value to u32 pub fn felt_to_u32(felt: &Felt252) -> Result { felt.to_u32() - .ok_or_else(|| MathError::Felt252ToU32Conversion(Box::new(felt.clone()))) + .ok_or_else(|| MathError::Felt252ToU32Conversion(Box::new(*felt))) } fn get_offset_value_reference( @@ -196,13 +197,13 @@ mod tests { let mut vm = vm!(); vm.segments = segments![((1, 0), 0)]; let mut hint_ref = HintReference::new(0, 0, false, true); - hint_ref.offset1 = OffsetValue::Immediate(Felt252::new(2)); + hint_ref.offset1 = OffsetValue::Immediate(Felt252::from(2)); assert_eq!( get_integer_from_reference(&vm, &hint_ref, &ApTracking::new()) .expect("Unexpected get integer fail") .into_owned(), - Felt252::new(2) + Felt252::from(2) ); } @@ -286,7 +287,7 @@ mod tests { let mut vm = vm!(); vm.segments = segments![((1, 0), (4, 0))]; let mut hint_reference = HintReference::new(0, 0, false, false); - hint_reference.offset1 = OffsetValue::Immediate(Felt252::new(2_i32)); + hint_reference.offset1 = OffsetValue::Immediate(Felt252::from(2_i32)); assert!(compute_addr_from_reference(&hint_reference, &vm, &ApTracking::new()).is_none()); } diff --git a/vm/src/lib.rs b/vm/src/lib.rs index 178ceb94c3..a1138650a7 100644 --- a/vm/src/lib.rs +++ b/vm/src/lib.rs @@ -53,7 +53,6 @@ pub mod stdlib { pub use crate::without_std::*; } -pub extern crate felt; pub mod air_public_input; pub mod cairo_run; pub mod hint_processor; @@ -63,5 +62,8 @@ pub mod types; pub mod utils; pub mod vm; +// TODO: use `Felt` directly +pub use starknet_types_core::felt::Felt as Felt252; + #[cfg(test)] mod tests; diff --git a/vm/src/math_utils/mod.rs b/vm/src/math_utils/mod.rs index bd337b3440..9539a97e13 100644 --- a/vm/src/math_utils/mod.rs +++ b/vm/src/math_utils/mod.rs @@ -4,13 +4,66 @@ pub use is_prime::is_prime; use core::cmp::min; -use crate::stdlib::{boxed::Box, ops::Shr}; +use crate::stdlib::{boxed::Box, ops::Shr, prelude::Vec}; use crate::types::errors::math_errors::MathError; -use felt::Felt252; -use num_bigint::{BigInt, BigUint, RandBigInt}; +use crate::utils::{felt_to_biguint, CAIRO_PRIME}; +use crate::Felt252; +use lazy_static::lazy_static; +use num_bigint::{BigInt, BigUint, RandBigInt, ToBigInt}; use num_integer::Integer; use num_traits::{One, Signed, Zero}; use rand::{rngs::SmallRng, SeedableRng}; +use starknet_types_core::felt::NonZeroFelt; + +lazy_static! { + pub static ref SIGNED_FELT_MAX: BigUint = (&*CAIRO_PRIME).shr(1_u32); + static ref POWERS_OF_TWO: Vec = + core::iter::successors(Some(Felt252::ONE), |x| Some(x * Felt252::TWO)) + .take(252) + .map(|x| x.try_into().unwrap()) + .collect::>(); +} + +/// Returns the `n`th (up to the `251`th power) power of 2 as a [`Felt252`] +/// in constant time. +/// It silently returns `1` if the input is out of bounds. +pub fn pow2_const(n: u32) -> Felt252 { + // If the conversion fails then it's out of range and we compute the power as usual + POWERS_OF_TWO + .get(n as usize) + .unwrap_or(&POWERS_OF_TWO[0]) + .into() +} + +/// Returns the `n`th (up to the `251`th power) power of 2 as a [`&stark_felt::NonZeroFelt`] +/// in constant time. +/// It silently returns `1` if the input is out of bounds. +pub fn pow2_const_nz(n: u32) -> &'static NonZeroFelt { + // If the conversion fails then it's out of range and we compute the power as usual + POWERS_OF_TWO.get(n as usize).unwrap_or(&POWERS_OF_TWO[0]) +} + +/// Converts [`Felt252`] into a [`BigInt`] number in the range: `(- FIELD / 2, FIELD / 2)`. +/// +/// # Examples +/// +/// ``` +/// # use crate::Felt252; +/// let positive = Felt252::new(5); +/// assert_eq!(signed_felt(positive), Felt252::from(5)); +/// +/// let negative = Felt252::max_value(); +/// assert_eq!(signed_felt(negative), Felt252::from(-1)); +/// ``` + +pub fn signed_felt(felt: Felt252) -> BigInt { + let biguint = felt_to_biguint(felt); + if biguint > *SIGNED_FELT_MAX { + BigInt::from_biguint(num_bigint::Sign::Minus, &*CAIRO_PRIME - &biguint) + } else { + biguint.to_bigint().expect("cannot fail") + } +} ///Returns the integer square root of the nonnegative integer n. ///This is the floor of the exact square root of n. @@ -43,17 +96,13 @@ pub fn isqrt(n: &BigUint) -> Result { /// Performs integer division between x and y; fails if x is not divisible by y. pub fn safe_div(x: &Felt252, y: &Felt252) -> Result { - if y.is_zero() { - return Err(MathError::DividedByZero); - } - - let (q, r) = x.div_mod_floor(y); + let (q, r) = x.div_rem(&y.try_into().map_err(|_| MathError::DividedByZero)?); if !r.is_zero() { - return Err(MathError::SafeDivFail(Box::new((x.clone(), y.clone())))); + Err(MathError::SafeDivFail(Box::new((*x, *y)))) + } else { + Ok(q) } - - Ok(q) } /// Performs integer division between x and y; fails if x is not divisible by y. @@ -359,7 +408,8 @@ mod tests { div_mod( &a, &b, - &BigInt::from_str_radix(&felt::PRIME_STR[2..], 16).expect("Couldn't parse prime") + &BigInt::from_str_radix(&crate::utils::PRIME_STR[2..], 16) + .expect("Couldn't parse prime") ) .unwrap() ); @@ -381,7 +431,8 @@ mod tests { div_mod( &a, &b, - &BigInt::from_str_radix(&felt::PRIME_STR[2..], 16).expect("Couldn't parse prime") + &BigInt::from_str_radix(&crate::utils::PRIME_STR[2..], 16) + .expect("Couldn't parse prime") ) .unwrap() ); @@ -403,7 +454,8 @@ mod tests { div_mod( &a, &b, - &BigInt::from_str_radix(&felt::PRIME_STR[2..], 16).expect("Couldn't parse prime") + &BigInt::from_str_radix(&crate::utils::PRIME_STR[2..], 16) + .expect("Couldn't parse prime") ) .unwrap() ); @@ -412,27 +464,27 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn compute_safe_div() { - let x = Felt252::new(26); - let y = Felt252::new(13); - assert_matches!(safe_div(&x, &y), Ok(i) if i == Felt252::new(2)); + let x = Felt252::from(26); + let y = Felt252::from(13); + assert_matches!(safe_div(&x, &y), Ok(i) if i == Felt252::from(2)); } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn compute_safe_div_non_divisor() { - let x = Felt252::new(25); - let y = Felt252::new(4); + let x = Felt252::from(25); + let y = Felt252::from(4); let result = safe_div(&x, &y); assert_matches!( result, - Err(MathError::SafeDivFail(bx)) if *bx == (Felt252::new(25), Felt252::new(4))); + Err(MathError::SafeDivFail(bx)) if *bx == (Felt252::from(25), Felt252::from(4))); } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn compute_safe_div_by_zero() { - let x = Felt252::new(25); - let y = Felt252::zero(); + let x = Felt252::from(25); + let y = Felt252::ZERO; let result = safe_div(&x, &y); assert_matches!(result, Err(MathError::DividedByZero)); } @@ -881,6 +933,26 @@ mod tests { #[cfg(feature = "std")] proptest! { + #[test] + fn pow2_const_in_range_returns_power_of_2(x in 0..=251u32) { + prop_assert_eq!(pow2_const(x), Felt252::TWO.pow(x)); + } + + #[test] + fn pow2_const_oob_returns_1(x in 252u32..) { + prop_assert_eq!(pow2_const(x), Felt252::ONE); + } + + #[test] + fn pow2_const_nz_in_range_returns_power_of_2(x in 0..=251u32) { + prop_assert_eq!(Felt252::from(pow2_const_nz(x)), Felt252::TWO.pow(x)); + } + + #[test] + fn pow2_const_nz_oob_returns_1(x in 252u32..) { + prop_assert_eq!(Felt252::from(pow2_const_nz(x)), Felt252::ONE); + } + #[test] // Test for sqrt_prime_power_ of a quadratic residue. Result should be the minimum root. fn sqrt_prime_power_using_random_prime(ref x in any::<[u8; 38]>(), ref y in any::()) { diff --git a/vm/src/serde/deserialize_program.rs b/vm/src/serde/deserialize_program.rs index 52c5e70a42..be314ac364 100644 --- a/vm/src/serde/deserialize_program.rs +++ b/vm/src/serde/deserialize_program.rs @@ -6,14 +6,19 @@ //! To generate a [`Program`] from a JSON string, see [`Program::from_bytes()`]. //! To do the same from a JSON file, see [`Program::from_file()`]. -use crate::stdlib::{ - collections::{BTreeMap, HashMap}, - fmt, - prelude::*, - sync::Arc, +use crate::{ + stdlib::{ + collections::{BTreeMap, HashMap}, + fmt, + prelude::*, + sync::Arc, + }, + utils::CAIRO_PRIME, }; +use crate::utils::PRIME_STR; use crate::vm::runners::builtin_runner::SEGMENT_ARENA_BUILTIN_NAME; +use crate::Felt252; use crate::{ serde::deserialize_utils, types::{ @@ -28,9 +33,8 @@ use crate::{ SIGNATURE_BUILTIN_NAME, }, }; -use felt::{Felt252, PRIME_STR}; -use num_traits::float::FloatCore; -use num_traits::{Num, Pow}; +use num_bigint::BigUint; +use num_traits::{float::FloatCore, Num}; use serde::{de, de::MapAccess, de::SeqAccess, Deserialize, Deserializer, Serialize}; use serde_json::Number; @@ -226,7 +230,7 @@ where D: Deserializer<'de>, { let n = Number::deserialize(deserializer)?; - match Felt252::parse_bytes(n.to_string().as_bytes(), 10) { + match Felt252::from_dec_str(&n.to_string()).ok() { Some(x) => Ok(Some(x)), None => { // Handle de Number with scientific notation cases @@ -248,12 +252,17 @@ fn deserialize_scientific_notation(n: Number) -> Option { None => { let str = n.to_string(); let list: [&str; 2] = str.split('e').collect::>().try_into().ok()?; - - let exponent = list[1].parse::().ok()?; - let base = Felt252::parse_bytes(list[0].to_string().as_bytes(), 10)?; + let exponent = list[1].parse::().ok()?; + // Apply % CAIRO_PRIME, BECAUSE Felt252::from_dec_str fails with big numbers + let base_biguint = BigUint::from_str_radix(list[0], 10).ok()? % CAIRO_PRIME.clone(); + let base = Felt252::from_dec_str(&base_biguint.to_string()).ok()?; Some(base * Felt252::from(10).pow(exponent)) } - Some(float) => Felt252::parse_bytes(FloatCore::round(float).to_string().as_bytes(), 10), + Some(float) => { + let number = BigUint::from_str_radix(&FloatCore::round(float).to_string(), 10).ok()?; + // Apply % CAIRO_PRIME, BECAUSE Felt252::from_dec_str fails with big numbers + Felt252::from_dec_str(&(number % CAIRO_PRIME.clone()).to_string()).ok() + } } } @@ -321,14 +330,9 @@ impl<'de> de::Visitor<'de> for Felt252Visitor { where E: de::Error, { - // Strip the '0x' prefix from the encoded hex string - if let Some(no_prefix_hex) = value.strip_prefix("0x") { - // Add padding if necessary - let no_prefix_hex = deserialize_utils::maybe_add_padding(no_prefix_hex.to_string()); - Ok(Felt252::from_str_radix(&no_prefix_hex, 16).map_err(de::Error::custom)?) - } else { - Err(String::from("hex prefix error")).map_err(de::Error::custom) - } + // Add padding if necessary + let value = deserialize_utils::maybe_add_padding(value.to_string()); + Felt252::from_hex(&value).map_err(de::Error::custom) } } @@ -348,15 +352,11 @@ impl<'de> de::Visitor<'de> for MaybeRelocatableVisitor { let mut data: Vec = vec![]; while let Some(value) = seq.next_element::()? { - if let Some(no_prefix_hex) = value.strip_prefix("0x") { - // Add padding if necessary - let no_prefix_hex = deserialize_utils::maybe_add_padding(no_prefix_hex.to_string()); - data.push(MaybeRelocatable::Int( - Felt252::from_str_radix(&no_prefix_hex, 16).map_err(de::Error::custom)?, - )); - } else { - return Err(String::from("hex prefix error")).map_err(de::Error::custom); - }; + // Add padding if necessary + let value = deserialize_utils::maybe_add_padding(value.to_string()); + data.push(MaybeRelocatable::Int( + Felt252::from_hex(&value).map_err(de::Error::custom)?, + )); } Ok(data) } @@ -475,7 +475,6 @@ pub fn parse_program_json( if value.type_.as_deref() == Some("const") { let value = value .value - .clone() .ok_or_else(|| ProgramError::ConstWithoutValue(key.clone()))?; constants.insert(key.clone(), value); } @@ -510,11 +509,9 @@ pub fn parse_program_json( #[cfg(test)] mod tests { use super::*; + use crate::felt_str; use assert_matches::assert_matches; use core::num::NonZeroUsize; - use felt::felt_str; - use num_traits::One; - use num_traits::Zero; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; @@ -674,12 +671,12 @@ mod tests { let program_json: ProgramJson = serde_json::from_str(valid_json).unwrap(); let data: Vec = vec![ - MaybeRelocatable::Int(Felt252::new(5189976364521848832_i64)), - MaybeRelocatable::Int(Felt252::new(1000_i64)), - MaybeRelocatable::Int(Felt252::new(5189976364521848832_i64)), - MaybeRelocatable::Int(Felt252::new(2000_i64)), - MaybeRelocatable::Int(Felt252::new(5201798304953696256_i64)), - MaybeRelocatable::Int(Felt252::new(2345108766317314046_i64)), + MaybeRelocatable::Int(Felt252::from(5189976364521848832_i64)), + MaybeRelocatable::Int(Felt252::from(1000_i64)), + MaybeRelocatable::Int(Felt252::from(5189976364521848832_i64)), + MaybeRelocatable::Int(Felt252::from(2000_i64)), + MaybeRelocatable::Int(Felt252::from(5201798304953696256_i64)), + MaybeRelocatable::Int(Felt252::from(2345108766317314046_i64)), ]; let mut hints = BTreeMap::new(); @@ -754,7 +751,7 @@ mod tests { pc: Some(0), value_address: ValueAddress { offset1: OffsetValue::Reference(Register::FP, -3, true), - offset2: OffsetValue::Immediate(Felt252::new(2)), + offset2: OffsetValue::Immediate(Felt252::from(2)), dereference: false, value_type: "felt".to_string(), }, @@ -880,12 +877,12 @@ mod tests { let builtins: Vec = Vec::new(); let data: Vec = vec![ - MaybeRelocatable::Int(Felt252::new(5189976364521848832_i64)), - MaybeRelocatable::Int(Felt252::new(1000)), - MaybeRelocatable::Int(Felt252::new(5189976364521848832_i64)), - MaybeRelocatable::Int(Felt252::new(2000)), - MaybeRelocatable::Int(Felt252::new(5201798304953696256_i64)), - MaybeRelocatable::Int(Felt252::new(2345108766317314046_i64)), + MaybeRelocatable::Int(Felt252::from(5189976364521848832_i64)), + MaybeRelocatable::Int(Felt252::from(1000)), + MaybeRelocatable::Int(Felt252::from(5189976364521848832_i64)), + MaybeRelocatable::Int(Felt252::from(2000)), + MaybeRelocatable::Int(Felt252::from(5201798304953696256_i64)), + MaybeRelocatable::Int(Felt252::from(2345108766317314046_i64)), ]; let hints: HashMap<_, _> = [ @@ -949,12 +946,12 @@ mod tests { let builtins: Vec = Vec::new(); let data: Vec = vec![ - MaybeRelocatable::Int(Felt252::new(5189976364521848832_i64)), - MaybeRelocatable::Int(Felt252::new(1000)), - MaybeRelocatable::Int(Felt252::new(5189976364521848832_i64)), - MaybeRelocatable::Int(Felt252::new(2000)), - MaybeRelocatable::Int(Felt252::new(5201798304953696256_i64)), - MaybeRelocatable::Int(Felt252::new(2345108766317314046_i64)), + MaybeRelocatable::Int(Felt252::from(5189976364521848832_i64)), + MaybeRelocatable::Int(Felt252::from(1000)), + MaybeRelocatable::Int(Felt252::from(5189976364521848832_i64)), + MaybeRelocatable::Int(Felt252::from(2000)), + MaybeRelocatable::Int(Felt252::from(5201798304953696256_i64)), + MaybeRelocatable::Int(Felt252::from(2345108766317314046_i64)), ]; let hints: HashMap<_, _> = [ @@ -1066,7 +1063,7 @@ mod tests { Identifier { pc: None, type_: Some(String::from("const")), - value: Some(Felt252::new(3)), + value: Some(Felt252::from(3)), full_name: None, members: None, cairo_type: None, @@ -1077,7 +1074,7 @@ mod tests { Identifier { pc: None, type_: Some(String::from("const")), - value: Some(Felt252::zero()), + value: Some(Felt252::ZERO), full_name: None, members: None, cairo_type: None, @@ -1500,7 +1497,7 @@ mod tests { assert_matches!( felt_from_number(n), - Ok(x) if x == Some(Felt252::one() * Felt252::from(10).pow(27)) + Ok(x) if x == Some(Felt252::ONE * Felt252::from(10).pow(27_u32)) ); } @@ -1511,7 +1508,7 @@ mod tests { assert_matches!( felt_from_number(n), - Ok(x) if x == Some(Felt252::from_str_radix("64", 10).unwrap() * Felt252::from(10).pow(74)) + Ok(x) if x == Some(Felt252::from_dec_str("64").unwrap() * Felt252::from(10).pow(74_u32)) ); } @@ -1522,9 +1519,8 @@ mod tests { assert_eq!( felt_from_number(n).unwrap(), Some( - Felt252::from_str_radix( + Felt252::from_dec_str( "2082797363194934431336897723140298717588791783575467744530053896730196177808", - 10 ) .unwrap() ) @@ -1550,9 +1546,8 @@ mod tests { .unwrap(); assert_eq!( f, - Felt252::from_str_radix( + Felt252::from_dec_str( "2471602022505793130446032259107029522557827898253184929958153020344968292412", - 10 ) .unwrap() ); diff --git a/vm/src/serde/deserialize_utils.rs b/vm/src/serde/deserialize_utils.rs index 5a90ec863d..d66e48e1c7 100644 --- a/vm/src/serde/deserialize_utils.rs +++ b/vm/src/serde/deserialize_utils.rs @@ -10,7 +10,9 @@ use crate::{ serde::deserialize_program::{OffsetValue, ValueAddress}, types::instruction::Register, }; -use felt::Felt252; + +use crate::Felt252; + use nom::{ branch::alt, bytes::{ @@ -27,9 +29,10 @@ use num_integer::Integer; // Checks if the hex string has an odd length. // If that is the case, prepends '0' to it. -pub(crate) fn maybe_add_padding(mut hex: String) -> String { +// Asumes hex string is prefixed by '0x' +pub fn maybe_add_padding(mut hex: String) -> String { if hex.len().is_odd() { - hex.insert(0, '0'); + hex.insert(2, '0'); return hex; } hex @@ -164,13 +167,13 @@ pub(crate) fn parse_value(input: &str) -> IResult<&str, ValueAddress> { let (offset1, offset2) = if struct_ == "felt" && indirection_level.is_empty() { let offset1 = match fst_offset { OffsetValue::Immediate(imm) => OffsetValue::Immediate(imm), - OffsetValue::Value(val) => OffsetValue::Immediate(Felt252::new(val)), + OffsetValue::Value(val) => OffsetValue::Immediate(Felt252::from(val)), OffsetValue::Reference(reg, val, refe) => OffsetValue::Reference(reg, val, refe), }; let offset2 = match snd_offset { OffsetValue::Immediate(imm) => OffsetValue::Immediate(imm), - OffsetValue::Value(val) => OffsetValue::Immediate(Felt252::new(val)), + OffsetValue::Value(val) => OffsetValue::Immediate(Felt252::from(val)), OffsetValue::Reference(reg, val, refe) => OffsetValue::Reference(reg, val, refe), }; @@ -275,7 +278,6 @@ fn take_until_unbalanced( mod tests { use super::*; use crate::stdlib::string::ToString; - use num_traits::{One, Zero}; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; @@ -483,7 +485,7 @@ mod tests { "", ValueAddress { offset1: OffsetValue::Reference(Register::AP, 0_i32, true), - offset2: OffsetValue::Immediate(Felt252::one()), + offset2: OffsetValue::Immediate(Felt252::ONE), dereference: true, value_type: "felt".to_string(), } @@ -562,8 +564,8 @@ mod tests { Ok(( "", ValueAddress { - offset1: OffsetValue::Immediate(Felt252::new(825323_i32)), - offset2: OffsetValue::Immediate(Felt252::zero()), + offset1: OffsetValue::Immediate(Felt252::from(825323_i32)), + offset2: OffsetValue::Immediate(Felt252::ZERO), dereference: false, value_type: "felt".to_string(), } diff --git a/vm/src/serde/serialize_program.rs b/vm/src/serde/serialize_program.rs index 5f55e3fd75..32550d187c 100644 --- a/vm/src/serde/serialize_program.rs +++ b/vm/src/serde/serialize_program.rs @@ -3,7 +3,6 @@ use crate::stdlib::{ prelude::*, }; -use felt::Felt252; use serde::{Deserialize, Serialize}; use super::deserialize_program::{ @@ -12,6 +11,7 @@ use super::deserialize_program::{ }; use crate::types::program::Program; use crate::types::relocatable::MaybeRelocatable; +use crate::Felt252; // This struct is used to Serialize and Deserialize a Program struct // Their fields are equal to the ProgramJson diff --git a/vm/src/tests/cairo_1_run_from_entrypoint_tests.rs b/vm/src/tests/cairo_1_run_from_entrypoint_tests.rs index e64564d298..c424dfec5e 100644 --- a/vm/src/tests/cairo_1_run_from_entrypoint_tests.rs +++ b/vm/src/tests/cairo_1_run_from_entrypoint_tests.rs @@ -1,5 +1,3 @@ -use num_traits::Num; - use crate::{tests::*, vm::runners::cairo_runner::ResourceTracker}; use assert_matches::assert_matches; @@ -106,9 +104,8 @@ fn factorial_50() { program_data.as_slice(), 0, &[50.into()], - &[Felt252::from_str_radix( + &[Felt252::from_dec_str( "30414093201713378043612608166064768844377641568960512000000000000", - 10, ) .unwrap()], ); @@ -121,9 +118,8 @@ fn factorial_2000() { program_data.as_slice(), 0, &[2000.into()], - &[Felt252::from_str_radix( + &[Felt252::from_dec_str( "2570376556569900799903105814841036176886569861654260254942280653735904624674", - 10, ) .unwrap()], ); diff --git a/vm/src/tests/cairo_pie_test.rs b/vm/src/tests/cairo_pie_test.rs index 93b5947510..933485fb73 100644 --- a/vm/src/tests/cairo_pie_test.rs +++ b/vm/src/tests/cairo_pie_test.rs @@ -1,3 +1,14 @@ +use crate::felt_str; + +#[cfg(target_arch = "wasm32")] +use wasm_bindgen_test::*; + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use alloc::{ + string::{String, ToString}, + vec::Vec, +}; + use crate::{ cairo_run::{cairo_run, CairoRunConfig}, hint_processor::builtin_hint_processor::builtin_hint_processor_definition::BuiltinHintProcessor, @@ -14,10 +25,6 @@ use crate::{ cairo_runner::ExecutionResources, }, }; -use felt::felt_str; - -#[cfg(target_arch = "wasm32")] -use wasm_bindgen_test::*; #[cfg(all(not(feature = "std"), feature = "alloc"))] use alloc::{ diff --git a/vm/src/tests/mod.rs b/vm/src/tests/mod.rs index cd0b18546c..3ef6f5d398 100644 --- a/vm/src/tests/mod.rs +++ b/vm/src/tests/mod.rs @@ -4,6 +4,8 @@ use crate::vm::errors::cairo_run_errors::CairoRunError; use crate::vm::runners::cairo_runner::RunResources; use crate::vm::trace::trace_entry::RelocatedTraceEntry; #[cfg(feature = "cairo-1-hints")] +use crate::Felt252; +#[cfg(feature = "cairo-1-hints")] use crate::{ hint_processor::cairo_1_hint_processor::hint_processor::Cairo1HintProcessor, serde::deserialize_program::BuiltinName, @@ -15,8 +17,6 @@ use crate::{ }; #[cfg(feature = "cairo-1-hints")] use cairo_lang_starknet::casm_contract_class::CasmContractClass; -#[cfg(feature = "cairo-1-hints")] -use felt::Felt252; use crate::stdlib::prelude::*; diff --git a/vm/src/tests/run_deprecated_contract_class_simplified.rs b/vm/src/tests/run_deprecated_contract_class_simplified.rs index c8717aed13..6a46e46cb4 100644 --- a/vm/src/tests/run_deprecated_contract_class_simplified.rs +++ b/vm/src/tests/run_deprecated_contract_class_simplified.rs @@ -16,8 +16,8 @@ */ use crate::stdlib::{collections::HashMap, prelude::*}; -use felt::{felt_str, Felt252}; -use num_traits::{Num, One, Zero}; +use crate::Felt252; +use num_traits::Zero; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; @@ -81,7 +81,7 @@ impl HintProcessorLogic for SimplifiedOsHintProcessor { //Data structure that can be downcasted to the structure generated by compile_hint _hint_data: &Box, //Constant values extracted from the program specification. - _constants: &HashMap, + _constants: &HashMap, ) -> Result<(), crate::vm::errors::hint_errors::HintError> { // Empty impl as we are using `execute_hint_extensive` instead for this case Ok(()) @@ -94,7 +94,7 @@ impl HintProcessorLogic for SimplifiedOsHintProcessor { //Data structure that can be downcasted to the structure generated by compile_hint hint_data: &Box, //Constant values extracted from the program specification. - constants: &HashMap, + constants: &HashMap, ) -> Result< crate::hint_processor::hint_processor_definition::HintExtension, crate::vm::errors::hint_errors::HintError, @@ -177,17 +177,15 @@ pub fn compile_class( vm.insert_value(ptr, Felt252::default())?; // Not relevant ptr.offset += 1; // n_external_functions: felt, - vm.insert_value(ptr, Felt252::one())?; // Only one external entrypoint + vm.insert_value(ptr, Felt252::ONE)?; // Only one external entrypoint ptr.offset += 1; // external_functions: DeprecatedContractEntryPoint*, let mut entrypoints_ptr = vm.add_memory_segment(); // struct DeprecatedContractEntryPoint { // selector: felt, - let selector = Felt252::from_str_radix( - "23180acc053dfb2dbc82a0da33515906d37498b42f34ee4ed308f9d5fb51b6c", - 16, - ) - .unwrap(); + let selector = + Felt252::from_hex("0x23180acc053dfb2dbc82a0da33515906d37498b42f34ee4ed308f9d5fb51b6c") + .unwrap(); vm.insert_value(entrypoints_ptr, selector)?; entrypoints_ptr.offset += 1; // offset: felt, @@ -211,12 +209,15 @@ pub fn compile_class( vm.insert_value(ptr, constructor_entrypoints_ptr)?; ptr.offset += 1; // n_builtins: felt, - vm.insert_value(ptr, Felt252::one())?; + vm.insert_value(ptr, Felt252::ONE)?; ptr.offset += 1; // builtin_list: felt*, let builtins_ptr = vm.add_memory_segment(); // One builtin: range_check = 138277649577220228665140075 - vm.insert_value(builtins_ptr, felt_str!("138277649577220228665140075"))?; + vm.insert_value( + builtins_ptr, + Felt252::from_dec_str("138277649577220228665140075").unwrap(), + )?; vm.insert_value(ptr, builtins_ptr)?; ptr.offset += 1; // hinted_class_hash: felt, @@ -224,75 +225,33 @@ pub fn compile_class( ptr.offset += 1; // bytecode_length: felt, let byte_code = vec![ - Felt252::from_str_radix("480680017fff8000", 16) - .unwrap() - .into(), - Felt252::from_str_radix("e", 16).unwrap().into(), - Felt252::from_str_radix("208b7fff7fff7ffe", 16) - .unwrap() - .into(), - Felt252::from_str_radix("40780017fff7fff", 16) - .unwrap() - .into(), - Felt252::from_str_radix("1", 16).unwrap().into(), - Felt252::from_str_radix("4003800080007ffc", 16) - .unwrap() - .into(), - Felt252::from_str_radix("4826800180008000", 16) - .unwrap() - .into(), - Felt252::from_str_radix("1", 16).unwrap().into(), - Felt252::from_str_radix("480a7ffd7fff8000", 16) - .unwrap() - .into(), - Felt252::from_str_radix("4828800080007ffe", 16) - .unwrap() - .into(), - Felt252::from_str_radix("480a80007fff8000", 16) - .unwrap() - .into(), - Felt252::from_str_radix("208b7fff7fff7ffe", 16) - .unwrap() - .into(), - Felt252::from_str_radix("402b7ffd7ffc7ffd", 16) - .unwrap() - .into(), - Felt252::from_str_radix("1104800180018000", 16) - .unwrap() - .into(), - Felt252::from_str_radix( - "800000000000010fffffffffffffffffffffffffffffffffffffffffffffff4", - 16, - ) - .unwrap() - .into(), - Felt252::from_str_radix("480280017ffb8000", 16) - .unwrap() - .into(), - Felt252::from_str_radix("1104800180018000", 16) - .unwrap() - .into(), - Felt252::from_str_radix( - "800000000000010fffffffffffffffffffffffffffffffffffffffffffffff4", - 16, - ) - .unwrap() - .into(), - Felt252::from_str_radix("480280007ffb8000", 16) - .unwrap() - .into(), - Felt252::from_str_radix("48127ffc7fff8000", 16) - .unwrap() - .into(), - Felt252::from_str_radix("48127ffc7fff8000", 16) - .unwrap() - .into(), - Felt252::from_str_radix("48127ffc7fff8000", 16) + Felt252::from_hex("0x480680017fff8000").unwrap().into(), + Felt252::from_hex("0xe").unwrap().into(), + Felt252::from_hex("0x208b7fff7fff7ffe").unwrap().into(), + Felt252::from_hex("0x40780017fff7fff").unwrap().into(), + Felt252::from_hex("0x1").unwrap().into(), + Felt252::from_hex("0x4003800080007ffc").unwrap().into(), + Felt252::from_hex("0x4826800180008000").unwrap().into(), + Felt252::from_hex("0x1").unwrap().into(), + Felt252::from_hex("0x480a7ffd7fff8000").unwrap().into(), + Felt252::from_hex("0x4828800080007ffe").unwrap().into(), + Felt252::from_hex("0x480a80007fff8000").unwrap().into(), + Felt252::from_hex("0x208b7fff7fff7ffe").unwrap().into(), + Felt252::from_hex("0x402b7ffd7ffc7ffd").unwrap().into(), + Felt252::from_hex("0x1104800180018000").unwrap().into(), + Felt252::from_hex("0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff4") .unwrap() .into(), - Felt252::from_str_radix("208b7fff7fff7ffe", 16) + Felt252::from_hex("0x480280017ffb8000").unwrap().into(), + Felt252::from_hex("0x1104800180018000").unwrap().into(), + Felt252::from_hex("0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff4") .unwrap() .into(), + Felt252::from_hex("0x480280007ffb8000").unwrap().into(), + Felt252::from_hex("0x48127ffc7fff8000").unwrap().into(), + Felt252::from_hex("0x48127ffc7fff8000").unwrap().into(), + Felt252::from_hex("0x48127ffc7fff8000").unwrap().into(), + Felt252::from_hex("0x208b7fff7fff7ffe").unwrap().into(), ]; vm.insert_value(ptr, Felt252::from(byte_code.len()))?; ptr.offset += 1; diff --git a/vm/src/types/errors/math_errors.rs b/vm/src/types/errors/math_errors.rs index f99c599f96..2a12efe12a 100644 --- a/vm/src/types/errors/math_errors.rs +++ b/vm/src/types/errors/math_errors.rs @@ -2,9 +2,8 @@ #![allow(clippy::explicit_auto_deref)] use crate::stdlib::boxed::Box; -use felt::Felt252; +use crate::Felt252; use num_bigint::{BigInt, BigUint}; - use thiserror_no_std::Error; use crate::types::relocatable::{MaybeRelocatable, Relocatable}; @@ -60,6 +59,8 @@ pub enum MathError { Felt252ToUsizeConversion(Box), #[error("Conversion to u64 failed for Felt252 {0}")] Felt252ToU64Conversion(Box), + #[error("Byte conversion error")] + ByteConversionError, #[error( "Operation failed: divmod({}, {}, {}), igcdex({}, {}) != 1 ", (*.0).0, (*.0).1, (*.0).2, (*.0).1, (*.0).2 )] diff --git a/vm/src/types/errors/program_errors.rs b/vm/src/types/errors/program_errors.rs index c10177aa5f..e4a7c96d90 100644 --- a/vm/src/types/errors/program_errors.rs +++ b/vm/src/types/errors/program_errors.rs @@ -1,9 +1,7 @@ use crate::stdlib::prelude::*; - +use crate::utils::PRIME_STR; use thiserror_no_std::Error; -use felt::PRIME_STR; - #[derive(Debug, Error)] pub enum ProgramError { #[cfg(feature = "std")] diff --git a/vm/src/types/exec_scope.rs b/vm/src/types/exec_scope.rs index af8481322c..a2209e1caf 100644 --- a/vm/src/types/exec_scope.rs +++ b/vm/src/types/exec_scope.rs @@ -193,9 +193,8 @@ impl Default for ExecutionScopes { #[cfg(test)] mod tests { use super::*; + use crate::Felt252; use assert_matches::assert_matches; - use felt::Felt252; - use num_traits::One; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; @@ -211,7 +210,7 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn get_local_variables_test() { let var_name = String::from("a"); - let var_value: Box = Box::new(Felt252::new(2)); + let var_value: Box = Box::new(Felt252::from(2)); let scope = HashMap::from([(var_name, var_value)]); @@ -224,7 +223,7 @@ mod tests { .get("a") .unwrap() .downcast_ref::(), - Some(&Felt252::new(2)) + Some(&Felt252::from(2)) ); } @@ -232,14 +231,14 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn enter_new_scope_test() { let var_name = String::from("a"); - let var_value: Box = Box::new(Felt252::new(2_i32)); + let var_value: Box = Box::new(Felt252::from(2_i32)); let new_scope = HashMap::from([(var_name, var_value)]); let mut scopes = ExecutionScopes { data: vec![HashMap::from([( String::from("b"), - (Box::new(Felt252::one()) as Box), + (Box::new(Felt252::ONE) as Box), )])], }; @@ -251,7 +250,7 @@ mod tests { .get("b") .unwrap() .downcast_ref::(), - Some(&Felt252::one()) + Some(&Felt252::ONE) ); scopes.enter_scope(new_scope); @@ -267,7 +266,7 @@ mod tests { .get("a") .unwrap() .downcast_ref::(), - Some(&Felt252::new(2)) + Some(&Felt252::from(2)) ); } @@ -275,7 +274,7 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn exit_scope_test() { let var_name = String::from("a"); - let var_value: Box = Box::new(Felt252::new(2)); + let var_value: Box = Box::new(Felt252::from(2)); let new_scope = HashMap::from([(var_name, var_value)]); @@ -293,7 +292,7 @@ mod tests { .get("a") .unwrap() .downcast_ref::(), - Some(&Felt252::new(2)) + Some(&Felt252::from(2)) ); // exit the current scope @@ -311,7 +310,7 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn assign_local_variable_test() { - let var_value: Box = Box::new(Felt252::new(2)); + let var_value: Box = Box::new(Felt252::from(2)); let mut scopes = ExecutionScopes::new(); @@ -325,7 +324,7 @@ mod tests { .get("a") .unwrap() .downcast_ref::(), - Some(&Felt252::new(2)) + Some(&Felt252::from(2)) ); } @@ -333,13 +332,13 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn re_assign_local_variable_test() { let var_name = String::from("a"); - let var_value: Box = Box::new(Felt252::new(2)); + let var_value: Box = Box::new(Felt252::from(2)); let scope = HashMap::from([(var_name, var_value)]); let mut scopes = ExecutionScopes { data: vec![scope] }; - let var_value_new: Box = Box::new(Felt252::new(3)); + let var_value_new: Box = Box::new(Felt252::from(3)); scopes.assign_or_update_variable("a", var_value_new); @@ -351,7 +350,7 @@ mod tests { .get("a") .unwrap() .downcast_ref::(), - Some(&Felt252::new(3)) + Some(&Felt252::from(3)) ); } @@ -359,7 +358,7 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn delete_local_variable_test() { let var_name = String::from("a"); - let var_value: Box = Box::new(Felt252::new(2)); + let var_value: Box = Box::new(Felt252::from(2)); let scope = HashMap::from([(var_name, var_value)]); @@ -437,14 +436,14 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn get_mut_int_ref_test() { - let bigint: Box = Box::new(Felt252::new(12)); + let bigint: Box = Box::new(Felt252::from(12)); let mut scopes = ExecutionScopes::new(); scopes.assign_or_update_variable("bigint", bigint); assert_matches!( scopes.get_mut_ref::("bigint"), - Ok(x) if x == &mut Felt252::new(12) + Ok(x) if x == &mut Felt252::from(12) ); } diff --git a/vm/src/types/instruction.rs b/vm/src/types/instruction.rs index 8d1e3f2f9c..49ecb19311 100644 --- a/vm/src/types/instruction.rs +++ b/vm/src/types/instruction.rs @@ -1,4 +1,4 @@ -use felt::Felt252; +use crate::Felt252; use num_traits::ToPrimitive; use serde::{Deserialize, Serialize}; @@ -112,28 +112,28 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn is_call_instruction_true() { - let encoded_instruction = Felt252::new(1226245742482522112_i64); + let encoded_instruction = Felt252::from(1226245742482522112_i64); assert!(is_call_instruction(&encoded_instruction)); } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn is_call_instruction_false() { - let encoded_instruction = Felt252::new(4612671187288031229_i64); + let encoded_instruction = Felt252::from(4612671187288031229_i64); assert!(!is_call_instruction(&encoded_instruction)); } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn is_call_instruction_invalid() { - let encoded_instruction = Felt252::new(1u64 << 63); + let encoded_instruction = Felt252::from(1u64 << 63); assert!(!is_call_instruction(&encoded_instruction)); } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn instruction_size() { - let encoded_instruction = Felt252::new(1226245742482522112_i64); + let encoded_instruction = Felt252::from(1226245742482522112_i64); let instruction = decode_instruction(encoded_instruction.to_u64().unwrap()).unwrap(); assert_eq!(instruction.size(), 2); } diff --git a/vm/src/types/program.rs b/vm/src/types/program.rs index d5bc7f86ef..9601aee445 100644 --- a/vm/src/types/program.rs +++ b/vm/src/types/program.rs @@ -13,6 +13,10 @@ use crate::{ #[cfg(feature = "cairo-1-hints")] use crate::serde::deserialize_program::{ApTracking, FlowTrackingData}; +#[cfg(feature = "cairo-1-hints")] +use crate::utils::biguint_to_felt; +use crate::utils::PRIME_STR; +use crate::Felt252; use crate::{ hint_processor::hint_processor_definition::HintReference, serde::deserialize_program::{ @@ -26,7 +30,6 @@ use crate::{ #[cfg(feature = "cairo-1-hints")] use cairo_lang_starknet::casm_contract_class::CasmContractClass; use core::num::NonZeroUsize; -use felt::{Felt252, PRIME_STR}; #[cfg(feature = "std")] use std::path::Path; @@ -147,8 +150,8 @@ impl HintsCollection { ); #[cfg(not(feature = "extensive_hints"))] { - hints_ranges[*pc] = Some(range) - }; + hints_ranges[*pc] = Some(range); + } #[cfg(feature = "extensive_hints")] hints_ranges.insert(Relocatable::from((0_isize, *pc)), range); hints_values.extend_from_slice(&hs[..]); @@ -345,7 +348,6 @@ impl Program { if value.type_.as_deref() == Some("const") { let value = value .value - .clone() .ok_or_else(|| ProgramError::ConstWithoutValue(key.clone()))?; constants.insert(key.clone(), value); } @@ -404,7 +406,7 @@ impl TryFrom for Program { let data = value .bytecode .iter() - .map(|x| MaybeRelocatable::from(Felt252::from(x.value.clone()))) + .map(|x| MaybeRelocatable::from(biguint_to_felt(&x.value).unwrap_or_default())) .collect(); //Hint data is going to be hosted processor-side, hints field will only store the pc where hints are located. // Only one pc will be stored, so the hint processor will be responsible for executing all hints for a given pc @@ -475,11 +477,12 @@ impl HintsCollection { #[cfg(test)] mod tests { + use core::ops::Neg; + use super::*; + use crate::felt_hex; use crate::serde::deserialize_program::{ApTracking, FlowTrackingData}; use crate::utils::test_utils::*; - use felt::felt_str; - use num_traits::Zero; use assert_matches::assert_matches; @@ -697,7 +700,7 @@ mod tests { Identifier { pc: None, type_: Some(String::from("const")), - value: Some(Felt252::zero()), + value: Some(Felt252::ZERO), full_name: None, members: None, cairo_type: None, @@ -722,7 +725,7 @@ mod tests { assert_eq!(program.shared_program_data.identifiers, identifiers); assert_eq!( program.constants, - [("__main__.main.SIZEOF_LOCALS", Felt252::zero())] + [("__main__.main.SIZEOF_LOCALS", Felt252::ZERO)] .into_iter() .map(|(key, value)| (key.to_string(), value)) .collect::>(), @@ -750,7 +753,7 @@ mod tests { Identifier { pc: None, type_: Some(String::from("const")), - value: Some(Felt252::zero()), + value: Some(Felt252::ZERO), full_name: None, members: None, cairo_type: None, @@ -759,7 +762,7 @@ mod tests { assert_eq!( Program::extract_constants(&identifiers).unwrap(), - [("__main__.main.SIZEOF_LOCALS", Felt252::zero())] + [("__main__.main.SIZEOF_LOCALS", Felt252::ZERO)] .into_iter() .map(|(key, value)| (key.to_string(), value)) .collect::>(), @@ -911,7 +914,7 @@ mod tests { Identifier { pc: None, type_: Some(String::from("const")), - value: Some(Felt252::zero()), + value: Some(Felt252::ZERO), full_name: None, members: None, cairo_type: None, @@ -981,7 +984,7 @@ mod tests { Identifier { pc: None, type_: Some(String::from("const")), - value: Some(Felt252::zero()), + value: Some(Felt252::ZERO), full_name: None, members: None, cairo_type: None, @@ -1136,7 +1139,7 @@ mod tests { Identifier { pc: None, type_: Some(String::from("const")), - value: Some(Felt252::zero()), + value: Some(Felt252::ZERO), full_name: None, members: None, cairo_type: None, @@ -1235,7 +1238,7 @@ mod tests { Identifier { pc: None, type_: Some(String::from("const")), - value: Some(Felt252::zero()), + value: Some(Felt252::ZERO), full_name: None, members: None, cairo_type: None, @@ -1264,26 +1267,23 @@ mod tests { .unwrap(); let constants = [ - ("__main__.compare_abs_arrays.SIZEOF_LOCALS", Felt252::zero()), + ("__main__.compare_abs_arrays.SIZEOF_LOCALS", Felt252::ZERO), ( "starkware.cairo.common.cairo_keccak.packed_keccak.ALL_ONES", - felt_str!( - "3618502788666131106986593281521497120414687020801267626233049500247285301247" - ), + felt_hex!("0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), ), ( "starkware.cairo.common.cairo_keccak.packed_keccak.BLOCK_SIZE", - Felt252::new(3), + Felt252::from(3), ), ( "starkware.cairo.common.alloc.alloc.SIZEOF_LOCALS", - felt_str!( - "-3618502788666131213697322783095070105623107215331596699973092056135872020481" - ), + felt_hex!("0x800000000000011000000000000000000000000000000000000000000000001") + .neg(), ), ( "starkware.cairo.common.uint256.SHIFT", - felt_str!("340282366920938463463374607431768211456"), + felt_hex!("0x100000000000000000000000000000000"), ), ] .into_iter() diff --git a/vm/src/types/relocatable.rs b/vm/src/types/relocatable.rs index 14f3c1bbdf..353be453ae 100644 --- a/vm/src/types/relocatable.rs +++ b/vm/src/types/relocatable.rs @@ -4,11 +4,11 @@ use crate::stdlib::{ prelude::*, }; +use crate::Felt252; use crate::{ relocatable, types::errors::math_errors::MathError, vm::errors::memory_errors::MemoryError, }; -use felt::Felt252; -use num_traits::{ToPrimitive, Zero}; +use num_traits::ToPrimitive; use serde::{Deserialize, Serialize}; #[cfg(all(feature = "arbitrary", feature = "std"))] @@ -22,12 +22,26 @@ pub struct Relocatable { } #[cfg_attr(all(feature = "arbitrary", feature = "std"), derive(Arbitrary))] -#[derive(Eq, Ord, Hash, PartialEq, PartialOrd, Clone, Debug, Serialize, Deserialize)] +#[derive(Eq, Ord, Hash, PartialEq, PartialOrd, Clone, Serialize, Deserialize)] pub enum MaybeRelocatable { RelocatableValue(Relocatable), Int(Felt252), } +// NOTE: implemented manually so we can format the felt properly +impl fmt::Debug for MaybeRelocatable { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + MaybeRelocatable::RelocatableValue(v) => { + f.debug_tuple("RelocatableValue").field(&v).finish() + } + MaybeRelocatable::Int(v) => { + f.debug_tuple("Int").field(&format_args!("{}", &v)).finish() + } + } + } +} + impl From<(isize, usize)> for Relocatable { fn from(index_offset: (isize, usize)) -> Self { Relocatable { @@ -45,7 +59,7 @@ impl From<(isize, usize)> for MaybeRelocatable { impl From for MaybeRelocatable { fn from(num: usize) -> Self { - MaybeRelocatable::Int(Felt252::new(num)) + MaybeRelocatable::Int(Felt252::from(num)) } } @@ -69,7 +83,7 @@ impl From<&Relocatable> for Relocatable { impl From<&Felt252> for MaybeRelocatable { fn from(val: &Felt252) -> Self { - MaybeRelocatable::Int(val.clone()) + MaybeRelocatable::Int(*val) } } @@ -127,7 +141,7 @@ impl Add<&Felt252> for Relocatable { let new_offset = (self.offset as u64 + other) .and_then(|x| x.to_usize()) .ok_or_else(|| { - MathError::RelocatableAddFelt252OffsetExceeded(Box::new((self, other.clone()))) + MathError::RelocatableAddFelt252OffsetExceeded(Box::new((self, *other))) })?; Ok((self.segment_index, new_offset).into()) } @@ -199,9 +213,7 @@ impl TryFrom<&MaybeRelocatable> for Relocatable { fn try_from(other: &MaybeRelocatable) -> Result { match other { MaybeRelocatable::RelocatableValue(rel) => Ok(*rel), - MaybeRelocatable::Int(num) => { - Err(MathError::Felt252ToRelocatable(Box::new(num.clone()))) - } + MaybeRelocatable::Int(num) => Err(MathError::Felt252ToRelocatable(Box::new(*num))), } } } @@ -212,9 +224,9 @@ impl MaybeRelocatable { match *self { MaybeRelocatable::Int(ref value) => Ok(MaybeRelocatable::Int(value + other)), MaybeRelocatable::RelocatableValue(ref rel) => { - let big_offset = other + rel.offset; + let big_offset = other + rel.offset as u64; let new_offset = big_offset.to_usize().ok_or_else(|| { - MathError::RelocatableAddFelt252OffsetExceeded(Box::new((*rel, other.clone()))) + MathError::RelocatableAddFelt252OffsetExceeded(Box::new((*rel, *other))) })?; Ok(MaybeRelocatable::RelocatableValue(Relocatable { segment_index: rel.segment_index, @@ -227,7 +239,7 @@ impl MaybeRelocatable { /// Adds a usize to self pub fn add_usize(&self, other: usize) -> Result { Ok(match *self { - MaybeRelocatable::Int(ref value) => MaybeRelocatable::Int(value + other), + MaybeRelocatable::Int(ref value) => MaybeRelocatable::Int(value + other as u64), MaybeRelocatable::RelocatableValue(rel) => (rel + other)?.into(), }) } @@ -274,14 +286,16 @@ impl MaybeRelocatable { (MaybeRelocatable::RelocatableValue(rel_a), MaybeRelocatable::Int(ref num_b)) => { Ok(MaybeRelocatable::from(( rel_a.segment_index, - (rel_a.offset - num_b).to_usize().ok_or_else(|| { - MathError::RelocatableSubFelt252NegOffset(Box::new((*rel_a, num_b.clone()))) - })?, + (rel_a.offset as u64 - num_b) + .and_then(|x| x.to_usize()) + .ok_or_else(|| { + MathError::RelocatableSubFelt252NegOffset(Box::new((*rel_a, *num_b))) + })?, ))) } - (MaybeRelocatable::Int(int), MaybeRelocatable::RelocatableValue(rel)) => Err( - MathError::SubRelocatableFromInt(Box::new((int.clone(), *rel))), - ), + (MaybeRelocatable::Int(int), MaybeRelocatable::RelocatableValue(rel)) => { + Err(MathError::SubRelocatableFromInt(Box::new((*int, *rel)))) + } } } @@ -293,9 +307,11 @@ impl MaybeRelocatable { ) -> Result<(MaybeRelocatable, MaybeRelocatable), MathError> { match (self, other) { (MaybeRelocatable::Int(val), MaybeRelocatable::Int(div)) => Ok(( - MaybeRelocatable::from(val / div), + MaybeRelocatable::from( + val.field_div(&div.try_into().map_err(|_| MathError::DividedByZero)?), + ), // NOTE: elements on a field element always have multiplicative inverse - MaybeRelocatable::from(Felt252::zero()), + MaybeRelocatable::from(Felt252::ZERO), )), _ => Err(MathError::DivModWrongType(Box::new(( self.clone(), @@ -371,25 +387,22 @@ pub fn relocate_address( #[cfg(test)] mod tests { use super::*; + use crate::{felt_hex, felt_str}; use crate::{relocatable, utils::test_utils::mayberelocatable}; - use felt::felt_str; - use num_traits::{One, Zero}; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; #[cfg(feature = "std")] - use num_traits::Bounded; - #[cfg(feature = "std")] use proptest::prelude::*; #[cfg(feature = "std")] proptest! { #[test] - fn add_relocatable_felt(offset in any::(), ref bigint in any::<[u8; 32]>()) { + fn add_relocatable_felt(offset in any::(), ref bigint in any::<[u8; 32]>()) { let big = &Felt252::from_bytes_be(bigint); - let rel = Relocatable::from((0, offset)); + let rel = Relocatable::from((0, offset as usize)); let sum = (big + offset).to_usize() .map(|offset| (0, offset).into()); @@ -397,11 +410,11 @@ mod tests { } #[test] - fn add_relocatable_felt_extremes(offset in any::()) { - let big_zero = &Felt252::zero(); - let big_max = &Felt252::max_value(); - let big_min = &(big_zero + (i64::MIN as usize)); - let rel = Relocatable::from((0, offset)); + fn add_relocatable_felt_extremes(offset in any::()) { + let big_zero = &Felt252::ZERO; + let big_max = &Felt252::MAX; + let big_min = &(big_zero + (i64::MIN as u64)); + let rel = Relocatable::from((0, offset as usize)); let sum_max = (big_max + offset).to_usize() .map(|offset| (0, offset).into()); @@ -418,24 +431,24 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn add_bigint_to_int() { - let addr = MaybeRelocatable::from(Felt252::new(7i32)); - let added_addr = addr.add_int(&Felt252::new(2i32)); - assert_eq!(added_addr, Ok(MaybeRelocatable::Int(Felt252::new(9)))); + let addr = MaybeRelocatable::from(Felt252::from(7i32)); + let added_addr = addr.add_int(&Felt252::from(2i32)); + assert_eq!(added_addr, Ok(MaybeRelocatable::Int(Felt252::from(9)))); } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn add_usize_to_int() { - let addr = MaybeRelocatable::from(Felt252::new(7_i32)); + let addr = MaybeRelocatable::from(Felt252::from(7_i32)); let added_addr = addr.add_usize(2).unwrap(); - assert_eq!(MaybeRelocatable::Int(Felt252::new(9)), added_addr); + assert_eq!(MaybeRelocatable::Int(Felt252::from(9)), added_addr); } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn add_bigint_to_relocatable() { let addr = MaybeRelocatable::RelocatableValue(relocatable!(7, 65)); - let added_addr = addr.add_int(&Felt252::new(2)); + let added_addr = addr.add_int(&Felt252::from(2)); assert_eq!( added_addr, Ok(MaybeRelocatable::RelocatableValue(Relocatable { @@ -449,12 +462,12 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn add_int_mod_offset_exceeded() { let addr = MaybeRelocatable::from((0, 0)); - let error = addr.add_int(&felt_str!("18446744073709551616")); + let error = addr.add_int(&felt_hex!("0x10000000000000000")); assert_eq!( error, Err(MathError::RelocatableAddFelt252OffsetExceeded(Box::new(( relocatable!(0, 0), - felt_str!("18446744073709551616") + felt_hex!("0x10000000000000000") )))) ); } @@ -476,12 +489,11 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn add_bigint_to_int_prime_mod() { - let addr = MaybeRelocatable::Int(felt_str!( - "800000000000011000000000000000000000000000000000000000000000004", - 16 + let addr = MaybeRelocatable::Int(felt_hex!( + "800000000000011000000000000000000000000000000000000000000000004" )); - let added_addr = addr.add_int(&Felt252::one()); - assert_eq!(added_addr, Ok(MaybeRelocatable::Int(Felt252::new(4)))); + let added_addr = addr.add_int(&Felt252::ONE); + assert_eq!(added_addr, Ok(MaybeRelocatable::Int(Felt252::from(4)))); } #[test] @@ -506,9 +518,9 @@ mod tests { let addr_a = &MaybeRelocatable::from(felt_str!( "3618502788666131213697322783095070105623107215331596699973092056135872020488" )); - let addr_b = &MaybeRelocatable::from(Felt252::new(17_i32)); + let addr_b = &MaybeRelocatable::from(Felt252::from(17_i32)); let added_addr = addr_a.add(addr_b); - assert_eq!(added_addr, Ok(MaybeRelocatable::Int(Felt252::new(24)))); + assert_eq!(added_addr, Ok(MaybeRelocatable::Int(Felt252::from(24)))); } #[test] @@ -530,7 +542,7 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn add_int_to_relocatable() { let addr_a = &MaybeRelocatable::from((7, 7)); - let addr_b = &MaybeRelocatable::from(Felt252::new(10)); + let addr_b = &MaybeRelocatable::from(Felt252::from(10)); let added_addr = addr_a.add(addr_b); assert_eq!( added_addr, @@ -544,7 +556,7 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn add_relocatable_to_int() { - let addr_a = &MaybeRelocatable::from(Felt252::new(10_i32)); + let addr_a = &MaybeRelocatable::from(Felt252::from(10_i32)); let addr_b = &MaybeRelocatable::RelocatableValue(relocatable!(7, 7)); let added_addr = addr_a.add(addr_b); assert_eq!( @@ -560,9 +572,8 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn add_int_to_relocatable_prime() { let addr_a = &MaybeRelocatable::from((7, 14)); - let addr_b = &MaybeRelocatable::Int(felt_str!( - "800000000000011000000000000000000000000000000000000000000000001", - 16 + let addr_b = &MaybeRelocatable::Int(felt_hex!( + "800000000000011000000000000000000000000000000000000000000000001" )); let added_addr = addr_a.add(addr_b); assert_eq!( @@ -578,12 +589,12 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn add_int_rel_int_offset_exceeded() { let addr = MaybeRelocatable::from((0, 0)); - let error = addr.add(&MaybeRelocatable::from(felt_str!("18446744073709551616"))); + let error = addr.add(&MaybeRelocatable::from(felt_hex!("0x10000000000000000"))); assert_eq!( error, Err(MathError::RelocatableAddFelt252OffsetExceeded(Box::new(( relocatable!(0, 0), - felt_str!("18446744073709551616") + felt_hex!("0x10000000000000000") )))) ); } @@ -591,7 +602,7 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn add_int_int_rel_offset_exceeded() { - let addr = MaybeRelocatable::Int(felt_str!("18446744073709551616")); + let addr = MaybeRelocatable::Int(felt_hex!("0x10000000000000000")); let relocatable = Relocatable { offset: 0, segment_index: 0, @@ -601,7 +612,7 @@ mod tests { error, Err(MathError::RelocatableAddFelt252OffsetExceeded(Box::new(( relocatable!(0, 0), - felt_str!("18446744073709551616") + felt_hex!("0x10000000000000000") )))) ); } @@ -609,10 +620,10 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn sub_int_from_int() { - let addr_a = &MaybeRelocatable::from(Felt252::new(7)); - let addr_b = &MaybeRelocatable::from(Felt252::new(5)); + let addr_a = &MaybeRelocatable::from(Felt252::from(7)); + let addr_b = &MaybeRelocatable::from(Felt252::from(5)); let sub_addr = addr_a.sub(addr_b); - assert_eq!(sub_addr, Ok(MaybeRelocatable::Int(Felt252::new(2)))); + assert_eq!(sub_addr, Ok(MaybeRelocatable::Int(Felt252::from(2)))); } #[test] @@ -621,7 +632,7 @@ mod tests { let addr_a = &MaybeRelocatable::from((7, 17)); let addr_b = &MaybeRelocatable::from((7, 7)); let sub_addr = addr_a.sub(addr_b); - assert_eq!(sub_addr, Ok(MaybeRelocatable::Int(Felt252::new(10)))); + assert_eq!(sub_addr, Ok(MaybeRelocatable::Int(Felt252::from(10)))); } #[test] @@ -643,7 +654,7 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn sub_int_addr_ref_from_relocatable_addr_ref() { let addr_a = &MaybeRelocatable::from((7, 17)); - let addr_b = &MaybeRelocatable::from(Felt252::new(5_i32)); + let addr_b = &MaybeRelocatable::from(Felt252::from(5_i32)); let addr_c = addr_a.sub(addr_b); assert_eq!(addr_c, Ok(MaybeRelocatable::from((7, 12)))); } @@ -652,9 +663,9 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn sub_rel_to_int_error() { assert_eq!( - MaybeRelocatable::from(Felt252::new(7_i32)).sub(&MaybeRelocatable::from((7, 10))), + MaybeRelocatable::from(Felt252::from(7_i32)).sub(&MaybeRelocatable::from((7, 10))), Err(MathError::SubRelocatableFromInt(Box::new(( - Felt252::new(7_i32), + Felt252::from(7_i32), Relocatable::from((7, 10)) )))) ); @@ -663,25 +674,27 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn divmod_working() { - let value = &MaybeRelocatable::from(Felt252::new(10)); - let div = &MaybeRelocatable::from(Felt252::new(3)); + let value = &MaybeRelocatable::from(Felt252::from(10)); + let div = &MaybeRelocatable::from(Felt252::from(3)); let (q, r) = value.divmod(div).expect("Unexpected error in divmod"); assert_eq!( q, - MaybeRelocatable::from(Felt252::new(10) / Felt252::new(3)) + MaybeRelocatable::from( + Felt252::from(10).field_div(&Felt252::from(3).try_into().unwrap()) + ) ); - assert_eq!(r, MaybeRelocatable::from(Felt252::zero())); + assert_eq!(r, MaybeRelocatable::from(Felt252::ZERO)); } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn divmod_bad_type() { - let value = &MaybeRelocatable::from(Felt252::new(10)); + let value = &MaybeRelocatable::from(Felt252::from(10)); let div = &MaybeRelocatable::from((2, 7)); assert_eq!( value.divmod(div), Err(MathError::DivModWrongType(Box::new(( - MaybeRelocatable::from(Felt252::new(10)), + MaybeRelocatable::from(Felt252::from(10)), MaybeRelocatable::from((2, 7)) )))) ); @@ -694,7 +707,7 @@ mod tests { let relocation_table = vec![1, 2, 5]; assert_eq!( relocate_value(value, &relocation_table), - Ok(Felt252::new(12)) + Ok(Felt252::from(12)) ); } @@ -734,11 +747,11 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn relocate_int_value() { - let value = MaybeRelocatable::from(Felt252::new(7)); + let value = MaybeRelocatable::from(Felt252::from(7)); let relocation_table = vec![1, 2, 5]; assert_eq!( relocate_value(value, &relocation_table), - Ok(Felt252::new(7)) + Ok(Felt252::from(7)) ); } @@ -757,23 +770,20 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn relocatable_add_int() { assert_eq!( - relocatable!(1, 2) + &Felt252::new(4), + relocatable!(1, 2) + &Felt252::from(4), Ok(relocatable!(1, 6)) ); - assert_eq!( - relocatable!(3, 2) + &Felt252::zero(), - Ok(relocatable!(3, 2)) - ); + assert_eq!(relocatable!(3, 2) + &Felt252::ZERO, Ok(relocatable!(3, 2))); } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn relocatable_add_int_mod_offset_exceeded_error() { assert_eq!( - relocatable!(0, 0) + &(Felt252::new(usize::MAX) + 1_usize), + relocatable!(0, 0) + &(Felt252::from(usize::MAX) + 1_u64), Err(MathError::RelocatableAddFelt252OffsetExceeded(Box::new(( relocatable!(0, 0), - Felt252::new(usize::MAX) + 1_usize + Felt252::from(usize::MAX) + 1_u64 )))) ); } @@ -880,7 +890,7 @@ mod tests { relocatable!(1, 0) + &mayberelocatable!(usize::MAX as i128 + 1), Err(MathError::RelocatableAddFelt252OffsetExceeded(Box::new(( relocatable!(1, 0), - Felt252::new(usize::MAX) + 1_usize + Felt252::from(usize::MAX) + 1_u64 )))) ); } @@ -917,7 +927,7 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn maybe_relocatable_int_display() { assert_eq!( - format!("{}", MaybeRelocatable::from(Felt252::new(6))), + format!("{}", MaybeRelocatable::from(Felt252::from(6))), String::from("6") ) } diff --git a/vm/src/utils.rs b/vm/src/utils.rs index 389be4e5c6..7627779754 100644 --- a/vm/src/utils.rs +++ b/vm/src/utils.rs @@ -1,9 +1,12 @@ -use crate::stdlib::prelude::*; - use crate::types::relocatable::Relocatable; -use felt::Felt252; +use crate::{stdlib::prelude::*, types::errors::math_errors::MathError}; +use core::ops::Neg; use lazy_static::lazy_static; -use num_bigint::BigUint; +use num_bigint::{BigInt, BigUint, Sign, ToBigInt}; +use num_integer::Integer; +use num_traits::Num; + +pub const PRIME_STR: &str = "0x800000000000011000000000000000000000000000000000000000000000001"; #[macro_export] macro_rules! relocatable { @@ -16,7 +19,7 @@ macro_rules! relocatable { } lazy_static! { - pub static ref CAIRO_PRIME: BigUint = Felt252::prime(); + pub static ref CAIRO_PRIME: BigUint = BigUint::from_str_radix(&PRIME_STR[2..], 16).unwrap(); } #[macro_export] @@ -48,6 +51,36 @@ pub fn from_relocatable_to_indexes(relocatable: Relocatable) -> (usize, usize) { } } +pub fn felt_to_biguint(felt: crate::Felt252) -> BigUint { + let big_digits = felt + .to_le_digits() + .into_iter() + .flat_map(|limb| [limb as u32, (limb >> 32) as u32]) + .collect(); + BigUint::new(big_digits) +} + +pub fn felt_to_bigint(felt: crate::Felt252) -> BigInt { + felt_to_biguint(felt).to_bigint().unwrap() +} + +pub fn biguint_to_felt(biguint: &BigUint) -> Result { + // TODO This funtions should return a Felt252 instead of a Result + Ok(crate::Felt252::from_bytes_le_slice(&biguint.to_bytes_le())) +} + +pub fn bigint_to_felt(bigint: &BigInt) -> Result { + let (sign, bytes) = bigint + .mod_floor(&CAIRO_PRIME.to_bigint().unwrap()) + .to_bytes_le(); + let felt = crate::Felt252::from_bytes_le_slice(&bytes); + if sign == Sign::Minus { + Ok(felt.neg()) + } else { + Ok(felt) + } +} + #[cfg(test)] #[macro_use] pub mod test_utils { @@ -55,6 +88,20 @@ pub mod test_utils { use crate::types::relocatable::MaybeRelocatable; use crate::vm::trace::trace_entry::TraceEntry; + #[macro_export] + macro_rules! felt_hex { + ($val: expr) => { + $crate::Felt252::from_hex($val).expect("Couldn't parse bytes") + }; + } + + #[macro_export] + macro_rules! felt_str { + ($val: expr) => { + $crate::Felt252::from_dec_str($val).expect("Couldn't parse bytes") + }; + } + #[macro_export] macro_rules! bigint { ($val : expr) => { @@ -95,7 +142,11 @@ pub mod test_utils { impl From<(&str, u8)> for MaybeRelocatable { fn from((string, radix): (&str, u8)) -> Self { - MaybeRelocatable::Int(felt::felt_str!(string, radix)) + match radix { + 16 => MaybeRelocatable::Int(crate::felt_hex!(string)), + 10 => MaybeRelocatable::Int(crate::felt_str!(string)), + _ => panic!(" Invalid radix"), + } } } @@ -202,7 +253,7 @@ pub mod test_utils { $crate::types::relocatable::MaybeRelocatable::from(($val1, $val2)) }; ($val1 : expr) => { - $crate::types::relocatable::MaybeRelocatable::from(felt::Felt252::new($val1 as i128)) + $crate::types::relocatable::MaybeRelocatable::from(crate::Felt252::from($val1 as i128)) }; } pub(crate) use mayberelocatable; @@ -313,10 +364,8 @@ pub mod test_utils { crate::stdlib::string::String, crate::serde::deserialize_program::Identifier, >, - pub(crate) constants: crate::stdlib::collections::HashMap< - crate::stdlib::string::String, - crate::utils::Felt252, - >, + pub(crate) constants: + crate::stdlib::collections::HashMap, pub(crate) builtins: crate::utils::Vec, pub(crate) reference_manager: crate::serde::deserialize_program::ReferenceManager, } @@ -620,8 +669,6 @@ mod test { utils::test_utils::*, vm::{trace::trace_entry::TraceEntry, vm_core::VirtualMachine, vm_memory::memory::Memory}, }; - use felt::Felt252; - use num_traits::One; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; @@ -638,7 +685,7 @@ mod test { memory .insert( Relocatable::from((1, 2)), - &MaybeRelocatable::from(Felt252::one()), + &MaybeRelocatable::from(crate::Felt252::ONE), ) .unwrap(); memory @@ -662,7 +709,7 @@ mod test { memory .insert( Relocatable::from((1, 2)), - &MaybeRelocatable::from(Felt252::one()), + &MaybeRelocatable::from(crate::Felt252::ONE), ) .unwrap(); @@ -683,7 +730,7 @@ mod test { memory .insert( Relocatable::from((1, 2)), - &MaybeRelocatable::from(Felt252::one()), + &MaybeRelocatable::from(crate::Felt252::ONE), ) .unwrap(); @@ -803,14 +850,14 @@ mod test { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn scope_macro_test() { - let scope_from_macro = scope![("a", Felt252::one())]; + let scope_from_macro = scope![("a", crate::Felt252::ONE)]; let mut scope_verbose = ExecutionScopes::new(); - scope_verbose.assign_or_update_variable("a", any_box!(Felt252::one())); + scope_verbose.assign_or_update_variable("a", any_box!(crate::Felt252::ONE)); assert_eq!(scope_from_macro.data.len(), scope_verbose.data.len()); assert_eq!(scope_from_macro.data[0].len(), scope_verbose.data[0].len()); assert_eq!( scope_from_macro.data[0].get("a").unwrap().downcast_ref(), - Some(&Felt252::one()) + Some(&crate::Felt252::ONE) ); } @@ -819,8 +866,8 @@ mod test { fn check_dictionary_pass() { let mut tracker = DictTracker::new_empty(relocatable!(2, 0)); tracker.insert_value( - &MaybeRelocatable::from(Felt252::new(5)), - &MaybeRelocatable::from(Felt252::new(10)), + &MaybeRelocatable::from(crate::Felt252::from(5)), + &MaybeRelocatable::from(crate::Felt252::from(10)), ); let mut dict_manager = DictManager::new(); dict_manager.trackers.insert(2, tracker); @@ -836,10 +883,7 @@ mod test { #[should_panic] fn check_dictionary_fail() { let mut tracker = DictTracker::new_empty(relocatable!(2, 0)); - tracker.insert_value( - &MaybeRelocatable::from(Felt252::new(5)), - &MaybeRelocatable::from(Felt252::new(10)), - ); + tracker.insert_value(&MaybeRelocatable::from(5), &MaybeRelocatable::from(10)); let mut dict_manager = DictManager::new(); dict_manager.trackers.insert(2, tracker); let mut exec_scopes = ExecutionScopes::new(); @@ -897,7 +941,7 @@ mod test { fn dict_manager_default_macro() { let tracker = DictTracker::new_default_dict( relocatable!(2, 0), - &MaybeRelocatable::from(Felt252::new(17)), + &MaybeRelocatable::from(crate::Felt252::from(17)), None, ); let mut dict_manager = DictManager::new(); diff --git a/vm/src/vm/context/run_context.rs b/vm/src/vm/context/run_context.rs index 4867a154de..32bad1fec8 100644 --- a/vm/src/vm/context/run_context.rs +++ b/vm/src/vm/context/run_context.rs @@ -105,8 +105,8 @@ mod tests { use crate::types::instruction::{ApUpdate, FpUpdate, Opcode, PcUpdate, Res}; use crate::utils::test_utils::mayberelocatable; use crate::vm::errors::memory_errors::MemoryError; + use crate::Felt252; use assert_matches::assert_matches; - use felt::Felt252; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; @@ -392,7 +392,7 @@ mod tests { fp: 6, }; - let op0 = MaybeRelocatable::from(Felt252::new(7)); + let op0 = MaybeRelocatable::from(Felt252::from(7)); assert_matches!( run_context.compute_op1_addr(&instruction, Some(&op0)), Err::(VirtualMachineError::Memory( diff --git a/vm/src/vm/errors/hint_errors.rs b/vm/src/vm/errors/hint_errors.rs index bcf8935c5d..0ba9c973c3 100644 --- a/vm/src/vm/errors/hint_errors.rs +++ b/vm/src/vm/errors/hint_errors.rs @@ -5,7 +5,7 @@ use crate::stdlib::prelude::*; use thiserror_no_std::Error; -use felt::Felt252; +use crate::Felt252; use num_bigint::{BigInt, BigUint}; use crate::types::{ @@ -191,12 +191,11 @@ mod tests { use super::*; #[test] fn test_multiple_members_variant_message_format() { - let a = Felt252::new(42); - let b = Felt252::new(53); + let a = Felt252::from(42); + let b = Felt252::from(53); let string = "test"; - let error_msg = - HintError::InvalidValue(Box::new((string, a.clone(), b.clone()))).to_string(); + let error_msg = HintError::InvalidValue(Box::new((string, a, b))).to_string(); let expected_msg = format!("Invalid value for {string}. Got: {a}. Expected: {b}"); assert_eq!(error_msg, expected_msg) @@ -204,9 +203,9 @@ mod tests { #[test] fn test_single_felt_variant_message_format() { - let x = Felt252::new(15131); + let x = Felt252::from(15131); - let error_msg = HintError::InvalidKeccakStateSizeFelt252s(Box::new(x.clone())).to_string(); + let error_msg = HintError::InvalidKeccakStateSizeFelt252s(Box::new(x)).to_string(); let expected_msg = format!("Expected size to be in the range from [0, 100), got: {x}"); assert_eq!(error_msg, expected_msg) diff --git a/vm/src/vm/errors/memory_errors.rs b/vm/src/vm/errors/memory_errors.rs index ee7e44b2be..6f28ef1d37 100644 --- a/vm/src/vm/errors/memory_errors.rs +++ b/vm/src/vm/errors/memory_errors.rs @@ -5,7 +5,7 @@ use crate::stdlib::prelude::*; use thiserror_no_std::Error; -use felt::Felt252; +use crate::Felt252; use crate::types::{ errors::math_errors::MathError, diff --git a/vm/src/vm/errors/runner_errors.rs b/vm/src/vm/errors/runner_errors.rs index a9b26a8d5a..05e371e34a 100644 --- a/vm/src/vm/errors/runner_errors.rs +++ b/vm/src/vm/errors/runner_errors.rs @@ -7,7 +7,7 @@ use thiserror_no_std::Error; use super::{memory_errors::MemoryError, trace_errors::TraceError}; use crate::types::{errors::math_errors::MathError, relocatable::Relocatable}; -use felt::Felt252; +use crate::Felt252; #[derive(Debug, PartialEq, Error)] pub enum RunnerError { diff --git a/vm/src/vm/errors/vm_errors.rs b/vm/src/vm/errors/vm_errors.rs index 711180d88a..db8f0278e4 100644 --- a/vm/src/vm/errors/vm_errors.rs +++ b/vm/src/vm/errors/vm_errors.rs @@ -5,6 +5,7 @@ use crate::stdlib::prelude::*; use thiserror_no_std::Error; +use crate::Felt252; use crate::{ types::{ errors::math_errors::MathError, @@ -15,7 +16,6 @@ use crate::{ runner_errors::RunnerError, trace_errors::TraceError, }, }; -use felt::Felt252; pub const HINT_ERROR_STR: &str = "Got an exception while executing a hint: "; diff --git a/vm/src/vm/hooks.rs b/vm/src/vm/hooks.rs index b0b6e3c484..d2f88e7eb7 100644 --- a/vm/src/vm/hooks.rs +++ b/vm/src/vm/hooks.rs @@ -11,7 +11,7 @@ use crate::stdlib::{any::Any, collections::HashMap, prelude::*, sync::Arc}; -use felt::Felt252; +use crate::Felt252; use crate::{ hint_processor::hint_processor_definition::HintProcessor, types::exec_scope::ExecutionScopes, diff --git a/vm/src/vm/runners/builtin_runner/bitwise.rs b/vm/src/vm/runners/builtin_runner/bitwise.rs index 1ea7d58bb1..fea49fa89a 100644 --- a/vm/src/vm/runners/builtin_runner/bitwise.rs +++ b/vm/src/vm/runners/builtin_runner/bitwise.rs @@ -1,4 +1,5 @@ use crate::stdlib::{boxed::Box, vec::Vec}; +use crate::Felt252; use crate::{ types::{ instance_definitions::bitwise_instance_def::{ @@ -72,38 +73,50 @@ impl BitwiseBuiltinRunner { if index <= 1 { return Ok(None); } - let x_addr = Relocatable::from((address.segment_index, address.offset - index)); + let x_addr = (address - index)?; let y_addr = (x_addr + 1_usize)?; - let num_x = memory.get(&x_addr); - let num_y = memory.get(&y_addr); - if let (Some(MaybeRelocatable::Int(ref num_x)), Some(MaybeRelocatable::Int(ref num_y))) = ( - num_x.as_ref().map(|x| x.as_ref()), - num_y.as_ref().map(|x| x.as_ref()), - ) { - if num_x.bits() > self.bitwise_builtin.total_n_bits as u64 { + let (Ok(num_x), Ok(num_y)) = (memory.get_integer(x_addr), memory.get_integer(y_addr)) else { + return Ok(None); + }; + + // NOTE: we could operate on bytes here, but it caused a 20% slowdown + // on several benchmarks. + let to_limbs = |x_addr, x: &Felt252| -> Result<[u64; 4], RunnerError> { + const LEADING_BITS: u64 = 0xf800000000000000; + let limbs = x.to_le_digits(); + if limbs[3] & LEADING_BITS != 0 { return Err(RunnerError::IntegerBiggerThanPowerOfTwo(Box::new(( x_addr, self.bitwise_builtin.total_n_bits, - num_x.clone(), + *x, )))); + } + Ok(limbs) + }; + let (limbs_x, limbs_y) = (to_limbs(x_addr, &num_x)?, to_limbs(y_addr, &num_y)?); + let mut limbs_xy = [0u64; 4]; + for (xy, (x, y)) in limbs_xy + .iter_mut() + .zip(limbs_x.into_iter().zip(limbs_y.into_iter())) + { + *xy = match index { + 2 => x & y, + 3 => x ^ y, + 4 => x | y, + _ => { + return Ok(None); + } }; - if num_y.bits() > self.bitwise_builtin.total_n_bits as u64 { - return Err(RunnerError::IntegerBiggerThanPowerOfTwo(Box::new(( - y_addr, - self.bitwise_builtin.total_n_bits, - num_y.clone(), - )))); - }; - let res = match index { - 2 => Some(MaybeRelocatable::from(num_x & num_y)), - 3 => Some(MaybeRelocatable::from(num_x ^ num_y)), - 4 => Some(MaybeRelocatable::from(num_x | num_y)), - _ => None, - }; - return Ok(res); } - Ok(None) + let mut bytes_xy = [0u8; 32]; + bytes_xy[..8].copy_from_slice(limbs_xy[0].to_le_bytes().as_slice()); + bytes_xy[8..16].copy_from_slice(limbs_xy[1].to_le_bytes().as_slice()); + bytes_xy[16..24].copy_from_slice(limbs_xy[2].to_le_bytes().as_slice()); + bytes_xy[24..].copy_from_slice(limbs_xy[3].to_le_bytes().as_slice()); + Ok(Some(MaybeRelocatable::from(Felt252::from_bytes_le_slice( + &bytes_xy, + )))) } pub fn get_memory_segment_addresses(&self) -> (usize, Option) { @@ -189,11 +202,11 @@ mod tests { use crate::vm::errors::memory_errors::MemoryError; use crate::vm::runners::builtin_runner::BuiltinRunner; use crate::vm::vm_core::VirtualMachine; + use crate::Felt252; use crate::{ hint_processor::builtin_hint_processor::builtin_hint_processor_definition::BuiltinHintProcessor, types::program::Program, utils::test_utils::*, vm::runners::cairo_runner::CairoRunner, }; - use felt::Felt252; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; @@ -415,7 +428,7 @@ mod tests { let memory = memory![((0, 5), 10), ((0, 6), 12), ((0, 7), 0)]; let builtin = BitwiseBuiltinRunner::new(&BitwiseInstanceDef::default(), true); let result = builtin.deduce_memory_cell(Relocatable::from((0, 7)), &memory); - assert_eq!(result, Ok(Some(MaybeRelocatable::from(Felt252::new(8))))); + assert_eq!(result, Ok(Some(MaybeRelocatable::from(Felt252::from(8))))); } #[test] @@ -424,7 +437,7 @@ mod tests { let memory = memory![((0, 5), 10), ((0, 6), 12), ((0, 8), 0)]; let builtin = BitwiseBuiltinRunner::new(&BitwiseInstanceDef::default(), true); let result = builtin.deduce_memory_cell(Relocatable::from((0, 8)), &memory); - assert_eq!(result, Ok(Some(MaybeRelocatable::from(Felt252::new(6))))); + assert_eq!(result, Ok(Some(MaybeRelocatable::from(Felt252::from(6))))); } #[test] @@ -433,7 +446,7 @@ mod tests { let memory = memory![((0, 5), 10), ((0, 6), 12), ((0, 9), 0)]; let builtin = BitwiseBuiltinRunner::new(&BitwiseInstanceDef::default(), true); let result = builtin.deduce_memory_cell(Relocatable::from((0, 9)), &memory); - assert_eq!(result, Ok(Some(MaybeRelocatable::from(Felt252::new(14))))); + assert_eq!(result, Ok(Some(MaybeRelocatable::from(Felt252::from(14))))); } #[test] diff --git a/vm/src/vm/runners/builtin_runner/ec_op.rs b/vm/src/vm/runners/builtin_runner/ec_op.rs index e416e5554a..c62e8dffd8 100644 --- a/vm/src/vm/runners/builtin_runner/ec_op.rs +++ b/vm/src/vm/runners/builtin_runner/ec_op.rs @@ -5,14 +5,15 @@ use crate::types::instance_definitions::ec_op_instance_def::{ EcOpInstanceDef, CELLS_PER_EC_OP, INPUT_CELLS_PER_EC_OP, }; use crate::types::relocatable::{MaybeRelocatable, Relocatable}; +use crate::utils::{bigint_to_felt, felt_to_bigint, CAIRO_PRIME}; use crate::vm::errors::memory_errors::MemoryError; use crate::vm::errors::runner_errors::RunnerError; use crate::vm::vm_memory::memory::Memory; use crate::vm::vm_memory::memory_segments::MemorySegmentManager; -use felt::Felt252; -use num_bigint::BigInt; +use crate::Felt252; +use num_bigint::{BigInt, ToBigInt}; use num_integer::{div_ceil, Integer}; -use num_traits::{Num, One, Pow, Zero}; +use num_traits::{One, Zero}; use super::EC_OP_BUILTIN_NAME; @@ -47,7 +48,7 @@ impl EcOpBuiltinRunner { ///y^2 = x^3 + alpha * x + beta (mod p) ///or False otherwise. fn point_on_curve(x: &Felt252, y: &Felt252, alpha: &Felt252, beta: &Felt252) -> bool { - y.pow(2) == &(x.pow(3) + alpha * x) + beta + y.pow(2_u32) == (x.pow(3_u32) + alpha * x) + beta } #[allow(deprecated)] @@ -65,14 +66,17 @@ impl EcOpBuiltinRunner { prime: &BigInt, height: u32, ) -> Result<(BigInt, BigInt), RunnerError> { - let mut slope = m.to_bigint(); - let mut partial_sum_b = (partial_sum.0.to_bigint(), partial_sum.1.to_bigint()); - let mut doubled_point_b = (doubled_point.0.to_bigint(), doubled_point.1.to_bigint()); + let mut slope = felt_to_bigint(*m); + let mut partial_sum_b = (felt_to_bigint(partial_sum.0), felt_to_bigint(partial_sum.1)); + let mut doubled_point_b = ( + felt_to_bigint(doubled_point.0), + felt_to_bigint(doubled_point.1), + ); for _ in 0..height { if (doubled_point_b.0.clone() - partial_sum_b.0.clone()).is_zero() { #[allow(deprecated)] return Err(RunnerError::EcOpSameXCoordinate( - Self::format_ec_op_error(partial_sum_b, m.clone().to_bigint(), doubled_point_b) + Self::format_ec_op_error(partial_sum_b, slope, doubled_point_b) .into_boxed_str(), )); }; @@ -115,10 +119,10 @@ impl EcOpBuiltinRunner { //Constant values declared here const EC_POINT_INDICES: [(usize, usize); 3] = [(0, 1), (2, 3), (5, 6)]; const OUTPUT_INDICES: (usize, usize) = EC_POINT_INDICES[2]; - let alpha: Felt252 = Felt252::one(); - let beta_low: Felt252 = Felt252::new(0x609ad26c15c915c1f4cdfcb99cee9e89_u128); - let beta_high: Felt252 = Felt252::new(0x6f21413efbe40de150e596d72f7a8c5_u128); - let beta: Felt252 = (beta_high << 128_usize) + beta_low; + let alpha: Felt252 = Felt252::ONE; + let beta_low: Felt252 = Felt252::from(0x609ad26c15c915c1f4cdfcb99cee9e89_u128); + let beta_high: Felt252 = Felt252::from(0x6f21413efbe40de150e596d72f7a8c5_u128); + let beta: Felt252 = (beta_high * (Felt252::ONE + Felt252::from(u128::MAX))) + beta_low; let index = address .offset @@ -128,7 +132,7 @@ impl EcOpBuiltinRunner { return Ok(None); } let instance = Relocatable::from((address.segment_index, address.offset - index)); - let x_addr = (instance + (&Felt252::new(INPUT_CELLS_PER_EC_OP))) + let x_addr = (instance + (&Felt252::from(INPUT_CELLS_PER_EC_OP))) .map_err(|_| RunnerError::Memory(MemoryError::ExpectedInteger(Box::new(instance))))?; if let Some(number) = self.cache.borrow().get(&address).cloned() { @@ -170,33 +174,31 @@ impl EcOpBuiltinRunner { &beta, ) { return Err(RunnerError::PointNotOnCurve(Box::new(( - input_cells[pair.0].clone(), - input_cells[pair.1].clone(), + *input_cells[pair.0], + *input_cells[pair.1], )))); }; } - let prime = BigInt::from_str_radix(&felt::PRIME_STR[2..], 16) - .map_err(|_| RunnerError::CouldntParsePrime)?; + let prime = CAIRO_PRIME.to_bigint().unwrap(); let result = EcOpBuiltinRunner::ec_op_impl( (input_cells[0].to_owned(), input_cells[1].to_owned()), (input_cells[2].to_owned(), input_cells[3].to_owned()), input_cells[4], #[allow(deprecated)] - &alpha.to_bigint(), + &felt_to_bigint(alpha), &prime, self.ec_op_builtin.scalar_height, )?; - self.cache - .borrow_mut() - .insert(x_addr, result.0.clone().into()); + let result = (bigint_to_felt(&result.0)?, bigint_to_felt(&result.1)?); + self.cache.borrow_mut().insert(x_addr, result.0); self.cache.borrow_mut().insert( (x_addr + 1usize) .map_err(|_| RunnerError::Memory(MemoryError::ExpectedInteger(Box::new(x_addr))))?, - result.1.clone().into(), + result.1, ); match index - self.n_input_cells as usize { - 0 => Ok(Some(MaybeRelocatable::Int(Felt252::new(result.0)))), - _ => Ok(Some(MaybeRelocatable::Int(Felt252::new(result.1)))), + 0 => Ok(Some(MaybeRelocatable::Int(result.0))), + _ => Ok(Some(MaybeRelocatable::Int(result.1))), //Default case corresponds to 1, as there are no other possible cases } } @@ -273,7 +275,6 @@ impl EcOpBuiltinRunner { mod tests { use super::*; use crate::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::BuiltinHintProcessor; - use crate::relocatable; use crate::serde::deserialize_program::BuiltinName; use crate::stdlib::collections::HashMap; use crate::types::program::Program; @@ -281,13 +282,13 @@ mod tests { use crate::vm::errors::cairo_run_errors::CairoRunError; use crate::vm::errors::vm_errors::VirtualMachineError; use crate::vm::runners::cairo_runner::CairoRunner; + use crate::{felt_hex, felt_str, relocatable}; use crate::vm::{ errors::{memory_errors::MemoryError, runner_errors::RunnerError}, runners::builtin_runner::BuiltinRunner, vm_core::VirtualMachine, }; - use felt::felt_str; use EcOpBuiltinRunner; #[cfg(target_arch = "wasm32")] @@ -498,64 +499,40 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn point_is_on_curve_a() { - let x = felt_str!( - "874739451078007766457464989774322083649278607533249481151382481072868806602" - ); - let y = felt_str!( - "152666792071518830868575557812948353041420400780739481342941381225525861407" - ); - let alpha = Felt252::one(); - let beta = felt_str!( - "3141592653589793238462643383279502884197169399375105820974944592307816406665" - ); + let x = felt_hex!("0x1ef15c18599971b7beced415a40f0c7deacfd9b0d1819e03d723d8bc943cfca"); + let y = felt_hex!("0x5668060aa49730b7be4801df46ec62de53ecd11abe43a32873000c36e8dc1f"); + let alpha = Felt252::ONE; + let beta = felt_hex!("0x6f21413efbe40de150e596d72f7a8c5609ad26c15c915c1f4cdfcb99cee9e89"); assert!(EcOpBuiltinRunner::point_on_curve(&x, &y, &alpha, &beta)); } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn point_is_on_curve_b() { - let x = felt_str!( - "3139037544796708144595053687182055617920475701120786241351436619796497072089" - ); - let y = felt_str!( - "2119589567875935397690285099786081818522144748339117565577200220779667999801" - ); - let alpha = Felt252::one(); - let beta = felt_str!( - "3141592653589793238462643383279502884197169399375105820974944592307816406665" - ); + let x = felt_hex!("0x6f0a1ddaf19c44781c8946db396f494a10ffab183c2d8cf6c4cd321a8d87fd9"); + let y = felt_hex!("0x4afa52a9ef8c023d3385fddb6e1d78d57b0693b9b02d45d0f939b526d474c39"); + let alpha = Felt252::ONE; + let beta = felt_hex!("0x6f21413efbe40de150e596d72f7a8c5609ad26c15c915c1f4cdfcb99cee9e89"); assert!(EcOpBuiltinRunner::point_on_curve(&x, &y, &alpha, &beta)); } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn point_is_not_on_curve_a() { - let x = felt_str!( - "874739454078007766457464989774322083649278607533249481151382481072868806602" - ); - let y = felt_str!( - "152666792071518830868575557812948353041420400780739481342941381225525861407" - ); - let alpha = Felt252::one(); - let beta = felt_str!( - "3141592653589793238462643383279502884197169399375105820974944592307816406665" - ); + let x = felt_hex!("0x1ef15c1a2162fb0d2e5d83196a6fb0509632fab5d746f0c3d723d8bc943cfca"); + let y = felt_hex!("0x5668060aa49730b7be4801df46ec62de53ecd11abe43a32873000c36e8dc1f"); + let alpha = Felt252::ONE; + let beta = felt_hex!("0x6f21413efbe40de150e596d72f7a8c5609ad26c15c915c1f4cdfcb99cee9e89"); assert!(!EcOpBuiltinRunner::point_on_curve(&x, &y, &alpha, &beta)); } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn point_is_not_on_curve_b() { - let x = felt_str!( - "3139037544756708144595053687182055617927475701120786241351436619796497072089" - ); - let y = felt_str!( - "2119589567875935397690885099786081818522144748339117565577200220779667999801" - ); - let alpha = Felt252::one(); - let beta = felt_str!( - "3141592653589793238462643383279502884197169399375105820974944592307816406665" - ); + let x = felt_hex!("0x6f0a1ddaeb88837dcc8ac9a48f894deed706bc3e8998e63535e2c91a8d87fd9"); + let y = felt_hex!("0x4afa52a9ef8c023d33ea3865fb4e0e49abfc50dd50ccea867539b526d474c39"); + let alpha = Felt252::ONE; + let beta = felt_hex!("0x6f21413efbe40de150e596d72f7a8c5609ad26c15c915c1f4cdfcb99cee9e89"); assert!(!EcOpBuiltinRunner::point_on_curve(&x, &y, &alpha, &beta)); } @@ -563,22 +540,14 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn compute_ec_op_impl_valid_a() { let partial_sum = ( - felt_str!( - "3139037544796708144595053687182055617920475701120786241351436619796497072089" - ), - felt_str!( - "2119589567875935397690285099786081818522144748339117565577200220779667999801" - ), + felt_hex!("0x6f0a1ddaf19c44781c8946db396f494a10ffab183c2d8cf6c4cd321a8d87fd9"), + felt_hex!("0x4afa52a9ef8c023d3385fddb6e1d78d57b0693b9b02d45d0f939b526d474c39"), ); let doubled_point = ( - felt_str!( - "874739451078007766457464989774322083649278607533249481151382481072868806602" - ), - felt_str!( - "152666792071518830868575557812948353041420400780739481342941381225525861407" - ), + felt_hex!("0x1ef15c18599971b7beced415a40f0c7deacfd9b0d1819e03d723d8bc943cfca"), + felt_hex!("0x5668060aa49730b7be4801df46ec62de53ecd11abe43a32873000c36e8dc1f"), ); - let m = Felt252::new(34); + let m = Felt252::from(34); let alpha = bigint!(1); let height = 256; let prime = (*CAIRO_PRIME).clone().into(); @@ -601,22 +570,14 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn compute_ec_op_impl_valid_b() { let partial_sum = ( - felt_str!( - "2962412995502985605007699495352191122971573493113767820301112397466445942584" - ), - felt_str!( - "214950771763870898744428659242275426967582168179217139798831865603966154129" - ), + felt_hex!("0x68caa9509b7c2e90b4d92661cbf7c465471c1e8598c5f989691eef6653e0f38"), + felt_hex!("0x79a8673f498531002fc549e06ff2010ffc0c191cceb7da5532acb95cdcb591"), ); let doubled_point = ( - felt_str!( - "874739451078007766457464989774322083649278607533249481151382481072868806602" - ), - felt_str!( - "152666792071518830868575557812948353041420400780739481342941381225525861407" - ), + felt_hex!("0x1ef15c18599971b7beced415a40f0c7deacfd9b0d1819e03d723d8bc943cfca"), + felt_hex!("0x5668060aa49730b7be4801df46ec62de53ecd11abe43a32873000c36e8dc1f"), ); - let m = Felt252::new(34); + let m = Felt252::from(34); let alpha = bigint!(1); let height = 256; let prime = (*CAIRO_PRIME).clone().into(); @@ -639,27 +600,24 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] #[allow(deprecated)] fn compute_ec_op_invalid_same_x_coordinate() { - let partial_sum = (Felt252::one(), Felt252::new(9)); - let doubled_point = (Felt252::one(), Felt252::new(12)); - let m = Felt252::new(34); + let partial_sum = (Felt252::ONE, Felt252::from(9)); + let doubled_point = (Felt252::ONE, Felt252::from(12)); + let m = Felt252::from(34); let alpha = bigint!(1); let height = 256; let prime = (*CAIRO_PRIME).clone().into(); - let result = EcOpBuiltinRunner::ec_op_impl( - partial_sum.clone(), - doubled_point.clone(), - &m, - &alpha, - &prime, - height, - ); + let result = + EcOpBuiltinRunner::ec_op_impl(partial_sum, doubled_point, &m, &alpha, &prime, height); assert_eq!( result, Err(RunnerError::EcOpSameXCoordinate( EcOpBuiltinRunner::format_ec_op_error( - (partial_sum.0.to_bigint(), partial_sum.1.to_bigint()), - m.to_bigint(), - (doubled_point.0.to_bigint(), doubled_point.1.to_bigint()) + (felt_to_bigint(partial_sum.0), felt_to_bigint(partial_sum.1)), + felt_to_bigint(m), + ( + felt_to_bigint(doubled_point.0), + felt_to_bigint(doubled_point.1) + ) ) .into_boxed_str() )) @@ -689,29 +647,29 @@ mod tests { ( (3, 0), ( - "2962412995502985605007699495352191122971573493113767820301112397466445942584", - 10 + "0x68caa9509b7c2e90b4d92661cbf7c465471c1e8598c5f989691eef6653e0f38", + 16 ) ), ( (3, 1), ( - "214950771763870898744428659242275426967582168179217139798831865603966154129", - 10 + "0x79a8673f498531002fc549e06ff2010ffc0c191cceb7da5532acb95cdcb591", + 16 ) ), ( (3, 2), ( - "874739451078007766457464989774322083649278607533249481151382481072868806602", - 10 + "0x1ef15c18599971b7beced415a40f0c7deacfd9b0d1819e03d723d8bc943cfca", + 16 ) ), ( (3, 3), ( - "152666792071518830868575557812948353041420400780739481342941381225525861407", - 10 + "0x5668060aa49730b7be4801df46ec62de53ecd11abe43a32873000c36e8dc1f", + 16 ) ), ((3, 4), 34), @@ -741,22 +699,22 @@ mod tests { ( (3, 1), ( - "214950771763870898744428659242275426967582168179217139798831865603966154129", - 10 + "0x79a8673f498531002fc549e06ff2010ffc0c191cceb7da5532acb95cdcb591", + 16 ) ), ( (3, 2), ( - "874739451078007766457464989774322083649278607533249481151382481072868806602", - 10 + "0x1ef15c18599971b7beced415a40f0c7deacfd9b0d1819e03d723d8bc943cfca", + 16 ) ), ( (3, 3), ( - "152666792071518830868575557812948353041420400780739481342941381225525861407", - 10 + "0x5668060aa49730b7be4801df46ec62de53ecd11abe43a32873000c36e8dc1f", + 16 ) ), ((3, 4), 34), @@ -781,29 +739,29 @@ mod tests { ( (3, 0), ( - "2962412995502985605007699495352191122971573493113767820301112397466445942584", - 10 + "0x68caa9509b7c2e90b4d92661cbf7c465471c1e8598c5f989691eef6653e0f38", + 16 ) ), ( (3, 1), ( - "214950771763870898744428659242275426967582168179217139798831865603966154129", - 10 + "0x79a8673f498531002fc549e06ff2010ffc0c191cceb7da5532acb95cdcb591", + 16 ) ), ( (3, 2), ( - "874739451078007766457464989774322083649278607533249481151382481072868806602", - 10 + "0x1ef15c18599971b7beced415a40f0c7deacfd9b0d1819e03d723d8bc943cfca", + 16 ) ), ( (3, 3), ( - "152666792071518830868575557812948353041420400780739481342941381225525861407", - 10 + "0x5668060aa49730b7be4801df46ec62de53ecd11abe43a32873000c36e8dc1f", + 16 ) ), ((3, 4), 34), @@ -828,22 +786,22 @@ mod tests { ( (3, 0), ( - "2962412995502985605007699495352191122971573493113767820301112397466445942584", - 10 + "0x68caa9509b7c2e90b4d92661cbf7c465471c1e8598c5f989691eef6653e0f38", + 16 ) ), ( (3, 1), ( - "214950771763870898744428659242275426967582168179217139798831865603966154129", - 10 + "0x79a8673f498531002fc549e06ff2010ffc0c191cceb7da5532acb95cdcb591", + 16 ) ), ( (3, 2), ( - "874739451078007766457464989774322083649278607533249481151382481072868806602", - 10 + "0x1ef15c18599971b7beced415a40f0c7deacfd9b0d1819e03d723d8bc943cfca", + 16 ) ), ((3, 3), (1, 2)), diff --git a/vm/src/vm/runners/builtin_runner/hash.rs b/vm/src/vm/runners/builtin_runner/hash.rs index bb3cd7d6c2..555f71f473 100644 --- a/vm/src/vm/runners/builtin_runner/hash.rs +++ b/vm/src/vm/runners/builtin_runner/hash.rs @@ -1,4 +1,5 @@ use crate::stdlib::{cell::RefCell, prelude::*}; +use crate::types::errors::math_errors::MathError; use crate::types::instance_definitions::pedersen_instance_def::{ CELLS_PER_HASH, INPUT_CELLS_PER_HASH, }; @@ -8,7 +9,7 @@ use crate::vm::errors::runner_errors::RunnerError; use crate::vm::runners::cairo_pie::BuiltinAdditionalData; use crate::vm::vm_memory::memory::Memory; use crate::vm::vm_memory::memory_segments::MemorySegmentManager; -use felt::Felt252; +use crate::Felt252; use num_integer::{div_ceil, Integer}; use starknet_crypto::{pedersen_hash, FieldElement}; @@ -104,20 +105,19 @@ impl HashBuiltinRunner { self.verified_addresses.borrow_mut()[address.offset] = true; //Convert MaybeRelocatable to FieldElement - let a_string = num_a.to_str_radix(10); - let b_string = num_b.to_str_radix(10); + let a_be_bytes = num_a.to_bytes_be(); + let b_be_bytes = num_b.to_bytes_be(); let (y, x) = match ( - FieldElement::from_dec_str(&a_string), - FieldElement::from_dec_str(&b_string), + FieldElement::from_bytes_be(&a_be_bytes), + FieldElement::from_bytes_be(&b_be_bytes), ) { (Ok(field_element_a), Ok(field_element_b)) => (field_element_a, field_element_b), - _ => return Err(RunnerError::FailedStringConversion), + _ => return Err(MathError::ByteConversionError.into()), }; //Compute pedersen Hash let fe_result = pedersen_hash(&x, &y); //Convert result from FieldElement to MaybeRelocatable - let r_byte_slice = fe_result.to_bytes_be(); - let result = Felt252::from_bytes_be(&r_byte_slice); + let result = Felt252::from_bytes_be(&fe_result.to_bytes_be()); return Ok(Some(MaybeRelocatable::from(result))); } Ok(None) @@ -193,18 +193,17 @@ impl HashBuiltinRunner { mod tests { use super::*; use crate::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::BuiltinHintProcessor; - use crate::relocatable; use crate::serde::deserialize_program::BuiltinName; use crate::stdlib::collections::HashMap; use crate::types::program::Program; use crate::utils::test_utils::*; use crate::vm::runners::cairo_runner::CairoRunner; + use crate::{felt_hex, relocatable}; use crate::vm::{ errors::memory_errors::MemoryError, runners::builtin_runner::BuiltinRunner, vm_core::VirtualMachine, }; - use felt::felt_str; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; @@ -419,8 +418,8 @@ mod tests { let result = builtin.deduce_memory_cell(Relocatable::from((0, 5)), &memory); assert_eq!( result, - Ok(Some(MaybeRelocatable::from(felt_str!( - "3270867057177188607814717243084834301278723532952411121381966378910183338911" + Ok(Some(MaybeRelocatable::from(felt_hex!( + "0x73b3ec210cccbb970f80c6826fb1c40ae9f487617696234ff147451405c339f" )))) ); assert_eq!( diff --git a/vm/src/vm/runners/builtin_runner/keccak.rs b/vm/src/vm/runners/builtin_runner/keccak.rs index 355b59a8ab..cf5c1868db 100644 --- a/vm/src/vm/runners/builtin_runner/keccak.rs +++ b/vm/src/vm/runners/builtin_runner/keccak.rs @@ -7,10 +7,9 @@ use crate::vm::errors::runner_errors::RunnerError; use crate::vm::vm_core::VirtualMachine; use crate::vm::vm_memory::memory::Memory; use crate::vm::vm_memory::memory_segments::MemorySegmentManager; -use felt::Felt252; +use crate::Felt252; use num_bigint::BigUint; use num_integer::div_ceil; -use num_traits::One; use super::KECCAK_BUILTIN_NAME; @@ -87,42 +86,43 @@ impl KeccakBuiltinRunner { let m_index = (first_input_addr + i)?; let val = match memory.get(&m_index) { Some(value) => { - let num = value.get_int_ref().ok_or_else(|| { - RunnerError::BuiltinExpectedInteger(Box::new(( + let num = value + .get_int_ref() + .ok_or(RunnerError::BuiltinExpectedInteger(Box::new(( KECCAK_BUILTIN_NAME, - m_index, - ))) - })?; - if num >= &(Felt252::one() << self.state_rep[i]) { + (first_input_addr + i)?, + ))))?; + if num >= &(Felt252::TWO.pow(self.state_rep[i])) { return Err(RunnerError::IntegerBiggerThanPowerOfTwo(Box::new(( - m_index, + (first_input_addr + i)?, self.state_rep[i], - num.clone(), + *num, )))); } - num.clone() + *num } _ => return Ok(None), }; - input_felts.push(val) } - let input_message: Vec = input_felts .iter() - .flat_map(|x| Self::right_pad(&x.to_biguint().to_bytes_le(), KECCAK_FELT_BYTE_SIZE)) + .flat_map(|x| { + let mut bytes = x.to_bytes_le().to_vec(); + bytes.resize(KECCAK_FELT_BYTE_SIZE, 0); + bytes + }) .collect(); let keccak_result = Self::keccak_f(&input_message)?; let mut start_index = 0_usize; for (i, bits) in self.state_rep.iter().enumerate() { let end_index = start_index + *bits as usize / 8; - self.cache.borrow_mut().insert( - (first_output_addr + i)?, - Felt252::from(BigUint::from_bytes_le( - &keccak_result[start_index..end_index], - )), - ); + self.cache.borrow_mut().insert((first_output_addr + i)?, { + let mut bytes = keccak_result[start_index..end_index].to_vec(); + bytes.resize(32, 0); + Felt252::from_bytes_le_slice(&bytes) + }); start_index = end_index; } Ok(self.cache.borrow().get(&address).map(|x| x.into())) @@ -211,13 +211,6 @@ impl KeccakBuiltinRunner { safe_div_usize(262144_usize, diluted_n_bits as usize).unwrap_or(0) } - fn right_pad(bytes: &[u8], final_size: usize) -> Vec { - let zeros: Vec = vec![0; final_size - bytes.len()]; - let mut bytes_vector = bytes.to_vec(); - bytes_vector.extend(zeros); - bytes_vector - } - fn keccak_f(input_message: &[u8]) -> Result, RunnerError> { let bigint = BigUint::from_bytes_le(input_message); let mut keccak_input = bigint.to_u64_digits(); @@ -231,15 +224,13 @@ impl KeccakBuiltinRunner { #[cfg(test)] mod tests { - use num_traits::Num; - use super::*; use crate::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::BuiltinHintProcessor; - use crate::relocatable; use crate::stdlib::collections::HashMap; use crate::types::program::Program; use crate::utils::test_utils::*; use crate::vm::runners::cairo_runner::CairoRunner; + use crate::{felt_hex, relocatable}; use crate::vm::{ errors::{memory_errors::MemoryError, runner_errors::RunnerError}, @@ -538,13 +529,9 @@ mod tests { let result = builtin.deduce_memory_cell(Relocatable::from((0, 25)), &memory); assert_eq!( result, - Ok(Some(MaybeRelocatable::from( - Felt252::from_str_radix( - "1006979841721999878391288827876533441431370448293338267890891", - 10 - ) - .unwrap() - ))) + Ok(Some(MaybeRelocatable::from(felt_hex!( + "0xa06bd018ba91b93146f53563cff2efba46fee2eabe9d89b4cb" + )))) ); } @@ -686,13 +673,6 @@ mod tests { assert_eq!(result, 16384); } - #[test] - fn right_pad() { - let num = [1_u8]; - let padded_num = KeccakBuiltinRunner::right_pad(&num, 5); - assert_eq!(padded_num, vec![1, 0, 0, 0, 0]); - } - #[test] fn keccak_f() { let input_bytes = b"\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; diff --git a/vm/src/vm/runners/builtin_runner/poseidon.rs b/vm/src/vm/runners/builtin_runner/poseidon.rs index 894627d622..75c809cd7f 100644 --- a/vm/src/vm/runners/builtin_runner/poseidon.rs +++ b/vm/src/vm/runners/builtin_runner/poseidon.rs @@ -1,4 +1,5 @@ use crate::stdlib::{cell::RefCell, collections::HashMap, prelude::*}; +use crate::types::errors::math_errors::MathError; use crate::types::instance_definitions::poseidon_instance_def::{ CELLS_PER_POSEIDON, INPUT_CELLS_PER_POSEIDON, }; @@ -7,7 +8,7 @@ use crate::vm::errors::memory_errors::MemoryError; use crate::vm::errors::runner_errors::RunnerError; use crate::vm::vm_memory::memory::Memory; use crate::vm::vm_memory::memory_segments::MemorySegmentManager; -use felt::Felt252; +use crate::Felt252; use num_integer::div_ceil; use starknet_crypto::{poseidon_permute_comp, FieldElement}; @@ -82,14 +83,14 @@ impl PoseidonBuiltinRunner { let m_index = (first_input_addr + i)?; let val = match memory.get(&m_index) { Some(value) => { - let num = value.get_int_ref().ok_or_else(|| { - RunnerError::BuiltinExpectedInteger(Box::new(( + let num = value + .get_int_ref() + .ok_or(RunnerError::BuiltinExpectedInteger(Box::new(( POSEIDON_BUILTIN_NAME, - m_index, - ))) - })?; - FieldElement::from_dec_str(&num.to_str_radix(10)) - .map_err(|_| RunnerError::FailedStringConversion)? + (first_input_addr + i)?, + ))))?; + FieldElement::from_bytes_be(&num.to_bytes_be()) + .map_err(|_| MathError::ByteConversionError)? } _ => return Ok(None), }; diff --git a/vm/src/vm/runners/builtin_runner/range_check.rs b/vm/src/vm/runners/builtin_runner/range_check.rs index 4ef0c23ade..1bee53200a 100644 --- a/vm/src/vm/runners/builtin_runner/range_check.rs +++ b/vm/src/vm/runners/builtin_runner/range_check.rs @@ -1,9 +1,9 @@ use crate::stdlib::{ cmp::{max, min}, - ops::Shl, prelude::*, }; +use crate::Felt252; use crate::{ types::{ instance_definitions::range_check_instance_def::CELLS_PER_RANGE_CHECK, @@ -17,8 +17,8 @@ use crate::{ }, }, }; -use felt::Felt252; -use num_traits::{One, Zero}; + +use num_traits::Zero; use super::RANGE_CHECK_BUILTIN_NAME; @@ -45,11 +45,11 @@ pub struct RangeCheckBuiltinRunner { impl RangeCheckBuiltinRunner { pub fn new(ratio: Option, n_parts: u32, included: bool) -> RangeCheckBuiltinRunner { - let bound = Felt252::one().shl(16 * n_parts); + let bound = Felt252::TWO.pow(16 * n_parts as u128); let _bound = if n_parts != 0 && bound.is_zero() { None } else { - Some(Felt252::new(bound)) + Some(bound) }; RangeCheckBuiltinRunner { @@ -91,12 +91,12 @@ impl RangeCheckBuiltinRunner { let num = memory .get_integer(address) .map_err(|_| MemoryError::RangeCheckFoundNonInt(Box::new(address)))?; - if num.bits() <= N_PARTS * INNER_RC_BOUND_SHIFT { + if num.bits() as u64 <= N_PARTS * INNER_RC_BOUND_SHIFT { Ok(vec![address.to_owned()]) } else { Err(MemoryError::RangeCheckNumOutOfBounds(Box::new(( num.into_owned(), - Felt252::one() << ((N_PARTS * INNER_RC_BOUND_SHIFT) as u32), + Felt252::TWO.pow((N_PARTS * INNER_RC_BOUND_SHIFT) as u128), )))) } }, diff --git a/vm/src/vm/runners/builtin_runner/signature.rs b/vm/src/vm/runners/builtin_runner/signature.rs index 7a253d9add..f5d256103a 100644 --- a/vm/src/vm/runners/builtin_runner/signature.rs +++ b/vm/src/vm/runners/builtin_runner/signature.rs @@ -1,6 +1,8 @@ use crate::stdlib::{cell::RefCell, collections::HashMap, prelude::*, rc::Rc}; +use crate::types::errors::math_errors::MathError; use crate::vm::runners::cairo_pie::BuiltinAdditionalData; +use crate::Felt252; use crate::{ types::{ instance_definitions::ecdsa_instance_def::EcdsaInstanceDef, @@ -14,7 +16,6 @@ use crate::{ }, }, }; -use felt::Felt252; use num_integer::div_ceil; use starknet_crypto::{verify, FieldElement, Signature}; @@ -53,15 +54,11 @@ impl SignatureBuiltinRunner { relocatable: Relocatable, (r, s): &(Felt252, Felt252), ) -> Result<(), MemoryError> { - let r_string = r.to_str_radix(10); - let s_string = s.to_str_radix(10); + let r_be_bytes = r.to_bytes_be(); + let s_be_bytes = s.to_bytes_be(); let (r_felt, s_felt) = ( - FieldElement::from_dec_str(&r_string).map_err(|_| { - MemoryError::FailedStringToFieldElementConversion(r_string.into_boxed_str()) - })?, - FieldElement::from_dec_str(&s_string).map_err(|_| { - MemoryError::FailedStringToFieldElementConversion(s_string.into_boxed_str()) - })?, + FieldElement::from_bytes_be(&r_be_bytes).map_err(|_| MathError::ByteConversionError)?, + FieldElement::from_bytes_be(&s_be_bytes).map_err(|_| MathError::ByteConversionError)?, ); let signature = Signature { @@ -127,14 +124,11 @@ impl SignatureBuiltinRunner { .get(&pubkey_addr) .ok_or_else(|| MemoryError::SignatureNotFound(Box::new(pubkey_addr)))?; - let public_key = - FieldElement::from_dec_str(&pubkey.to_str_radix(10)).map_err(|_| { - MemoryError::ErrorParsingPubKey(pubkey.to_str_radix(10).into_boxed_str()) - })?; + let public_key = FieldElement::from_bytes_be(&pubkey.to_bytes_be()) + .map_err(|_| MathError::ByteConversionError)?; let (r, s) = (signature.r, signature.s); - let message = FieldElement::from_dec_str(&msg.to_str_radix(10)).map_err(|_| { - MemoryError::ErrorRetrievingMessage(msg.to_str_radix(10).into_boxed_str()) - })?; + let message = FieldElement::from_bytes_be(&msg.to_bytes_be()) + .map_err(|_| MathError::ByteConversionError)?; match verify(&public_key, &message, &r, &s) { Ok(true) => Ok(vec![]), _ => Err(MemoryError::InvalidSignature(Box::new(( @@ -250,7 +244,7 @@ mod tests { }, }; - use felt::felt_str; + use crate::felt_str; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; diff --git a/vm/src/vm/runners/cairo_pie.rs b/vm/src/vm/runners/cairo_pie.rs index 60a0fa147e..d464065899 100644 --- a/vm/src/vm/runners/cairo_pie.rs +++ b/vm/src/vm/runners/cairo_pie.rs @@ -1,9 +1,9 @@ use super::cairo_runner::ExecutionResources; use crate::{ - felt::Felt252, serde::deserialize_program::BuiltinName, stdlib::{collections::HashMap, prelude::*}, types::relocatable::{MaybeRelocatable, Relocatable}, + Felt252, }; use serde::{Deserialize, Serialize}; @@ -98,8 +98,7 @@ pub struct CairoPieVersion { mod serde_impl { use super::CAIRO_PIE_VERSION; - use crate::{types::relocatable::MaybeRelocatable, utils::CAIRO_PRIME}; - use felt::Felt252; + use crate::{types::relocatable::MaybeRelocatable, utils::CAIRO_PRIME, Felt252}; use num_bigint::BigUint; use num_traits::Num; use serde::{ser::SerializeSeq, Serialize, Serializer}; @@ -187,7 +186,7 @@ mod serde_impl { MaybeRelocatable::Int(data_val) => { let mem_addr = ADDR_BASE + *segment as u64 * OFFSET_BASE + *offset as u64; res.extend_from_slice(mem_addr.to_le_bytes().as_ref()); - res.extend_from_slice(data_val.to_le_bytes().as_ref()); + res.extend_from_slice(data_val.to_bytes_le().as_ref()); } }; } diff --git a/vm/src/vm/runners/cairo_runner.rs b/vm/src/vm/runners/cairo_runner.rs index cb52546cd8..57b72fe8b7 100644 --- a/vm/src/vm/runners/cairo_runner.rs +++ b/vm/src/vm/runners/cairo_runner.rs @@ -13,6 +13,7 @@ use crate::{ }, }; +use crate::Felt252; use crate::{ hint_processor::hint_processor_definition::{HintProcessor, HintReference}, math_utils::safe_div_usize, @@ -48,7 +49,6 @@ use crate::{ }, }, }; -use felt::Felt252; use num_integer::div_rem; use num_traits::{ToPrimitive, Zero}; use serde::{Deserialize, Serialize}; @@ -1519,6 +1519,7 @@ mod tests { }; use crate::vm::vm_memory::memory::MemoryCell; + use crate::felt_hex; use crate::{ hint_processor::builtin_hint_processor::builtin_hint_processor_definition::BuiltinHintProcessor, relocatable, @@ -1528,8 +1529,6 @@ mod tests { vm::trace::trace_entry::TraceEntry, }; use assert_matches::assert_matches; - use felt::felt_str; - use num_traits::One; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; @@ -1728,8 +1727,8 @@ mod tests { offset: 0, }); let stack = vec![ - MaybeRelocatable::from(Felt252::new(4_i32)), - MaybeRelocatable::from(Felt252::new(6_i32)), + MaybeRelocatable::from(Felt252::from(4_i32)), + MaybeRelocatable::from(Felt252::from(6_i32)), ]; assert!(cairo_runner.initialize_state(&mut vm, 1, stack).is_err()); } @@ -1746,8 +1745,8 @@ mod tests { } cairo_runner.program_base = Some(relocatable!(1, 0)); let stack = vec![ - MaybeRelocatable::from(Felt252::new(4_i32)), - MaybeRelocatable::from(Felt252::new(6_i32)), + MaybeRelocatable::from(Felt252::from(4_i32)), + MaybeRelocatable::from(Felt252::from(6_i32)), ]; cairo_runner.initialize_state(&mut vm, 1, stack).unwrap(); } @@ -1765,7 +1764,7 @@ mod tests { cairo_runner.program_base = Some(relocatable!(0, 0)); cairo_runner.execution_base = Some(relocatable!(1, 0)); let stack = Vec::new(); - let return_fp = MaybeRelocatable::from(Felt252::new(9_i32)); + let return_fp = MaybeRelocatable::from(Felt252::from(9_i32)); cairo_runner .initialize_function_entrypoint(&mut vm, 0, stack, return_fp) .unwrap(); @@ -1786,8 +1785,8 @@ mod tests { } cairo_runner.program_base = Some(relocatable!(0, 0)); cairo_runner.execution_base = Some(relocatable!(1, 0)); - let stack = vec![MaybeRelocatable::from(Felt252::new(7_i32))]; - let return_fp = MaybeRelocatable::from(Felt252::new(9_i32)); + let stack = vec![MaybeRelocatable::from(Felt252::from(7_i32))]; + let return_fp = MaybeRelocatable::from(Felt252::from(9_i32)); cairo_runner .initialize_function_entrypoint(&mut vm, 1, stack, return_fp) .unwrap(); @@ -1808,8 +1807,8 @@ mod tests { let program = program![BuiltinName::output]; let mut cairo_runner = cairo_runner!(program); let mut vm = vm!(); - let stack = vec![MaybeRelocatable::from(Felt252::new(7_i32))]; - let return_fp = MaybeRelocatable::from(Felt252::new(9_i32)); + let stack = vec![MaybeRelocatable::from(Felt252::from(7_i32))]; + let return_fp = MaybeRelocatable::from(Felt252::from(9_i32)); cairo_runner .initialize_function_entrypoint(&mut vm, 1, stack, return_fp) .unwrap(); @@ -2658,21 +2657,21 @@ mod tests { .memory .insert( Relocatable::from((0, 0)), - &MaybeRelocatable::from(Felt252::new(4613515612218425347_i64)), + &MaybeRelocatable::from(Felt252::from(4613515612218425347_i64)), ) .unwrap(); vm.segments .memory .insert( Relocatable::from((0, 1)), - &MaybeRelocatable::from(Felt252::new(5)), + &MaybeRelocatable::from(Felt252::from(5)), ) .unwrap(); vm.segments .memory .insert( Relocatable::from((0, 2)), - &MaybeRelocatable::from(Felt252::new(2345108766317314046_i64)), + &MaybeRelocatable::from(Felt252::from(2345108766317314046_i64)), ) .unwrap(); vm.segments @@ -2687,7 +2686,7 @@ mod tests { .memory .insert( Relocatable::from((1, 5)), - &MaybeRelocatable::from(Felt252::new(5)), + &MaybeRelocatable::from(Felt252::from(5)), ) .unwrap(); vm.segments.compute_effective_sizes(); @@ -2699,19 +2698,19 @@ mod tests { assert_eq!(cairo_runner.relocated_memory[0], None); assert_eq!( cairo_runner.relocated_memory[1], - Some(Felt252::new(4613515612218425347_i64)) + Some(Felt252::from(4613515612218425347_i64)) ); - assert_eq!(cairo_runner.relocated_memory[2], Some(Felt252::new(5))); + assert_eq!(cairo_runner.relocated_memory[2], Some(Felt252::from(5))); assert_eq!( cairo_runner.relocated_memory[3], - Some(Felt252::new(2345108766317314046_i64)) + Some(Felt252::from(2345108766317314046_i64)) ); - assert_eq!(cairo_runner.relocated_memory[4], Some(Felt252::new(10))); - assert_eq!(cairo_runner.relocated_memory[5], Some(Felt252::new(10))); + assert_eq!(cairo_runner.relocated_memory[4], Some(Felt252::from(10))); + assert_eq!(cairo_runner.relocated_memory[5], Some(Felt252::from(10))); assert_eq!(cairo_runner.relocated_memory[6], None); assert_eq!(cairo_runner.relocated_memory[7], None); assert_eq!(cairo_runner.relocated_memory[8], None); - assert_eq!(cairo_runner.relocated_memory[9], Some(Felt252::new(5))); + assert_eq!(cairo_runner.relocated_memory[9], Some(Felt252::from(5))); } #[test] @@ -2805,72 +2804,72 @@ mod tests { assert_eq!(cairo_runner.relocated_memory[0], None); assert_eq!( cairo_runner.relocated_memory[1], - Some(Felt252::new(4612671182993129469_i64)) + Some(Felt252::from(4612671182993129469_u64)) ); assert_eq!( cairo_runner.relocated_memory[2], - Some(Felt252::new(5198983563776393216_i64)) + Some(Felt252::from(5198983563776393216_u64)) ); - assert_eq!(cairo_runner.relocated_memory[3], Some(Felt252::one())); + assert_eq!(cairo_runner.relocated_memory[3], Some(Felt252::ONE)); assert_eq!( cairo_runner.relocated_memory[4], - Some(Felt252::new(2345108766317314046_i64)) + Some(Felt252::from(2345108766317314046_u64)) ); assert_eq!( cairo_runner.relocated_memory[5], - Some(Felt252::new(5191102247248822272_i64)) + Some(Felt252::from(5191102247248822272_u64)) ); assert_eq!( cairo_runner.relocated_memory[6], - Some(Felt252::new(5189976364521848832_i64)) + Some(Felt252::from(5189976364521848832_u64)) ); - assert_eq!(cairo_runner.relocated_memory[7], Some(Felt252::one())); + assert_eq!(cairo_runner.relocated_memory[7], Some(Felt252::ONE)); assert_eq!( cairo_runner.relocated_memory[8], - Some(Felt252::new(1226245742482522112_i64)) + Some(Felt252::from(1226245742482522112_u64)) ); assert_eq!( cairo_runner.relocated_memory[9], - Some(felt_str!( - "3618502788666131213697322783095070105623107215331596699973092056135872020474" + Some(felt_hex!( + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffffa" )) ); assert_eq!( cairo_runner.relocated_memory[10], - Some(Felt252::new(5189976364521848832_i64)) + Some(Felt252::from(5189976364521848832_u64)) ); - assert_eq!(cairo_runner.relocated_memory[11], Some(Felt252::new(17))); + assert_eq!(cairo_runner.relocated_memory[11], Some(Felt252::from(17))); assert_eq!( cairo_runner.relocated_memory[12], - Some(Felt252::new(1226245742482522112_i64)) + Some(Felt252::from(1226245742482522112_u64)) ); assert_eq!( cairo_runner.relocated_memory[13], - Some(felt_str!( - "3618502788666131213697322783095070105623107215331596699973092056135872020470" + Some(felt_hex!( + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff6" )) ); assert_eq!( cairo_runner.relocated_memory[14], - Some(Felt252::new(2345108766317314046_i64)) + Some(Felt252::from(2345108766317314046_u64)) ); assert_eq!( cairo_runner.relocated_memory[15], - Some(Felt252::new(27_i32)) - ); - assert_eq!(cairo_runner.relocated_memory[16], Some(Felt252::new(29))); - assert_eq!(cairo_runner.relocated_memory[17], Some(Felt252::new(29))); - assert_eq!(cairo_runner.relocated_memory[18], Some(Felt252::new(27))); - assert_eq!(cairo_runner.relocated_memory[19], Some(Felt252::one())); - assert_eq!(cairo_runner.relocated_memory[20], Some(Felt252::new(18))); - assert_eq!(cairo_runner.relocated_memory[21], Some(Felt252::new(10))); - assert_eq!(cairo_runner.relocated_memory[22], Some(Felt252::new(28))); - assert_eq!(cairo_runner.relocated_memory[23], Some(Felt252::new(17))); - assert_eq!(cairo_runner.relocated_memory[24], Some(Felt252::new(18))); - assert_eq!(cairo_runner.relocated_memory[25], Some(Felt252::new(14))); - assert_eq!(cairo_runner.relocated_memory[26], Some(Felt252::new(29))); - assert_eq!(cairo_runner.relocated_memory[27], Some(Felt252::one())); - assert_eq!(cairo_runner.relocated_memory[28], Some(Felt252::new(17))); + Some(Felt252::from(27_u64)) + ); + assert_eq!(cairo_runner.relocated_memory[16], Some(Felt252::from(29))); + assert_eq!(cairo_runner.relocated_memory[17], Some(Felt252::from(29))); + assert_eq!(cairo_runner.relocated_memory[18], Some(Felt252::from(27))); + assert_eq!(cairo_runner.relocated_memory[19], Some(Felt252::ONE)); + assert_eq!(cairo_runner.relocated_memory[20], Some(Felt252::from(18))); + assert_eq!(cairo_runner.relocated_memory[21], Some(Felt252::from(10))); + assert_eq!(cairo_runner.relocated_memory[22], Some(Felt252::from(28))); + assert_eq!(cairo_runner.relocated_memory[23], Some(Felt252::from(17))); + assert_eq!(cairo_runner.relocated_memory[24], Some(Felt252::from(18))); + assert_eq!(cairo_runner.relocated_memory[25], Some(Felt252::from(14))); + assert_eq!(cairo_runner.relocated_memory[26], Some(Felt252::from(29))); + assert_eq!(cairo_runner.relocated_memory[27], Some(Felt252::ONE)); + assert_eq!(cairo_runner.relocated_memory[28], Some(Felt252::from(17))); } #[test] @@ -3529,8 +3528,8 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn get_constants() { let program_constants = HashMap::from([ - ("MAX".to_string(), Felt252::new(300)), - ("MIN".to_string(), Felt252::new(20)), + ("MAX".to_string(), Felt252::from(300)), + ("MIN".to_string(), Felt252::from(20)), ]); let program = program!(constants = program_constants.clone(),); let cairo_runner = cairo_runner!(program); @@ -4038,9 +4037,9 @@ mod tests { vm.segments.memory.data = vec![ vec![ - Some(MemoryCell::new(Felt252::new(0x8000_8023_8012u64).into())), - Some(MemoryCell::new(Felt252::new(0xBFFF_8000_0620u64).into())), - Some(MemoryCell::new(Felt252::new(0x8FFF_8000_0750u64).into())), + Some(MemoryCell::new(Felt252::from(0x8000_8023_8012u64).into())), + Some(MemoryCell::new(Felt252::from(0xBFFF_8000_0620u64).into())), + Some(MemoryCell::new(Felt252::from(0x8FFF_8000_0750u64).into())), ], vec![Some(MemoryCell::new((0isize, 0usize).into())); 128 * 1024], ]; @@ -4163,7 +4162,7 @@ mod tests { } cairo_runner.program_base = Some(relocatable!(0, 0)); cairo_runner.execution_base = Some(relocatable!(1, 0)); - let return_fp = Felt252::new(9_i32).into(); + let return_fp = Felt252::from(9_i32).into(); cairo_runner .initialize_function_entrypoint(&mut vm, 0, vec![], return_fp) .unwrap(); diff --git a/vm/src/vm/security.rs b/vm/src/vm/security.rs index 7ddbe29d1f..a18e43421a 100644 --- a/vm/src/vm/security.rs +++ b/vm/src/vm/security.rs @@ -91,10 +91,9 @@ mod test { use crate::types::relocatable::Relocatable; + use crate::Felt252; use crate::{relocatable, types::program::Program, utils::test_utils::*}; use assert_matches::assert_matches; - use felt::Felt252; - use num_traits::Zero; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; @@ -207,10 +206,10 @@ mod test { fn verify_secure_runner_success() { let program = program!( data = vec![ - Felt252::zero().into(), - Felt252::zero().into(), - Felt252::zero().into(), - Felt252::zero().into(), + Felt252::ZERO.into(), + Felt252::ZERO.into(), + Felt252::ZERO.into(), + Felt252::ZERO.into(), ], main = Some(0), ); @@ -235,10 +234,10 @@ mod test { fn verify_secure_runner_temporary_memory_properly_relocated() { let program = program!( data = vec![ - Felt252::zero().into(), - Felt252::zero().into(), - Felt252::zero().into(), - Felt252::zero().into(), + Felt252::ZERO.into(), + Felt252::ZERO.into(), + Felt252::ZERO.into(), + Felt252::ZERO.into(), ], main = Some(0), ); @@ -263,10 +262,10 @@ mod test { fn verify_secure_runner_temporary_memory_not_fully_relocated() { let program = program!( data = vec![ - Felt252::zero().into(), - Felt252::zero().into(), - Felt252::zero().into(), - Felt252::zero().into(), + Felt252::ZERO.into(), + Felt252::ZERO.into(), + Felt252::ZERO.into(), + Felt252::ZERO.into(), ], main = Some(0), ); diff --git a/vm/src/vm/vm_core.rs b/vm/src/vm/vm_core.rs index 2f098adfeb..98b0c32904 100644 --- a/vm/src/vm/vm_core.rs +++ b/vm/src/vm/vm_core.rs @@ -1,3 +1,4 @@ +use crate::math_utils::signed_felt; use crate::stdlib::{any::Any, borrow::Cow, collections::HashMap, prelude::*}; #[cfg(feature = "extensive_hints")] use crate::types::program::HintRange; @@ -24,10 +25,10 @@ use crate::{ }, }; +use crate::Felt252; use core::cmp::Ordering; #[cfg(feature = "extensive_hints")] use core::num::NonZeroUsize; -use felt::Felt252; use num_traits::{ToPrimitive, Zero}; use super::errors::runner_errors::RunnerError; @@ -135,7 +136,7 @@ impl VirtualMachine { MaybeRelocatable::RelocatableValue(ref rel) => rel.offset, MaybeRelocatable::Int(ref num) => num .to_usize() - .ok_or_else(|| MathError::Felt252ToUsizeConversion(Box::new(num.clone())))?, + .ok_or_else(|| MathError::Felt252ToUsizeConversion(Box::new(*num)))?, }, FpUpdate::Regular => return Ok(()), }; @@ -232,9 +233,12 @@ impl VirtualMachine { Res::Mul, Some(MaybeRelocatable::Int(num_dst)), Some(MaybeRelocatable::Int(num_op1)), - ) if !num_op1.is_zero() => { - Ok((Some(MaybeRelocatable::Int(num_dst / num_op1)), dst.cloned())) - } + ) if !num_op1.is_zero() => Ok(( + Some(MaybeRelocatable::Int(num_dst.field_div( + &num_op1.try_into().map_err(|_| MathError::DividedByZero)?, + ))), + dst.cloned(), + )), _ => Ok((None, None)), }, _ => Ok((None, None)), @@ -264,7 +268,12 @@ impl VirtualMachine { Some(MaybeRelocatable::Int(num_dst)), Some(MaybeRelocatable::Int(num_op0)), ) if !num_op0.is_zero() => { - return Ok((Some(MaybeRelocatable::Int(num_dst / num_op0)), dst.cloned())) + return Ok(( + Some(MaybeRelocatable::Int(num_dst.field_div( + &num_op0.try_into().map_err(|_| MathError::DividedByZero)?, + ))), + dst.cloned(), + )) } _ => (), }, @@ -1012,7 +1021,7 @@ impl VirtualMachine { .get(&Relocatable::from((segment_index as isize, i))) { Some(val) => match val.as_ref() { - MaybeRelocatable::Int(num) => format!("{}", num.to_signed_felt()), + MaybeRelocatable::Int(num) => format!("{}", signed_felt(*num)), MaybeRelocatable::RelocatableValue(rel) => format!("{}", rel), }, _ => "".to_string(), @@ -1170,6 +1179,7 @@ impl VirtualMachineBuilder { #[cfg(test)] mod tests { use super::*; + use crate::felt_hex; use crate::stdlib::collections::HashMap; use crate::types::program::Program; use crate::vm::runners::builtin_runner::{ @@ -1200,8 +1210,6 @@ mod tests { }; use assert_matches::assert_matches; - use felt::felt_str; - #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; @@ -1223,10 +1231,10 @@ mod tests { }; let operands = Operands { - dst: MaybeRelocatable::Int(Felt252::new(11)), - res: Some(MaybeRelocatable::Int(Felt252::new(8))), - op0: MaybeRelocatable::Int(Felt252::new(9)), - op1: MaybeRelocatable::Int(Felt252::new(10)), + dst: MaybeRelocatable::Int(Felt252::from(11)), + res: Some(MaybeRelocatable::Int(Felt252::from(8))), + op0: MaybeRelocatable::Int(Felt252::from(9)), + op1: MaybeRelocatable::Int(Felt252::from(10)), }; let mut vm = vm!(); @@ -1289,10 +1297,10 @@ mod tests { }; let operands = Operands { - dst: MaybeRelocatable::Int(Felt252::new(11)), - res: Some(MaybeRelocatable::Int(Felt252::new(8))), - op0: MaybeRelocatable::Int(Felt252::new(9)), - op1: MaybeRelocatable::Int(Felt252::new(10)), + dst: MaybeRelocatable::Int(Felt252::from(11_u64)), + res: Some(MaybeRelocatable::Int(Felt252::from(8_u64))), + op0: MaybeRelocatable::Int(Felt252::from(9_u64)), + op1: MaybeRelocatable::Int(Felt252::from(10_u64)), }; let mut vm = vm!(); @@ -1322,10 +1330,10 @@ mod tests { }; let operands = Operands { - dst: MaybeRelocatable::Int(Felt252::new(11)), - res: Some(MaybeRelocatable::Int(Felt252::new(8))), - op0: MaybeRelocatable::Int(Felt252::new(9)), - op1: MaybeRelocatable::Int(Felt252::new(10)), + dst: MaybeRelocatable::Int(Felt252::from(11)), + res: Some(MaybeRelocatable::Int(Felt252::from(8))), + op0: MaybeRelocatable::Int(Felt252::from(9)), + op1: MaybeRelocatable::Int(Felt252::from(10)), }; let mut vm = vm!(); @@ -1356,10 +1364,10 @@ mod tests { }; let operands = Operands { - dst: MaybeRelocatable::Int(Felt252::new(11)), - res: Some(MaybeRelocatable::Int(Felt252::new(8))), - op0: MaybeRelocatable::Int(Felt252::new(9)), - op1: MaybeRelocatable::Int(Felt252::new(10)), + dst: MaybeRelocatable::Int(Felt252::from(11)), + res: Some(MaybeRelocatable::Int(Felt252::from(8))), + op0: MaybeRelocatable::Int(Felt252::from(9)), + op1: MaybeRelocatable::Int(Felt252::from(10)), }; let mut vm = VirtualMachine::new(false); @@ -1392,10 +1400,10 @@ mod tests { }; let operands = Operands { - dst: MaybeRelocatable::Int(Felt252::new(11)), + dst: MaybeRelocatable::Int(Felt252::from(11)), res: None, - op0: MaybeRelocatable::Int(Felt252::new(9)), - op1: MaybeRelocatable::Int(Felt252::new(10)), + op0: MaybeRelocatable::Int(Felt252::from(9)), + op1: MaybeRelocatable::Int(Felt252::from(10)), }; let mut vm = vm!(); @@ -1427,10 +1435,10 @@ mod tests { }; let operands = Operands { - dst: MaybeRelocatable::Int(Felt252::new(11)), - res: Some(MaybeRelocatable::Int(Felt252::new(8))), - op0: MaybeRelocatable::Int(Felt252::new(9)), - op1: MaybeRelocatable::Int(Felt252::new(10)), + dst: MaybeRelocatable::Int(Felt252::from(11)), + res: Some(MaybeRelocatable::Int(Felt252::from(8))), + op0: MaybeRelocatable::Int(Felt252::from(9)), + op1: MaybeRelocatable::Int(Felt252::from(10)), }; let mut vm = vm!(); @@ -1463,10 +1471,10 @@ mod tests { }; let operands = Operands { - dst: MaybeRelocatable::Int(Felt252::new(11)), - res: Some(MaybeRelocatable::Int(Felt252::new(8))), - op0: MaybeRelocatable::Int(Felt252::new(9)), - op1: MaybeRelocatable::Int(Felt252::new(10)), + dst: MaybeRelocatable::Int(Felt252::from(11_u64)), + res: Some(MaybeRelocatable::Int(Felt252::from(8_u64))), + op0: MaybeRelocatable::Int(Felt252::from(9_u64)), + op1: MaybeRelocatable::Int(Felt252::from(10_u64)), }; let mut vm = vm!(); @@ -1499,10 +1507,10 @@ mod tests { }; let operands = Operands { - dst: MaybeRelocatable::Int(Felt252::new(11)), - res: Some(MaybeRelocatable::Int(Felt252::new(8))), - op0: MaybeRelocatable::Int(Felt252::new(9)), - op1: MaybeRelocatable::Int(Felt252::new(10)), + dst: MaybeRelocatable::Int(Felt252::from(11)), + res: Some(MaybeRelocatable::Int(Felt252::from(8))), + op0: MaybeRelocatable::Int(Felt252::from(9)), + op1: MaybeRelocatable::Int(Felt252::from(10)), }; let mut vm = vm!(); @@ -1535,10 +1543,10 @@ mod tests { }; let operands = Operands { - dst: MaybeRelocatable::Int(Felt252::new(11)), - res: Some(MaybeRelocatable::Int(Felt252::new(8))), - op0: MaybeRelocatable::Int(Felt252::new(9)), - op1: MaybeRelocatable::Int(Felt252::new(10)), + dst: MaybeRelocatable::Int(Felt252::from(11)), + res: Some(MaybeRelocatable::Int(Felt252::from(8))), + op0: MaybeRelocatable::Int(Felt252::from(9)), + op1: MaybeRelocatable::Int(Felt252::from(10)), }; let mut vm = vm!(); @@ -1568,10 +1576,10 @@ mod tests { }; let operands = Operands { - dst: MaybeRelocatable::Int(Felt252::new(11)), - res: Some(MaybeRelocatable::Int(Felt252::new(8))), - op0: MaybeRelocatable::Int(Felt252::new(9)), - op1: MaybeRelocatable::Int(Felt252::new(10)), + dst: MaybeRelocatable::Int(Felt252::from(11)), + res: Some(MaybeRelocatable::Int(Felt252::from(8))), + op0: MaybeRelocatable::Int(Felt252::from(9)), + op1: MaybeRelocatable::Int(Felt252::from(10)), }; let mut vm = vm!(); @@ -1603,8 +1611,8 @@ mod tests { let operands = Operands { dst: mayberelocatable!(1, 11), res: Some(mayberelocatable!(0, 8)), - op0: MaybeRelocatable::Int(Felt252::new(9)), - op1: MaybeRelocatable::Int(Felt252::new(10)), + op0: MaybeRelocatable::Int(Felt252::from(9)), + op1: MaybeRelocatable::Int(Felt252::from(10)), }; let mut vm = vm!(); @@ -1634,10 +1642,10 @@ mod tests { }; let operands = Operands { - dst: MaybeRelocatable::Int(Felt252::new(11)), + dst: MaybeRelocatable::Int(Felt252::from(11)), res: None, - op0: MaybeRelocatable::Int(Felt252::new(9)), - op1: MaybeRelocatable::Int(Felt252::new(10)), + op0: MaybeRelocatable::Int(Felt252::from(9)), + op1: MaybeRelocatable::Int(Felt252::from(10)), }; let mut vm = vm!(); @@ -1669,10 +1677,10 @@ mod tests { }; let operands = Operands { - dst: MaybeRelocatable::Int(Felt252::new(11)), - res: Some(MaybeRelocatable::Int(Felt252::new(8))), - op0: MaybeRelocatable::Int(Felt252::new(9)), - op1: MaybeRelocatable::Int(Felt252::new(10)), + dst: MaybeRelocatable::Int(Felt252::from(11)), + res: Some(MaybeRelocatable::Int(Felt252::from(8))), + op0: MaybeRelocatable::Int(Felt252::from(9)), + op1: MaybeRelocatable::Int(Felt252::from(10)), }; let mut vm = vm!(); @@ -1703,10 +1711,10 @@ mod tests { }; let operands = Operands { - dst: MaybeRelocatable::Int(Felt252::new(11)), + dst: MaybeRelocatable::Int(Felt252::from(11)), res: None, - op0: MaybeRelocatable::Int(Felt252::new(9)), - op1: MaybeRelocatable::Int(Felt252::new(10)), + op0: MaybeRelocatable::Int(Felt252::from(9)), + op1: MaybeRelocatable::Int(Felt252::from(10)), }; let mut vm = vm!(); @@ -1735,10 +1743,10 @@ mod tests { }; let operands = Operands { - dst: MaybeRelocatable::Int(Felt252::new(11)), + dst: MaybeRelocatable::Int(Felt252::from(11)), res: Some(MaybeRelocatable::from((1, 4))), - op0: MaybeRelocatable::Int(Felt252::new(9)), - op1: MaybeRelocatable::Int(Felt252::new(10)), + op0: MaybeRelocatable::Int(Felt252::from(9)), + op1: MaybeRelocatable::Int(Felt252::from(10)), }; let mut vm = vm!(); @@ -1766,10 +1774,10 @@ mod tests { }; let operands = Operands { - dst: MaybeRelocatable::Int(Felt252::new(0)), - res: Some(MaybeRelocatable::Int(Felt252::new(0))), - op0: MaybeRelocatable::Int(Felt252::new(9)), - op1: MaybeRelocatable::Int(Felt252::new(10)), + dst: MaybeRelocatable::Int(Felt252::from(0)), + res: Some(MaybeRelocatable::Int(Felt252::from(0))), + op0: MaybeRelocatable::Int(Felt252::from(9)), + op1: MaybeRelocatable::Int(Felt252::from(10)), }; let mut vm = vm!(); @@ -1799,10 +1807,10 @@ mod tests { }; let operands = Operands { - dst: MaybeRelocatable::Int(Felt252::new(11)), - res: Some(MaybeRelocatable::Int(Felt252::new(8))), - op0: MaybeRelocatable::Int(Felt252::new(9)), - op1: MaybeRelocatable::Int(Felt252::new(10)), + dst: MaybeRelocatable::Int(Felt252::from(11)), + res: Some(MaybeRelocatable::Int(Felt252::from(8))), + op0: MaybeRelocatable::Int(Felt252::from(9)), + op1: MaybeRelocatable::Int(Felt252::from(10)), }; let mut vm = vm!(); @@ -1832,10 +1840,10 @@ mod tests { }; let operands = Operands { - dst: MaybeRelocatable::Int(Felt252::new(11)), - res: Some(MaybeRelocatable::Int(Felt252::new(8))), - op0: MaybeRelocatable::Int(Felt252::new(9)), - op1: MaybeRelocatable::Int(Felt252::new(10)), + dst: MaybeRelocatable::Int(Felt252::from(11)), + res: Some(MaybeRelocatable::Int(Felt252::from(8))), + op0: MaybeRelocatable::Int(Felt252::from(9)), + op1: MaybeRelocatable::Int(Felt252::from(10)), }; let mut vm = vm!(); @@ -1871,9 +1879,9 @@ mod tests { let operands = Operands { dst: MaybeRelocatable::from((1, 11)), - res: Some(MaybeRelocatable::Int(Felt252::new(8))), - op0: MaybeRelocatable::Int(Felt252::new(9)), - op1: MaybeRelocatable::Int(Felt252::new(10)), + res: Some(MaybeRelocatable::Int(Felt252::from(8))), + op0: MaybeRelocatable::Int(Felt252::from(9)), + op1: MaybeRelocatable::Int(Felt252::from(10)), }; let mut vm = vm!(); @@ -1891,7 +1899,7 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn is_zero_int_value() { - let value = MaybeRelocatable::Int(Felt252::new(1)); + let value = MaybeRelocatable::Int(Felt252::from(1)); assert!(!VirtualMachine::is_zero(&value)); } @@ -1949,16 +1957,16 @@ mod tests { let vm = vm!(); - let dst = MaybeRelocatable::Int(Felt252::new(3)); - let op1 = MaybeRelocatable::Int(Felt252::new(2)); + let dst = MaybeRelocatable::Int(Felt252::from(3)); + let op1 = MaybeRelocatable::Int(Felt252::from(2)); assert_matches!( vm.deduce_op0(&instruction, Some(&dst), Some(&op1)), Ok::<(Option, Option), VirtualMachineError>(( x, y - )) if x == Some(MaybeRelocatable::Int(Felt252::new(1))) && - y == Some(MaybeRelocatable::Int(Felt252::new(3))) + )) if x == Some(MaybeRelocatable::Int(Felt252::from(1))) && + y == Some(MaybeRelocatable::Int(Felt252::from(3))) ); } @@ -2008,16 +2016,16 @@ mod tests { let vm = vm!(); - let dst = MaybeRelocatable::Int(Felt252::new(4)); - let op1 = MaybeRelocatable::Int(Felt252::new(2)); + let dst = MaybeRelocatable::Int(Felt252::from(4)); + let op1 = MaybeRelocatable::Int(Felt252::from(2)); assert_matches!( vm.deduce_op0(&instruction, Some(&dst), Some(&op1)), Ok::<(Option, Option), VirtualMachineError>(( Some(x), Some(y) - )) if x == MaybeRelocatable::Int(Felt252::new(2)) && - y == MaybeRelocatable::Int(Felt252::new(4)) + )) if x == MaybeRelocatable::Int(Felt252::from(2)) && + y == MaybeRelocatable::Int(Felt252::from(4)) ); } @@ -2040,8 +2048,8 @@ mod tests { let vm = vm!(); - let dst = MaybeRelocatable::Int(Felt252::new(4)); - let op1 = MaybeRelocatable::Int(Felt252::new(0)); + let dst = MaybeRelocatable::Int(Felt252::from(4)); + let op1 = MaybeRelocatable::Int(Felt252::from(0)); assert_matches!( vm.deduce_op0(&instruction, Some(&dst), Some(&op1)), Ok::<(Option, Option), VirtualMachineError>(( @@ -2069,8 +2077,8 @@ mod tests { let vm = vm!(); - let dst = MaybeRelocatable::Int(Felt252::new(4)); - let op1 = MaybeRelocatable::Int(Felt252::new(0)); + let dst = MaybeRelocatable::Int(Felt252::from(4)); + let op1 = MaybeRelocatable::Int(Felt252::from(0)); assert_matches!( vm.deduce_op0(&instruction, Some(&dst), Some(&op1)), Ok::<(Option, Option), VirtualMachineError>(( @@ -2098,8 +2106,8 @@ mod tests { let vm = vm!(); - let dst = MaybeRelocatable::Int(Felt252::new(4)); - let op1 = MaybeRelocatable::Int(Felt252::new(0)); + let dst = MaybeRelocatable::Int(Felt252::from(4)); + let op1 = MaybeRelocatable::Int(Felt252::from(0)); assert_matches!( vm.deduce_op0(&instruction, Some(&dst), Some(&op1)), @@ -2155,15 +2163,15 @@ mod tests { let vm = vm!(); - let dst = MaybeRelocatable::Int(Felt252::new(3)); - let op0 = MaybeRelocatable::Int(Felt252::new(2)); + let dst = MaybeRelocatable::Int(Felt252::from(3)); + let op0 = MaybeRelocatable::Int(Felt252::from(2)); assert_matches!( vm.deduce_op1(&instruction, Some(&dst), Some(op0)), Ok::<(Option, Option), VirtualMachineError>(( x, y - )) if x == Some(MaybeRelocatable::Int(Felt252::new(1))) && - y == Some(MaybeRelocatable::Int(Felt252::new(3))) + )) if x == Some(MaybeRelocatable::Int(Felt252::from(1))) && + y == Some(MaybeRelocatable::Int(Felt252::from(3))) ); } @@ -2212,15 +2220,15 @@ mod tests { let vm = vm!(); - let dst = MaybeRelocatable::Int(Felt252::new(4)); - let op0 = MaybeRelocatable::Int(Felt252::new(2)); + let dst = MaybeRelocatable::Int(Felt252::from(4)); + let op0 = MaybeRelocatable::Int(Felt252::from(2)); assert_matches!( vm.deduce_op1(&instruction, Some(&dst), Some(op0)), Ok::<(Option, Option), VirtualMachineError>(( x, y - )) if x == Some(MaybeRelocatable::Int(Felt252::new(2))) && - y == Some(MaybeRelocatable::Int(Felt252::new(4))) + )) if x == Some(MaybeRelocatable::Int(Felt252::from(2))) && + y == Some(MaybeRelocatable::Int(Felt252::from(4))) ); } @@ -2243,8 +2251,8 @@ mod tests { let vm = vm!(); - let dst = MaybeRelocatable::Int(Felt252::new(4)); - let op0 = MaybeRelocatable::Int(Felt252::new(0)); + let dst = MaybeRelocatable::Int(Felt252::from(4)); + let op0 = MaybeRelocatable::Int(Felt252::from(0)); assert_matches!( vm.deduce_op1(&instruction, Some(&dst), Some(op0)), Ok::<(Option, Option), VirtualMachineError>(( @@ -2272,7 +2280,7 @@ mod tests { let vm = vm!(); - let op0 = MaybeRelocatable::Int(Felt252::new(0)); + let op0 = MaybeRelocatable::Int(Felt252::from(0)); assert_matches!( vm.deduce_op1(&instruction, None, Some(op0)), Ok::<(Option, Option), VirtualMachineError>(( @@ -2300,14 +2308,14 @@ mod tests { let vm = vm!(); - let dst = MaybeRelocatable::Int(Felt252::new(7)); + let dst = MaybeRelocatable::Int(Felt252::from(7)); assert_matches!( vm.deduce_op1(&instruction, Some(&dst), None), Ok::<(Option, Option), VirtualMachineError>(( x, y - )) if x == Some(MaybeRelocatable::Int(Felt252::new(7))) && - y == Some(MaybeRelocatable::Int(Felt252::new(7))) + )) if x == Some(MaybeRelocatable::Int(Felt252::from(7))) && + y == Some(MaybeRelocatable::Int(Felt252::from(7))) ); } @@ -2330,13 +2338,13 @@ mod tests { let vm = vm!(); - let op1 = MaybeRelocatable::Int(Felt252::new(7)); - let op0 = MaybeRelocatable::Int(Felt252::new(9)); + let op1 = MaybeRelocatable::Int(Felt252::from(7)); + let op0 = MaybeRelocatable::Int(Felt252::from(9)); assert_matches!( vm.compute_res(&instruction, &op0, &op1), Ok::, VirtualMachineError>(Some(MaybeRelocatable::Int( x - ))) if x == Felt252::new(7) + ))) if x == Felt252::from(7) ); } @@ -2359,13 +2367,13 @@ mod tests { let vm = vm!(); - let op1 = MaybeRelocatable::Int(Felt252::new(7)); - let op0 = MaybeRelocatable::Int(Felt252::new(9)); + let op1 = MaybeRelocatable::Int(Felt252::from(7)); + let op0 = MaybeRelocatable::Int(Felt252::from(9)); assert_matches!( vm.compute_res(&instruction, &op0, &op1), Ok::, VirtualMachineError>(Some(MaybeRelocatable::Int( x - ))) if x == Felt252::new(16) + ))) if x == Felt252::from(16) ); } @@ -2388,13 +2396,13 @@ mod tests { let vm = vm!(); - let op1 = MaybeRelocatable::Int(Felt252::new(7)); - let op0 = MaybeRelocatable::Int(Felt252::new(9)); + let op1 = MaybeRelocatable::Int(Felt252::from(7)); + let op0 = MaybeRelocatable::Int(Felt252::from(9)); assert_matches!( vm.compute_res(&instruction, &op0, &op1), Ok::, VirtualMachineError>(Some(MaybeRelocatable::Int( x - ))) if x == Felt252::new(63) + ))) if x == Felt252::from(63) ); } @@ -2444,8 +2452,8 @@ mod tests { let vm = vm!(); - let op1 = MaybeRelocatable::Int(Felt252::new(7)); - let op0 = MaybeRelocatable::Int(Felt252::new(9)); + let op1 = MaybeRelocatable::Int(Felt252::from(7)); + let op0 = MaybeRelocatable::Int(Felt252::from(9)); assert_matches!( vm.compute_res(&instruction, &op0, &op1), Ok::, VirtualMachineError>(None) @@ -2471,9 +2479,9 @@ mod tests { let vm = vm!(); - let res = MaybeRelocatable::Int(Felt252::new(7)); + let res = MaybeRelocatable::Int(Felt252::from(7)); assert_eq!( - MaybeRelocatable::Int(Felt252::new(7)), + MaybeRelocatable::Int(Felt252::from(7)), vm.deduce_dst(&instruction, &Some(res)).unwrap() ); } @@ -2571,11 +2579,11 @@ mod tests { vm.segments.memory.data.push(Vec::new()); let dst_addr = Relocatable::from((1, 0)); - let dst_addr_value = MaybeRelocatable::Int(Felt252::new(5)); + let dst_addr_value = MaybeRelocatable::Int(Felt252::from(5)); let op0_addr = Relocatable::from((1, 1)); - let op0_addr_value = MaybeRelocatable::Int(Felt252::new(2)); + let op0_addr_value = MaybeRelocatable::Int(Felt252::from(2)); let op1_addr = Relocatable::from((1, 2)); - let op1_addr_value = MaybeRelocatable::Int(Felt252::new(3)); + let op1_addr_value = MaybeRelocatable::Int(Felt252::from(3)); vm.segments .memory .insert(dst_addr, &dst_addr_value) @@ -2764,10 +2772,10 @@ mod tests { }; let operands = Operands { - dst: MaybeRelocatable::Int(Felt252::new(8)), + dst: MaybeRelocatable::Int(Felt252::from(8)), res: None, - op0: MaybeRelocatable::Int(Felt252::new(9)), - op1: MaybeRelocatable::Int(Felt252::new(10)), + op0: MaybeRelocatable::Int(Felt252::from(9)), + op1: MaybeRelocatable::Int(Felt252::from(10)), }; let vm = vm!(); @@ -2794,10 +2802,10 @@ mod tests { }; let operands = Operands { - dst: MaybeRelocatable::Int(Felt252::new(9_i32)), - res: Some(MaybeRelocatable::Int(Felt252::new(8_i32))), - op0: MaybeRelocatable::Int(Felt252::new(9_i32)), - op1: MaybeRelocatable::Int(Felt252::new(10_i32)), + dst: MaybeRelocatable::Int(Felt252::from(9_i32)), + res: Some(MaybeRelocatable::Int(Felt252::from(8_i32))), + op0: MaybeRelocatable::Int(Felt252::from(9_i32)), + op1: MaybeRelocatable::Int(Felt252::from(10_i32)), }; let vm = vm!(); @@ -2805,8 +2813,8 @@ mod tests { assert_matches!( vm.opcode_assertions(&instruction, &operands), Err(VirtualMachineError::DiffAssertValues(bx)) - if *bx == (MaybeRelocatable::Int(Felt252::new(9_i32)), - MaybeRelocatable::Int(Felt252::new(8_i32))) + if *bx == (MaybeRelocatable::Int(Felt252::from(9_i32)), + MaybeRelocatable::Int(Felt252::from(8_i32))) ); } @@ -2830,8 +2838,8 @@ mod tests { let operands = Operands { dst: MaybeRelocatable::from((1, 1)), res: Some(MaybeRelocatable::from((1, 2))), - op0: MaybeRelocatable::Int(Felt252::new(9_i32)), - op1: MaybeRelocatable::Int(Felt252::new(10_i32)), + op0: MaybeRelocatable::Int(Felt252::from(9_i32)), + op1: MaybeRelocatable::Int(Felt252::from(10_i32)), }; let vm = vm!(); @@ -3146,7 +3154,7 @@ mod tests { .get(&vm.run_context.get_ap()) .unwrap() .as_ref(), - &MaybeRelocatable::Int(Felt252::new(0x4)), + &MaybeRelocatable::Int(Felt252::from(0x4)), ); let mut hint_processor = BuiltinHintProcessor::new_empty(); assert_matches!( @@ -3169,7 +3177,7 @@ mod tests { .get(&vm.run_context.get_ap()) .unwrap() .as_ref(), - &MaybeRelocatable::Int(Felt252::new(0x5)) + &MaybeRelocatable::Int(Felt252::from(0x5)) ); let mut hint_processor = BuiltinHintProcessor::new_empty(); @@ -3193,7 +3201,7 @@ mod tests { .get(&vm.run_context.get_ap()) .unwrap() .as_ref(), - &MaybeRelocatable::Int(Felt252::new(0x14)), + &MaybeRelocatable::Int(Felt252::from(0x14)), ); } @@ -3213,8 +3221,8 @@ mod tests { vm.segments = segments![((0, 3), 32), ((0, 4), 72), ((0, 5), 0)]; assert_matches!( vm.deduce_memory_cell(Relocatable::from((0, 5))), - Ok(i) if i == Some(MaybeRelocatable::from(felt::felt_str!( - "3270867057177188607814717243084834301278723532952411121381966378910183338911" + Ok(i) if i == Some(MaybeRelocatable::from(crate::felt_hex!( + "0x73b3ec210cccbb970f80c6826fb1c40ae9f487617696234ff147451405c339f" ))) ); } @@ -3284,15 +3292,15 @@ mod tests { ]; let expected_operands = Operands { - dst: MaybeRelocatable::from(felt_str!( - "3270867057177188607814717243084834301278723532952411121381966378910183338911" + dst: MaybeRelocatable::from(crate::felt_hex!( + "0x73b3ec210cccbb970f80c6826fb1c40ae9f487617696234ff147451405c339f" )), - res: Some(MaybeRelocatable::from(felt_str!( - "3270867057177188607814717243084834301278723532952411121381966378910183338911" + res: Some(MaybeRelocatable::from(crate::felt_hex!( + "0x73b3ec210cccbb970f80c6826fb1c40ae9f487617696234ff147451405c339f" ))), op0: MaybeRelocatable::from((3, 0)), - op1: MaybeRelocatable::from(felt_str!( - "3270867057177188607814717243084834301278723532952411121381966378910183338911" + op1: MaybeRelocatable::from(crate::felt_hex!( + "0x73b3ec210cccbb970f80c6826fb1c40ae9f487617696234ff147451405c339f" )), }; let expected_operands_mem_addresses = OperandsAddresses { @@ -3314,7 +3322,7 @@ mod tests { vm.segments = segments![((0, 5), 10), ((0, 6), 12), ((0, 7), 0)]; assert_matches!( vm.deduce_memory_cell(Relocatable::from((0, 7))), - Ok(i) if i == Some(MaybeRelocatable::from(Felt252::new(8_i32))) + Ok(i) if i == Some(MaybeRelocatable::from(Felt252::from(8_i32))) ); } @@ -3369,10 +3377,10 @@ mod tests { ]; let expected_operands = Operands { - dst: MaybeRelocatable::from(Felt252::new(8_i32)), - res: Some(MaybeRelocatable::from(Felt252::new(8_i32))), + dst: MaybeRelocatable::from(Felt252::from(8_i32)), + res: Some(MaybeRelocatable::from(Felt252::from(8_i32))), op0: MaybeRelocatable::from((2, 0)), - op1: MaybeRelocatable::from(Felt252::new(8_i32)), + op1: MaybeRelocatable::from(Felt252::from(8_i32)), }; let expected_operands_mem_addresses = OperandsAddresses { dst_addr: Relocatable::from((1, 9)), @@ -3395,45 +3403,45 @@ mod tests { ( (0, 0), ( - "2962412995502985605007699495352191122971573493113767820301112397466445942584", - 10 + "0x68caa9509b7c2e90b4d92661cbf7c465471c1e8598c5f989691eef6653e0f38", + 16 ) ), ( (0, 1), ( - "214950771763870898744428659242275426967582168179217139798831865603966154129", - 10 + "0x79a8673f498531002fc549e06ff2010ffc0c191cceb7da5532acb95cdcb591", + 16 ) ), ( (0, 2), ( - "874739451078007766457464989774322083649278607533249481151382481072868806602", - 10 + "0x1ef15c18599971b7beced415a40f0c7deacfd9b0d1819e03d723d8bc943cfca", + 16 ) ), ( (0, 3), ( - "152666792071518830868575557812948353041420400780739481342941381225525861407", - 10 + "0x5668060aa49730b7be4801df46ec62de53ecd11abe43a32873000c36e8dc1f", + 16 ) ), ((0, 4), 34), ( (0, 5), ( - "2778063437308421278851140253538604815869848682781135193774472480292420096757", - 10 + "0x6245403e2fafe5df3b79ea28d050d477771bc560fc59e915b302cc9b70a92f5", + 16 ) ) ]; assert_matches!( vm.deduce_memory_cell(Relocatable::from((0, 6))), - Ok(i) if i == Some(MaybeRelocatable::from(felt_str!( - "3598390311618116577316045819420613574162151407434885460365915347732568210029" + Ok(i) if i == Some(MaybeRelocatable::from(felt_hex!( + "0x7f49de2c3a7d1671437406869edb1805ba43e1c0173b35f8c2e8fcc13c3fa6d" ))) ); } @@ -3548,15 +3556,14 @@ mod tests { ) ]; let error = vm.verify_auto_deductions(); - assert_eq!(error.as_ref().unwrap_err().to_string(), "Inconsistent auto-deduction for builtin ec_op_builtin, expected 2739017437753868763038285897969098325279422804143820990343394856167768859289, got Some(Int(2778063437308421278851140253538604815869848682781135193774472480292420096757))"); assert_matches!( error, Err(VirtualMachineError::InconsistentAutoDeduction(bx)) if *bx == (EC_OP_BUILTIN_NAME, - MaybeRelocatable::Int(felt_str!( + MaybeRelocatable::Int(crate::felt_str!( "2739017437753868763038285897969098325279422804143820990343394856167768859289" )), - Some(MaybeRelocatable::Int(felt_str!( + Some(MaybeRelocatable::Int(crate::felt_str!( "2778063437308421278851140253538604815869848682781135193774472480292420096757" )))) ); @@ -3656,10 +3663,10 @@ mod tests { vm.set_ap(4); vm.segments = segments![((1, 0), 1), ((1, 1), 2), ((1, 2), 3), ((1, 3), 4)]; let expected = vec![ - MaybeRelocatable::Int(Felt252::new(1_i32)), - MaybeRelocatable::Int(Felt252::new(2_i32)), - MaybeRelocatable::Int(Felt252::new(3_i32)), - MaybeRelocatable::Int(Felt252::new(4_i32)), + MaybeRelocatable::Int(Felt252::from(1_i32)), + MaybeRelocatable::Int(Felt252::from(2_i32)), + MaybeRelocatable::Int(Felt252::from(3_i32)), + MaybeRelocatable::Int(Felt252::from(4_i32)), ]; assert_eq!(vm.get_return_values(4).unwrap(), expected); } @@ -3815,9 +3822,9 @@ mod tests { let mut vm = vm!(); vm.segments = segments![((1, 0), 2), ((1, 1), 3), ((1, 2), 4)]; - let value1 = MaybeRelocatable::from(Felt252::new(2_i32)); - let value2 = MaybeRelocatable::from(Felt252::new(3_i32)); - let value3 = MaybeRelocatable::from(Felt252::new(4_i32)); + let value1 = MaybeRelocatable::from(Felt252::from(2_i32)); + let value2 = MaybeRelocatable::from(Felt252::from(3_i32)); + let value3 = MaybeRelocatable::from(Felt252::from(4_i32)); let expected_vec = vec![ Some(Cow::Borrowed(&value1)), @@ -3833,9 +3840,9 @@ mod tests { let mut vm = vm!(); vm.segments = segments![((1, 0), 2), ((1, 1), 3), ((1, 3), 4)]; - let value1 = MaybeRelocatable::from(Felt252::new(2_i32)); - let value2 = MaybeRelocatable::from(Felt252::new(3_i32)); - let value3 = MaybeRelocatable::from(Felt252::new(4_i32)); + let value1 = MaybeRelocatable::from(Felt252::from(2_i32)); + let value2 = MaybeRelocatable::from(Felt252::from(3_i32)); + let value3 = MaybeRelocatable::from(Felt252::from(4_i32)); let expected_vec = vec![ Some(Cow::Borrowed(&value1)), @@ -3852,9 +3859,9 @@ mod tests { let mut vm = vm!(); vm.segments = segments![((1, 0), 2), ((1, 1), 3), ((1, 2), 4)]; - let value1 = MaybeRelocatable::from(Felt252::new(2_i32)); - let value2 = MaybeRelocatable::from(Felt252::new(3_i32)); - let value3 = MaybeRelocatable::from(Felt252::new(4_i32)); + let value1 = MaybeRelocatable::from(Felt252::from(2_i32)); + let value2 = MaybeRelocatable::from(Felt252::from(3_i32)); + let value3 = MaybeRelocatable::from(Felt252::from(4_i32)); let expected_vec = vec![value1, value2, value3]; assert_eq!( @@ -3980,7 +3987,7 @@ mod tests { fn get_maybe_error() { let vm = vm!(); assert_eq!( - vm.get_maybe(&MaybeRelocatable::Int(Felt252::new(0_i32))), + vm.get_maybe(&MaybeRelocatable::Int(Felt252::from(0_i32))), None, ); } @@ -4090,7 +4097,7 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn gen_arg_bigint_prime() { let mut vm = vm!(); - let prime = felt_str!(felt::PRIME_STR[2..], 16); + let prime = felt_hex!(crate::utils::PRIME_STR); let prime_maybe = MaybeRelocatable::from(prime); assert_matches!(vm.gen_arg(&prime_maybe), Ok(x) if x == mayberelocatable!(0)); diff --git a/vm/src/vm/vm_memory/memory.rs b/vm/src/vm/vm_memory/memory.rs index c178d93cde..56d6fe0f41 100644 --- a/vm/src/vm/vm_memory/memory.rs +++ b/vm/src/vm/vm_memory/memory.rs @@ -1,6 +1,7 @@ use crate::stdlib::{borrow::Cow, collections::HashMap, fmt, prelude::*}; use crate::vm::runners::cairo_pie::CairoPieMemory; +use crate::Felt252; use crate::{ types::relocatable::{MaybeRelocatable, Relocatable}, utils::from_relocatable_to_indexes, @@ -8,7 +9,6 @@ use crate::{ }; use bitvec::prelude as bv; use core::cmp::Ordering; -use felt::Felt252; use num_traits::ToPrimitive; pub struct ValidationRule( @@ -597,11 +597,10 @@ impl Default for Memory { #[cfg(test)] mod memory_tests { - use core::ops::Shl; use super::*; use crate::{ - relocatable, + felt_hex, relocatable, types::instance_definitions::ecdsa_instance_def::EcdsaInstanceDef, utils::test_utils::*, vm::{ @@ -610,8 +609,6 @@ mod memory_tests { }, }; use assert_matches::assert_matches; - use felt::felt_str; - use num_traits::One; use crate::vm::errors::memory_errors::MemoryError; @@ -625,13 +622,13 @@ mod memory_tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn insert_and_get_succesful() { let key = Relocatable::from((0, 0)); - let val = MaybeRelocatable::from(Felt252::new(5)); + let val = MaybeRelocatable::from(Felt252::from(5_u64)); let mut memory = Memory::new(); memory.data.push(Vec::new()); memory.insert(key, &val).unwrap(); assert_eq!( memory.get(&key).unwrap().as_ref(), - &MaybeRelocatable::from(Felt252::new(5)) + &MaybeRelocatable::from(Felt252::from(5_u64)) ); } @@ -654,13 +651,15 @@ mod memory_tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn insert_value_in_temp_segment() { let key = Relocatable::from((-1, 3)); - let val = MaybeRelocatable::from(Felt252::new(8)); + let val = MaybeRelocatable::from(Felt252::from(8_u64)); let mut memory = Memory::new(); memory.temp_data.push(Vec::new()); memory.insert(key, &val).unwrap(); assert_eq!( memory.temp_data[0][3], - Some(MemoryCell::new(MaybeRelocatable::from(Felt252::new(8)))) + Some(MemoryCell::new(MaybeRelocatable::from(Felt252::from( + 8_u64 + )))) ); } @@ -668,13 +667,13 @@ mod memory_tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn insert_and_get_from_temp_segment_succesful() { let key = Relocatable::from((-1, 0)); - let val = MaybeRelocatable::from(Felt252::new(5)); + let val = MaybeRelocatable::from(Felt252::from(5_u64)); let mut memory = Memory::new(); memory.temp_data.push(Vec::new()); memory.insert(key, &val).unwrap(); assert_eq!( memory.get(&key).unwrap().as_ref(), - &MaybeRelocatable::from(Felt252::new(5)), + &MaybeRelocatable::from(Felt252::from(5_u64)), ); } @@ -714,7 +713,7 @@ mod memory_tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn insert_non_allocated_memory() { let key = Relocatable::from((0, 0)); - let val = MaybeRelocatable::from(Felt252::new(5)); + let val = MaybeRelocatable::from(Felt252::from(5_u64)); let mut memory = Memory::new(); let error = memory.insert(key, &val); assert_eq!( @@ -727,8 +726,8 @@ mod memory_tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn insert_inconsistent_memory() { let key = Relocatable::from((0, 0)); - let val_a = MaybeRelocatable::from(Felt252::new(5)); - let val_b = MaybeRelocatable::from(Felt252::new(6)); + let val_a = MaybeRelocatable::from(Felt252::from(5_u64)); + let val_b = MaybeRelocatable::from(Felt252::from(6_u64)); let mut memory = Memory::new(); memory.data.push(Vec::new()); memory @@ -748,7 +747,7 @@ mod memory_tests { fn insert_non_contiguous_element() { let key_a = Relocatable::from((0, 0)); let key_b = Relocatable::from((0, 2)); - let val = MaybeRelocatable::from(Felt252::new(5)); + let val = MaybeRelocatable::from(Felt252::from(5_u64)); let mut memory = Memory::new(); memory.data.push(Vec::new()); memory.insert(key_a, &val).unwrap(); @@ -761,7 +760,7 @@ mod memory_tests { fn insert_non_contiguous_element_memory_gaps_none() { let key_a = Relocatable::from((0, 0)); let key_b = Relocatable::from((0, 5)); - let val = MaybeRelocatable::from(Felt252::new(5)); + let val = MaybeRelocatable::from(Felt252::from(5_u64)); let mut memory = Memory::new(); memory.data.push(Vec::new()); memory.insert(key_a, &val).unwrap(); @@ -788,7 +787,7 @@ mod memory_tests { .memory .insert( Relocatable::from((0, 0)), - &MaybeRelocatable::from(Felt252::new(45)), + &MaybeRelocatable::from(Felt252::from(45_u64)), ) .unwrap(); segments.memory.validate_existing_memory().unwrap(); @@ -809,7 +808,7 @@ mod memory_tests { .memory .insert( Relocatable::from((1, 0)), - &MaybeRelocatable::from(Felt252::new(-10)), + &MaybeRelocatable::from(Felt252::from(-10)), ) .unwrap(); builtin.add_validation_rule(&mut segments.memory); @@ -817,8 +816,8 @@ mod memory_tests { assert_eq!( error, Err(MemoryError::RangeCheckNumOutOfBounds(Box::new(( - Felt252::new(-10), - Felt252::one().shl(128_u32) + Felt252::from(-10), + Felt252::TWO.pow(128_u128) )))) ); } @@ -858,12 +857,10 @@ mod memory_tests { fn validate_existing_memory_for_valid_signature() { let mut builtin = SignatureBuiltinRunner::new(&EcdsaInstanceDef::default(), true); - let signature_r = felt_str!( - "1839793652349538280924927302501143912227271479439798783640887258675143576352" - ); - let signature_s = felt_str!( - "1819432147005223164874083361865404672584671743718628757598322238853218813979" - ); + let signature_r = + felt_hex!("0x411494b501a98abd8262b0da1351e17899a0c4ef23dd2f96fec5ba847310b20"); + let signature_s = + felt_hex!("0x405c3191ab3883ef2b763af35bc5f5d15b3b4e99461d70e84c654a351a7c81b"); builtin .add_signature(Relocatable::from((1, 0)), &(signature_r, signature_s)) @@ -920,7 +917,7 @@ mod memory_tests { .memory .insert( Relocatable::from((0, 0)), - &MaybeRelocatable::from(Felt252::new(-45)), + &MaybeRelocatable::from(Felt252::from(-45_i128)), ) .unwrap(); builtin.add_validation_rule(&mut segments.memory); @@ -936,7 +933,7 @@ mod memory_tests { .get_integer(Relocatable::from((0, 0))) .unwrap() .as_ref(), - &Felt252::new(10) + &Felt252::from(10) ); } @@ -971,7 +968,7 @@ mod memory_tests { memory.temp_data.push(Vec::new()); let key = Relocatable::from((-1, 0)); - let val = MaybeRelocatable::from(Felt252::new(5)); + let val = MaybeRelocatable::from(Felt252::from(5)); memory.insert(key, &val).unwrap(); assert_eq!(memory.get(&key).unwrap().as_ref(), &val); @@ -1017,8 +1014,8 @@ mod memory_tests { // Test when value is Some(BigInt): assert_eq!( - memory.relocate_value(&MaybeRelocatable::Int(Felt252::new(0))), - Cow::Owned(MaybeRelocatable::Int(Felt252::new(0))), + memory.relocate_value(&MaybeRelocatable::Int(Felt252::from(0))), + Cow::Owned(MaybeRelocatable::Int(Felt252::from(0))), ); } @@ -1099,9 +1096,9 @@ mod memory_tests { fn get_range_for_continuous_memory() { let memory = memory![((1, 0), 2), ((1, 1), 3), ((1, 2), 4)]; - let value1 = MaybeRelocatable::from(Felt252::new(2)); - let value2 = MaybeRelocatable::from(Felt252::new(3)); - let value3 = MaybeRelocatable::from(Felt252::new(4)); + let value1 = MaybeRelocatable::from(Felt252::from(2)); + let value2 = MaybeRelocatable::from(Felt252::from(3)); + let value3 = MaybeRelocatable::from(Felt252::from(4)); let expected_vec = vec![ Some(Cow::Borrowed(&value1)), @@ -1116,9 +1113,9 @@ mod memory_tests { fn get_range_for_non_continuous_memory() { let memory = memory![((1, 0), 2), ((1, 1), 3), ((1, 3), 4)]; - let value1 = MaybeRelocatable::from(Felt252::new(2)); - let value2 = MaybeRelocatable::from(Felt252::new(3)); - let value3 = MaybeRelocatable::from(Felt252::new(4)); + let value1 = MaybeRelocatable::from(Felt252::from(2)); + let value2 = MaybeRelocatable::from(Felt252::from(3)); + let value3 = MaybeRelocatable::from(Felt252::from(4)); let expected_vec = vec![ Some(Cow::Borrowed(&value1)), @@ -1134,9 +1131,9 @@ mod memory_tests { fn get_continuous_range_for_continuous_memory() { let memory = memory![((1, 0), 2), ((1, 1), 3), ((1, 2), 4)]; - let value1 = MaybeRelocatable::from(Felt252::new(2)); - let value2 = MaybeRelocatable::from(Felt252::new(3)); - let value3 = MaybeRelocatable::from(Felt252::new(4)); + let value1 = MaybeRelocatable::from(Felt252::from(2)); + let value2 = MaybeRelocatable::from(Felt252::from(3)); + let value3 = MaybeRelocatable::from(Felt252::from(4)); let expected_vec = vec![value1, value2, value3]; assert_eq!( @@ -1598,14 +1595,14 @@ mod memory_tests { #[test] fn insert_alloc_fails_gracefully() { let mut mem = memory![((0, 0), 1)]; - let err = mem.insert((0, usize::MAX >> 1).into(), Felt252::one()); + let err = mem.insert((0, usize::MAX >> 1).into(), Felt252::ONE); assert_eq!(err, Err(MemoryError::VecCapacityExceeded)); } #[test] fn insert_overflow_fails_gracefully() { let mut mem = memory![((0, 0), 1)]; - let err = mem.insert((0, usize::MAX).into(), Felt252::one()); + let err = mem.insert((0, usize::MAX).into(), Felt252::ONE); assert_eq!(err, Err(MemoryError::VecCapacityExceeded)); } diff --git a/vm/src/vm/vm_memory/memory_segments.rs b/vm/src/vm/vm_memory/memory_segments.rs index 984b4c0074..49aee11fa6 100644 --- a/vm/src/vm/vm_memory/memory_segments.rs +++ b/vm/src/vm/vm_memory/memory_segments.rs @@ -263,10 +263,9 @@ impl Default for MemorySegmentManager { #[cfg(test)] mod tests { use super::*; + use crate::Felt252; use crate::{relocatable, utils::test_utils::*, vm::vm_memory::memory::MemoryCell}; use assert_matches::assert_matches; - use felt::Felt252; - use num_traits::Num; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; @@ -334,7 +333,7 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn load_data_one_element() { - let data = vec![MaybeRelocatable::from(Felt252::new(4))]; + let data = vec![MaybeRelocatable::from(Felt252::from(4))]; let ptr = Relocatable::from((0, 0)); let mut segments = MemorySegmentManager::new(); segments.add(); @@ -342,7 +341,7 @@ mod tests { assert_eq!(current_ptr, Relocatable::from((0, 1))); assert_eq!( segments.memory.get(&ptr).unwrap().as_ref(), - &MaybeRelocatable::from(Felt252::new(4)) + &MaybeRelocatable::from(Felt252::from(4)) ); } @@ -350,9 +349,9 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn load_data_three_elements() { let data = vec![ - MaybeRelocatable::from(Felt252::new(4)), - MaybeRelocatable::from(Felt252::new(5)), - MaybeRelocatable::from(Felt252::new(6)), + MaybeRelocatable::from(Felt252::from(4)), + MaybeRelocatable::from(Felt252::from(5)), + MaybeRelocatable::from(Felt252::from(6)), ]; let ptr = Relocatable::from((0, 0)); let mut segments = MemorySegmentManager::new(); @@ -362,7 +361,7 @@ mod tests { assert_eq!( segments.memory.get(&ptr).unwrap().as_ref(), - &MaybeRelocatable::from(Felt252::new(4)) + &MaybeRelocatable::from(Felt252::from(4)) ); assert_eq!( segments @@ -370,7 +369,7 @@ mod tests { .get(&MaybeRelocatable::from((0, 1))) .unwrap() .as_ref(), - &MaybeRelocatable::from(Felt252::new(5)) + &MaybeRelocatable::from(Felt252::from(5)) ); assert_eq!( segments @@ -378,7 +377,7 @@ mod tests { .get(&MaybeRelocatable::from((0, 2))) .unwrap() .as_ref(), - &MaybeRelocatable::from(Felt252::new(6)) + &MaybeRelocatable::from(Felt252::from(6)) ); } #[test] @@ -398,7 +397,7 @@ mod tests { .memory .insert( Relocatable::from((0, 6)), - &MaybeRelocatable::from(Felt252::new(1)), + &MaybeRelocatable::from(Felt252::from(1)), ) .unwrap(); segments.compute_effective_sizes(); @@ -496,33 +495,6 @@ mod tests { ) } - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn write_arg_with_apply_modulo() { - let mut big_num = num_bigint::BigInt::from_str_radix(&felt::PRIME_STR[2..], 16) - .expect("Couldn't parse prime"); - big_num += 1; - let big_maybe_rel = MaybeRelocatable::from(Felt252::new(big_num)); - let data = vec![mayberelocatable!(11), mayberelocatable!(12), big_maybe_rel]; - let ptr = Relocatable::from((1, 0)); - let mut segments = MemorySegmentManager::new(); - for _ in 0..2 { - segments.add(); - } - - let exec = segments.write_arg(ptr, &data); - - assert_eq!(exec, Ok(MaybeRelocatable::from((1, 3)))); - assert_eq!( - segments.memory.data[1], - vec![ - Some(MemoryCell::new(mayberelocatable!(11))), - Some(MemoryCell::new(mayberelocatable!(12))), - Some(MemoryCell::new(mayberelocatable!(1))), - ] - ); - } - #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn write_arg_relocatable() {