Skip to content

Commit

Permalink
feat: post compilation size limit validation
Browse files Browse the repository at this point in the history
  • Loading branch information
ArniStarkware committed Aug 7, 2024
1 parent 59228b7 commit f75f21d
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 34 deletions.
7 changes: 6 additions & 1 deletion config/mempool/default_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
"privacy": "Public",
"value": 81920
},
"gateway_config.compiler_config.max_raw_casm_class_size": {
"description": "Limitation of contract class object size.",
"privacy": "Public",
"value": 4089446
},
"gateway_config.network_config.ip": {
"description": "The gateway server ip.",
"privacy": "Public",
Expand Down Expand Up @@ -119,4 +124,4 @@
"privacy": "Public",
"value": ""
}
}
}
36 changes: 35 additions & 1 deletion crates/gateway/src/compilation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use starknet_sierra_compile::compile::SierraToCasmCompiler;
use starknet_sierra_compile::errors::CompilationUtilError;
use starknet_sierra_compile::utils::into_contract_class_for_compilation;

use crate::config::{GatewayCompilerConfig, PostCompilationConfig};
use crate::errors::{GatewayError, GatewayResult};

#[cfg(test)]
Expand All @@ -18,10 +19,20 @@ mod compilation_test;
// TODO(Arni): Pass the compiler with dependancy injection.
#[derive(Clone)]
pub struct GatewayCompiler {
pub sierra_to_casm_compiler: SierraToCasmCompiler,
config: PostCompilationConfig,
sierra_to_casm_compiler: SierraToCasmCompiler,
}

