Skip to content

Commit

Permalink
feat: declare post compilation builtin validation
Browse files Browse the repository at this point in the history
  • Loading branch information
ArniStarkware committed Jun 27, 2024
1 parent 203eed8 commit 332ec2c
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 2 deletions.
4 changes: 3 additions & 1 deletion crates/gateway/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub enum GatewayError {
CompilationError(#[from] starknet_sierra_compile::compile::CompilationUtilError),
#[error(
"The supplied compiled class hash {supplied:?} does not match the hash of the Casm class \
compiled from the supplied Sierra {hash_result:?}."
compiled from the supplied Sierra {hash_result:?}"
)]
CompiledClassHashMismatch { supplied: CompiledClassHash, hash_result: CompiledClassHash },
#[error(transparent)]
Expand All @@ -36,6 +36,8 @@ pub enum GatewayError {
StatefulTransactionValidatorError(#[from] StatefulTransactionValidatorError),
#[error(transparent)]
StatelessTransactionValidatorError(#[from] StatelessTransactionValidatorError),
#[error("{builtins:?} is not a subsquence of {supported_builtins:?}")]
SupportedBuiltins { builtins: Vec<String>, supported_builtins: Vec<String> },
}

impl IntoResponse for GatewayError {
Expand Down
39 changes: 38 additions & 1 deletion crates/gateway/src/gateway.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ use axum::routing::{get, post};
use axum::{Json, Router};
use blockifier::execution::contract_class::{ClassInfo, ContractClass, ContractClassV1};
use blockifier::execution::execution_utils::felt_to_stark_felt;
use cairo_lang_starknet_classes::casm_contract_class::{
CasmContractClass, CasmContractEntryPoints,
};
use starknet_api::core::CompiledClassHash;
use starknet_api::rpc_transaction::{RPCDeclareTransaction, RPCTransaction};
use starknet_api::transaction::TransactionHash;
Expand All @@ -22,7 +25,7 @@ use crate::starknet_api_test_utils::get_sender_address;
use crate::state_reader::StateReaderFactory;
use crate::stateful_transaction_validator::StatefulTransactionValidator;
use crate::stateless_transaction_validator::StatelessTransactionValidator;
use crate::utils::external_tx_to_thin_tx;
use crate::utils::{external_tx_to_thin_tx, is_subsequence};

#[cfg(test)]
#[path = "gateway_test.rs"]
Expand Down Expand Up @@ -158,6 +161,7 @@ pub fn compile_contract_class(declare_tx: &RPCDeclareTransaction) -> GatewayResu
return Err(GatewayError::CompilationError(CompilationUtilError::CompilationPanic));
}
};
validate_casm_class(&casm_contract_class)?;

let hash_result =
CompiledClassHash(felt_to_stark_felt(&casm_contract_class.compiled_class_hash()));
Expand All @@ -178,3 +182,36 @@ pub fn compile_contract_class(declare_tx: &RPCDeclareTransaction) -> GatewayResu
)?;
Ok(class_info)
}

// TODO(Arni): Add to a config.
fn get_supported_builtins() -> Vec<String> {
vec![
"pedersen".to_string(),
"range_check".to_string(),
"ecdsa".to_string(),
"bitwise".to_string(),
"ec_op".to_string(),
"poseidon".to_string(),
"segment_arena".to_string(),
]
}

// TODO(Arni): Add test.
fn validate_casm_class(contract_class: &CasmContractClass) -> Result<(), GatewayError> {
let CasmContractEntryPoints { external, l1_handler, constructor } =
&contract_class.entry_points_by_type;
let entry_points_iterator = external.iter().chain(l1_handler.iter()).chain(constructor.iter());

let supported_builtins = &get_supported_builtins();
for entry_point in entry_points_iterator {
let builtins = &entry_point.builtins;
println!("{builtins:?}");
if !is_subsequence(builtins, supported_builtins) {
return Err(GatewayError::SupportedBuiltins {
builtins: builtins.clone(),
supported_builtins: supported_builtins.clone(),
});
}
}
Ok(())
}
17 changes: 17 additions & 0 deletions crates/gateway/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,3 +145,20 @@ pub fn get_tx_hash(tx: &AccountTransaction) -> TransactionHash {
AccountTransaction::Invoke(tx) => tx.tx_hash,
}
}

/// Checks whether 'subsequence' is a subsequence of 'sequence'.
pub fn is_subsequence(subsequence: &[String], sequence: &[String]) -> bool {
let mut offset = 0;

for item in sequence {
if offset == subsequence.len() {
return true;
}

if item == &subsequence[offset] {
offset += 1;
}
}

offset == subsequence.len()
}

0 comments on commit 332ec2c

Please sign in to comment.