Skip to content

Commit

Permalink
feat: check for invalid seirra version in stateless validator
Browse files Browse the repository at this point in the history
  • Loading branch information
ArniStarkware committed Jun 16, 2024
1 parent 0b9493f commit 58327dc
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 2 deletions.
23 changes: 23 additions & 0 deletions crates/gateway/src/compiler_version.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use cairo_lang_starknet_classes::compiler_version::VersionId as CairoLangVersionId;
use validator::Validate;

// TODO(Arni): Share this struct with the Cairo lang crate.
#[derive(Clone, Copy, Debug, Validate, PartialEq)]
pub struct VersionId {
pub major: usize,
pub minor: usize,
pub patch: usize,
}

impl From<VersionId> for CairoLangVersionId {
fn from(version: VersionId) -> Self {
CairoLangVersionId { major: version.major, minor: version.minor, patch: version.patch }
}
}

impl std::fmt::Display for VersionId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let version_id: CairoLangVersionId = (*self).into();
version_id.fmt(f)
}
}
3 changes: 3 additions & 0 deletions crates/gateway/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use blockifier::blockifier::stateful_validator::StatefulValidatorError;
use blockifier::state::errors::StateError;
use blockifier::transaction::errors::TransactionExecutionError;
use starknet_api::block::BlockNumber;
use starknet_api::hash::StarkFelt;
use starknet_api::transaction::{Resource, ResourceBounds};
use starknet_api::StarknetApiError;
use thiserror::Error;
Expand Down Expand Up @@ -46,6 +47,8 @@ pub enum StatelessTransactionValidatorError {
(allowed length: {max_signature_length})."
)]
SignatureTooLong { signature_length: usize, max_signature_length: usize },
#[error("Invalid Sierra version: {version:?}.")]
InvalidSierraVersion { version: [StarkFelt; 3] },
#[error(
"Cannot declare contract class with bytecode size of {bytecode_size}; max allowed size: \
{max_bytecode_size}."
Expand Down
1 change: 1 addition & 0 deletions crates/gateway/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod compiler_version;
pub mod config;
pub mod errors;
pub mod gateway;
Expand Down
5 changes: 3 additions & 2 deletions crates/gateway/src/starknet_api_test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,10 @@ pub fn external_tx_for_testing(
) -> ExternalTransaction {
match tx_type {
TransactionType::Declare => {
// Minimal contract class.
let contract_class = ContractClass {
sierra_program: vec![stark_felt!(1_u32); 3],
..ContractClass::default()
sierra_program: vec![stark_felt!(1_u32), stark_felt!(3_u32), stark_felt!(0_u32)],
..Default::default()
};
external_declare_tx(declare_tx_args!(resource_bounds, signature, contract_class))
}
Expand Down
32 changes: 32 additions & 0 deletions crates/gateway/src/stateless_transaction_validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ use starknet_api::external_transaction::{
ExternalDeclareTransaction, ExternalDeployAccountTransaction, ExternalInvokeTransaction,
ExternalTransaction, ResourceBoundsMapping,
};
use starknet_api::hash::StarkFelt;
use starknet_api::transaction::Resource;

use crate::compiler_version::VersionId;
use crate::config::StatelessTransactionValidatorConfig;
use crate::errors::{StatelessTransactionValidatorError, StatelessTransactionValidatorResult};

Expand Down Expand Up @@ -106,9 +108,20 @@ impl StatelessTransactionValidator {
let contract_class = match declare_tx {
ExternalDeclareTransaction::V3(tx) => &tx.contract_class,
};
self.validate_sierra_version(&contract_class.sierra_program)?;
self.validate_class_length(contract_class)
}

fn validate_sierra_version(
&self,
sierra_program: &[StarkFelt],
) -> StatelessTransactionValidatorResult<()> {
// TODO(Arni): Validate the sierra version is Supported.
let _sierra_version = sierra_program_version_id(sierra_program)?;

Ok(())
}

fn validate_class_length(
&self,
contract_class: &starknet_api::external_transaction::ContractClass,
Expand All @@ -135,6 +148,25 @@ impl StatelessTransactionValidator {
}
}

fn sierra_program_version_id(
sierra_program: &[StarkFelt],
) -> StatelessTransactionValidatorResult<VersionId> {
let length_of_version = sierra_program.len().min(3);
let mut version = [StarkFelt::default(); 3];
version[..length_of_version].copy_from_slice(&sierra_program[..length_of_version]);

if length_of_version < 3 {
return Err(StatelessTransactionValidatorError::InvalidSierraVersion { version });
}

let map_err = || StatelessTransactionValidatorError::InvalidSierraVersion { version };
Ok(VersionId {
major: sierra_program[0].try_into().map_err(|_| map_err())?,
minor: sierra_program[1].try_into().map_err(|_| map_err())?,
patch: sierra_program[2].try_into().map_err(|_| map_err())?,
})
}

fn validate_resource_is_non_zero(
resource_bounds_mapping: &ResourceBoundsMapping,
resource: Resource,
Expand Down
50 changes: 50 additions & 0 deletions crates/gateway/src/stateless_transaction_validator_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,56 @@ fn test_signature_too_long(
);
}

#[rstest]
fn test_declare_sierra_program_too_short(
#[values(
vec![],
vec![stark_felt!(1_u128)],
vec![stark_felt!(1_u128), stark_felt!(3_u128)]
)]
sierra_program: Vec<StarkFelt>,
) {
let tx_validator =
StatelessTransactionValidator { config: DEFAULT_VALIDATOR_CONFIG_FOR_TESTING };

let contract_class = ContractClass { sierra_program, ..Default::default() };
let tx = external_declare_tx(declare_tx_args!(contract_class));

assert_matches!(
tx_validator.validate(&tx).unwrap_err(),
StatelessTransactionValidatorError::InvalidSierraVersion { .. }
);
}

#[rstest]
#[case::invalid_sierra_version(
vec![
stark_felt!(1_u128),
stark_felt!(3_u128),
stark_felt!(0x10000000000000000_u128), // Does not fit into a usize.
],
StatelessTransactionValidatorError::InvalidSierraVersion {
version: [
stark_felt!(1_u128),
stark_felt!(3_u128),
stark_felt!(0x10000000000000000_u128)
]
}
)
]
fn test_declare_sierra_version(
#[case] sierra_program: Vec<StarkFelt>,
#[case] expected_error: StatelessTransactionValidatorError,
) {
let tx_validator =
StatelessTransactionValidator { config: DEFAULT_VALIDATOR_CONFIG_FOR_TESTING };

let contract_class = ContractClass { sierra_program, ..Default::default() };
let tx = external_declare_tx(declare_tx_args!(contract_class));

assert_eq!(tx_validator.validate(&tx).unwrap_err(), expected_error);
}

#[test]
fn test_declare_bytecode_size_too_long() {
let config_max_bytecode_size = 10;
Expand Down

0 comments on commit 58327dc

Please sign in to comment.