impl GatewayCompiler {
pub fn new(config: GatewayCompilerConfig) -> Self {
GatewayCompiler {
config: config.post_compilation_config,
sierra_to_casm_compiler: SierraToCasmCompiler {
config: config.sierra_to_casm_compiler_config,
},
}
}

/// Formats the contract class for compilation, compiles it, and returns the compiled contract
/// class wrapped in a [`ClassInfo`].
/// Assumes the contract class is of a Sierra program which is compiled to Casm.
Expand All @@ -36,6 +47,7 @@ impl GatewayCompiler {
let casm_contract_class = self.compile(cairo_lang_contract_class)?;

validate_compiled_class_hash(&casm_contract_class, &tx.compiled_class_hash)?;
self.validate_casm_class_size(&casm_contract_class)?;

Ok(ClassInfo::new(
&ContractClass::V1(ContractClassV1::try_from(casm_contract_class)?),
Expand All @@ -55,6 +67,28 @@ impl GatewayCompiler {

Ok(casm_contract_class)
}

// TODO(Arni): consider validating the size of other members of the Casm class. Cosider removing
// the validation of the raw class size. The validation should be linked to the way the class is
// saved in Papyrus etc.
/// Validates that the Casm class is within size limit. Specifically, this function validates
/// the size of the serialized class.
fn validate_casm_class_size(
&self,
casm_contract_class: &CasmContractClass,
) -> Result<(), GatewayError> {
let contract_class_object_size = serde_json::to_string(&casm_contract_class)
.expect("Unexpected error serializing Casm contract class.")
.len();
if contract_class_object_size > self.config.max_raw_casm_class_size {
return Err(GatewayError::CasmContractClassObjectSizeTooLarge {
contract_class_object_size,
max_contract_class_object_size: self.config.max_raw_casm_class_size,
});
}

Ok(())
}
}

/// Validates that the compiled class hash of the compiled contract class matches the supplied
Expand Down
25 changes: 18 additions & 7 deletions crates/gateway/src/compilation_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@ use starknet_api::rpc_transaction::{
RpcDeclareTransactionV3,
RpcTransaction,
};
use starknet_sierra_compile::compile::SierraToCasmCompiler;
use starknet_sierra_compile::config::SierraToCasmCompilationConfig;
use starknet_sierra_compile::errors::CompilationUtilError;

use crate::compilation::GatewayCompiler;
use crate::config::{GatewayCompilerConfig, PostCompilationConfig};
use crate::errors::GatewayError;

#[fixture]
fn gateway_compiler() -> GatewayCompiler {
GatewayCompiler { sierra_to_casm_compiler: SierraToCasmCompiler { config: Default::default() } }
GatewayCompiler::new(GatewayCompilerConfig::default())
}

#[fixture]
Expand Down Expand Up @@ -53,11 +53,10 @@ fn test_compile_contract_class_compiled_class_hash_mismatch(
// TODO(Arni): Redesign this test once the compiler is passed with dependancy injection.
#[rstest]
fn test_compile_contract_class_bytecode_size_validation(declare_tx_v3: RpcDeclareTransactionV3) {
let gateway_compiler = GatewayCompiler {
sierra_to_casm_compiler: SierraToCasmCompiler {
config: SierraToCasmCompilationConfig { max_bytecode_size: 1 },
},
};
let gateway_compiler = GatewayCompiler::new(GatewayCompilerConfig {
sierra_to_casm_compiler_config: SierraToCasmCompilationConfig { max_bytecode_size: 1 },
..Default::default()
});

let result = gateway_compiler.process_declare_tx(&RpcDeclareTransaction::V3(declare_tx_v3));
assert_matches!(
Expand All @@ -69,6 +68,18 @@ fn test_compile_contract_class_bytecode_size_validation(declare_tx_v3: RpcDeclar
)
}

// TODO(Arni): Redesign this test once the compiler is passed with dependancy injection.
#[rstest]
fn test_compile_contract_class_raw_class_size_validation(declare_tx_v3: RpcDeclareTransactionV3) {
let gateway_compiler = GatewayCompiler::new(GatewayCompilerConfig {
post_compilation_config: PostCompilationConfig { max_raw_casm_class_size: 1 },
..Default::default()
});

let result = gateway_compiler.process_declare_tx(&RpcDeclareTransaction::V3(declare_tx_v3));
assert_matches!(result.unwrap_err(), GatewayError::CasmContractClassObjectSizeTooLarge { .. })
}

#[rstest]
fn test_compile_contract_class_bad_sierra(
gateway_compiler: GatewayCompiler,
Expand Down
38 changes: 34 additions & 4 deletions crates/gateway/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,13 +228,43 @@ impl StatefulTransactionValidatorConfig {
#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, Validate, PartialEq)]
pub struct GatewayCompilerConfig {
pub sierra_to_casm_compiler_config: SierraToCasmCompilationConfig,
pub post_compilation_config: PostCompilationConfig,
}

impl SerializeConfig for GatewayCompilerConfig {
fn dump(&self) -> BTreeMap<ParamPath, SerializedParam> {
append_sub_config_name(
self.sierra_to_casm_compiler_config.dump(),
"sierra_to_casm_compiler_config",
)
vec![
append_sub_config_name(
self.sierra_to_casm_compiler_config.dump(),
"sierra_to_casm_compiler_config",
),
append_sub_config_name(self.post_compilation_config.dump(), "post_compilation_config"),
]
.into_iter()
.flatten()
.collect()
}
}

/// The configuration for the post compilation process in the gateway compiler.
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Validate, PartialEq)]
pub struct PostCompilationConfig {
pub max_raw_casm_class_size: usize,
}

impl Default for PostCompilationConfig {
fn default() -> Self {
PostCompilationConfig { max_raw_casm_class_size: 4089446 }
}
}

impl SerializeConfig for PostCompilationConfig {
fn dump(&self) -> BTreeMap<ParamPath, SerializedParam> {
BTreeMap::from_iter([ser_param(
"max_raw_casm_class_size",
&self.max_raw_casm_class_size,
"Limitation of contract class object size.",
ParamPrivacyInput::Public,
)])
}
}
8 changes: 8 additions & 0 deletions crates/gateway/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@ use crate::compiler_version::{VersionId, VersionIdError};
/// Errors directed towards the end-user, as a result of gateway requests.
#[derive(Debug, Error)]
pub enum GatewayError {
#[error(
"Cannot declare Casm contract class with size of {contract_class_object_size}; max \
allowed size: {max_contract_class_object_size}."
)]
CasmContractClassObjectSizeTooLarge {
contract_class_object_size: usize,
max_contract_class_object_size: usize,
},
#[error(transparent)]
CompilationError(#[from] CompilationUtilError),
#[error(
Expand Down
7 changes: 1 addition & 6 deletions crates/gateway/src/gateway.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use starknet_api::transaction::TransactionHash;
use starknet_mempool_infra::component_runner::{ComponentStartError, ComponentStarter};
use starknet_mempool_types::communication::SharedMempoolClient;
use starknet_mempool_types::mempool_types::{Account, AccountState, MempoolInput};
use starknet_sierra_compile::compile::SierraToCasmCompiler;
use tracing::{info, instrument};

use crate::compilation::GatewayCompiler;
Expand Down Expand Up @@ -155,11 +154,7 @@ pub fn create_gateway(
mempool_client: SharedMempoolClient,
) -> Gateway {
let state_reader_factory = Arc::new(RpcStateReaderFactory { config: rpc_state_reader_config });
let gateway_compiler = GatewayCompiler {
sierra_to_casm_compiler: SierraToCasmCompiler {
config: config.compiler_config.sierra_to_casm_compiler_config,
},
};
let gateway_compiler = GatewayCompiler::new(config.compiler_config);
Gateway::new(config, state_reader_factory, gateway_compiler, mempool_client)
}

Expand Down
14 changes: 6 additions & 8 deletions crates/gateway/src/gateway_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ use starknet_api::rpc_transaction::RpcTransaction;
use starknet_api::transaction::TransactionHash;
use starknet_mempool_types::communication::MockMempoolClient;
use starknet_mempool_types::mempool_types::{Account, AccountState, MempoolInput, ThinTransaction};
use starknet_sierra_compile::compile::SierraToCasmCompiler;
use starknet_sierra_compile::config::SierraToCasmCompilationConfig;

use crate::compilation::GatewayCompiler;
use crate::config::{StatefulTransactionValidatorConfig, StatelessTransactionValidatorConfig};
use crate::config::{
GatewayCompilerConfig,
StatefulTransactionValidatorConfig,
StatelessTransactionValidatorConfig,
};
use crate::gateway::{add_tx, AppState, SharedMempoolClient};
use crate::state_reader_test_utils::{local_test_state_reader_factory, TestStateReaderFactory};
use crate::stateful_transaction_validator::StatefulTransactionValidator;
Expand All @@ -35,11 +37,7 @@ pub fn app_state(
stateful_tx_validator: Arc::new(StatefulTransactionValidator {
config: StatefulTransactionValidatorConfig::create_for_testing(),
}),
gateway_compiler: GatewayCompiler {
sierra_to_casm_compiler: SierraToCasmCompiler {
config: SierraToCasmCompilationConfig::default(),
},
},
gateway_compiler: GatewayCompiler::new(GatewayCompilerConfig::default()),
state_reader_factory: Arc::new(state_reader_factory),
mempool_client,
}
Expand Down
11 changes: 4 additions & 7 deletions crates/gateway/src/stateful_transaction_validator_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,10 @@ use starknet_api::core::{ContractAddress, Nonce};
use starknet_api::felt;
use starknet_api::rpc_transaction::RpcTransaction;
use starknet_api::transaction::TransactionHash;
use starknet_sierra_compile::compile::SierraToCasmCompiler;
use starknet_types_core::felt::Felt;

use crate::compilation::GatewayCompiler;
use crate::config::StatefulTransactionValidatorConfig;
use crate::config::{GatewayCompilerConfig, StatefulTransactionValidatorConfig};
use crate::errors::{StatefulTransactionValidatorError, StatefulTransactionValidatorResult};
use crate::state_reader::{MockStateReaderFactory, StateReaderFactory};
use crate::state_reader_test_utils::local_test_state_reader_factory;
Expand Down Expand Up @@ -84,11 +83,9 @@ fn test_stateful_tx_validator(
) {
let optional_class_info = match &external_tx {
RpcTransaction::Declare(declare_tx) => Some(
GatewayCompiler {
sierra_to_casm_compiler: SierraToCasmCompiler { config: Default::default() },
}
.process_declare_tx(declare_tx)
.unwrap(),
GatewayCompiler::new(GatewayCompilerConfig::default())
.process_declare_tx(declare_tx)
.unwrap(),
),
_ => None,
};
Expand Down

0 comments on commit f75f21d

Please sign in to comment.