Skip to content

Commit

Permalink
feat: compile sierra to casm in declare tx
Browse files Browse the repository at this point in the history
  • Loading branch information
ArniStarkware committed Jun 16, 2024
1 parent c94d1d7 commit af43060
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 3 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ futures = "0.3.30"
hyper = { version = "0.14", features = ["client", "http1"] }
indexmap = "2.1.0"
itertools = "0.13.0"
num-bigint = { version = "0.4.5", default-features = false }
# TODO(YaelD, 28/5/2024): The special Papyrus version is needed in order to be aligned with the
# starknet-api version. This should be removed once we have a mono-repo.
papyrus_common = { git = "https://github.com/starkware-libs/papyrus.git", rev = "5d37fc32" }
Expand Down
3 changes: 3 additions & 0 deletions crates/gateway/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ testing = []
axum.workspace = true
blockifier.workspace = true
cairo-lang-starknet-classes.workspace = true
cairo-lang-utils.workspace = true
hyper.workspace = true
indexmap.workspace = true
num-bigint.workspace = true
papyrus_common.workspace = true
papyrus_config.workspace = true
papyrus_rpc.workspace = true
Expand All @@ -27,6 +29,7 @@ serde_json.workspace = true
starknet_api.workspace = true
starknet_client.workspace = true
starknet_mempool_types = { path = "../mempool_types", version = "0.0" }
starknet_sierra_compile ={ path = "../starknet_sierra_compile", version = "0.0" }
strum.workspace = true
tempfile.workspace = true
thiserror.workspace = true
Expand Down
2 changes: 2 additions & 0 deletions crates/gateway/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ use tokio::task::JoinError;
/// Errors directed towards the end-user, as a result of gateway requests.
#[derive(Debug, Error)]
pub enum GatewayError {
#[error(transparent)]
CompilationUtilError(#[from] starknet_sierra_compile::compile::CompilationUtilError),
#[error("Internal server error: {0}")]
InternalServerError(#[from] JoinError),
#[error("Error sending message: {0}")]
Expand Down
119 changes: 116 additions & 3 deletions crates/gateway/src/gateway.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,27 @@
use std::clone::Clone;
use std::net::SocketAddr;
use std::panic;
use std::sync::Arc;

use axum::extract::State;
use axum::routing::{get, post};
use axum::{Json, Router};
use starknet_api::external_transaction::ExternalTransaction;
use blockifier::execution::contract_class::{ClassInfo, ContractClassV1};
use cairo_lang_starknet_classes::contract_class::{
ContractClass as CairoLangContractClass, ContractEntryPoint as CairoLangContractEntryPoint,
ContractEntryPoints as CairoLangContractEntryPoints,
};
use cairo_lang_utils::bigint::BigUintAsHex;
use num_bigint::BigUint;
use starknet_api::external_transaction::{
ContractClass as StarknetApiContractClass, EntryPointByType as StarknetApiEntryPointByType,
ExternalDeclareTransaction, ExternalTransaction,
};
use starknet_api::hash::StarkFelt;
use starknet_api::state::EntryPoint as StarknetApiEntryPoint;
use starknet_api::transaction::TransactionHash;
use starknet_mempool_types::mempool_types::{Account, MempoolInput, SharedMempoolClient};
use starknet_sierra_compile::compile::{compile_sierra_to_casm, CompilationUtilError};

use crate::config::{GatewayConfig, GatewayNetworkConfig};
use crate::errors::{GatewayError, GatewayRunError};
Expand Down Expand Up @@ -117,11 +131,110 @@ fn process_tx(
// Perform stateless validations.
stateless_tx_validator.validate(&tx)?;

// TODO(Yael, 19/5/2024): pass the relevant class_info and deploy_account_hash.
let tx_hash = stateful_tx_validator.run_validate(state_reader_factory, &tx, None, None)?;
// Compile Sierra to Casm.
let optional_class_info = get_optional_class_info(&tx)?;

// TODO(Yael, 19/5/2024): pass the relevant deploy_account_hash.
let tx_hash =
stateful_tx_validator.run_validate(state_reader_factory, &tx, optional_class_info, None)?;

// TODO(Arni): Add the Sierra and the Casm to the mempool input.
Ok(MempoolInput {
tx: external_tx_to_thin_tx(&tx, tx_hash),
account: Account { sender_address: get_sender_address(&tx), ..Default::default() },
})
}

fn get_optional_class_info(tx: &ExternalTransaction) -> GatewayResult<Option<ClassInfo>> {
let declare_tx = match tx {
ExternalTransaction::Declare(declare_tx) => declare_tx,
_ => return Ok(None),
};

let ExternalDeclareTransaction::V3(tx) = declare_tx;
let starknet_api_contract_class = tx.contract_class.clone();
let sierra_program_length = starknet_api_contract_class.sierra_program.len();
let abi_length = starknet_api_contract_class.abi.len();
let cairo_lang_contract_class =
starknet_api_contract_class_to_cairo_lang_contract_class(starknet_api_contract_class);

// Compile Sierra to Casm.
let catch_unwind_result =
panic::catch_unwind(|| compile_sierra_to_casm(cairo_lang_contract_class));
let casm_contract_class = match catch_unwind_result {
Ok(compilation_result) => compilation_result?,
Err(_) => {
// TODO(Arni): Log the panic.
return Err(GatewayError::CompilationUtilError(CompilationUtilError::CompilationPanic));
}
};

// Convert Casm contract class to Starknet contract class directly.
let raw_contract_class = serde_json::to_string(&casm_contract_class).unwrap();
let contact_class_v1: ContractClassV1 =
ContractClassV1::try_from_json_string(&raw_contract_class).unwrap();

let blockifier_contract_class = contact_class_v1.into();
let class_info = ClassInfo::new(&blockifier_contract_class, sierra_program_length, abi_length)
.expect("Expects a Cairo 1 contract class");
Ok(Some(class_info))
}

fn starknet_api_contract_class_to_cairo_lang_contract_class(
starknet_api_contract_class: StarknetApiContractClass,
) -> CairoLangContractClass {
let sierra_program = starknet_api_contract_class
.sierra_program
.into_iter()
.map(stark_felt_to_big_uint_as_hex)
.collect();
let contract_class_version = starknet_api_contract_class.contract_class_version;
let entry_points_by_type = entry_point_by_type_to_contract_entry_points(
starknet_api_contract_class.entry_points_by_type,
);

CairoLangContractClass {
sierra_program,
sierra_program_debug_info: None,
contract_class_version,
entry_points_by_type,
// The Abi is irrelevant to the computlation.
abi: None,
}
}

fn entry_point_by_type_to_contract_entry_points(
entry_points_by_type: StarknetApiEntryPointByType,
) -> CairoLangContractEntryPoints {
let StarknetApiEntryPointByType { constructor, external, l1handler } = entry_points_by_type;
CairoLangContractEntryPoints {
external: starknet_api_entry_points_to_contract_entry_points(external),
l1_handler: starknet_api_entry_points_to_contract_entry_points(l1handler),
constructor: starknet_api_entry_points_to_contract_entry_points(constructor),
}
}

fn starknet_api_entry_points_to_contract_entry_points(
entry_points: Vec<StarknetApiEntryPoint>,
) -> Vec<CairoLangContractEntryPoint> {
entry_points.into_iter().map(entry_point_into_contract_entry_point).collect()
}

fn entry_point_into_contract_entry_point(
entry_point: StarknetApiEntryPoint,
) -> CairoLangContractEntryPoint {
CairoLangContractEntryPoint {
selector: stark_felt_to_big_uint(entry_point.selector.0),
function_idx: entry_point.function_idx.0,
}
}

fn stark_felt_to_big_uint_as_hex(stark_felt: StarkFelt) -> BigUintAsHex {
BigUintAsHex { value: stark_felt_to_big_uint(stark_felt) }
}

fn stark_felt_to_big_uint(stark_felt: StarkFelt) -> BigUint {
// When the value of radix is 256, the following function always returns a Some value.
let radix = 256;
BigUint::from_radix_be(stark_felt.bytes(), radix).expect("Unexpected None value.")
}
2 changes: 2 additions & 0 deletions crates/starknet_sierra_compile/src/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ pub enum CompilationUtilError {
AllowedLibfuncsError(#[from] AllowedLibfuncsError),
#[error(transparent)]
StarknetSierraCompilationError(#[from] StarknetSierraCompilationError),
#[error("Compilation panicked")]
CompilationPanic,
}

/// This function may panic.
Expand Down

0 comments on commit af43060

Please sign in to comment.