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 1, 2024
1 parent 92f1dc5 commit 229f578
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 8 deletions.
5 changes: 5 additions & 0 deletions 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
23 changes: 23 additions & 0 deletions crates/gateway/src/compilation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,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 @@ -58,6 +59,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
11 changes: 11 additions & 0 deletions crates/gateway/src/compilation_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,17 @@ fn test_compile_contract_class_bytecode_size_validation(declare_tx: RpcDeclareTr
)
}

// 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: RpcDeclareTransaction) {
let gateway_compiler = GatewayCompiler {
config: GatewayCompilerConfig { max_raw_casm_class_size: 1, ..Default::default() },
};

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

#[rstest]
fn test_compile_contract_class_bad_sierra(
gateway_compiler: GatewayCompiler,
Expand Down
27 changes: 19 additions & 8 deletions crates/gateway/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,25 +234,36 @@ impl StatefulTransactionValidatorConfig {
}
}
}

#[derive(Clone, Copy, Debug, Serialize, Deserialize, Validate, PartialEq)]
pub struct GatewayCompilerConfig {
pub max_casm_bytecode_size: usize,
pub max_raw_casm_class_size: usize,
}

impl Default for GatewayCompilerConfig {
fn default() -> Self {
Self { max_casm_bytecode_size: MAX_BYTECODE_SIZE }
Self {
max_casm_bytecode_size: MAX_BYTECODE_SIZE,
max_raw_casm_class_size: MAX_RAW_CLASS_SIZE,
}
}
}

impl SerializeConfig for GatewayCompilerConfig {
fn dump(&self) -> BTreeMap<ParamPath, SerializedParam> {
BTreeMap::from_iter([ser_param(
"max_casm_bytecode_size",
&self.max_casm_bytecode_size,
"Limitation of contract bytecode size.",
ParamPrivacyInput::Public,
)])
BTreeMap::from_iter([
ser_param(
"max_casm_bytecode_size",
&self.max_casm_bytecode_size,
"Limitation of contract bytecode size.",
ParamPrivacyInput::Public,
),
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

0 comments on commit 229f578

Please sign in to comment.