Skip to content

Commit

Permalink
feat: add contract address in range validation (#1790)
Browse files Browse the repository at this point in the history
  • Loading branch information
ArniStarkware authored Nov 5, 2024
1 parent 413515b commit 357b5ec
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 4 deletions.
4 changes: 4 additions & 0 deletions crates/gateway/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use blockifier::state::errors::StateError;
use serde_json::{Error as SerdeError, Value};
use starknet_api::block::GasPrice;
use starknet_api::transaction::{Resource, ResourceBounds};
use starknet_api::StarknetApiError;
use starknet_gateway_types::errors::GatewaySpecError;
use thiserror::Error;

Expand Down Expand Up @@ -35,6 +36,8 @@ pub enum StatelessTransactionValidatorError {
(allowed length: {max_signature_length})."
)]
SignatureTooLong { signature_length: usize, max_signature_length: usize },
#[error(transparent)]
StarknetApiError(#[from] StarknetApiError),
#[error(
"Sierra versions older than {min_version} or newer than {max_version} are not supported. \
The Sierra version of the declared contract is {version}."
Expand All @@ -57,6 +60,7 @@ impl From<StatelessTransactionValidatorError> for GatewaySpecError {
| StatelessTransactionValidatorError::EntryPointsNotUniquelySorted
| StatelessTransactionValidatorError::InvalidSierraVersion(..)
| StatelessTransactionValidatorError::SignatureTooLong { .. }
| StatelessTransactionValidatorError::StarknetApiError(..)
| StatelessTransactionValidatorError::ZeroResourceBounds { .. } => {
GatewaySpecError::ValidationFailure { data: e.to_string() }
}
Expand Down
11 changes: 11 additions & 0 deletions crates/gateway/src/stateless_transaction_validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ impl StatelessTransactionValidator {
// TODO(Arni, 1/5/2024): Add a mechanism that validate the sender address is not blocked.
// TODO(Arni, 1/5/2024): Validate transaction version.

Self::validate_contract_address(tx)?;
self.validate_resource_bounds(tx)?;
self.validate_tx_size(tx)?;

Expand All @@ -55,6 +56,16 @@ impl StatelessTransactionValidator {
Ok(())
}

fn validate_contract_address(tx: &RpcTransaction) -> StatelessTransactionValidatorResult<()> {
let sender_address = match tx {
RpcTransaction::Declare(RpcDeclareTransaction::V3(tx)) => tx.sender_address,
RpcTransaction::DeployAccount(_) => return Ok(()),
RpcTransaction::Invoke(RpcInvokeTransaction::V3(tx)) => tx.sender_address,
};

Ok(sender_address.validate()?)
}

fn validate_tx_size(&self, tx: &RpcTransaction) -> StatelessTransactionValidatorResult<()> {
self.validate_tx_calldata_size(tx)?;
self.validate_tx_signature_size(tx)?;
Expand Down
14 changes: 10 additions & 4 deletions crates/mempool_test_utils/src/starknet_api_test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,17 +85,23 @@ pub fn rpc_tx_for_testing(
],
..Default::default()
};
rpc_declare_tx(declare_tx_args!(resource_bounds, signature, contract_class))
rpc_declare_tx(declare_tx_args!(
signature,
sender_address: TEST_SENDER_ADDRESS.into(),
resource_bounds,
contract_class,
))
}
TransactionType::DeployAccount => rpc_deploy_account_tx(deploy_account_tx_args!(
signature,
resource_bounds: ValidResourceBounds::AllResources(resource_bounds),
constructor_calldata: calldata,
signature
)),
TransactionType::Invoke => rpc_invoke_tx(invoke_tx_args!(
signature,
sender_address: TEST_SENDER_ADDRESS.into(),
calldata,
resource_bounds: ValidResourceBounds::AllResources(resource_bounds),
calldata
)),
}
}
Expand Down Expand Up @@ -456,7 +462,7 @@ impl Default for DeclareTxArgs {
fn default() -> Self {
Self {
signature: TransactionSignature::default(),
sender_address: ContractAddress::default(),
sender_address: TEST_SENDER_ADDRESS.into(),
version: TransactionVersion::THREE,
resource_bounds: zero_resource_bounds_mapping(),
tip: Tip::default(),
Expand Down
16 changes: 16 additions & 0 deletions crates/starknet_api/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ impl ChainId {
// The block hash table is stored in address 0x1,
// this is a special address that is not used for contracts.
pub const BLOCK_HASH_TABLE_ADDRESS: ContractAddress = ContractAddress(PatriciaKey(StarkHash::ONE));

#[derive(
Debug,
Default,
Expand All @@ -107,6 +108,21 @@ pub const BLOCK_HASH_TABLE_ADDRESS: ContractAddress = ContractAddress(PatriciaKe
)]
pub struct ContractAddress(pub PatriciaKey);

impl ContractAddress {
/// Validates the contract address is in the valid range for external access.
/// The lower bound is above the special saved addresses and the upper bound is congruent with
/// the storage var address upper bound.
pub fn validate(&self) -> Result<(), StarknetApiError> {
let value = self.0.0;
let l2_address_upper_bound = Felt::from(*L2_ADDRESS_UPPER_BOUND);
if (value > BLOCK_HASH_TABLE_ADDRESS.0.0) && (value < l2_address_upper_bound) {
return Ok(());
}

Err(StarknetApiError::OutOfRange { string: format!("[0x2, {})", l2_address_upper_bound) })
}
}

impl From<ContractAddress> for Felt {
fn from(contract_address: ContractAddress) -> Felt {
**contract_address
Expand Down

0 comments on commit 357b5ec

Please sign in to comment.