diff --git a/Cargo.lock b/Cargo.lock index 0491c040..c8cb0627 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5494,6 +5494,7 @@ dependencies = [ "cairo-lang-starknet-classes", "cairo-vm", "hyper", + "lazy_static", "papyrus_config", "pretty_assertions", "reqwest", diff --git a/crates/gateway/Cargo.toml b/crates/gateway/Cargo.toml index c9514273..decc3bea 100644 --- a/crates/gateway/Cargo.toml +++ b/crates/gateway/Cargo.toml @@ -18,6 +18,7 @@ blockifier.workspace = true cairo-lang-starknet-classes.workspace = true cairo-vm.workspace = true hyper.workspace = true +lazy_static.workspace = true papyrus_config.workspace = true reqwest.workspace = true serde.workspace = true diff --git a/crates/gateway/src/gateway.rs b/crates/gateway/src/gateway.rs index e1c167dd..de4b4d26 100644 --- a/crates/gateway/src/gateway.rs +++ b/crates/gateway/src/gateway.rs @@ -11,9 +11,10 @@ use blockifier::execution::execution_utils::felt_to_stark_felt; use cairo_lang_starknet_classes::casm_contract_class::{ CasmContractClass, CasmContractEntryPoints, }; +use lazy_static::lazy_static; use starknet_api::core::CompiledClassHash; use starknet_api::rpc_transaction::{RPCDeclareTransaction, RPCTransaction}; -use starknet_api::transaction::TransactionHash; +use starknet_api::transaction::{Builtin, TransactionHash}; use starknet_mempool_types::communication::SharedMempoolClient; use starknet_mempool_types::mempool_types::{Account, MempoolInput}; use starknet_sierra_compile::compile::compile_sierra_to_casm; @@ -27,7 +28,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, is_subsequence}; +use crate::utils::{external_tx_to_thin_tx, is_subsequence, IntoEnumIteratorExt, NameExt}; #[cfg(test)] #[path = "gateway_test.rs"] @@ -194,11 +195,30 @@ pub fn create_gateway( Gateway::new(config, state_reader_factory, client) } +// List of supported builtins. +// This is an explicit function so that it is explicitly desiced which builtins are supported. +// If new builtins are added, they should be added here. +fn is_supported_builtin(builtin: &Builtin) -> bool { + match builtin { + Builtin::RangeCheck + | Builtin::Pedersen + | Builtin::Poseidon + | Builtin::EcOp + | Builtin::Ecdsa + | Builtin::Bitwise + | Builtin::SegmentArena => true, + Builtin::Keccak => false, + } +} + // TODO(Arni): Add to a config. -fn get_supported_builtins() -> Vec { - let builtins = - ["pedersen", "range_check", "ecdsa", "bitwise", "ec_op", "poseidon", "segment_arena"]; - builtins.iter().map(|builtin| builtin.to_string()).collect() +lazy_static! { + static ref SUPPORTED_BUILTINS: Vec = { + Builtin::iter() + .filter(is_supported_builtin) + .map(|builtin| builtin.name().to_string()) + .collect::>() + }; } // TODO(Arni): Add test. @@ -207,13 +227,13 @@ fn validate_casm_class(contract_class: &CasmContractClass) -> Result<(), Gateway &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(); + let supported_builtins = &SUPPORTED_BUILTINS; for entry_point in entry_points_iterator { let builtins = &entry_point.builtins; if !is_subsequence(builtins, supported_builtins) { return Err(GatewayError::SupportedBuiltins { builtins: builtins.clone(), - supported_builtins: supported_builtins.clone(), + supported_builtins: supported_builtins.to_vec(), }); } } diff --git a/crates/gateway/src/utils.rs b/crates/gateway/src/utils.rs index 396c3c01..7b4acb76 100644 --- a/crates/gateway/src/utils.rs +++ b/crates/gateway/src/utils.rs @@ -10,8 +10,9 @@ use starknet_api::rpc_transaction::{ RPCDeclareTransaction, RPCDeployAccountTransaction, RPCInvokeTransaction, RPCTransaction, }; use starknet_api::transaction::{ - DeclareTransaction, DeclareTransactionV3, DeployAccountTransaction, DeployAccountTransactionV3, - InvokeTransaction, InvokeTransactionV3, Tip, TransactionHash, TransactionHasher, + Builtin, DeclareTransaction, DeclareTransactionV3, DeployAccountTransaction, + DeployAccountTransactionV3, InvokeTransaction, InvokeTransactionV3, Tip, TransactionHash, + TransactionHasher, }; use starknet_mempool_types::mempool_types::ThinTransaction; @@ -166,3 +167,54 @@ pub fn is_subsequence(subsequence: &[T], sequence: &[T]) -> bool { offset == subsequence.len() } + +// TODO(Arni): Remove the trait NameExt and IntoEnumIteratorExt once it is implemented in starknet +// API. +const RANGE_CHACK_BUILTIN_NAME: &str = "range_check"; +const PEDERSEN_BUILTIN_NAME: &str = "pedersen"; +const POSEIDON_BUILTIN_NAME: &str = "poseidon"; +const EC_OP_BUILTIN_NAME: &str = "ec_op"; +const ECDSA_BUILTIN_NAME: &str = "ecdsa"; +const BITWISE_BUILTIN_NAME: &str = "bitwise"; +const KECCAK_BUILTIN_NAME: &str = "keccak"; +const SEGMENT_ARENA_BUILTIN_NAME: &str = "segment_arena"; + +impl NameExt for Builtin { + fn name(&self) -> &'static str { + match self { + Builtin::RangeCheck => RANGE_CHACK_BUILTIN_NAME, + Builtin::Pedersen => PEDERSEN_BUILTIN_NAME, + Builtin::Poseidon => POSEIDON_BUILTIN_NAME, + Builtin::EcOp => EC_OP_BUILTIN_NAME, + Builtin::Ecdsa => ECDSA_BUILTIN_NAME, + Builtin::Bitwise => BITWISE_BUILTIN_NAME, + Builtin::Keccak => KECCAK_BUILTIN_NAME, + Builtin::SegmentArena => SEGMENT_ARENA_BUILTIN_NAME, + } + } +} + +impl IntoEnumIteratorExt for Builtin { + fn iter() -> impl Iterator { + vec![ + Builtin::Pedersen, + Builtin::RangeCheck, + Builtin::Ecdsa, + Builtin::Bitwise, + Builtin::EcOp, + Builtin::Poseidon, + Builtin::SegmentArena, + Builtin::Keccak, + ] + .into_iter() + } +} + +pub trait NameExt { + fn name(&self) -> &'static str; +} + +pub trait IntoEnumIteratorExt { + #[allow(opaque_hidden_inferred_bound)] + fn iter() -> impl Iterator; +}