Skip to content

Commit

Permalink
refactor: create executable tx in the gateway process_tx
Browse files Browse the repository at this point in the history
  • Loading branch information
ArniStarkware committed Aug 21, 2024
1 parent 10fc2e9 commit b056be0
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 18 deletions.
18 changes: 11 additions & 7 deletions crates/gateway/src/gateway.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use async_trait::async_trait;
use axum::extract::State;
use axum::routing::{get, post};
use axum::{Json, Router};
use blockifier::execution::contract_class::ClassInfo;
use starknet_api::executable_transaction::Transaction;
use starknet_api::rpc_transaction::RpcTransaction;
use starknet_api::transaction::TransactionHash;
Expand All @@ -22,6 +21,7 @@ use crate::rpc_state_reader::RpcStateReaderFactory;
use crate::state_reader::StateReaderFactory;
use crate::stateful_transaction_validator::StatefulTransactionValidator;
use crate::stateless_transaction_validator::StatelessTransactionValidator;
use crate::utils::external_tx_to_executable_tx;

#[cfg(test)]
#[path = "gateway_test.rs"]
Expand Down Expand Up @@ -129,14 +129,18 @@ fn process_tx(
// Perform stateless validations.
stateless_tx_validator.validate(&tx)?;

// Compile Sierra to Casm.
let optional_class_info = match &tx {
RpcTransaction::Declare(declare_tx) => Some(
ClassInfo::try_from(gateway_compiler.process_declare_tx(declare_tx)?).map_err(|e| {
let executable_tx = external_tx_to_executable_tx(
&tx,
&gateway_compiler,
&stateful_tx_validator.config.chain_info.chain_id,
)?;
let optional_class_info = match executable_tx {
starknet_api::executable_transaction::Transaction::Declare(tx) => {
Some(tx.class_info.try_into().map_err(|e| {
error!("Failed to convert Starknet API ClassInfo to Blockifier ClassInfo: {:?}", e);
GatewaySpecError::UnexpectedError { data: "Internal server error.".to_owned() }
})?,
),
})?)
}
_ => None,
};

Expand Down
15 changes: 4 additions & 11 deletions crates/gateway/src/gateway_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ 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;
use crate::stateless_transaction_validator::StatelessTransactionValidator;
use crate::utils::external_tx_to_account_tx;
use crate::utils::external_tx_to_executable_tx;

pub fn app_state(
mempool_client: SharedMempoolClient,
Expand Down Expand Up @@ -88,18 +88,11 @@ async fn to_bytes(res: Response) -> Bytes {
}

fn calculate_hash(external_tx: &RpcTransaction) -> TransactionHash {
let optional_class_info = match &external_tx {
RpcTransaction::Declare(_declare_tx) => {
panic!("Declare transactions are not supported in this test")
}
_ => None,
};

let account_tx = external_tx_to_account_tx(
let executable_tx = external_tx_to_executable_tx(
external_tx,
optional_class_info,
&GatewayCompiler::new_cairo_lang_compiler(Default::default()),
&ChainInfo::create_for_testing().chain_id,
)
.unwrap();
account_tx.tx_hash()
executable_tx.tx_hash()
}
120 changes: 120 additions & 0 deletions crates/gateway/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ use blockifier::transaction::transactions::{
InvokeTransaction as BlockifierInvokeTransaction,
};
use starknet_api::core::{calculate_contract_address, ChainId, ClassHash, ContractAddress};
use starknet_api::executable_transaction::{
DeclareTransaction as ExecutableDeclareTransaction,
DeployAccountTransaction as ExecutableDeployAccountTransaction,
InvokeTransaction as ExecutableInvokeTransaction,
Transaction as ExecutableTransaction,
};
use starknet_api::rpc_transaction::{
RpcDeclareTransaction,
RpcDeployAccountTransaction,
Expand All @@ -17,13 +23,127 @@ use starknet_api::transaction::{
DeclareTransactionV3,
DeployAccountTransaction,
DeployAccountTransactionV3,
InvokeTransaction,
InvokeTransactionV3,
TransactionHasher,
};
use tracing::error;

use crate::compilation::GatewayCompiler;
use crate::errors::{GatewaySpecError, StatefulTransactionValidatorResult};

pub fn external_tx_to_executable_tx(
external_tx: &RpcTransaction,
gateway_compiler: &GatewayCompiler,
chain_id: &ChainId,
) -> Result<ExecutableTransaction, GatewaySpecError> {
Ok(match external_tx {
RpcTransaction::Declare(rpc_declare_tx) => ExecutableTransaction::Declare(
external_declare_tx_to_executable_tx(rpc_declare_tx, gateway_compiler, chain_id)?,
),
RpcTransaction::DeployAccount(rpc_deploy_account_tx) => {
ExecutableTransaction::DeployAccount(external_deploy_account_tx_to_executable_tx(
rpc_deploy_account_tx,
chain_id,
)?)
}
RpcTransaction::Invoke(rpc_invoke_tx) => ExecutableTransaction::Invoke(
external_invoke_tx_to_executable_tx(rpc_invoke_tx, chain_id)?,
),
})
}

fn external_declare_tx_to_executable_tx(
external_tx: &RpcDeclareTransaction,
gateway_compiler: &GatewayCompiler,
chain_id: &ChainId,
) -> Result<ExecutableDeclareTransaction, GatewaySpecError> {
let class_info = gateway_compiler.process_declare_tx(external_tx)?;
let RpcDeclareTransaction::V3(tx) = external_tx;
let declare_tx = DeclareTransaction::V3(DeclareTransactionV3 {
class_hash: ClassHash::default(), /* FIXME(yael 15/4/24): call the starknet-api
* function once ready */
resource_bounds: tx.resource_bounds.clone().into(),
tip: tx.tip,
signature: tx.signature.clone(),
nonce: tx.nonce,
compiled_class_hash: tx.compiled_class_hash,
sender_address: tx.sender_address,
nonce_data_availability_mode: tx.nonce_data_availability_mode,
fee_data_availability_mode: tx.fee_data_availability_mode,
paymaster_data: tx.paymaster_data.clone(),
account_deployment_data: tx.account_deployment_data.clone(),
});
let tx_hash =
declare_tx.calculate_transaction_hash(chain_id, &declare_tx.version()).map_err(|e| {
error!("Failed to calculate tx hash: {}", e);
GatewaySpecError::UnexpectedError { data: "Internal server error".to_owned() }
})?;
Ok(ExecutableDeclareTransaction { tx: declare_tx, tx_hash, class_info })
}

fn external_deploy_account_tx_to_executable_tx(
external_tx: &RpcDeployAccountTransaction,
chain_id: &ChainId,
) -> Result<ExecutableDeployAccountTransaction, GatewaySpecError> {
let RpcDeployAccountTransaction::V3(tx) = external_tx;
let deploy_account_tx = DeployAccountTransaction::V3(DeployAccountTransactionV3 {
resource_bounds: tx.resource_bounds.clone().into(),
tip: tx.tip,
signature: tx.signature.clone(),
nonce: tx.nonce,
class_hash: tx.class_hash,
contract_address_salt: tx.contract_address_salt,
constructor_calldata: tx.constructor_calldata.clone(),
nonce_data_availability_mode: tx.nonce_data_availability_mode,
fee_data_availability_mode: tx.fee_data_availability_mode,
paymaster_data: tx.paymaster_data.clone(),
});
let contract_address = calculate_contract_address(
deploy_account_tx.contract_address_salt(),
deploy_account_tx.class_hash(),
&deploy_account_tx.constructor_calldata(),
ContractAddress::default(),
)
.map_err(|e| {
error!("Failed to calculate contract address: {}", e);
GatewaySpecError::UnexpectedError { data: "Internal server error".to_owned() }
})?;
let tx_hash = deploy_account_tx
.calculate_transaction_hash(chain_id, &deploy_account_tx.version())
.map_err(|e| {
error!("Failed to calculate tx hash: {}", e);
GatewaySpecError::UnexpectedError { data: "Internal server error".to_owned() }
})?;
Ok(ExecutableDeployAccountTransaction { tx: deploy_account_tx, tx_hash, contract_address })
}

fn external_invoke_tx_to_executable_tx(
invoke_tx: &RpcInvokeTransaction,
chain_id: &ChainId,
) -> Result<ExecutableInvokeTransaction, GatewaySpecError> {
let RpcInvokeTransaction::V3(tx) = invoke_tx;
let invoke_tx = InvokeTransaction::V3(InvokeTransactionV3 {
resource_bounds: tx.resource_bounds.clone().into(),
tip: tx.tip,
signature: tx.signature.clone(),
nonce: tx.nonce,
sender_address: tx.sender_address,
calldata: tx.calldata.clone(),
nonce_data_availability_mode: tx.nonce_data_availability_mode,
fee_data_availability_mode: tx.fee_data_availability_mode,
paymaster_data: tx.paymaster_data.clone(),
account_deployment_data: tx.account_deployment_data.clone(),
});
let tx_hash =
invoke_tx.calculate_transaction_hash(chain_id, &invoke_tx.version()).map_err(|e| {
error!("Failed to calculate tx hash: {}", e);
GatewaySpecError::UnexpectedError { data: "Internal server error".to_owned() }
})?;
Ok(ExecutableInvokeTransaction { tx: invoke_tx, tx_hash })
}

// TODO(Arni): Delete this function.
pub fn external_tx_to_account_tx(
external_tx: &RpcTransaction,
// FIXME(yael 15/4/24): calculate class_info inside the function once compilation code is ready
Expand Down

0 comments on commit b056be0

Please sign in to comment.