diff --git a/Cargo.lock b/Cargo.lock index 9adf7ed6e..ddd7d227a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -954,6 +954,10 @@ version = "0.2.0-alpha.2" dependencies = [ "anyhow", "aquamarine", + "ark-ec", + "ark-ff", + "ark-secp256k1", + "ark-secp256r1", "bumpalo", "cairo-lang-compiler", "cairo-lang-defs", @@ -977,7 +981,6 @@ dependencies = [ "criterion", "educe", "itertools 0.13.0", - "k256", "keccak", "lambdaworks-math 0.10.0", "lazy_static", @@ -987,8 +990,8 @@ dependencies = [ "melior", "mlir-sys", "num-bigint", + "num-integer", "num-traits 0.2.19", - "p256", "pretty_assertions_sorted", "proptest", "rstest", @@ -1383,7 +1386,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array", - "rand_core", "subtle", "zeroize", ] @@ -1466,7 +1468,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ "const-oid", - "pem-rfc7468", "zeroize", ] @@ -1549,7 +1550,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", - "const-oid", "crypto-common", "subtle", ] @@ -1581,20 +1581,6 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" -[[package]] -name = "ecdsa" -version = "0.16.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" -dependencies = [ - "der", - "digest", - "elliptic-curve", - "rfc6979", - "signature", - "spki", -] - [[package]] name = "educe" version = "0.5.11" @@ -1613,26 +1599,6 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" -[[package]] -name = "elliptic-curve" -version = "0.13.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" -dependencies = [ - "base16ct", - "crypto-bigint", - "digest", - "ff", - "generic-array", - "group", - "pem-rfc7468", - "pkcs8", - "rand_core", - "sec1", - "subtle", - "zeroize", -] - [[package]] name = "ena" version = "0.14.3" @@ -1696,16 +1662,6 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" -[[package]] -name = "ff" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" -dependencies = [ - "rand_core", - "subtle", -] - [[package]] name = "fixedbitset" version = "0.4.2" @@ -1859,7 +1815,6 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", - "zeroize", ] [[package]] @@ -1904,17 +1859,6 @@ dependencies = [ "minilp", ] -[[package]] -name = "group" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" -dependencies = [ - "ff", - "rand_core", - "subtle", -] - [[package]] name = "half" version = "2.4.1" @@ -2208,20 +2152,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "k256" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" -dependencies = [ - "cfg-if", - "ecdsa", - "elliptic-curve", - "once_cell", - "sha2", - "signature", -] - [[package]] name = "keccak" version = "0.1.5" @@ -2632,18 +2562,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" -[[package]] -name = "p256" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" -dependencies = [ - "ecdsa", - "elliptic-curve", - "primeorder", - "sha2", -] - [[package]] name = "parity-scale-codec" version = "3.6.12" @@ -2728,15 +2646,6 @@ dependencies = [ "sha2", ] -[[package]] -name = "pem-rfc7468" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" -dependencies = [ - "base64ct", -] - [[package]] name = "petgraph" version = "0.6.5" @@ -2774,16 +2683,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -[[package]] -name = "pkcs8" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" -dependencies = [ - "der", - "spki", -] - [[package]] name = "pkg-config" version = "0.3.31" @@ -2875,15 +2774,6 @@ dependencies = [ "syn 2.0.79", ] -[[package]] -name = "primeorder" -version = "0.13.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" -dependencies = [ - "elliptic-curve", -] - [[package]] name = "proc-macro-crate" version = "3.2.0" @@ -3318,8 +3208,6 @@ dependencies = [ "base16ct", "der", "generic-array", - "pkcs8", - "subtle", "zeroize", ] @@ -3431,16 +3319,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" -[[package]] -name = "signature" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" -dependencies = [ - "digest", - "rand_core", -] - [[package]] name = "siphasher" version = "0.3.11" @@ -3487,16 +3365,6 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" -[[package]] -name = "spki" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" -dependencies = [ - "base64ct", - "der", -] - [[package]] name = "sprs" version = "0.7.1" diff --git a/Cargo.toml b/Cargo.toml index 455369e39..bed677ae6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -106,8 +106,6 @@ cairo-lang-runner = { version = "2.8.2", optional = true } colored = { version = "2.1.0", optional = true } # needed to interface with cairo-lang-* keccak = "0.1.5" -k256 = "0.13.4" -p256 = "0.13.2" sha2 = "0.10.8" # needed for the syscall handler stub scarb-metadata = { version = "1.12.0", optional = true } scarb-ui = { version = "0.1.5", optional = true } @@ -115,6 +113,13 @@ sec1 = "0.7.3" serde_json = { version = "1.0.125" } stats_alloc = "0.1.10" +# for the syscallhandler stub to match blockifier +ark-secp256k1 = "0.4.0" +ark-secp256r1 = "0.4.0" +ark-ec = "0.4.2" +ark-ff = "0.4.2" +num-integer = "0.1.46" + [dev-dependencies] cairo-vm = { version = "1.0.1", features = ["cairo-1-hints"] } cairo-lang-runner = "2.8.2" diff --git a/src/starknet_stub.rs b/src/starknet_stub.rs index 8b6bc4a55..7bf81a84e 100644 --- a/src/starknet_stub.rs +++ b/src/starknet_stub.rs @@ -2,18 +2,18 @@ use std::{ collections::{HashMap, VecDeque}, - iter::once, + fmt, }; use crate::starknet::{ BlockInfo, ExecutionInfo, ExecutionInfoV2, Secp256k1Point, Secp256r1Point, StarknetSyscallHandler, SyscallResult, TxInfo, TxV2Info, U256, }; -use k256::elliptic_curve::{ - generic_array::GenericArray, - sec1::{FromEncodedPoint, ToEncodedPoint}, -}; -use sec1::point::Coordinates; +use ark_ec::short_weierstrass::{Affine, Projective, SWCurveConfig}; +use ark_ff::{BigInt, PrimeField}; +use itertools::Itertools; +use num_bigint::BigUint; +use num_traits::Zero; use starknet_types_core::felt::Felt; use tracing::instrument; @@ -78,6 +78,191 @@ pub struct ContractLogs { type L2ToL1Message = (Felt, Vec); +#[derive(PartialEq, Clone, Copy)] +struct Secp256Point(Affine); + +impl fmt::Debug for Secp256Point { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Secp256Point").field(&self.0).finish() + } +} + +impl From> for Secp256k1Point { + fn from(Secp256Point(Affine { x, y, infinity }): Secp256Point) -> Self { + Secp256k1Point { + x: big4int_to_u256(x.into()), + y: big4int_to_u256(y.into()), + is_infinity: infinity, + } + } +} + +impl From> for Secp256r1Point { + fn from(Secp256Point(Affine { x, y, infinity }): Secp256Point) -> Self { + Secp256r1Point { + x: big4int_to_u256(x.into()), + y: big4int_to_u256(y.into()), + is_infinity: infinity, + } + } +} + +impl From for Secp256Point { + fn from(p: Secp256k1Point) -> Self { + Secp256Point(Affine { + x: u256_to_biguint(p.x).into(), + y: u256_to_biguint(p.y).into(), + infinity: p.is_infinity, + }) + } +} + +impl From for Secp256Point { + fn from(p: Secp256r1Point) -> Self { + Secp256Point(Affine { + x: u256_to_biguint(p.x).into(), + y: u256_to_biguint(p.y).into(), + infinity: p.is_infinity, + }) + } +} + +pub fn u256_to_biguint(u256: U256) -> BigUint { + let lo = BigUint::from(u256.lo); + let hi = BigUint::from(u256.hi); + + (hi << 128) + lo +} + +pub fn big4int_to_u256(b_int: BigInt<4>) -> U256 { + let [a, b, c, d] = b_int.0; + + let lo = u128::from(a) | (u128::from(b) << 64); + let hi = u128::from(c) | (u128::from(d) << 64); + + U256 { lo, hi } +} + +pub fn encode_str_as_felts(msg: &str) -> Vec { + const CHUNK_SIZE: usize = 32; + + let data = msg.as_bytes().chunks(CHUNK_SIZE - 1); + let mut encoding = vec![Felt::default(); data.len()]; + for (i, data_chunk) in data.enumerate() { + let mut chunk = [0_u8; CHUNK_SIZE]; + chunk[1..data_chunk.len() + 1].copy_from_slice(data_chunk); + encoding[i] = Felt::from_bytes_be(&chunk); + } + encoding +} + +pub fn decode_felts_as_str(encoding: &[Felt]) -> String { + let bytes_err: Vec<_> = encoding + .iter() + .flat_map(|felt| felt.to_bytes_be()[1..32].to_vec()) + .collect(); + + match String::from_utf8(bytes_err) { + Ok(s) => s.trim_matches('\0').to_owned(), + Err(_) => { + let err_msgs = encoding + .iter() + .map( + |felt| match String::from_utf8(felt.to_bytes_be()[1..32].to_vec()) { + Ok(s) => format!("{} ({})", s.trim_matches('\0'), felt), + Err(_) => felt.to_string(), + }, + ) + .join(", "); + format!("[{}]", err_msgs) + } + } +} + +impl Secp256Point +where + Curve::BaseField: PrimeField, // constraint for get_point_by_id +{ + // Given a (x,y) pair it will + // - return the point at infinity for (0,0) + // - Err if either x or y is outside of the modulus + // - Ok(None) if (x,y) are within the modules but not on the curve + // - Ok(Some(Point)) if (x,y) are on the curve + fn new(x: U256, y: U256) -> Result, Vec> { + let x = u256_to_biguint(x); + let y = u256_to_biguint(y); + let modulos = Curve::BaseField::MODULUS.into(); + + if x >= modulos || y >= modulos { + let error = Felt::from_hex( + "0x00000000000000000000000000000000496e76616c696420617267756d656e74", + ) // INVALID_ARGUMENT + .map_err(|err| encode_str_as_felts(&err.to_string()))?; + + return Err(vec![error]); + } + + Ok(maybe_affine(x.into(), y.into())) + } + + fn add(p0: Self, p1: Self) -> Self { + let result: Projective = p0.0 + p1.0; + Secp256Point(result.into()) + } + + fn mul(p: Self, m: U256) -> Self { + let result = p.0 * Curve::ScalarField::from(u256_to_biguint(m)); + Secp256Point(result.into()) + } + + fn get_point_from_x(x: U256, y_parity: bool) -> Result, Vec> { + let modulos = Curve::BaseField::MODULUS.into(); + let x = u256_to_biguint(x); + + if x >= modulos { + let error = Felt::from_hex( + "0x00000000000000000000000000000000496e76616c696420617267756d656e74", + ) // INVALID_ARGUMENT + .map_err(|err| encode_str_as_felts(&err.to_string()))?; + + return Err(vec![error]); + } + + let x = x.into(); + let maybe_ec_point = Affine::::get_ys_from_x_unchecked(x) + .map(|(smaller, greater)| { + // Return the correct y coordinate based on the parity. + if ark_ff::BigInteger::is_odd(&smaller.into_bigint()) == y_parity { + smaller + } else { + greater + } + }) + .map(|y| Affine::::new_unchecked(x, y)) + .filter(|p| p.is_in_correct_subgroup_assuming_on_curve()); + + Ok(maybe_ec_point.map(Secp256Point)) + } +} + +/// Variation on [`Affine::new`] that doesn't panic and maps (x,y) = (0,0) -> infinity +fn maybe_affine( + x: Curve::BaseField, + y: Curve::BaseField, +) -> Option> { + let ec_point = if x.is_zero() && y.is_zero() { + Affine::::identity() + } else { + Affine::::new_unchecked(x, y) + }; + + if ec_point.is_on_curve() && ec_point.is_in_correct_subgroup_assuming_on_curve() { + Some(Secp256Point(ec_point)) + } else { + None + } +} + impl StarknetSyscallHandler for &mut StubSyscallHandler { #[instrument(skip(self))] fn get_block_hash( @@ -228,38 +413,30 @@ impl StarknetSyscallHandler for &mut StubSyscallHandler { #[instrument(skip(self))] fn keccak(&mut self, input: &[u64], gas: &mut u128) -> SyscallResult { - tracing::debug!("called"); + const KECCAK_FULL_RATE_IN_WORDS: usize = 17; + let length = input.len(); + let (_n_rounds, remainder) = num_integer::div_rem(length, KECCAK_FULL_RATE_IN_WORDS); - if length % 17 != 0 { - let error_msg = b"Invalid keccak input size"; - let felt_error = Felt::from_bytes_be_slice(error_msg); - return Err(vec![felt_error]); + if remainder != 0 { + // In VM this error is wrapped into `SyscallExecutionError::SyscallError` + return Err(vec![Felt::from_hex( + "0x000000000000000000000000496e76616c696420696e707574206c656e677468", + ) + .unwrap()]); } - let n_chunks = length / 17; let mut state = [0u64; 25]; - - for i in 0..n_chunks { - if *gas < KECCAK_ROUND_COST { - let error_msg = b"Syscall out of gas"; - let felt_error = Felt::from_bytes_be_slice(error_msg); - return Err(vec![felt_error]); - } - const KECCAK_ROUND_COST: u128 = 180000; - *gas -= KECCAK_ROUND_COST; - let chunk = &input[i * 17..(i + 1) * 17]; //(request.input_start + i * 17)?; + for chunk in input.chunks(KECCAK_FULL_RATE_IN_WORDS) { for (i, val) in chunk.iter().enumerate() { state[i] ^= val; } keccak::f1600(&mut state) } - // state[0] and state[1] conform the hash_high (u128) - // state[2] and state[3] conform the hash_low (u128) - SyscallResult::Ok(U256 { - lo: state[0] as u128 | ((state[1] as u128) << 64), - hi: state[2] as u128 | ((state[3] as u128) << 64), + Ok(U256 { + hi: u128::from(state[2]) | (u128::from(state[3]) << 64), + lo: u128::from(state[0]) | (u128::from(state[1]) << 64), }) } @@ -270,32 +447,7 @@ impl StarknetSyscallHandler for &mut StubSyscallHandler { y: U256, _remaining_gas: &mut u128, ) -> SyscallResult> { - tracing::debug!("called"); - // The following unwraps should be unreachable because the iterator we provide has the - // expected number of bytes. - let point = k256::ProjectivePoint::from_encoded_point( - &k256::EncodedPoint::from_affine_coordinates( - &GenericArray::from_exact_iter( - x.hi.to_be_bytes().into_iter().chain(x.lo.to_be_bytes()), - ) - .unwrap(), - &GenericArray::from_exact_iter( - y.hi.to_be_bytes().into_iter().chain(y.lo.to_be_bytes()), - ) - .unwrap(), - false, - ), - ); - - if bool::from(point.is_some()) { - Ok(Some(Secp256k1Point { - x, - y, - is_infinity: false, - })) - } else { - Ok(None) - } + Secp256Point::new(x, y).map(|op| op.map(|p| p.into())) } #[instrument(skip(self))] @@ -307,178 +459,17 @@ impl StarknetSyscallHandler for &mut StubSyscallHandler { ) -> SyscallResult { tracing::debug!("called"); - if p0.is_infinity || p1.is_infinity { - if p1.is_infinity { - return Ok(p0); - } else if p0.is_infinity { - return Ok(p1); - } else { - return Ok(Secp256k1Point { - x: U256 { hi: 0, lo: 0 }, - y: U256 { hi: 0, lo: 0 }, - is_infinity: true, - }); - } - } - - // The inner unwraps should be unreachable because the iterator we provide has the expected - // number of bytes. The outer unwraps depend on the felt values, which should be valid since - // they'll be provided by secp256 syscalls. - - let p0 = k256::ProjectivePoint::from_encoded_point(&if p0.is_infinity { - k256::EncodedPoint::identity() - } else { - k256::EncodedPoint::from_affine_coordinates( - &GenericArray::from_exact_iter( - p0.x.hi - .to_be_bytes() - .into_iter() - .chain(p0.x.lo.to_be_bytes()), - ) - .unwrap(), - &GenericArray::from_exact_iter( - p0.y.hi - .to_be_bytes() - .into_iter() - .chain(p0.y.lo.to_be_bytes()), - ) - .unwrap(), - false, - ) - }) - .unwrap(); - let p1 = k256::ProjectivePoint::from_encoded_point(&if p1.is_infinity { - k256::EncodedPoint::identity() - } else { - k256::EncodedPoint::from_affine_coordinates( - &GenericArray::from_exact_iter( - p1.x.hi - .to_be_bytes() - .into_iter() - .chain(p1.x.lo.to_be_bytes()), - ) - .unwrap(), - &GenericArray::from_exact_iter( - p1.y.hi - .to_be_bytes() - .into_iter() - .chain(p1.y.lo.to_be_bytes()), - ) - .unwrap(), - false, - ) - }) - .unwrap(); - - let p = p0 + p1; - - let p = p.to_encoded_point(false); - let (x, y, is_infinity) = match p.coordinates() { - Coordinates::Uncompressed { x, y } => (x.as_slice(), y.as_slice(), false), - Coordinates::Identity => ([0u8; 32].as_slice(), [0; 32].as_slice(), true), - _ => { - // This should be unreachable because we explicitly asked for the uncompressed - // encoding. - unreachable!() - } - }; - - // The following two unwraps should be safe because the array always has 32 bytes. The other - // four are definitely safe because the slicing guarantees its length to be the right one. - let x: [u8; 32] = x.try_into().unwrap(); - let y: [u8; 32] = y.try_into().unwrap(); - Ok(Secp256k1Point { - x: U256 { - hi: u128::from_be_bytes(x[0..16].try_into().unwrap()), - lo: u128::from_be_bytes(x[16..32].try_into().unwrap()), - }, - y: U256 { - hi: u128::from_be_bytes(y[0..16].try_into().unwrap()), - lo: u128::from_be_bytes(y[16..32].try_into().unwrap()), - }, - is_infinity, - }) + Ok(Secp256Point::add(p0.into(), p1.into()).into()) } #[instrument(skip(self))] fn secp256k1_mul( &mut self, - p_arg: Secp256k1Point, + p: Secp256k1Point, m: U256, _remaining_gas: &mut u128, ) -> SyscallResult { - // The inner unwrap should be unreachable because the iterator we provide has the expected - // number of bytes. The outer unwrap depends on the felt values, which should be valid since - // they'll be provided by secp256 syscalls. - - let p = k256::ProjectivePoint::from_encoded_point(&if p_arg.is_infinity { - k256::EncodedPoint::identity() - } else { - k256::EncodedPoint::from_affine_coordinates( - &GenericArray::from_exact_iter( - p_arg - .x - .hi - .to_be_bytes() - .into_iter() - .chain(p_arg.x.lo.to_be_bytes()), - ) - .unwrap(), - &GenericArray::from_exact_iter( - p_arg - .y - .hi - .to_be_bytes() - .into_iter() - .chain(p_arg.y.lo.to_be_bytes()), - ) - .unwrap(), - false, - ) - }) - .unwrap(); - - let m: k256::Scalar = k256::elliptic_curve::ScalarPrimitive::from_slice(&{ - let mut buf = [0u8; 32]; - buf[0..16].copy_from_slice(&m.hi.to_be_bytes()); - buf[16..32].copy_from_slice(&m.lo.to_be_bytes()); - buf - }) - .map_err(|_| { - vec![Felt::from_bytes_be( - b"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0invalid scalar", - )] - })? - .into(); - - let p = p * m; - - let p = p.to_encoded_point(false); - let (x, y, is_infinity) = match p.coordinates() { - Coordinates::Uncompressed { x, y } => (x.as_slice(), y.as_slice(), false), - Coordinates::Identity => ([0u8; 32].as_slice(), [0; 32].as_slice(), true), - _ => { - // This should be unreachable because we explicitly asked for the uncompressed - // encoding. - unreachable!() - } - }; - - // The following two unwraps should be safe because the array always has 32 bytes. The other - // four are definitely safe because the slicing guarantees its length to be the right one. - let x: [u8; 32] = x.try_into().unwrap(); - let y: [u8; 32] = y.try_into().unwrap(); - Ok(Secp256k1Point { - x: U256 { - hi: u128::from_be_bytes(x[0..16].try_into().unwrap()), - lo: u128::from_be_bytes(x[16..32].try_into().unwrap()), - }, - y: U256 { - hi: u128::from_be_bytes(y[0..16].try_into().unwrap()), - lo: u128::from_be_bytes(y[16..32].try_into().unwrap()), - }, - is_infinity, - }) + Ok(Secp256Point::mul(p.into(), m).into()) } #[instrument(skip(self))] @@ -488,51 +479,7 @@ impl StarknetSyscallHandler for &mut StubSyscallHandler { y_parity: bool, _remaining_gas: &mut u128, ) -> SyscallResult> { - tracing::debug!("called"); - // The inner unwrap should be unreachable because the iterator we provide has the expected - // number of bytes. The outer unwrap depends on the encoding format, which should be valid - // since it's hardcoded.. - let point = k256::ProjectivePoint::from_encoded_point( - &k256::EncodedPoint::from_bytes( - k256::CompressedPoint::from_exact_iter( - once(0x02 | y_parity as u8) - .chain(x.hi.to_be_bytes()) - .chain(x.lo.to_be_bytes()), - ) - .unwrap(), - ) - .unwrap(), - ); - - if bool::from(point.is_some()) { - // This unwrap has already been checked in the `if` expression's condition. - let p = point.unwrap(); - - let p = p.to_encoded_point(false); - let y = match p.coordinates() { - Coordinates::Uncompressed { y, .. } => y, - _ => { - // This should be unreachable because we explicitly asked for the uncompressed - // encoding. - unreachable!() - } - }; - - // The following unwrap should be safe because the array always has 32 bytes. The other - // two are definitely safe because the slicing guarantees its length to be the right - // one. - let y: [u8; 32] = y.as_slice().try_into().unwrap(); - Ok(Some(Secp256k1Point { - x, - y: U256 { - hi: u128::from_be_bytes(y[0..16].try_into().unwrap()), - lo: u128::from_be_bytes(y[16..32].try_into().unwrap()), - }, - is_infinity: false, - })) - } else { - Ok(None) - } + Secp256Point::get_point_from_x(x, y_parity).map(|op| op.map(|p| p.into())) } #[instrument(skip(self))] @@ -541,7 +488,6 @@ impl StarknetSyscallHandler for &mut StubSyscallHandler { p: Secp256k1Point, _remaining_gas: &mut u128, ) -> SyscallResult<(U256, U256)> { - tracing::debug!("called"); Ok((p.x, p.y)) } @@ -552,32 +498,7 @@ impl StarknetSyscallHandler for &mut StubSyscallHandler { y: U256, _remaining_gas: &mut u128, ) -> SyscallResult> { - tracing::debug!("called"); - // The following unwraps should be unreachable because the iterator we provide has the - // expected number of bytes. - let point = p256::ProjectivePoint::from_encoded_point( - &k256::EncodedPoint::from_affine_coordinates( - &GenericArray::from_exact_iter( - x.hi.to_be_bytes().into_iter().chain(x.lo.to_be_bytes()), - ) - .unwrap(), - &GenericArray::from_exact_iter( - y.hi.to_be_bytes().into_iter().chain(y.lo.to_be_bytes()), - ) - .unwrap(), - false, - ), - ); - - if bool::from(point.is_some()) { - Ok(Some(Secp256r1Point { - x, - y, - is_infinity: false, - })) - } else { - Ok(None) - } + Secp256Point::new(x, y).map(|op| op.map(|p| p.into())) } #[instrument(skip(self))] @@ -587,177 +508,17 @@ impl StarknetSyscallHandler for &mut StubSyscallHandler { p1: Secp256r1Point, _remaining_gas: &mut u128, ) -> SyscallResult { - tracing::debug!("called"); - - if p0.is_infinity || p1.is_infinity { - if p1.is_infinity { - return Ok(p0); - } else if p0.is_infinity { - return Ok(p1); - } else { - return Ok(Secp256r1Point { - x: U256 { hi: 0, lo: 0 }, - y: U256 { hi: 0, lo: 0 }, - is_infinity: true, - }); - } - } - - // The inner unwraps should be unreachable because the iterator we provide has the expected - // number of bytes. The outer unwraps depend on the felt values, which should be valid since - // they'll be provided by secp256 syscalls. - let p0 = p256::ProjectivePoint::from_encoded_point(&if p0.is_infinity { - p256::EncodedPoint::identity() - } else { - p256::EncodedPoint::from_affine_coordinates( - &GenericArray::from_exact_iter( - p0.x.hi - .to_be_bytes() - .into_iter() - .chain(p0.x.lo.to_be_bytes()), - ) - .unwrap(), - &GenericArray::from_exact_iter( - p0.y.hi - .to_be_bytes() - .into_iter() - .chain(p0.y.lo.to_be_bytes()), - ) - .unwrap(), - false, - ) - }) - .unwrap(); - let p1 = p256::ProjectivePoint::from_encoded_point(&if p1.is_infinity { - p256::EncodedPoint::identity() - } else { - p256::EncodedPoint::from_affine_coordinates( - &GenericArray::from_exact_iter( - p1.x.hi - .to_be_bytes() - .into_iter() - .chain(p1.x.lo.to_be_bytes()), - ) - .unwrap(), - &GenericArray::from_exact_iter( - p1.y.hi - .to_be_bytes() - .into_iter() - .chain(p1.y.lo.to_be_bytes()), - ) - .unwrap(), - false, - ) - }) - .unwrap(); - - let p = p0 + p1; - - let p = p.to_encoded_point(false); - let (x, y) = match p.coordinates() { - Coordinates::Uncompressed { x, y } => (x, y), - _ => { - // This should be unreachable because we explicitly asked for the uncompressed - // encoding. - unreachable!() - } - }; - - // The following two unwraps should be safe because the array always has 32 bytes. The other - // four are definitely safe because the slicing guarantees its length to be the right one. - let x: [u8; 32] = x.as_slice().try_into().unwrap(); - let y: [u8; 32] = y.as_slice().try_into().unwrap(); - Ok(Secp256r1Point { - x: U256 { - hi: u128::from_be_bytes(x[0..16].try_into().unwrap()), - lo: u128::from_be_bytes(x[16..32].try_into().unwrap()), - }, - y: U256 { - hi: u128::from_be_bytes(y[0..16].try_into().unwrap()), - lo: u128::from_be_bytes(y[16..32].try_into().unwrap()), - }, - is_infinity: false, - }) + Ok(Secp256Point::add(p0.into(), p1.into()).into()) } #[instrument(skip(self))] fn secp256r1_mul( &mut self, - p_arg: Secp256r1Point, + p: Secp256r1Point, m: U256, _remaining_gas: &mut u128, ) -> SyscallResult { - // The inner unwrap should be unreachable because the iterator we provide has the expected - // number of bytes. The outer unwrap depends on the felt values, which should be valid since - // they'll be provided by secp256 syscalls. - - let p = p256::ProjectivePoint::from_encoded_point(&if p_arg.is_infinity { - p256::EncodedPoint::identity() - } else { - p256::EncodedPoint::from_affine_coordinates( - &GenericArray::from_exact_iter( - p_arg - .x - .hi - .to_be_bytes() - .into_iter() - .chain(p_arg.x.lo.to_be_bytes()), - ) - .unwrap(), - &GenericArray::from_exact_iter( - p_arg - .y - .hi - .to_be_bytes() - .into_iter() - .chain(p_arg.y.lo.to_be_bytes()), - ) - .unwrap(), - false, - ) - }) - .unwrap(); - - let m: p256::Scalar = p256::elliptic_curve::ScalarPrimitive::from_slice(&{ - let mut buf = [0u8; 32]; - buf[0..16].copy_from_slice(&m.hi.to_be_bytes()); - buf[16..32].copy_from_slice(&m.lo.to_be_bytes()); - buf - }) - .map_err(|_| { - vec![Felt::from_bytes_be( - b"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0invalid scalar", - )] - })? - .into(); - - let p = p * m; - let p = p.to_encoded_point(false); - let (x, y, is_infinity) = match p.coordinates() { - Coordinates::Uncompressed { x, y } => (x.as_slice(), y.as_slice(), false), - Coordinates::Identity => ([0u8; 32].as_slice(), [0; 32].as_slice(), true), - _ => { - // This should be unreachable because we explicitly asked for the uncompressed - // encoding. - unreachable!() - } - }; - - // The following two unwraps should be safe because the array always has 32 bytes. The other - // four are definitely safe because the slicing guarantees its length to be the right one. - let x: [u8; 32] = x.try_into().unwrap(); - let y: [u8; 32] = y.try_into().unwrap(); - Ok(Secp256r1Point { - x: U256 { - hi: u128::from_be_bytes(x[0..16].try_into().unwrap()), - lo: u128::from_be_bytes(x[16..32].try_into().unwrap()), - }, - y: U256 { - hi: u128::from_be_bytes(y[0..16].try_into().unwrap()), - lo: u128::from_be_bytes(y[16..32].try_into().unwrap()), - }, - is_infinity, - }) + Ok(Secp256Point::mul(p.into(), m).into()) } #[instrument(skip(self))] @@ -767,39 +528,7 @@ impl StarknetSyscallHandler for &mut StubSyscallHandler { y_parity: bool, _remaining_gas: &mut u128, ) -> SyscallResult> { - let point = p256::ProjectivePoint::from_encoded_point( - &p256::EncodedPoint::from_bytes( - p256::CompressedPoint::from_exact_iter( - once(0x02 | y_parity as u8) - .chain(x.hi.to_be_bytes()) - .chain(x.lo.to_be_bytes()), - ) - .unwrap(), - ) - .unwrap(), - ); - - if bool::from(point.is_some()) { - let p = point.unwrap(); - - let p = p.to_encoded_point(false); - let y = match p.coordinates() { - Coordinates::Uncompressed { y, .. } => y, - _ => unreachable!(), - }; - - let y: [u8; 32] = y.as_slice().try_into().unwrap(); - Ok(Some(Secp256r1Point { - x, - y: U256 { - hi: u128::from_be_bytes(y[0..16].try_into().unwrap()), - lo: u128::from_be_bytes(y[16..32].try_into().unwrap()), - }, - is_infinity: false, - })) - } else { - Ok(None) - } + Secp256Point::get_point_from_x(x, y_parity).map(|op| op.map(|p| p.into())) } #[instrument(skip(self))] @@ -808,7 +537,6 @@ impl StarknetSyscallHandler for &mut StubSyscallHandler { p: Secp256r1Point, _remaining_gas: &mut u128, ) -> SyscallResult<(U256, U256)> { - tracing::debug!("called"); Ok((p.x, p.y)) } diff --git a/tests/tests/starknet/secp256.rs b/tests/tests/starknet/secp256.rs index b142621d0..e5d5456d9 100644 --- a/tests/tests/starknet/secp256.rs +++ b/tests/tests/starknet/secp256.rs @@ -307,7 +307,7 @@ fn secp256k1_new() { Some(u128::MAX), Some(&mut syscall_handler), ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( result.return_value, Value::Enum { tag: 0, @@ -339,7 +339,7 @@ fn secp256k1_new() { Some(u128::MAX), Some(&mut syscall_handler), ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( result.return_value, Value::Enum { tag: 0, @@ -371,7 +371,7 @@ fn secp256k1_new() { Some(u128::MAX), Some(&mut syscall_handler), ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( result.return_value, Value::Enum { tag: 0, @@ -387,7 +387,7 @@ fn secp256k1_new() { }, ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( syscall_handler.secp256k1_new.0, [ (U256 { hi: 0, lo: 0 }, U256 { hi: 0, lo: 0 }), @@ -470,7 +470,7 @@ fn secp256k1_add() { Some(u128::MAX), Some(&mut syscall_handler), ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( result.return_value, Value::Enum { tag: 0, @@ -498,7 +498,7 @@ fn secp256k1_add() { Some(u128::MAX), Some(&mut syscall_handler), ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( result.return_value, Value::Enum { tag: 0, @@ -526,7 +526,7 @@ fn secp256k1_add() { Some(u128::MAX), Some(&mut syscall_handler), ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( result.return_value, Value::Enum { tag: 0, @@ -538,7 +538,7 @@ fn secp256k1_add() { }, ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( syscall_handler.secp256k1_add.0, [ ( @@ -549,8 +549,11 @@ fn secp256k1_add() { }, Secp256k1Point { x: U256 { hi: 0, lo: 0 }, - y: U256 { hi: 0, lo: 0 }, - is_infinity: false + y: U256 { + hi: 1733168570990207326437046234223328, + lo: 2577042349707038322317355628978192 + }, + is_infinity: true }, ), ( @@ -563,7 +566,7 @@ fn secp256k1_add() { hi: 0, lo: u128::MAX }, - is_infinity: false + is_infinity: true }, Secp256k1Point { x: U256 { @@ -584,10 +587,10 @@ fn secp256k1_add() { hi: u128::MAX }, y: U256 { - lo: u128::MAX, - hi: u128::MAX + lo: 2577042349707038322317355628978192, + hi: 1733168570990207326437046234223328 }, - is_infinity: false + is_infinity: true }, Secp256k1Point { x: U256 { @@ -660,7 +663,7 @@ fn secp256k1_mul() { Some(u128::MAX), Some(&mut syscall_handler), ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( result.return_value, Value::Enum { tag: 0, @@ -688,7 +691,7 @@ fn secp256k1_mul() { Some(u128::MAX), Some(&mut syscall_handler), ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( result.return_value, Value::Enum { tag: 0, @@ -716,7 +719,7 @@ fn secp256k1_mul() { Some(u128::MAX), Some(&mut syscall_handler), ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( result.return_value, Value::Enum { tag: 0, @@ -728,7 +731,7 @@ fn secp256k1_mul() { }, ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( syscall_handler.secp256k1_mul.0, [ ( @@ -737,7 +740,10 @@ fn secp256k1_mul() { y: U256 { hi: 0, lo: 0 }, is_infinity: false }, - U256 { hi: 0, lo: 0 }, + U256 { + hi: 1733875197492387889953657239909088, + lo: 2592175575017578238863278680044832 + }, ), ( Secp256k1Point { @@ -749,11 +755,11 @@ fn secp256k1_mul() { lo: 0, hi: u128::MAX, }, - is_infinity: false + is_infinity: true }, U256 { - lo: u128::MAX, - hi: 0, + lo: 2592175575017578238863278680044832, + hi: 1733875197492387889953657239909088, }, ), ( @@ -766,11 +772,11 @@ fn secp256k1_mul() { hi: u128::MAX, lo: 0, }, - is_infinity: false + is_infinity: true }, U256 { - hi: 0, - lo: u128::MAX, + hi: 1733875197492387889953657239909088, + lo: 2592175575017578238863278680044832, }, ), ], @@ -837,7 +843,7 @@ fn secp256k1_get_point_from_x() { Some(u128::MAX), Some(&mut syscall_handler), ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( result.return_value, Value::Enum { tag: 0, @@ -873,7 +879,7 @@ fn secp256k1_get_point_from_x() { Some(u128::MAX), Some(&mut syscall_handler), ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( result.return_value, Value::Enum { tag: 0, @@ -909,7 +915,7 @@ fn secp256k1_get_point_from_x() { Some(u128::MAX), Some(&mut syscall_handler), ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( result.return_value, Value::Enum { tag: 0, @@ -945,7 +951,7 @@ fn secp256k1_get_point_from_x() { Some(u128::MAX), Some(&mut syscall_handler), ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( result.return_value, Value::Enum { tag: 0, @@ -961,7 +967,7 @@ fn secp256k1_get_point_from_x() { }, ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( syscall_handler.secp256k1_get_point_from_x.0, [ (U256 { hi: 0, lo: 0 }, false), @@ -1043,7 +1049,7 @@ fn secp256k1_get_xy() { Some(u128::MAX), Some(&mut syscall_handler), ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( result.return_value, Value::Enum { tag: 0, @@ -1074,7 +1080,7 @@ fn secp256k1_get_xy() { Some(u128::MAX), Some(&mut syscall_handler), ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( result.return_value, Value::Enum { tag: 0, @@ -1105,7 +1111,7 @@ fn secp256k1_get_xy() { Some(u128::MAX), Some(&mut syscall_handler), ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( result.return_value, Value::Enum { tag: 0, @@ -1136,7 +1142,7 @@ fn secp256k1_get_xy() { Some(u128::MAX), Some(&mut syscall_handler), ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( result.return_value, Value::Enum { tag: 0, @@ -1157,13 +1163,13 @@ fn secp256k1_get_xy() { } ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( syscall_handler.secp256k1_get_xy.0, [ Secp256k1Point { x: U256 { hi: 0, lo: 0 }, y: U256 { hi: 0, lo: 0 }, - is_infinity: false + is_infinity: true }, Secp256k1Point { x: U256 { @@ -1174,7 +1180,7 @@ fn secp256k1_get_xy() { lo: u128::MAX, hi: 0, }, - is_infinity: false + is_infinity: true }, Secp256k1Point { x: U256 { @@ -1185,7 +1191,7 @@ fn secp256k1_get_xy() { lo: 0, hi: u128::MAX, }, - is_infinity: false + is_infinity: true }, Secp256k1Point { x: U256 { @@ -1196,7 +1202,7 @@ fn secp256k1_get_xy() { hi: u128::MAX, lo: u128::MAX, }, - is_infinity: false + is_infinity: true }, ], ); @@ -1247,7 +1253,7 @@ fn secp256r1_new() { Some(u128::MAX), Some(&mut syscall_handler), ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( result.return_value, Value::Enum { tag: 0, @@ -1279,7 +1285,7 @@ fn secp256r1_new() { Some(u128::MAX), Some(&mut syscall_handler), ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( result.return_value, Value::Enum { tag: 0, @@ -1311,7 +1317,7 @@ fn secp256r1_new() { Some(u128::MAX), Some(&mut syscall_handler), ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( result.return_value, Value::Enum { tag: 0, @@ -1327,7 +1333,7 @@ fn secp256r1_new() { }, ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( syscall_handler.secp256r1_new.0, [ (U256 { hi: 0, lo: 0 }, U256 { hi: 0, lo: 0 }), @@ -1410,7 +1416,7 @@ fn secp256r1_add() { Some(u128::MAX), Some(&mut syscall_handler), ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( result.return_value, Value::Enum { tag: 0, @@ -1438,7 +1444,7 @@ fn secp256r1_add() { Some(u128::MAX), Some(&mut syscall_handler), ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( result.return_value, Value::Enum { tag: 0, @@ -1466,7 +1472,7 @@ fn secp256r1_add() { Some(u128::MAX), Some(&mut syscall_handler), ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( result.return_value, Value::Enum { tag: 0, @@ -1478,7 +1484,7 @@ fn secp256r1_add() { }, ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( syscall_handler.secp256r1_add.0, [ ( @@ -1489,8 +1495,11 @@ fn secp256r1_add() { }, Secp256r1Point { x: U256 { hi: 0, lo: 0 }, - y: U256 { hi: 0, lo: 0 }, - is_infinity: false + y: U256 { + hi: 1742999308907772698323868375982816, + lo: 2580844755753273318242893811019792 + }, + is_infinity: true }, ), ( @@ -1511,10 +1520,10 @@ fn secp256r1_add() { hi: u128::MAX }, y: U256 { - lo: u128::MAX, - hi: 0 + lo: 2577605247555989237902197454245904, + hi: 1737150117704455138713203495650016 }, - is_infinity: false + is_infinity: true }, ), ( @@ -1600,7 +1609,7 @@ fn secp256r1_mul() { Some(u128::MAX), Some(&mut syscall_handler), ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( result.return_value, Value::Enum { tag: 0, @@ -1628,7 +1637,7 @@ fn secp256r1_mul() { Some(u128::MAX), Some(&mut syscall_handler), ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( result.return_value, Value::Enum { tag: 0, @@ -1656,7 +1665,7 @@ fn secp256r1_mul() { Some(u128::MAX), Some(&mut syscall_handler), ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( result.return_value, Value::Enum { tag: 0, @@ -1668,7 +1677,7 @@ fn secp256r1_mul() { }, ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( syscall_handler.secp256r1_mul.0, [ ( @@ -1777,7 +1786,7 @@ fn secp256r1_get_point_from_x() { Some(u128::MAX), Some(&mut syscall_handler), ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( result.return_value, Value::Enum { tag: 0, @@ -1813,7 +1822,7 @@ fn secp256r1_get_point_from_x() { Some(u128::MAX), Some(&mut syscall_handler), ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( result.return_value, Value::Enum { tag: 0, @@ -1849,7 +1858,7 @@ fn secp256r1_get_point_from_x() { Some(u128::MAX), Some(&mut syscall_handler), ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( result.return_value, Value::Enum { tag: 0, @@ -1885,7 +1894,7 @@ fn secp256r1_get_point_from_x() { Some(u128::MAX), Some(&mut syscall_handler), ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( result.return_value, Value::Enum { tag: 0, @@ -1901,7 +1910,7 @@ fn secp256r1_get_point_from_x() { }, ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( syscall_handler.secp256r1_get_point_from_x.0, [ (U256 { hi: 0, lo: 0 }, false), @@ -1983,7 +1992,7 @@ fn secp256r1_get_xy() { Some(u128::MAX), Some(&mut syscall_handler), ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( result.return_value, Value::Enum { tag: 0, @@ -2014,7 +2023,7 @@ fn secp256r1_get_xy() { Some(u128::MAX), Some(&mut syscall_handler), ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( result.return_value, Value::Enum { tag: 0, @@ -2045,7 +2054,7 @@ fn secp256r1_get_xy() { Some(u128::MAX), Some(&mut syscall_handler), ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( result.return_value, Value::Enum { tag: 0, @@ -2076,7 +2085,7 @@ fn secp256r1_get_xy() { Some(u128::MAX), Some(&mut syscall_handler), ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( result.return_value, Value::Enum { tag: 0, @@ -2097,13 +2106,13 @@ fn secp256r1_get_xy() { } ); - assert_eq!( + pretty_assertions_sorted::assert_eq_sorted!( syscall_handler.secp256r1_get_xy.0, [ Secp256r1Point { x: U256 { hi: 0, lo: 0 }, y: U256 { hi: 0, lo: 0 }, - is_infinity: false + is_infinity: true }, Secp256r1Point { x: U256 { @@ -2114,7 +2123,7 @@ fn secp256r1_get_xy() { lo: u128::MAX, hi: 0, }, - is_infinity: false + is_infinity: true }, Secp256r1Point { x: U256 { @@ -2125,7 +2134,7 @@ fn secp256r1_get_xy() { lo: 0, hi: u128::MAX, }, - is_infinity: false + is_infinity: true }, Secp256r1Point { x: U256 { @@ -2136,7 +2145,7 @@ fn secp256r1_get_xy() { hi: u128::MAX, lo: u128::MAX, }, - is_infinity: false + is_infinity: true }, ], );