From 63f30af8804fbf2f66a5ab11980c78f2a66688db Mon Sep 17 00:00:00 2001 From: Shahak Shama Date: Sun, 4 Feb 2024 16:08:05 +0200 Subject: [PATCH] Return OutOfRange instead of StarknetApiError whenever a method can only return OutOfRange --- src/core.rs | 25 ++++++++++++------------- src/core_test.rs | 8 ++++---- src/data_availability.rs | 12 ++++++------ src/hash.rs | 18 +++++++++--------- src/hash_test.rs | 7 ++----- src/lib.rs | 16 ++++++++++++++-- src/state.rs | 4 ++-- 7 files changed, 49 insertions(+), 41 deletions(-) diff --git a/src/core.rs b/src/core.rs index f356371d..92c56fe5 100644 --- a/src/core.rs +++ b/src/core.rs @@ -14,7 +14,7 @@ use crate::crypto::PublicKey; use crate::hash::{pedersen_hash_array, StarkFelt, StarkHash}; use crate::serde_utils::{BytesAsHex, PrefixedBytesAsHex}; use crate::transaction::{Calldata, ContractAddressSalt}; -use crate::{impl_from_through_intermediate, StarknetApiError}; +use crate::{impl_from_through_intermediate, OutOfRangeError, StarknetApiError}; /// A chain id. #[derive(Clone, Debug, Display, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] @@ -78,7 +78,7 @@ pub static L2_ADDRESS_UPPER_BOUND: Lazy = Lazy::new(|| { }); impl TryFrom for ContractAddress { - type Error = StarknetApiError; + type Error = OutOfRangeError; fn try_from(hash: StarkHash) -> Result { Ok(Self(PatriciaKey::try_from(hash)?)) } @@ -102,7 +102,7 @@ pub fn calculate_contract_address( ])); address = address % *L2_ADDRESS_UPPER_BOUND; - ContractAddress::try_from(StarkFelt::from(address)) + Ok(ContractAddress::try_from(StarkFelt::from(address))?) } /// The hash of a ContractClass. @@ -158,12 +158,12 @@ pub struct CompiledClassHash(pub StarkHash); pub struct Nonce(pub StarkFelt); impl Nonce { - pub fn try_increment(&self) -> Result { + pub fn try_increment(&self) -> Result { let current_nonce = FieldElement::from(self.0); // Check if an overflow occurred during increment. match StarkFelt::from(current_nonce + FieldElement::ONE) { - StarkFelt::ZERO => Err(StarknetApiError::OutOfRange { string: format!("{:?}", self) }), + StarkFelt::ZERO => Err(OutOfRangeError { string: format!("{:?}", self) }), incremented_felt => Ok(Self(incremented_felt)), } } @@ -229,13 +229,13 @@ impl From for PatriciaKey { impl_from_through_intermediate!(u128, PatriciaKey, u8, u16, u32, u64); impl TryFrom for PatriciaKey { - type Error = StarknetApiError; + type Error = OutOfRangeError; fn try_from(value: StarkHash) -> Result { if value < *CONTRACT_ADDRESS_DOMAIN_SIZE { return Ok(PatriciaKey(value)); } - Err(StarknetApiError::OutOfRange { string: format!("[0x0, {PATRICIA_KEY_UPPER_BOUND})") }) + Err(OutOfRangeError { string: format!("[0x0, {PATRICIA_KEY_UPPER_BOUND})") }) } } @@ -281,13 +281,13 @@ macro_rules! contract_address { pub struct EthAddress(pub H160); impl TryFrom for EthAddress { - type Error = StarknetApiError; + type Error = OutOfRangeError; fn try_from(felt: StarkFelt) -> Result { const COMPLIMENT_OF_H160: usize = std::mem::size_of::() - H160::len_bytes(); let (rest, h160_bytes) = felt.bytes().split_at(COMPLIMENT_OF_H160); if rest != [0u8; COMPLIMENT_OF_H160] { - return Err(StarknetApiError::OutOfRange { string: felt.to_string() }); + return Err(OutOfRangeError { string: felt.to_string() }); } Ok(EthAddress(H160::from_slice(h160_bytes))) @@ -303,10 +303,9 @@ impl From for StarkFelt { } } -impl TryFrom> for EthAddress { - type Error = StarknetApiError; - fn try_from(val: PrefixedBytesAsHex<20_usize>) -> Result { - Ok(EthAddress(H160::from_slice(&val.0))) +impl From> for EthAddress { + fn from(val: PrefixedBytesAsHex<20_usize>) -> Self { + EthAddress(H160::from_slice(&val.0)) } } diff --git a/src/core_test.rs b/src/core_test.rs index 40587837..4805552e 100644 --- a/src/core_test.rs +++ b/src/core_test.rs @@ -2,8 +2,8 @@ use assert_matches::assert_matches; use starknet_crypto::FieldElement; use crate::core::{ - calculate_contract_address, ClassHash, ContractAddress, EthAddress, Nonce, PatriciaKey, - StarknetApiError, CONTRACT_ADDRESS_PREFIX, L2_ADDRESS_UPPER_BOUND, + calculate_contract_address, ClassHash, ContractAddress, EthAddress, Nonce, OutOfRangeError, + PatriciaKey, CONTRACT_ADDRESS_PREFIX, L2_ADDRESS_UPPER_BOUND, }; use crate::hash::{pedersen_hash_array, StarkFelt, StarkHash}; use crate::transaction::{Calldata, ContractAddressSalt}; @@ -21,7 +21,7 @@ fn patricia_key_out_of_range() { // 2**251 let hash = stark_felt!("0x800000000000000000000000000000000000000000000000000000000000000"); let err = PatriciaKey::try_from(hash); - assert_matches!(err, Err(StarknetApiError::OutOfRange { string: _err_str })); + assert_matches!(err, Err(OutOfRangeError { string: _err_str })); } #[test] @@ -82,5 +82,5 @@ fn nonce_overflow() { let max_nonce = Nonce(StarkFelt::from(FieldElement::MAX)); let overflowed_nonce = max_nonce.try_increment(); - assert_matches!(overflowed_nonce, Err(StarknetApiError::OutOfRange { string: _err_str })); + assert_matches!(overflowed_nonce, Err(OutOfRangeError { string: _err_str })); } diff --git a/src/data_availability.rs b/src/data_availability.rs index d494ca84..e436a021 100644 --- a/src/data_availability.rs +++ b/src/data_availability.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Serialize}; use crate::hash::StarkFelt; -use crate::StarknetApiError; +use crate::OutOfRangeError; #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] pub enum DataAvailabilityMode { @@ -10,15 +10,15 @@ pub enum DataAvailabilityMode { } impl TryFrom for DataAvailabilityMode { - type Error = StarknetApiError; + type Error = OutOfRangeError; - fn try_from(felt: StarkFelt) -> Result { + fn try_from(felt: StarkFelt) -> Result { match felt { StarkFelt::ZERO => Ok(DataAvailabilityMode::L1), StarkFelt::ONE => Ok(DataAvailabilityMode::L2), - _ => Err(StarknetApiError::OutOfRange { - string: format!("Invalid data availability mode: {felt}."), - }), + _ => { + Err(OutOfRangeError { string: format!("Invalid data availability mode: {felt}.") }) + } } } } diff --git a/src/hash.rs b/src/hash.rs index e9ab99d2..3d352098 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -11,7 +11,7 @@ use starknet_crypto::{ }; use crate::serde_utils::{bytes_from_hex_str, hex_str_from_bytes, BytesAsHex, PrefixedBytesAsHex}; -use crate::{impl_from_through_intermediate, StarknetApiError}; +use crate::{impl_from_through_intermediate, OutOfRangeError, StarknetApiError}; /// Genesis state hash. pub const GENESIS_HASH: &str = "0x0"; @@ -61,12 +61,12 @@ pub struct StarkFelt([u8; 32]); impl StarkFelt { /// Returns a new [`StarkFelt`]. - pub fn new(bytes: [u8; 32]) -> Result { + pub fn new(bytes: [u8; 32]) -> Result { // msb nibble must be 0. This is not a tight bound. if bytes[0] < 0x10 { return Ok(Self(bytes)); } - Err(StarknetApiError::OutOfRange { string: hex_str_from_bytes::<32, true>(bytes) }) + Err(OutOfRangeError { string: hex_str_from_bytes::<32, true>(bytes) }) } /// Returns a new *unchecked* [`StarkFelt`] @@ -183,7 +183,7 @@ impl StarkFelt { } impl TryFrom> for StarkFelt { - type Error = StarknetApiError; + type Error = OutOfRangeError; fn try_from(val: PrefixedBytesAsHex<32_usize>) -> Result { StarkFelt::new(val.0) } @@ -194,7 +194,7 @@ impl TryFrom<&str> for StarkFelt { fn try_from(val: &str) -> Result { let val = val.trim_start_matches("0x"); let bytes = bytes_from_hex_str::<32, false>(val)?; - Self::new(bytes) + Ok(Self::new(bytes)?) } } @@ -229,14 +229,14 @@ impl From for PrefixedBytesAsHex<32_usize> { // TODO(Arni, 25/6/2023): Remove impl TryFrom for usize. Leave only one conversion from // StarkFelt to integer type. impl TryFrom for usize { - type Error = StarknetApiError; + type Error = OutOfRangeError; fn try_from(felt: StarkFelt) -> Result { const COMPLIMENT_OF_USIZE: usize = std::mem::size_of::() - std::mem::size_of::(); let (rest, usize_bytes) = felt.bytes().split_at(COMPLIMENT_OF_USIZE); if rest != [0u8; COMPLIMENT_OF_USIZE] { - return Err(StarknetApiError::OutOfRange { string: felt.to_string() }); + return Err(OutOfRangeError { string: felt.to_string() }); } Ok(usize::from_be_bytes( @@ -247,12 +247,12 @@ impl TryFrom for usize { // TODO(Arni, 1/1/2024): This is a Hack. Remove this and implement arethmetics for StarkFelt. impl TryFrom for u64 { - type Error = StarknetApiError; + type Error = OutOfRangeError; fn try_from(felt: StarkFelt) -> Result { const COMPLIMENT_OF_U64: usize = 24; // 32 - 8 let (rest, u64_bytes) = felt.bytes().split_at(COMPLIMENT_OF_U64); if rest != [0u8; COMPLIMENT_OF_U64] { - return Err(StarknetApiError::OutOfRange { string: felt.to_string() }); + return Err(OutOfRangeError { string: felt.to_string() }); } let bytes: [u8; 8] = u64_bytes.try_into().unwrap(); diff --git a/src/hash_test.rs b/src/hash_test.rs index f510aef3..f71c28f3 100644 --- a/src/hash_test.rs +++ b/src/hash_test.rs @@ -1,8 +1,6 @@ -use assert_matches::assert_matches; - use crate::hash::{pedersen_hash, pedersen_hash_array, StarkFelt}; +use crate::stark_felt; use crate::transaction::Fee; -use crate::{stark_felt, StarknetApiError}; #[test] fn pedersen_hash_correctness() { @@ -88,6 +86,5 @@ fn felt_to_u64_and_back() { // Negative flow. let value: u128 = u128::from(u64::MAX) + 1; let another_felt: StarkFelt = value.into(); - let err = u64::try_from(another_felt).unwrap_err(); - assert_matches!(err, StarknetApiError::OutOfRange { .. }); + u64::try_from(another_felt).unwrap_err(); } diff --git a/src/lib.rs b/src/lib.rs index 31dcc50f..13ef1131 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,9 +23,9 @@ pub enum StarknetApiError { /// Error in the inner deserialization of the node. #[error(transparent)] InnerDeserialization(#[from] InnerDeserializationError), - #[error("Out of range {string}.")] /// An error for when a value is out of range. - OutOfRange { string: String }, + #[error(transparent)] + OutOfRange(OutOfRangeError), /// Error when serializing into number. #[error(transparent)] ParseIntError(#[from] ParseIntError), @@ -33,3 +33,15 @@ pub enum StarknetApiError { #[error("Missing resource type / duplicated resource type; got {0}.")] InvalidResourceMappingInitializer(String), } + +#[derive(thiserror::Error, Clone, Debug)] +#[error("Out of range {string}.")] +pub struct OutOfRangeError { + string: String, +} + +impl From for StarknetApiError { + fn from(error: OutOfRangeError) -> Self { + Self::OutOfRange(error) + } +} diff --git a/src/state.rs b/src/state.rs index 823c3e2d..b1b66641 100644 --- a/src/state.rs +++ b/src/state.rs @@ -15,7 +15,7 @@ use crate::core::{ }; use crate::deprecated_contract_class::ContractClass as DeprecatedContractClass; use crate::hash::{StarkFelt, StarkHash}; -use crate::{impl_from_through_intermediate, StarknetApiError}; +use crate::{impl_from_through_intermediate, OutOfRangeError}; pub type DeclaredClasses = IndexMap; pub type DeprecatedDeclaredClasses = IndexMap; @@ -149,7 +149,7 @@ impl From for StarkFelt { } impl TryFrom for StorageKey { - type Error = StarknetApiError; + type Error = OutOfRangeError; fn try_from(val: StarkHash) -> Result { Ok(Self(PatriciaKey::try_from(val)?))