diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b18e615c7..13ce934e72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ More expansive patch notes and explanations may be found in the specific [pathfi The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Changed + +- BREAKING: JSON-RPC input no longer accepts hex strings that are missing the `0x` prefix, in line with the Starknet API spec. + ## [0.22.2] - 2026-04-07 ### Changed diff --git a/crates/class-hash/src/lib.rs b/crates/class-hash/src/lib.rs index 2400fe0097..d9818f8848 100644 --- a/crates/class-hash/src/lib.rs +++ b/crates/class-hash/src/lib.rs @@ -846,7 +846,7 @@ pub mod json { // fields (which we now need to ignore if empty). let expected = ComputedClassHash::Cairo(class_hash!( - "056b96c1d1bbfa01af44b465763d1b71150fa00c6c9d54c3947f57e979ff68c3" + "0x056b96c1d1bbfa01af44b465763d1b71150fa00c6c9d54c3947f57e979ff68c3" )); // Known contract which triggered a hash mismatch failure. diff --git a/crates/common/src/consts.rs b/crates/common/src/consts.rs index 31d44e3757..5fb9c9df81 100644 --- a/crates/common/src/consts.rs +++ b/crates/common/src/consts.rs @@ -4,10 +4,10 @@ use crate::macro_prelude::block_hash; use crate::BlockHash; pub const MAINNET_GENESIS_HASH: BlockHash = - block_hash!("047C3637B57C2B079B93C61539950C17E868A28F46CDEF28F88521067F21E943"); + block_hash!("0x047C3637B57C2B079B93C61539950C17E868A28F46CDEF28F88521067F21E943"); pub const SEPOLIA_TESTNET_GENESIS_HASH: BlockHash = - block_hash!("5c627d4aeb51280058bed93c7889bce78114d63baad1be0f0aeb32496d5f19c"); + block_hash!("0x5c627d4aeb51280058bed93c7889bce78114d63baad1be0f0aeb32496d5f19c"); pub const SEPOLIA_INTEGRATION_GENESIS_HASH: BlockHash = - block_hash!("19f675d3fb226821493a6ab9a1955e384bba80f130de625621a418e9a7c0ca3"); + block_hash!("0x19f675d3fb226821493a6ab9a1955e384bba80f130de625621a418e9a7c0ca3"); diff --git a/crates/common/src/event.rs b/crates/common/src/event.rs index 235c04332d..0eca48ab47 100644 --- a/crates/common/src/event.rs +++ b/crates/common/src/event.rs @@ -46,13 +46,13 @@ fn starkhash_to_dec_str(h: &Felt) -> String { /// A helper conversion function. Only use with __sequencer API related types__. fn starkhash_from_dec_str(s: &str) -> Result { - match BigUint::from_str(s) { - Ok(b) => { - let h = Felt::from_be_slice(&b.to_bytes_be())?; - Ok(h) - } + // The order here matters because `Felt::from_hex_str` requires the '0x' + // prefix, so we'll never parse a hex string as a decimal string by mistake. + match Felt::from_hex_str(s) { + Ok(h) => Ok(h), Err(_) => { - let h = Felt::from_hex_str(s)?; + let b = BigUint::from_str(s)?; + let h = Felt::from_be_slice(&b.to_bytes_be())?; Ok(h) } } diff --git a/crates/common/src/macros.rs b/crates/common/src/macros.rs index cede112a7b..3d257374d9 100644 --- a/crates/common/src/macros.rs +++ b/crates/common/src/macros.rs @@ -304,6 +304,9 @@ macro_rules! felt { Err(pathfinder_crypto::HexParseError::InvalidLength { .. }) => { panic!("Too many hex digits") } + Err(pathfinder_crypto::HexParseError::MissingPrefix) => { + panic!("Missing '0x' prefix") + } Err(pathfinder_crypto::HexParseError::Overflow) => panic!("Felt overflow"), }; CONST_FELT diff --git a/crates/crypto/src/algebra/field/felt.rs b/crates/crypto/src/algebra/field/felt.rs index 2b01e12832..4d6295eabd 100644 --- a/crates/crypto/src/algebra/field/felt.rs +++ b/crates/crypto/src/algebra/field/felt.rs @@ -323,8 +323,8 @@ impl From for Felt { impl Felt { /// A convenience function which parses a hex string into a [Felt]. /// - /// Supports both upper and lower case hex strings, as well as an optional - /// "0x" prefix. + /// Supports both upper and lower case hex strings. The '0x' prefix is + /// mandatory. pub const fn from_hex_str(hex_str: &str) -> Result { const fn parse_hex_digit(digit: u8) -> Result { match digit { @@ -336,19 +336,16 @@ impl Felt { } let bytes = hex_str.as_bytes(); - let start = if bytes.len() >= 2 && bytes[0] == b'0' && bytes[1] == b'x' { - 2 - } else { - 0 + let len = match bytes { + [b'0', b'x', rest @ ..] if rest.len() > 64 => { + return Err(HexParseError::InvalidLength { + max: 64, + actual: rest.len(), + }) + } + [b'0', b'x', rest @ ..] => rest.len(), + _ => return Err(HexParseError::MissingPrefix), }; - let len = bytes.len() - start; - - if len > 64 { - return Err(HexParseError::InvalidLength { - max: 64, - actual: bytes.len(), - }); - } let mut buf = [0u8; 32]; @@ -358,7 +355,7 @@ impl Felt { // Handle a possible odd nibble remaining nibble. if len % 2 == 1 { let idx = len / 2; - buf[31 - idx] = match parse_hex_digit(bytes[start]) { + buf[31 - idx] = match parse_hex_digit(bytes[2]) { Ok(b) => b, Err(e) => return Err(e), }; @@ -461,6 +458,7 @@ impl Felt { pub enum HexParseError { InvalidNibble(u8), InvalidLength { max: usize, actual: usize }, + MissingPrefix, Overflow, } @@ -479,6 +477,7 @@ impl std::fmt::Display for HexParseError { Self::InvalidLength { max, actual } => { f.write_fmt(format_args!("More than {} digits found: {}", *max, *actual)) } + Self::MissingPrefix => f.write_str("Missing '0x' prefix"), Self::Overflow => f.write_str(OVERFLOW_MSG), } } @@ -498,7 +497,7 @@ mod tests { #[test] fn view_bits() { - let one = Felt::from_hex_str("1").unwrap(); + let one = Felt::from_hex_str("0x1").unwrap(); let one = one.view_bits().to_bitvec(); @@ -566,7 +565,7 @@ mod tests { #[test] fn round_trip() { - let original = Felt::from_hex_str("abcdef0123456789").unwrap(); + let original = Felt::from_hex_str("0xabcdef0123456789").unwrap(); let bytes = original.to_be_bytes(); let result = Felt::from_be_slice(&bytes[..]).unwrap(); @@ -575,7 +574,7 @@ mod tests { #[test] fn too_long() { - let original = Felt::from_hex_str("abcdef0123456789").unwrap(); + let original = Felt::from_hex_str("0xabcdef0123456789").unwrap(); let mut bytes = original.to_be_bytes().to_vec(); bytes.push(0); Felt::from_be_slice(&bytes[..]).unwrap_err(); @@ -583,7 +582,7 @@ mod tests { #[test] fn short_slice() { - let original = Felt::from_hex_str("abcdef0123456789").unwrap(); + let original = Felt::from_hex_str("0xabcdef0123456789").unwrap(); let bytes = original.to_be_bytes(); let result = Felt::from_be_slice(&bytes[24..]); @@ -610,25 +609,25 @@ mod tests { #[test] fn debug() { - let hex_str = "1234567890abcdef000edcba0987654321"; + let hex_str = "0x1234567890abcdef000edcba0987654321"; let felt = Felt::from_hex_str(hex_str).unwrap(); let result = format!("{felt:?}"); - let mut expected = "0".repeat(64 - hex_str.len()); - expected.push_str(hex_str); - let expected = format!("Felt({felt})"); + let leading_zeros = "0".repeat(64 + 2 - hex_str.len()); + let hex_upper_stripped = hex_str.strip_prefix("0x").unwrap().to_uppercase(); + let expected = format!("Felt(0x{leading_zeros}{hex_upper_stripped})"); assert_eq!(result, expected); } #[test] fn fmt() { - let hex_str = "1234567890abcdef000edcba0987654321"; + let hex_str = "0x1234567890abcdef000edcba0987654321"; let starkhash = Felt::from_hex_str(hex_str).unwrap(); let result = format!("{starkhash:x}"); - let mut expected = "0".repeat(64 - hex_str.len()); - expected.push_str(hex_str); + let mut expected = "0".repeat(64 - hex_str.len() + 2); + expected.push_str(&hex_str[2..]); // We don't really care which casing is used by fmt. assert_eq!(result.to_lowercase(), expected.to_lowercase()); @@ -636,24 +635,24 @@ mod tests { #[test] fn lower_hex() { - let hex_str = "1234567890abcdef000edcba0987654321"; + let hex_str = "0x1234567890abcdef000edcba0987654321"; let starkhash = Felt::from_hex_str(hex_str).unwrap(); let result = format!("{starkhash:x}"); - let mut expected = "0".repeat(64 - hex_str.len()); - expected.push_str(hex_str); + let mut expected = "0".repeat(64 - hex_str.len() + 2); + expected.push_str(&hex_str[2..]); assert_eq!(result, expected.to_lowercase()); } #[test] fn upper_hex() { - let hex_str = "1234567890abcdef000edcba0987654321"; + let hex_str = "0x1234567890abcdef000edcba0987654321"; let starkhash = Felt::from_hex_str(hex_str).unwrap(); let result = format!("{starkhash:X}"); - let mut expected = "0".repeat(64 - hex_str.len()); - expected.push_str(hex_str); + let mut expected = "0".repeat(64 - hex_str.len() + 2); + expected.push_str(&hex_str[2..]); assert_eq!(result, expected.to_uppercase()); } @@ -686,13 +685,6 @@ mod tests { #[test] fn simple() { - let (test_str, expected) = test_data(); - let uut = Felt::from_hex_str(test_str).unwrap(); - assert_eq!(uut, expected); - } - - #[test] - fn prefix() { let (test_str, expected) = test_data(); let uut = Felt::from_hex_str(&format!("0x{test_str}")).unwrap(); assert_eq!(uut, expected); @@ -700,13 +692,6 @@ mod tests { #[test] fn leading_zeros() { - let (test_str, expected) = test_data(); - let uut = Felt::from_hex_str(&format!("000000000{test_str}")).unwrap(); - assert_eq!(uut, expected); - } - - #[test] - fn prefix_and_leading_zeros() { let (test_str, expected) = test_data(); let uut = Felt::from_hex_str(&format!("0x000000000{test_str}")).unwrap(); assert_eq!(uut, expected); @@ -717,9 +702,24 @@ mod tests { assert_matches!(Felt::from_hex_str("0x123z").unwrap_err(), HexParseError::InvalidNibble(n) => assert_eq!(n, b'z')) } + #[test] + fn missing_prefix() { + assert_matches!( + Felt::from_hex_str("123").unwrap_err(), + HexParseError::MissingPrefix + ) + } + #[test] fn invalid_len() { - assert_matches!(Felt::from_hex_str(&"1".repeat(65)).unwrap_err(), HexParseError::InvalidLength{max: 64, actual: n} => assert_eq!(n, 65)) + let invalid_str = "0".repeat(65); + assert_matches!( + Felt::from_hex_str(&format!("0x{invalid_str}")).unwrap_err(), + HexParseError::InvalidLength { + max: 64, + actual: 65 + } + ); } #[test] diff --git a/crates/crypto/src/algebra/field/serde.rs b/crates/crypto/src/algebra/field/serde.rs index c333aa3b52..b1889633c6 100644 --- a/crates/crypto/src/algebra/field/serde.rs +++ b/crates/crypto/src/algebra/field/serde.rs @@ -26,7 +26,7 @@ impl<'de> Deserialize<'de> for Felt { type Value = Felt; fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("a hex string of up to 64 digits with an optional '0x' prefix") + formatter.write_str("a hex string of up to 64 digits with a mandatory '0x' prefix") } fn visit_str(self, v: &str) -> Result @@ -53,7 +53,11 @@ mod tests { #[test] fn empty() { - assert_eq!(serde_json::from_str::(r#""""#).unwrap(), Felt::ZERO); + assert!(serde_json::from_str::(r#""""#) + .unwrap_err() + .to_string() + // Serde errors also include the line/column. + .starts_with("Missing '0x' prefix")); assert_eq!(serde_json::from_str::(r#""0x""#).unwrap(), Felt::ZERO); } diff --git a/crates/crypto/src/hash/pedersen/hash.rs b/crates/crypto/src/hash/pedersen/hash.rs index 13348da54f..9eea97b065 100644 --- a/crates/crypto/src/hash/pedersen/hash.rs +++ b/crates/crypto/src/hash/pedersen/hash.rs @@ -52,15 +52,18 @@ mod tests { #[test] fn test_pedersen() { // Test vector from https://github.com/starkware-libs/crypto-cpp/blob/master/src/starkware/crypto/pedersen_hash_test.cc - let a = - Felt::from_hex_str("03d937c035c878245caf64531a5756109c53068da139362728feb561405371cb") - .unwrap(); - let b = - Felt::from_hex_str("0208a0a10250e382e1e4bbe2880906c2791bf6275695e02fbbc6aeff9cd8b31a") - .unwrap(); - let expected = - Felt::from_hex_str("030e480bed5fe53fa909cc0f8c4d99b8f9f2c016be4c41e13a4848797979c662") - .unwrap(); + let a = Felt::from_hex_str( + "0x03d937c035c878245caf64531a5756109c53068da139362728feb561405371cb", + ) + .unwrap(); + let b = Felt::from_hex_str( + "0x0208a0a10250e382e1e4bbe2880906c2791bf6275695e02fbbc6aeff9cd8b31a", + ) + .unwrap(); + let expected = Felt::from_hex_str( + "0x030e480bed5fe53fa909cc0f8c4d99b8f9f2c016be4c41e13a4848797979c662", + ) + .unwrap(); let hash = pedersen_hash(a, b); assert_eq!(hash, expected); diff --git a/crates/crypto/src/hash/poseidon/hash.rs b/crates/crypto/src/hash/poseidon/hash.rs index 20ead3bedc..af13fc6ab0 100644 --- a/crates/crypto/src/hash/poseidon/hash.rs +++ b/crates/crypto/src/hash/poseidon/hash.rs @@ -170,8 +170,10 @@ mod tests { #[test] fn test_sponge() { let expected_result = MontFelt::from( - Felt::from_hex_str("07b8f30ac298ea12d170c0873f1fa631a18c00756c6e7d1fd273b9a239d0d413") - .unwrap(), + Felt::from_hex_str( + "0x07b8f30ac298ea12d170c0873f1fa631a18c00756c6e7d1fd273b9a239d0d413", + ) + .unwrap(), ); // Construct messages, the first few integers diff --git a/crates/crypto/src/signature/ecdsa.rs b/crates/crypto/src/signature/ecdsa.rs index ae67876149..6ddfa25776 100644 --- a/crates/crypto/src/signature/ecdsa.rs +++ b/crates/crypto/src/signature/ecdsa.rs @@ -215,10 +215,10 @@ mod tests { #[test] fn test_get_pk() { - let sk = felt_hex("03c1e9550e66958296d11b60f8e8e7a7ad990d07fa65d5f7652c4a6c87d4e3cc"); + let sk = felt_hex("0x03c1e9550e66958296d11b60f8e8e7a7ad990d07fa65d5f7652c4a6c87d4e3cc"); - let pk_x = felm_hex("77a3b314db07c45076d11f62b6f9e748a39790441823307743cf00d6597ea43"); - let pk_y = felm_hex("54d7beec5ec728223671c627557efc5c9a6508425dc6c900b7741bf60afec06"); + let pk_x = felm_hex("0x77a3b314db07c45076d11f62b6f9e748a39790441823307743cf00d6597ea43"); + let pk_y = felm_hex("0x54d7beec5ec728223671c627557efc5c9a6508425dc6c900b7741bf60afec06"); let pk = get_pk(sk).expect("valid sk"); let pk_affine = AffinePoint::from_x(pk.into()).unwrap(); @@ -229,17 +229,17 @@ mod tests { #[test] fn from_x() { - let pk_x = felm_hex("77a3b314db07c45076d11f62b6f9e748a39790441823307743cf00d6597ea43"); - let pk_y = felm_hex("54d7beec5ec728223671c627557efc5c9a6508425dc6c900b7741bf60afec06"); + let pk_x = felm_hex("0x77a3b314db07c45076d11f62b6f9e748a39790441823307743cf00d6597ea43"); + let pk_y = felm_hex("0x54d7beec5ec728223671c627557efc5c9a6508425dc6c900b7741bf60afec06"); let pk_affine = AffinePoint::from_x(pk_x).unwrap(); assert_eq!(pk_affine.y, pk_y); } #[test] fn get_partial_pk() { - let pk_x = felt_hex("77a3b314db07c45076d11f62b6f9e748a39790441823307743cf00d6597ea43"); + let pk_x = felt_hex("0x77a3b314db07c45076d11f62b6f9e748a39790441823307743cf00d6597ea43"); - let sk = felt_hex("03c1e9550e66958296d11b60f8e8e7a7ad990d07fa65d5f7652c4a6c87d4e3cc"); + let sk = felt_hex("0x03c1e9550e66958296d11b60f8e8e7a7ad990d07fa65d5f7652c4a6c87d4e3cc"); let pk = get_pk(sk).unwrap(); assert_eq!(pk, pk_x); @@ -247,8 +247,8 @@ mod tests { #[test] fn verify_partial() { - let sk = felt_hex("03c1e9550e66958296d11b60f8e8e7a7ad990d07fa65d5f7652c4a6c87d4e3cc"); - let msg = felt_hex("397e76d1667c4454bfb83514e120583af836f8e32a516765497823eabe16a3f"); + let sk = felt_hex("0x03c1e9550e66958296d11b60f8e8e7a7ad990d07fa65d5f7652c4a6c87d4e3cc"); + let msg = felt_hex("0x397e76d1667c4454bfb83514e120583af836f8e32a516765497823eabe16a3f"); let sig = ecdsa_sign(sk, msg).expect("can sign"); let pk = get_pk(sk).expect("can get pk"); assert!(ecdsa_verify_partial(pk, msg, sig.0, sig.1).is_ok()); @@ -257,12 +257,12 @@ mod tests { #[test] fn verify_inner() { // Test vector from https://github.com/starkware-libs/crypto-cpp/blob/master/src/starkware/crypto/ecdsa_test.cc - let pk_x = felm_hex("77a3b314db07c45076d11f62b6f9e748a39790441823307743cf00d6597ea43"); + let pk_x = felm_hex("0x77a3b314db07c45076d11f62b6f9e748a39790441823307743cf00d6597ea43"); let pk = ProjectivePoint::from_x(pk_x).unwrap(); - let msg = felt_hex("397e76d1667c4454bfb83514e120583af836f8e32a516765497823eabe16a3f"); - let r = felt_hex("173fd03d8b008ee7432977ac27d1e9d1a1f6c98b1a2f05fa84a21c84c44e882"); - let w = felt_hex("1f2c44a7798f55192f153b4c48ea5c1241fbb69e6132cc8a0da9c5b62a4286e"); + let msg = felt_hex("0x397e76d1667c4454bfb83514e120583af836f8e32a516765497823eabe16a3f"); + let r = felt_hex("0x173fd03d8b008ee7432977ac27d1e9d1a1f6c98b1a2f05fa84a21c84c44e882"); + let w = felt_hex("0x1f2c44a7798f55192f153b4c48ea5c1241fbb69e6132cc8a0da9c5b62a4286e"); // Compute s=1/w let w = CurveOrderMontFelt::try_from(MontFelt::from(w)).unwrap(); @@ -274,31 +274,31 @@ mod tests { #[test] fn verify_bad() { // Changed last byte of pk from 3 to 4 - let pk = felt_hex("77a3b314db07c45076d11f62b6f9e748a39790441823307743cf00d6597ea44"); - let msg = felt_hex("397e76d1667c4454bfb83514e120583af836f8e32a516765497823eabe16a3f"); - let r = felt_hex("173fd03d8b008ee7432977ac27d1e9d1a1f6c98b1a2f05fa84a21c84c44e882"); - let s = felt_hex("1f2c44a7798f55192f153b4c48ea5c1241fbb69e6132cc8a0da9c5b62a4286e"); + let pk = felt_hex("0x77a3b314db07c45076d11f62b6f9e748a39790441823307743cf00d6597ea44"); + let msg = felt_hex("0x397e76d1667c4454bfb83514e120583af836f8e32a516765497823eabe16a3f"); + let r = felt_hex("0x173fd03d8b008ee7432977ac27d1e9d1a1f6c98b1a2f05fa84a21c84c44e882"); + let s = felt_hex("0x1f2c44a7798f55192f153b4c48ea5c1241fbb69e6132cc8a0da9c5b62a4286e"); assert!(ecdsa_verify_partial(pk, msg, r, s).is_err()); // Changed last byte of msg from f to 0 - let pk = felt_hex("77a3b314db07c45076d11f62b6f9e748a39790441823307743cf00d6597ea43"); - let msg = felt_hex("397e76d1667c4454bfb83514e120583af836f8e32a516765497823eabe16a30"); - let r = felt_hex("173fd03d8b008ee7432977ac27d1e9d1a1f6c98b1a2f05fa84a21c84c44e882"); - let s = felt_hex("1f2c44a7798f55192f153b4c48ea5c1241fbb69e6132cc8a0da9c5b62a4286e"); + let pk = felt_hex("0x77a3b314db07c45076d11f62b6f9e748a39790441823307743cf00d6597ea43"); + let msg = felt_hex("0x397e76d1667c4454bfb83514e120583af836f8e32a516765497823eabe16a30"); + let r = felt_hex("0x173fd03d8b008ee7432977ac27d1e9d1a1f6c98b1a2f05fa84a21c84c44e882"); + let s = felt_hex("0x1f2c44a7798f55192f153b4c48ea5c1241fbb69e6132cc8a0da9c5b62a4286e"); assert!(ecdsa_verify_partial(pk, msg, r, s).is_err()); // Changed last byte of r from 2 to 3 - let pk = felt_hex("77a3b314db07c45076d11f62b6f9e748a39790441823307743cf00d6597ea43"); - let msg = felt_hex("397e76d1667c4454bfb83514e120583af836f8e32a516765497823eabe16a3f"); - let r = felt_hex("173fd03d8b008ee7432977ac27d1e9d1a1f6c98b1a2f05fa84a21c84c44e883"); - let s = felt_hex("1f2c44a7798f55192f153b4c48ea5c1241fbb69e6132cc8a0da9c5b62a4286e"); + let pk = felt_hex("0x77a3b314db07c45076d11f62b6f9e748a39790441823307743cf00d6597ea43"); + let msg = felt_hex("0x397e76d1667c4454bfb83514e120583af836f8e32a516765497823eabe16a3f"); + let r = felt_hex("0x173fd03d8b008ee7432977ac27d1e9d1a1f6c98b1a2f05fa84a21c84c44e883"); + let s = felt_hex("0x1f2c44a7798f55192f153b4c48ea5c1241fbb69e6132cc8a0da9c5b62a4286e"); assert!(ecdsa_verify_partial(pk, msg, r, s).is_err()); // Changed last byte of s from e to f - let pk = felt_hex("77a3b314db07c45076d11f62b6f9e748a39790441823307743cf00d6597ea43"); - let msg = felt_hex("397e76d1667c4454bfb83514e120583af836f8e32a516765497823eabe16a3f"); - let r = felt_hex("173fd03d8b008ee7432977ac27d1e9d1a1f6c98b1a2f05fa84a21c84c44e882"); - let s = felt_hex("1f2c44a7798f55192f153b4c48ea5c1241fbb69e6132cc8a0da9c5b62a4286f"); + let pk = felt_hex("0x77a3b314db07c45076d11f62b6f9e748a39790441823307743cf00d6597ea43"); + let msg = felt_hex("0x397e76d1667c4454bfb83514e120583af836f8e32a516765497823eabe16a3f"); + let r = felt_hex("0x173fd03d8b008ee7432977ac27d1e9d1a1f6c98b1a2f05fa84a21c84c44e882"); + let s = felt_hex("0x1f2c44a7798f55192f153b4c48ea5c1241fbb69e6132cc8a0da9c5b62a4286f"); assert!(ecdsa_verify_partial(pk, msg, r, s).is_err()); } @@ -322,10 +322,10 @@ mod tests { #[test] fn openzeppelin_signature() { // From https://testnet.starkscan.co/tx/0x0630a81628900577eea4b4a677767e57a56dabd730c2f64772ecbbde22ff485a - let pk = felt_hex("792c60ec4fdfea7ce6409db046b8dde11f595911cb74906be02a87ae6a4f70d"); - let msg = felt_hex("0630a81628900577eea4b4a677767e57a56dabd730c2f64772ecbbde22ff485a"); - let r = felt_hex("176846ea9b114f4f27f0d4d3cefacb5f830513fbd2d2f69a1a4d7552ae040be"); - let s = felt_hex("601a87d6bc3e3a6513bafa1d449ffb3a0dd6cbe72f927a8e7271af0e8dd1302"); + let pk = felt_hex("0x792c60ec4fdfea7ce6409db046b8dde11f595911cb74906be02a87ae6a4f70d"); + let msg = felt_hex("0x0630a81628900577eea4b4a677767e57a56dabd730c2f64772ecbbde22ff485a"); + let r = felt_hex("0x176846ea9b114f4f27f0d4d3cefacb5f830513fbd2d2f69a1a4d7552ae040be"); + let s = felt_hex("0x601a87d6bc3e3a6513bafa1d449ffb3a0dd6cbe72f927a8e7271af0e8dd1302"); assert!(ecdsa_verify_partial(pk, msg, r, s).is_ok()); } } diff --git a/crates/gateway-client/src/lib.rs b/crates/gateway-client/src/lib.rs index 440ae5fb7f..f9d5242aa6 100644 --- a/crates/gateway-client/src/lib.rs +++ b/crates/gateway-client/src/lib.rs @@ -866,7 +866,7 @@ mod tests { ) { ( TransactionVersion::ONE, - fee!("4F388496839"), + fee!("0x4F388496839"), vec![ transaction_signature_elem!( "0x07dd3a55d94a0de6f3d6c104d7e6c88ec719a82f4e2bbc12587c8c187584d3d5" @@ -882,10 +882,10 @@ mod tests { vec![ call_param!("0x1"), call_param!( - "0677bb1cdc050e8d63855e8743ab6e09179138def390676cc03c484daf112ba1" + "0x0677bb1cdc050e8d63855e8743ab6e09179138def390676cc03c484daf112ba1" ), call_param!( - "0362398bec32bc0ebb411203221a35a0301193a96f317ebe5e40be9f60d15320" + "0x0362398bec32bc0ebb411203221a35a0301193a96f317ebe5e40be9f60d15320" ), CallParam(Felt::ZERO), call_param!("0x1"), @@ -1114,11 +1114,11 @@ mod tests { vec![ SelectorAndOffset { offset: byte_code_offset!("0x3a"), - selector: entry_point!("0362398bec32bc0ebb411203221a35a0301193a96f317ebe5e40be9f60d15320"), + selector: entry_point!("0x0362398bec32bc0ebb411203221a35a0301193a96f317ebe5e40be9f60d15320"), }, SelectorAndOffset { offset: byte_code_offset!("0x5b"), - selector: entry_point!("039e11d48192e4333233c7eb19d10ad67c362bb28580c604d67884c85da39695"), + selector: entry_point!("0x039e11d48192e4333233c7eb19d10ad67c362bb28580c604d67884c85da39695"), }, ], ), diff --git a/crates/gateway-test-fixtures/src/lib.rs b/crates/gateway-test-fixtures/src/lib.rs index 70b5f132b1..38d36f3b67 100644 --- a/crates/gateway-test-fixtures/src/lib.rs +++ b/crates/gateway-test-fixtures/src/lib.rs @@ -125,7 +125,7 @@ pub mod class_definitions { pub const CONTRACT_DEFINITION: &[u8] = bytes_fixture!("contracts/contract_definition.json"); pub const CONTRACT_DEFINITION_CLASS_HASH: ClassHash = - class_hash!("050b2148c0d782914e0b12a1a32abe5e398930b7e914f82c65cb7afce0a0ab9b"); + class_hash!("0x050b2148c0d782914e0b12a1a32abe5e398930b7e914f82c65cb7afce0a0ab9b"); pub const DUMMY_ACCOUNT: &[u8] = bytes_fixture!("contracts/dummy_account.json"); pub const DUMMY_ACCOUNT_CLASS_HASH: ClassHash = class_hash!("0x0791563da22895f1e398b689866718346106c0cc71207a4ada68e6687ce1badf"); @@ -209,26 +209,26 @@ pub mod testnet { use pathfinder_crypto::Felt; pub const VALID_TX_HASH: TransactionHash = - transaction_hash!("0493d8fab73af67e972788e603aee18130facd3c7685f16084ecd98b07153e24"); + transaction_hash!("0x0493d8fab73af67e972788e603aee18130facd3c7685f16084ecd98b07153e24"); pub const INVALID_TX_HASH: TransactionHash = - transaction_hash!("0393d8fab73af67e972788e603aee18130facd3c7685f16084ecd98b07153e24"); + transaction_hash!("0x0393d8fab73af67e972788e603aee18130facd3c7685f16084ecd98b07153e24"); pub const VALID_CONTRACT_ADDR: ContractAddress = - contract_address!("06fbd460228d843b7fbef670ff15607bf72e19fa94de21e29811ada167b4ca39"); + contract_address!("0x06fbd460228d843b7fbef670ff15607bf72e19fa94de21e29811ada167b4ca39"); pub const INVALID_CONTRACT_ADDR: ContractAddress = - contract_address!("05fbd460228d843b7fbef670ff15607bf72e19fa94de21e29811ada167b4ca39"); + contract_address!("0x05fbd460228d843b7fbef670ff15607bf72e19fa94de21e29811ada167b4ca39"); pub const VALID_ENTRY_POINT: EntryPoint = - entry_point!("0362398bec32bc0ebb411203221a35a0301193a96f317ebe5e40be9f60d15320"); + entry_point!("0x0362398bec32bc0ebb411203221a35a0301193a96f317ebe5e40be9f60d15320"); pub const INVALID_ENTRY_POINT: EntryPoint = EntryPoint(Felt::ZERO); pub const VALID_KEY: StorageAddress = - storage_address!("0206F38F7E4F15E87567361213C28F235CCCDAA1D7FD34C9DB1DFE9489C6A091"); + storage_address!("0x0206F38F7E4F15E87567361213C28F235CCCDAA1D7FD34C9DB1DFE9489C6A091"); pub const VALID_KEY_DEC: &str = "916907772491729262376534102982219947830828984996257231353398618781993312401"; pub const VALID_CALL_DATA: [CallParam; 1] = [call_param!("0x4d2")]; /// Class hash for VALID_CONTRACT_ADDR pub const VALID_CLASS_HASH: ClassHash = - class_hash!("021a7f43387573b68666669a0ed764252ce5367708e696e31967764a90b429c2"); + class_hash!("0x021a7f43387573b68666669a0ed764252ce5367708e696e31967764a90b429c2"); pub const INVALID_CLASS_HASH: ClassHash = - class_hash!("031a7f43387573b68666669a0ed764252ce5367708e696e31967764a90b429c2"); + class_hash!("0x031a7f43387573b68666669a0ed764252ce5367708e696e31967764a90b429c2"); } pub mod traces { diff --git a/crates/gateway-types/src/reply.rs b/crates/gateway-types/src/reply.rs index e08b13a11e..3599c03fd4 100644 --- a/crates/gateway-types/src/reply.rs +++ b/crates/gateway-types/src/reply.rs @@ -2308,7 +2308,7 @@ pub mod add_transaction { let expected = InvokeResponse { code: "TRANSACTION_RECEIVED".to_owned(), transaction_hash: transaction_hash!( - "0389dd0629f42176cc8b6c43acefc0713d0064ecdfc0470e0fc179f53421a38b" + "0x0389dd0629f42176cc8b6c43acefc0713d0064ecdfc0470e0fc179f53421a38b" ), }; assert_eq!(expected, result); @@ -2320,10 +2320,10 @@ pub mod add_transaction { let expected = DeployResponse { code: "TRANSACTION_RECEIVED".to_owned(), transaction_hash: transaction_hash!( - "0296fb89b8a1c7487a1d4b27e1a1e33f440b05548e64980d06052bc089b1a51f" + "0x0296fb89b8a1c7487a1d4b27e1a1e33f440b05548e64980d06052bc089b1a51f" ), address: contract_address!( - "0677bb1cdc050e8d63855e8743ab6e09179138def390676cc03c484daf112ba1" + "0x0677bb1cdc050e8d63855e8743ab6e09179138def390676cc03c484daf112ba1" ), }; assert_eq!(expected, result); diff --git a/crates/merkle-tree/src/merkle_node.rs b/crates/merkle-tree/src/merkle_node.rs index b539f702de..08788920b2 100644 --- a/crates/merkle-tree/src/merkle_node.rs +++ b/crates/merkle-tree/src/merkle_node.rs @@ -274,7 +274,7 @@ mod tests { // Note that the hash function must be exchanged for `async_stark_hash_func`, // otherwise it just uses some other test hash function. let expected = Felt::from_hex_str( - "0615bb8d47888d2987ad0c63fc06e9e771930986a4dd8adc55617febfcf3639e", + "0x0615bb8d47888d2987ad0c63fc06e9e771930986a4dd8adc55617febfcf3639e", ) .unwrap(); let left = felt!("0x1234"); @@ -300,7 +300,7 @@ mod tests { // Note that the hash function must be exchanged for `async_stark_hash_func`, // otherwise it just uses some other test hash function. let expected = Felt::from_hex_str( - "1d937094c09b5f8e26a662d21911871e3cbc6858d55cc49af9848ea6fed4e9", + "0x1d937094c09b5f8e26a662d21911871e3cbc6858d55cc49af9848ea6fed4e9", ) .unwrap(); let child = felt!("0x1234ABCD"); diff --git a/crates/pathfinder/src/state/block_hash.rs b/crates/pathfinder/src/state/block_hash.rs index b223879e68..8298fd2520 100644 --- a/crates/pathfinder/src/state/block_hash.rs +++ b/crates/pathfinder/src/state/block_hash.rs @@ -221,7 +221,7 @@ mod meta { const MAINNET_METAINFO: BlockHashMetaInfo = BlockHashMetaInfo { first_0_7_block: BlockNumber::new_or_panic(833), fallback_sequencer_address: Some(sequencer_address!( - "021f4b90b0377c82bf330b7b5295820769e72d79d8acd0effa0ebde6e9988bc5" + "0x021f4b90b0377c82bf330b7b5295820769e72d79d8acd0effa0ebde6e9988bc5" )), }; diff --git a/crates/rpc/src/felt.rs b/crates/rpc/src/felt.rs index 9f6a5354a3..91674fde9a 100644 --- a/crates/rpc/src/felt.rs +++ b/crates/rpc/src/felt.rs @@ -227,21 +227,16 @@ mod deserialization { fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { formatter - .write_str("a hex string of up to 64 digits with an optional '0x' prefix") + .write_str("a hex string of up to 64 digits with a mandatory '0x' prefix") } fn visit_str(self, v: &str) -> Result where E: serde::de::Error, { - // Felt::from_hex_str currently does not enforce `0x` prefix, add it here to - // prevent breaking other serde related code. - match v.as_bytes() { - &[b'0', b'x', ..] => pathfinder_crypto::Felt::from_hex_str(v) - .map_err(|e| serde::de::Error::custom(e)) - .map(RpcFelt), - _missing_prefix => Err(serde::de::Error::custom("Missing '0x' prefix")), - } + pathfinder_crypto::Felt::from_hex_str(v) + .map_err(|e| serde::de::Error::custom(e)) + .map(RpcFelt) } } diff --git a/crates/rpc/src/lib.rs b/crates/rpc/src/lib.rs index d337bb645c..22e48a2ff1 100644 --- a/crates/rpc/src/lib.rs +++ b/crates/rpc/src/lib.rs @@ -1504,9 +1504,9 @@ mod tests { line!(), r#"{"starting_block_hash":"0xa","starting_block_num":"0x1","current_block_hash":"0xb","current_block_num":"0x2","highest_block_hash":"0xc","highest_block_num":"0x3"}"#, Syncing::Status(Status { - starting: NumberedBlock::from(("a", 1)), - current: NumberedBlock::from(("b", 2)), - highest: NumberedBlock::from(("c", 3)), + starting: NumberedBlock::from(("0xa", 1)), + current: NumberedBlock::from(("0xb", 2)), + highest: NumberedBlock::from(("0xc", 3)), }), ), ]; diff --git a/crates/rpc/src/method/add_deploy_account_transaction.rs b/crates/rpc/src/method/add_deploy_account_transaction.rs index de7d8aeb47..d7873f297e 100644 --- a/crates/rpc/src/method/add_deploy_account_transaction.rs +++ b/crates/rpc/src/method/add_deploy_account_transaction.rs @@ -423,22 +423,22 @@ mod tests { max_fee: fee!("0xbf391377813"), signature: vec![ transaction_signature_elem!( - "07dd3a55d94a0de6f3d6c104d7e6c88ec719a82f4e2bbc12587c8c187584d3d5" + "0x07dd3a55d94a0de6f3d6c104d7e6c88ec719a82f4e2bbc12587c8c187584d3d5" ), transaction_signature_elem!( - "071456dded17015d1234779889d78f3e7c763ddcfd2662b19e7843c7542614f8" + "0x071456dded17015d1234779889d78f3e7c763ddcfd2662b19e7843c7542614f8" ), ], nonce: TransactionNonce::ZERO, contract_address_salt: contract_address_salt!( - "06d44a6aecb4339e23a9619355f101cf3cb9baec289fcd9fd51486655c1bb8a8" + "0x06d44a6aecb4339e23a9619355f101cf3cb9baec289fcd9fd51486655c1bb8a8" ), constructor_calldata: vec![call_param!( - "0677bb1cdc050e8d63855e8743ab6e09179138def390676cc03c484daf112ba1" + "0x0677bb1cdc050e8d63855e8743ab6e09179138def390676cc03c484daf112ba1" )], class_hash: class_hash!( - "01fac3074c9d5282f0acc5c69a4781a1c711efea5e73c550c5d9fb253cf7fd3d" + "0x01fac3074c9d5282f0acc5c69a4781a1c711efea5e73c550c5d9fb253cf7fd3d" ), }), ), diff --git a/crates/rpc/src/method/add_invoke_transaction.rs b/crates/rpc/src/method/add_invoke_transaction.rs index 74e3971532..ef1c6e7020 100644 --- a/crates/rpc/src/method/add_invoke_transaction.rs +++ b/crates/rpc/src/method/add_invoke_transaction.rs @@ -355,20 +355,24 @@ mod tests { max_fee: fee!("0x4F388496839"), signature: vec![ transaction_signature_elem!( - "07dd3a55d94a0de6f3d6c104d7e6c88ec719a82f4e2bbc12587c8c187584d3d5" + "0x07dd3a55d94a0de6f3d6c104d7e6c88ec719a82f4e2bbc12587c8c187584d3d5" ), transaction_signature_elem!( - "071456dded17015d1234779889d78f3e7c763ddcfd2662b19e7843c7542614f8" + "0x071456dded17015d1234779889d78f3e7c763ddcfd2662b19e7843c7542614f8" ), ], nonce: transaction_nonce!("0x1"), sender_address: contract_address!( - "023371b227eaecd8e8920cd429357edddd2cd0f3fee6abaacca08d3ab82a7cdd" + "0x023371b227eaecd8e8920cd429357edddd2cd0f3fee6abaacca08d3ab82a7cdd" ), calldata: vec![ call_param!("0x1"), - call_param!("0677bb1cdc050e8d63855e8743ab6e09179138def390676cc03c484daf112ba1"), - call_param!("0362398bec32bc0ebb411203221a35a0301193a96f317ebe5e40be9f60d15320"), + call_param!( + "0x0677bb1cdc050e8d63855e8743ab6e09179138def390676cc03c484daf112ba1" + ), + call_param!( + "0x0362398bec32bc0ebb411203221a35a0301193a96f317ebe5e40be9f60d15320" + ), call_param!("0x0"), call_param!("0x1"), call_param!("0x1"), @@ -507,7 +511,7 @@ mod tests { signature: vec![], nonce: transaction_nonce!("0x2"), sender_address: contract_address!( - "03fdcbeb68e607c8febf01d7ef274cbf68091a0bd1556c0b8f8e80d732f7850f" + "0x03fdcbeb68e607c8febf01d7ef274cbf68091a0bd1556c0b8f8e80d732f7850f" ), calldata: vec![], }, diff --git a/crates/rpc/src/method/call.rs b/crates/rpc/src/method/call.rs index 85be8a28cf..f0b557864d 100644 --- a/crates/rpc/src/method/call.rs +++ b/crates/rpc/src/method/call.rs @@ -829,7 +829,7 @@ mod tests { // Entry point selector for the called contract CallParam(EntryPoint::hashed(b"call").0), // Length of the call data for the called contract - call_param!("1"), + call_param!("0x1"), // Number of calls, but then no more data; leads to deserialization error call_param!("0x1"), ], @@ -875,8 +875,8 @@ mod tests { // Calldata length over the limit, the rest of the fields should not matter. calldata: vec![call_param!("0x123"); CALLDATA_LIMIT + 5], - contract_address: contract_address!("deadbeef"), - entry_point_selector: entry_point!("deadbeef"), + contract_address: contract_address!("0xdeadbeef"), + entry_point_selector: entry_point!("0xdeadbeef"), }, block_id: BlockId::Latest, }; @@ -898,7 +898,7 @@ mod tests { // Mainnet block number 5 const BLOCK_5: BlockId = BlockId::Hash(block_hash!( - "00dcbd2a4b597d051073f40a0329e585bb94b26d73df69f8d72798924fd097d3" + "0x00dcbd2a4b597d051073f40a0329e585bb94b26d73df69f8d72798924fd097d3" )); // Data from transaction @@ -906,14 +906,16 @@ mod tests { fn valid_mainnet_call() -> FunctionCall { FunctionCall { contract_address: contract_address!( - "020cfa74ee3564b4cd5435cdace0f9c4d43b939620e4a0bb5076105df0a626c6" + "0x020cfa74ee3564b4cd5435cdace0f9c4d43b939620e4a0bb5076105df0a626c6" ), entry_point_selector: entry_point!( - "03d7905601c217734671143d457f0db37f7f8883112abd34b92c4abfeafde0c3" + "0x03d7905601c217734671143d457f0db37f7f8883112abd34b92c4abfeafde0c3" ), calldata: vec![ - call_param!("e150b6c2db6ed644483b01685571de46d2045f267d437632b508c19f3eb877"), - call_param!("0494196e88ce16bff11180d59f3c75e4ba3475d9fba76249ab5f044bcd25add6"), + call_param!("0xe150b6c2db6ed644483b01685571de46d2045f267d437632b508c19f3eb877"), + call_param!( + "0x0494196e88ce16bff11180d59f3c75e4ba3475d9fba76249ab5f044bcd25add6" + ), ], } } diff --git a/crates/rpc/src/method/estimate_fee.rs b/crates/rpc/src/method/estimate_fee.rs index b4afdf719a..9f44b85477 100644 --- a/crates/rpc/src/method/estimate_fee.rs +++ b/crates/rpc/src/method/estimate_fee.rs @@ -261,7 +261,7 @@ mod tests { fn declare_transaction(account_contract_address: ContractAddress) -> BroadcastedTransaction { let sierra_definition = include_bytes!("../../fixtures/contracts/storage_access.json"); let sierra_hash = - class_hash!("0544b92d358447cb9e50b65092b7169f931d29e05c1404a2cd08c6fd7e32ba90"); + class_hash!("0x0544b92d358447cb9e50b65092b7169f931d29e05c1404a2cd08c6fd7e32ba90"); let casm_hash = casm_hash!("0x069032ff71f77284e1a0864a573007108ca5cc08089416af50f03260f5d6d4d8"); @@ -294,7 +294,7 @@ mod tests { ) -> BroadcastedTransaction { let max_fee = Fee::default(); let sierra_hash = - class_hash!("0544b92d358447cb9e50b65092b7169f931d29e05c1404a2cd08c6fd7e32ba90"); + class_hash!("0x0544b92d358447cb9e50b65092b7169f931d29e05c1404a2cd08c6fd7e32ba90"); BroadcastedTransaction::Invoke(BroadcastedInvokeTransaction::V1( BroadcastedInvokeTransactionV1 { @@ -312,7 +312,7 @@ mod tests { CallParam(EntryPoint::hashed(b"deployContract").0), // Length of the call data for the called contract, i.e. // AccountCallArray::data_len - call_param!("4"), + call_param!("0x4"), // classHash CallParam(sierra_hash.0), // salt @@ -348,7 +348,7 @@ mod tests { CallParam(EntryPoint::hashed(b"get_data").0), // Length of the call data for the called contract, i.e. // AccountCallArray::data_len - call_param!("0"), + call_param!("0x0"), ], }, )) @@ -389,7 +389,7 @@ mod tests { CallParam(EntryPoint::hashed(b"get_data").0), // Length of the call data for the called contract, i.e. // AccountCallArray::data_len - call_param!("0"), + call_param!("0x0"), ], nonce: transaction_nonce!("0x3"), resource_bounds: ResourceBounds::default(), @@ -694,7 +694,7 @@ mod tests { CallParam(EntryPoint::hashed(b"deployContract").0), // Length of the call data for the called contract, i.e. // AccountCallArray::data_len - call_param!("4"), + call_param!("0x4"), // classHash CallParam(sierra_hash.0), // salt @@ -732,7 +732,7 @@ mod tests { // Entry point selector for the called contract, i.e. CallParam(EntryPoint::hashed(b"test_redeposits").0), // Length of the call data for the called contract, i.e. - call_param!("1"), + call_param!("0x1"), depth, ], nonce, @@ -784,14 +784,14 @@ mod tests { let invoke_transaction = invoke_v3_transaction_with_data_gas( account_contract_address, transaction_nonce!("0x2"), - call_param!("7"), + call_param!("0x7"), ); // Invoke once more to test that the execution state updates properly with L2 // gas accounting aware code. let invoke_transaction2 = invoke_v3_transaction_with_data_gas( account_contract_address, transaction_nonce!("0x3"), - call_param!("7"), + call_param!("0x7"), ); let input = Input { @@ -839,14 +839,14 @@ mod tests { let invoke_transaction = invoke_v3_transaction_with_data_gas( account_contract_address, transaction_nonce!("0x2"), - call_param!("7"), + call_param!("0x7"), ); // Invoke once more to test that the execution state updates properly with L2 // gas accounting aware code. let invoke_transaction2 = invoke_v3_transaction_with_data_gas( account_contract_address, transaction_nonce!("0x3"), - call_param!("7"), + call_param!("0x7"), ); let input = Input { @@ -895,14 +895,14 @@ mod tests { let invoke_transaction = invoke_v3_transaction_with_data_gas( account_contract_address, transaction_nonce!("0x2"), - call_param!("7"), + call_param!("0x7"), ); // Invoke once more to test that the execution state updates properly with L2 // gas accounting aware code. let invoke_transaction2 = invoke_v3_transaction_with_data_gas( account_contract_address, transaction_nonce!("0x3"), - call_param!("7"), + call_param!("0x7"), ); let input = Input { @@ -949,7 +949,7 @@ mod tests { // Entry point selector for the called contract, i.e. CallParam(EntryPoint::hashed(b"bogus").0), // Length of the call data for the called contract, i.e. - call_param!("1"), + call_param!("0x1"), depth, ], nonce, @@ -995,7 +995,7 @@ mod tests { let invoke_transaction = invoke_v3_transaction_with_invalid_entry_point( account_contract_address, transaction_nonce!("0x2"), - call_param!("7"), + call_param!("0x7"), ); let input = Input { @@ -1056,7 +1056,7 @@ mod tests { let invoke_transaction = invoke_v3_transaction_with_data_gas( account_contract_address, transaction_nonce!("0x2"), - call_param!("100000"), + call_param!("0x100000"), ); let input = Input { @@ -1087,7 +1087,7 @@ mod tests { let invoke_transaction = invoke_v3_transaction_with_data_gas( account_contract_address, transaction_nonce!("0x2"), - call_param!("100"), + call_param!("0x100"), ); let input = Input { diff --git a/crates/rpc/src/method/get_events.rs b/crates/rpc/src/method/get_events.rs index 244bae1689..081b7a5c41 100644 --- a/crates/rpc/src/method/get_events.rs +++ b/crates/rpc/src/method/get_events.rs @@ -1000,7 +1000,7 @@ mod tests { let limit = EVENT_KEY_FILTER_LIMIT; - let keys = [vec![event_key!("01")]] + let keys = [vec![event_key!("0x01")]] .iter() .cloned() .cycle() diff --git a/crates/rpc/src/method/simulate_transactions.rs b/crates/rpc/src/method/simulate_transactions.rs index ee28c576c0..ddec1ab316 100644 --- a/crates/rpc/src/method/simulate_transactions.rs +++ b/crates/rpc/src/method/simulate_transactions.rs @@ -715,7 +715,7 @@ pub(crate) mod tests { include_bytes!("../../fixtures/contracts/cairo0_test.json"); pub const CAIRO0_HASH: ClassHash = - class_hash!("02c52e7084728572ea940b4df708a2684677c19fa6296de2ea7ba5327e3a84ef"); + class_hash!("0x02c52e7084728572ea940b4df708a2684677c19fa6296de2ea7ba5327e3a84ef"); let contract_class = crate::types::ContractClass::from_definition_bytes(CAIRO0_DEFINITION) .unwrap() @@ -897,7 +897,7 @@ pub(crate) mod tests { pub const SIERRA_DEFINITION: &[u8] = include_bytes!("../../fixtures/contracts/storage_access.json"); pub const SIERRA_HASH: ClassHash = - class_hash!("0544b92d358447cb9e50b65092b7169f931d29e05c1404a2cd08c6fd7e32ba90"); + class_hash!("0x0544b92d358447cb9e50b65092b7169f931d29e05c1404a2cd08c6fd7e32ba90"); pub const CASM_HASH: CasmHash = casm_hash!("0x069032ff71f77284e1a0864a573007108ca5cc08089416af50f03260f5d6d4d8"); pub const CASM_DEFINITION: &[u8] = @@ -968,7 +968,7 @@ pub(crate) mod tests { CallParam(EntryPoint::hashed(b"deployContract").0), // Length of the call data for the called contract, i.e. // AccountCallArray::data_len - call_param!("4"), + call_param!("0x4"), // classHash CallParam(SIERRA_HASH.0), // salt @@ -999,7 +999,7 @@ pub(crate) mod tests { CallParam(EntryPoint::hashed(b"get_data").0), // Length of the call data for the called contract, i.e. // AccountCallArray::data_len - call_param!("0"), + call_param!("0x0"), ], }, )) @@ -1037,7 +1037,7 @@ pub(crate) mod tests { CallParam(EntryPoint::hashed(b"get_data").0), // Length of the call data for the called contract, i.e. // AccountCallArray::data_len - call_param!("0"), + call_param!("0x0"), ], proof_facts: vec![], proof: Default::default(), @@ -1082,7 +1082,7 @@ pub(crate) mod tests { CallParam(EntryPoint::hashed(b"get_data").0), // Length of the call data for the called contract, i.e. // AccountCallArray::data_len - call_param!("0"), + call_param!("0x0"), ], proof_facts: vec![], proof: Default::default(), diff --git a/crates/serde/src/lib.rs b/crates/serde/src/lib.rs index fd063d98a3..d96fdd2d2e 100644 --- a/crates/serde/src/lib.rs +++ b/crates/serde/src/lib.rs @@ -113,7 +113,7 @@ impl<'de> DeserializeAs<'de, H256> for H256AsNoLeadingZerosHexStr { type Value = H256; fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("a hex string of up to 64 digits with an optional '0x' prefix") + formatter.write_str("a hex string of up to 64 digits with a mandatory '0x' prefix") } fn visit_str(self, v: &str) -> Result @@ -323,13 +323,13 @@ pub fn starkhash_to_dec_str(h: &Felt) -> String { /// A helper conversion function. Only use with __sequencer API related types__. fn starkhash_from_dec_str(s: &str) -> Result { - match BigUint::from_str(s) { - Ok(b) => { - let h = starkhash_from_biguint(b)?; - Ok(h) - } + // The order here matters because `Felt::from_hex_str` requires the '0x' + // prefix, so we'll never parse a hex string as a decimal string by mistake. + match Felt::from_hex_str(s) { + Ok(h) => Ok(h), Err(_) => { - let h = Felt::from_hex_str(s)?; + let b = BigUint::from_str(s)?; + let h = starkhash_from_biguint(b)?; Ok(h) } } @@ -337,8 +337,8 @@ fn starkhash_from_dec_str(s: &str) -> Result { /// A convenience function which parses a hex string into a byte array. /// -/// Supports both upper and lower case hex strings, as well as an -/// optional "0x" prefix. +/// Supports both upper and lower case hex strings. The '0x' prefix is +/// mandatory. fn bytes_from_hex_str(hex_str: &str) -> Result<[u8; N], HexParseError> { fn parse_hex_digit(digit: u8) -> Result { match digit { @@ -349,7 +349,9 @@ fn bytes_from_hex_str(hex_str: &str) -> Result<[u8; N], HexParse } } - let hex_str = hex_str.strip_prefix("0x").unwrap_or(hex_str); + let Some(hex_str) = hex_str.strip_prefix("0x") else { + return Err(HexParseError::MissingPrefix); + }; if hex_str.len() > N * 2 { return Err(HexParseError::InvalidLength { max: N * 2, @@ -488,6 +490,7 @@ pub fn extract_program_and_entry_points_by_type( #[cfg(test)] mod tests { + use num_bigint::ParseBigIntError; use pretty_assertions_sorted::assert_eq; use super::*; @@ -639,20 +642,21 @@ mod tests { // Regression: previously max in the error message was hard-coded at 64, // so try another buf size to make sure it is not anymore assert_eq!( - &format!("{}", bytes_from_hex_str::<1>("abc").unwrap_err()), + &format!("{}", bytes_from_hex_str::<1>("0xabc").unwrap_err()), "More than 2 digits found: 3" ); } #[test] fn invalid_digit() { - starkhash_from_dec_str("123a").unwrap(); + starkhash_from_dec_str("0x123a").unwrap(); assert_eq!( starkhash_from_dec_str("123z") .unwrap_err() - .downcast::() - .unwrap(), - HexParseError::InvalidNibble(b'z') + .downcast::() + .unwrap() + .to_string(), + "invalid digit found in string" ); assert_eq!( bytes_from_hex_str::<32>("0x123z"), diff --git a/crates/storage/src/connection/block.rs b/crates/storage/src/connection/block.rs index 57f157ddab..fa80ed1a09 100644 --- a/crates/storage/src/connection/block.rs +++ b/crates/storage/src/connection/block.rs @@ -695,7 +695,7 @@ mod tests { event_count: 40, l1_da_mode: L1DataAvailabilityMode::Blob, receipt_commitment: receipt_commitment_bytes!(b"receipt commitment genesis"), - state_diff_commitment: state_diff_commitment!("12"), + state_diff_commitment: state_diff_commitment!("0x12"), state_diff_length: 12, }; diff --git a/crates/storage/src/connection/ethereum.rs b/crates/storage/src/connection/ethereum.rs index f3f8aae5ee..d895466600 100644 --- a/crates/storage/src/connection/ethereum.rs +++ b/crates/storage/src/connection/ethereum.rs @@ -101,9 +101,13 @@ mod tests { fn create_updates() -> [EthereumStateUpdate; 3] { (0..3usize) .map(|i| EthereumStateUpdate { - state_root: StateCommitment(Felt::from_hex_str(&"3".repeat(i + 1)).unwrap()), + state_root: Felt::from_hex_str(&format!("0x{}", &"3".repeat(i + 1))) + .map(StateCommitment) + .unwrap(), block_number: BlockNumber::GENESIS + i as u64, - block_hash: BlockHash(Felt::from_hex_str(&"F".repeat(i + 1)).unwrap()), + block_hash: Felt::from_hex_str(&format!("0x{}", &"F".repeat(i + 1))) + .map(BlockHash) + .unwrap(), }) .collect::>() .try_into() diff --git a/crates/storage/src/connection/trie.rs b/crates/storage/src/connection/trie.rs index 141b7cb4e6..0227936d59 100644 --- a/crates/storage/src/connection/trie.rs +++ b/crates/storage/src/connection/trie.rs @@ -1277,14 +1277,14 @@ mod tests { &TrieUpdate { nodes_added: vec![ ( - felt!("0"), + felt!("0x0"), Node::Binary { left: NodeRef::Index(1), right: NodeRef::Index(2), }, ), - (felt!("1"), Node::LeafBinary), - (felt!("2"), Node::LeafBinary), + (felt!("0x1"), Node::LeafBinary), + (felt!("0x2"), Node::LeafBinary), ], nodes_removed: vec![], root_commitment: Felt::ZERO, @@ -1296,14 +1296,14 @@ mod tests { &TrieUpdate { nodes_added: vec![ ( - felt!("3"), + felt!("0x3"), Node::Binary { left: NodeRef::Index(1), right: NodeRef::Index(2), }, ), - (felt!("4"), Node::LeafBinary), - (felt!("5"), Node::LeafBinary), + (felt!("0x4"), Node::LeafBinary), + (felt!("0x5"), Node::LeafBinary), ], nodes_removed: vec![TrieStorageIndex(1)], root_commitment: Felt::ZERO, @@ -1315,14 +1315,14 @@ mod tests { &TrieUpdate { nodes_added: vec![ ( - felt!("6"), + felt!("0x6"), Node::Binary { left: NodeRef::Index(1), right: NodeRef::Index(2), }, ), - (felt!("7"), Node::LeafBinary), - (felt!("8"), Node::LeafBinary), + (felt!("0x7"), Node::LeafBinary), + (felt!("0x8"), Node::LeafBinary), ], nodes_removed: vec![], root_commitment: Felt::ZERO, @@ -1334,14 +1334,14 @@ mod tests { &TrieUpdate { nodes_added: vec![ ( - felt!("9"), + felt!("0x9"), Node::Binary { left: NodeRef::Index(1), right: NodeRef::Index(2), }, ), - (felt!("10"), Node::LeafBinary), - (felt!("11"), Node::LeafBinary), + (felt!("0x10"), Node::LeafBinary), + (felt!("0x11"), Node::LeafBinary), ], nodes_removed: vec![], root_commitment: Felt::ZERO, @@ -1357,14 +1357,14 @@ mod tests { &TrieUpdate { nodes_added: vec![ ( - felt!("12"), + felt!("0x12"), Node::Binary { left: NodeRef::Index(1), right: NodeRef::Index(2), }, ), - (felt!("13"), Node::LeafBinary), - (felt!("14"), Node::LeafBinary), + (felt!("0x13"), Node::LeafBinary), + (felt!("0x14"), Node::LeafBinary), ], nodes_removed: vec![], root_commitment: Felt::ZERO, @@ -1391,14 +1391,14 @@ mod tests { &TrieUpdate { nodes_added: vec![ ( - felt!("0"), + felt!("0x0"), Node::Binary { left: NodeRef::Index(1), right: NodeRef::Index(2), }, ), - (felt!("1"), Node::LeafBinary), - (felt!("2"), Node::LeafBinary), + (felt!("0x1"), Node::LeafBinary), + (felt!("0x2"), Node::LeafBinary), ], nodes_removed: vec![], root_commitment: Felt::ZERO, @@ -1410,14 +1410,14 @@ mod tests { &TrieUpdate { nodes_added: vec![ ( - felt!("3"), + felt!("0x3"), Node::Binary { left: NodeRef::Index(1), right: NodeRef::Index(2), }, ), - (felt!("4"), Node::LeafBinary), - (felt!("5"), Node::LeafBinary), + (felt!("0x4"), Node::LeafBinary), + (felt!("0x5"), Node::LeafBinary), ], nodes_removed: vec![TrieStorageIndex(1)], root_commitment: Felt::ZERO, @@ -1429,14 +1429,14 @@ mod tests { &TrieUpdate { nodes_added: vec![ ( - felt!("6"), + felt!("0x6"), Node::Binary { left: NodeRef::Index(1), right: NodeRef::Index(2), }, ), - (felt!("7"), Node::LeafBinary), - (felt!("8"), Node::LeafBinary), + (felt!("0x7"), Node::LeafBinary), + (felt!("0x8"), Node::LeafBinary), ], nodes_removed: vec![], root_commitment: Felt::ZERO, @@ -1448,14 +1448,14 @@ mod tests { &TrieUpdate { nodes_added: vec![ ( - felt!("9"), + felt!("0x9"), Node::Binary { left: NodeRef::Index(1), right: NodeRef::Index(2), }, ), - (felt!("10"), Node::LeafBinary), - (felt!("11"), Node::LeafBinary), + (felt!("0x10"), Node::LeafBinary), + (felt!("0x11"), Node::LeafBinary), ], nodes_removed: vec![], root_commitment: Felt::ZERO, @@ -1468,14 +1468,14 @@ mod tests { &TrieUpdate { nodes_added: vec![ ( - felt!("12"), + felt!("0x12"), Node::Binary { left: NodeRef::Index(1), right: NodeRef::Index(2), }, ), - (felt!("13"), Node::LeafBinary), - (felt!("14"), Node::LeafBinary), + (felt!("0x13"), Node::LeafBinary), + (felt!("0x14"), Node::LeafBinary), ], nodes_removed: vec![], root_commitment: Felt::ZERO, @@ -1514,14 +1514,14 @@ mod tests { &TrieUpdate { nodes_added: vec![ ( - felt!("0"), + felt!("0x0"), Node::Binary { left: NodeRef::Index(1), right: NodeRef::Index(2), }, ), - (felt!("1"), Node::LeafBinary), - (felt!("2"), Node::LeafBinary), + (felt!("0x1"), Node::LeafBinary), + (felt!("0x2"), Node::LeafBinary), ], nodes_removed: vec![], root_commitment: Felt::ZERO, @@ -1533,14 +1533,14 @@ mod tests { &TrieUpdate { nodes_added: vec![ ( - felt!("3"), + felt!("0x3"), Node::Binary { left: NodeRef::Index(1), right: NodeRef::Index(2), }, ), - (felt!("4"), Node::LeafBinary), - (felt!("5"), Node::LeafBinary), + (felt!("0x4"), Node::LeafBinary), + (felt!("0x5"), Node::LeafBinary), ], nodes_removed: vec![], root_commitment: Felt::ZERO, @@ -1552,14 +1552,14 @@ mod tests { &TrieUpdate { nodes_added: vec![ ( - felt!("6"), + felt!("0x6"), Node::Binary { left: NodeRef::Index(1), right: NodeRef::Index(2), }, ), - (felt!("7"), Node::LeafBinary), - (felt!("8"), Node::LeafBinary), + (felt!("0x7"), Node::LeafBinary), + (felt!("0x8"), Node::LeafBinary), ], nodes_removed: vec![], root_commitment: Felt::ZERO, @@ -1577,14 +1577,14 @@ mod tests { &TrieUpdate { nodes_added: vec![ ( - felt!("3"), + felt!("0x3"), Node::Binary { left: NodeRef::Index(1), right: NodeRef::Index(2), }, ), - (felt!("4"), Node::LeafBinary), - (felt!("5"), Node::LeafBinary), + (felt!("0x4"), Node::LeafBinary), + (felt!("0x5"), Node::LeafBinary), ], nodes_removed: vec![1, 2, 3].into_iter().map(TrieStorageIndex).collect(), root_commitment: Felt::ZERO, @@ -1596,14 +1596,14 @@ mod tests { &TrieUpdate { nodes_added: vec![ ( - felt!("6"), + felt!("0x6"), Node::Binary { left: NodeRef::Index(1), right: NodeRef::Index(2), }, ), - (felt!("7"), Node::LeafBinary), - (felt!("8"), Node::LeafBinary), + (felt!("0x7"), Node::LeafBinary), + (felt!("0x8"), Node::LeafBinary), ], nodes_removed: vec![], root_commitment: Felt::ZERO, @@ -1633,14 +1633,14 @@ mod tests { &TrieUpdate { nodes_added: vec![ ( - felt!("0"), + felt!("0x0"), Node::Binary { left: NodeRef::Index(1), right: NodeRef::Index(2), }, ), - (felt!("1"), Node::LeafBinary), - (felt!("2"), Node::LeafBinary), + (felt!("0x1"), Node::LeafBinary), + (felt!("0x2"), Node::LeafBinary), ], nodes_removed: vec![], root_commitment: Felt::ZERO, diff --git a/crates/storage/src/test_utils.rs b/crates/storage/src/test_utils.rs index 6babd39b1c..fda0edfbd6 100644 --- a/crates/storage/src/test_utils.rs +++ b/crates/storage/src/test_utils.rs @@ -29,9 +29,13 @@ pub(crate) fn create_blocks(n_blocks: usize) -> Vec { (0..n_blocks) .map(|block_number| { let storage_commitment = - StorageCommitment(Felt::from_hex_str(&"b".repeat(block_number + 3)).unwrap()); + Felt::from_hex_str(&format!("0x{}", "b".repeat(block_number + 3))) + .map(StorageCommitment) + .unwrap(); let class_commitment = - ClassCommitment(Felt::from_hex_str(&"c".repeat(block_number + 3)).unwrap()); + Felt::from_hex_str(&format!("0x{}", "c".repeat(block_number + 3))) + .map(ClassCommitment) + .unwrap(); let index_as_felt = Felt::from_be_slice(&[block_number as u8]).unwrap(); BlockHeader::builder() @@ -42,9 +46,11 @@ pub(crate) fn create_blocks(n_blocks: usize) -> Vec { .sequencer_address(SequencerAddress(index_as_felt)) .transaction_commitment(TransactionCommitment(index_as_felt)) .event_commitment(EventCommitment(index_as_felt)) - .finalize_with_hash(BlockHash( - Felt::from_hex_str(&"a".repeat(block_number + 3)).unwrap(), - )) + .finalize_with_hash( + Felt::from_hex_str(&format!("0x{}", "a".repeat(block_number + 3))) + .map(BlockHash) + .unwrap(), + ) }) .collect::>() } @@ -63,22 +69,28 @@ pub(crate) fn create_transactions_and_receipts( ); let transactions = (0..n_transactions).map(|i| match i % transactions_per_block { x if x < INVOKE_TRANSACTIONS_PER_BLOCK => Transaction { - hash: TransactionHash(Felt::from_hex_str(&"4".repeat(i + 3)).unwrap()), + hash: Felt::from_hex_str(&format!("0x{}", "4".repeat(i + 3))) + .map(TransactionHash) + .unwrap(), variant: TransactionVariant::InvokeV0(InvokeTransactionV0 { - calldata: vec![CallParam(Felt::from_hex_str(&"0".repeat(i + 3)).unwrap())], - sender_address: ContractAddress::new_or_panic( - Felt::from_hex_str(&"1".repeat(i + 3)).unwrap(), - ), - entry_point_selector: EntryPoint(Felt::from_hex_str(&"2".repeat(i + 3)).unwrap()), + calldata: vec![Felt::from_hex_str(&format!("0x{}", "0".repeat(i + 3))) + .map(CallParam) + .unwrap()], + sender_address: Felt::from_hex_str(&format!("0x{}", "1".repeat(i + 3))) + .map(ContractAddress::new_or_panic) + .unwrap(), + entry_point_selector: Felt::from_hex_str(&format!("0x{}", "2".repeat(i + 3))) + .map(EntryPoint) + .unwrap(), entry_point_type: Some(if i & 1 == 0 { EntryPointType::External } else { EntryPointType::L1Handler }), max_fee: Fee::ZERO, - signature: vec![TransactionSignatureElem( - Felt::from_hex_str(&"3".repeat(i + 3)).unwrap(), - )], + signature: vec![Felt::from_hex_str(&format!("0x{}", "3".repeat(i + 3))) + .map(TransactionSignatureElem) + .unwrap()], }), }, x if (INVOKE_TRANSACTIONS_PER_BLOCK @@ -86,33 +98,46 @@ pub(crate) fn create_transactions_and_receipts( .contains(&x) => { Transaction { - hash: TransactionHash(Felt::from_hex_str(&"9".repeat(i + 3)).unwrap()), + hash: Felt::from_hex_str(&format!("0x{}", "9".repeat(i + 3))) + .map(TransactionHash) + .unwrap(), variant: TransactionVariant::DeployV0(DeployTransactionV0 { - contract_address: ContractAddress::new_or_panic( - Felt::from_hex_str(&"5".repeat(i + 3)).unwrap(), - ), - contract_address_salt: ContractAddressSalt( - Felt::from_hex_str(&"6".repeat(i + 3)).unwrap(), - ), - class_hash: ClassHash(Felt::from_hex_str(&"7".repeat(i + 3)).unwrap()), - constructor_calldata: vec![ConstructorParam( - Felt::from_hex_str(&"8".repeat(i + 3)).unwrap(), - )], + contract_address: Felt::from_hex_str(&format!("0x{}", "5".repeat(i + 3))) + .map(ContractAddress::new_or_panic) + .unwrap(), + contract_address_salt: Felt::from_hex_str(&format!("0x{}", "6".repeat(i + 3))) + .map(ContractAddressSalt) + .unwrap(), + class_hash: Felt::from_hex_str(&format!("0x{}", "7".repeat(i + 3))) + .map(ClassHash) + .unwrap(), + constructor_calldata: vec![Felt::from_hex_str(&format!( + "0x{}", + "8".repeat(i + 3) + )) + .map(ConstructorParam) + .unwrap()], }), } } _ => Transaction { - hash: TransactionHash(Felt::from_hex_str(&"e".repeat(i + 3)).unwrap()), + hash: Felt::from_hex_str(&format!("0x{}", "e".repeat(i + 3))) + .map(TransactionHash) + .unwrap(), variant: TransactionVariant::DeclareV0(DeclareTransactionV0V1 { - class_hash: ClassHash(Felt::from_hex_str(&"a".repeat(i + 3)).unwrap()), + class_hash: Felt::from_hex_str(&format!("0x{}", "a".repeat(i + 3))) + .map(ClassHash) + .unwrap(), max_fee: Fee::ZERO, - nonce: TransactionNonce(Felt::from_hex_str(&"b".repeat(i + 3)).unwrap()), - sender_address: ContractAddress::new_or_panic( - Felt::from_hex_str(&"c".repeat(i + 3)).unwrap(), - ), - signature: vec![TransactionSignatureElem( - Felt::from_hex_str(&"d".repeat(i + 3)).unwrap(), - )], + nonce: Felt::from_hex_str(&format!("0x{}", "b".repeat(i + 3))) + .map(TransactionNonce) + .unwrap(), + sender_address: Felt::from_hex_str(&format!("0x{}", "c".repeat(i + 3))) + .map(ContractAddress::new_or_panic) + .unwrap(), + signature: vec![Felt::from_hex_str(&format!("0x{}", "d".repeat(i + 3))) + .map(TransactionSignatureElem) + .unwrap()], }), }, }); @@ -144,12 +169,16 @@ pub(crate) fn create_transactions_and_receipts( }; let events = if i % transactions_per_block < EVENTS_PER_BLOCK { vec![pathfinder_common::event::Event { - from_address: ContractAddress::new_or_panic( - Felt::from_hex_str(&"2".repeat(i + 3)).unwrap(), - ), - data: vec![EventData(Felt::from_hex_str(&"c".repeat(i + 3)).unwrap())], + from_address: Felt::from_hex_str(&format!("0x{}", "2".repeat(i + 3))) + .map(ContractAddress::new_or_panic) + .unwrap(), + data: vec![Felt::from_hex_str(&format!("0x{}", "c".repeat(i + 3))) + .map(EventData) + .unwrap()], keys: vec![ - EventKey(Felt::from_hex_str(&"d".repeat(i + 3)).unwrap()), + Felt::from_hex_str(&format!("0x{}", "d".repeat(i + 3))) + .map(EventKey) + .unwrap(), event_key!("0xdeadbeef"), ], }]