diff --git a/Cargo.lock b/Cargo.lock index 740834f0f..b39102595 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6029,6 +6029,7 @@ dependencies = [ "serde", "serde_json", "serde_with 3.9.0", + "starknet-core", "starknet-types-core", ] diff --git a/crates/client/gateway/src/client/methods.rs b/crates/client/gateway/src/client/methods.rs index 91b93cf92..9de714b86 100644 --- a/crates/client/gateway/src/client/methods.rs +++ b/crates/client/gateway/src/client/methods.rs @@ -77,14 +77,14 @@ mod tests { async fn test_get_state_update() { let client = FeederClient::starknet_alpha_mainnet(); - let block = client.get_state_update(BlockId::Number(0)).await.unwrap(); - let block = client + let _block = client.get_state_update(BlockId::Number(0)).await.unwrap(); + let _block = client .get_state_update(BlockId::Hash(Felt::from_hex_unchecked( "0x47c3637b57c2b079b93c61539950c17e868a28f46cdef28f88521067f21e943", ))) .await .unwrap(); - let block = client.get_state_update(BlockId::Tag(BlockTag::Latest)).await.unwrap(); - let block = client.get_state_update(BlockId::Tag(BlockTag::Pending)).await.unwrap(); + let _block = client.get_state_update(BlockId::Tag(BlockTag::Latest)).await.unwrap(); + let _block = client.get_state_update(BlockId::Tag(BlockTag::Pending)).await.unwrap(); } } diff --git a/crates/client/gateway/src/server/handler.rs b/crates/client/gateway/src/server/handler.rs index 92405a358..fd9c97e2a 100644 --- a/crates/client/gateway/src/server/handler.rs +++ b/crates/client/gateway/src/server/handler.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use hyper::{Body, Request, Response}; +use hyper::{body, Body, Request, Response}; use mc_db::MadaraBackend; use mc_rpc::providers::AddTransactionProvider; use mp_block::{BlockId, BlockTag, MadaraBlock, MadaraPendingBlock}; @@ -10,7 +10,10 @@ use mp_gateway::{ state_update::{PendingStateUpdateProvider, StateUpdateProvider}, }; use serde_json::json; -use starknet_core::types::BroadcastedTransaction; +use starknet_core::types::{ + BroadcastedDeclareTransaction, BroadcastedDeployAccountTransaction, BroadcastedInvokeTransaction, + BroadcastedTransaction, +}; use starknet_types_core::felt::Felt; use crate::error::{StarknetError, StarknetErrorCode}; @@ -19,7 +22,7 @@ use super::{ error::{GatewayError, ResultExt}, helpers::{ block_id_from_params, create_json_response, create_response_with_json_body, get_params_from_request, - include_block_params, not_implemented_response, + include_block_params, }, }; @@ -245,18 +248,60 @@ pub async fn handle_get_class_by_hash(req: Request, backend: Arc, - backend: Arc, add_transaction_provider: Arc, ) -> Response { - // let transaction = match serde_json::from_slice::(req.body())) { - // Ok(transaction) => transaction, - // Err(e) => { - // return GatewayError::StarknetError(StarknetError { - // code: StarknetErrorCode::MalformedRequest, - // message: format!("Failed to parse transaction: {}", e), - // }) - // .into() - // } - // }; - not_implemented_response() + let whole_body = match body::to_bytes(req.into_body()).await { + Ok(body) => body, + Err(e) => { + log::error!("Failed to read request body: {}", e); + return GatewayError::InternalServerError.into(); + } + }; + + let transaction = match serde_json::from_slice::(whole_body.as_ref()) { + Ok(transaction) => transaction, + Err(e) => { + return GatewayError::StarknetError(StarknetError { + code: StarknetErrorCode::MalformedRequest, + message: format!("Failed to parse transaction: {}", e), + }) + .into() + } + }; + + match transaction { + BroadcastedTransaction::Declare(tx) => declare_transaction(tx, add_transaction_provider).await, + BroadcastedTransaction::DeployAccount(tx) => deploy_account_transaction(tx, add_transaction_provider).await, + BroadcastedTransaction::Invoke(tx) => invoke_transaction(tx, add_transaction_provider).await, + } +} + +async fn declare_transaction( + tx: BroadcastedDeclareTransaction, + add_transaction_provider: Arc, +) -> Response { + match add_transaction_provider.add_declare_transaction(tx).await { + Ok(result) => create_json_response(hyper::StatusCode::OK, &result), + Err(e) => create_json_response(hyper::StatusCode::OK, &e), + } +} + +async fn deploy_account_transaction( + tx: BroadcastedDeployAccountTransaction, + add_transaction_provider: Arc, +) -> Response { + match add_transaction_provider.add_deploy_account_transaction(tx).await { + Ok(result) => create_json_response(hyper::StatusCode::OK, &result), + Err(e) => create_json_response(hyper::StatusCode::OK, &e), + } +} + +async fn invoke_transaction( + tx: BroadcastedInvokeTransaction, + add_transaction_provider: Arc, +) -> Response { + match add_transaction_provider.add_invoke_transaction(tx).await { + Ok(result) => create_json_response(hyper::StatusCode::OK, &result), + Err(e) => create_json_response(hyper::StatusCode::OK, &e), + } } diff --git a/crates/client/gateway/src/server/router.rs b/crates/client/gateway/src/server/router.rs index 4af0aa99d..baba97260 100644 --- a/crates/client/gateway/src/server/router.rs +++ b/crates/client/gateway/src/server/router.rs @@ -18,7 +18,7 @@ pub(crate) async fn main_router( match (req.uri().path(), feeder_gateway_enable, gateway_enable) { ("/health", _, _) => Ok(Response::new(Body::from("OK"))), (path, true, _) if path.starts_with("/feeder_gateway/") => feeder_gateway_router(req, backend).await, - (path, _, true) if path.starts_with("/feeder/") => gateway_router(req, backend, add_transaction_provider).await, + (path, _, true) if path.starts_with("/feeder/") => gateway_router(req, add_transaction_provider).await, (path, false, _) if path.starts_with("/feeder_gateway/") => Ok(service_unavailable_response("Feeder Gateway")), (path, _, false) if path.starts_with("/feeder/") => Ok(service_unavailable_response("Feeder")), _ => Ok(not_found_response()), @@ -38,13 +38,10 @@ async fn feeder_gateway_router(req: Request, backend: Arc) // Router for requests related to feeder async fn gateway_router( req: Request, - backend: Arc, add_transaction_provider: Arc, ) -> Result, Infallible> { match (req.method(), req.uri().path()) { - (&Method::POST, "/feeder/add_transaction") => { - Ok(handle_add_transaction(req, backend, add_transaction_provider).await) - } + (&Method::POST, "/feeder/add_transaction") => Ok(handle_add_transaction(req, add_transaction_provider).await), _ => Ok(not_found_response()), } } diff --git a/crates/node/src/main.rs b/crates/node/src/main.rs index 3cd5946ad..f87ccb5eb 100644 --- a/crates/node/src/main.rs +++ b/crates/node/src/main.rs @@ -10,8 +10,8 @@ use std::sync::Arc; use anyhow::Context; use clap::Parser; +use cli::{NetworkType, RunCmd}; use mc_block_import::BlockImporter; - use mc_db::DatabaseService; use mc_mempool::{GasPriceProvider, L1DataProvider, Mempool}; use mc_metrics::MetricsService; @@ -19,13 +19,9 @@ use mc_rpc::providers::{AddTransactionProvider, ForwardToProvider, MempoolAddTxP use mc_telemetry::{SysInfo, TelemetryService}; use mp_convert::ToFelt; use mp_utils::service::{Service, ServiceGroup}; -use service::{BlockProductionService, GatewayService, RpcService, SyncService}; +use service::{BlockProductionService, GatewayService, L1SyncService, RpcService, SyncService}; use starknet_providers::SequencerGatewayProvider; -use cli::{NetworkType, RunCmd}; -use service::L1SyncService; -use service::{BlockProductionService, RpcService, SyncService}; - const GREET_IMPL_NAME: &str = "Madara"; const GREET_SUPPORT_URL: &str = "https://github.com/madara-alliance/madara/issues"; diff --git a/crates/primitives/gateway/Cargo.toml b/crates/primitives/gateway/Cargo.toml index 2d4723405..7bac4798c 100644 --- a/crates/primitives/gateway/Cargo.toml +++ b/crates/primitives/gateway/Cargo.toml @@ -16,13 +16,14 @@ targets = ["x86_64-unknown-linux-gnu"] # Deoxys mp-block = { workspace = true } mp-chain-config = { workspace = true } -mp-convert = { workspace = true } mp-class = { workspace = true } +mp-convert = { workspace = true } mp-receipt = { workspace = true } mp-state-update = { workspace = true } mp-transactions = { workspace = true } # Starknet +starknet-core = { workspace = true } starknet-types-core = { workspace = true } # Other diff --git a/crates/primitives/gateway/src/user_transaction.rs b/crates/primitives/gateway/src/user_transaction.rs index cb7d6f9ee..621b8f382 100644 --- a/crates/primitives/gateway/src/user_transaction.rs +++ b/crates/primitives/gateway/src/user_transaction.rs @@ -1,30 +1,58 @@ +use std::sync::Arc; + use mp_class::{CompressedLegacyContractClass, FlattenedSierraClass}; use mp_transactions::{DataAvailabilityMode, ResourceBoundsMapping}; use serde::{Deserialize, Serialize}; +use starknet_core::types::{ + BroadcastedDeclareTransaction, BroadcastedDeclareTransactionV1, BroadcastedDeclareTransactionV2, + BroadcastedDeclareTransactionV3, BroadcastedDeployAccountTransaction, BroadcastedDeployAccountTransactionV1, + BroadcastedDeployAccountTransactionV3, BroadcastedInvokeTransaction, BroadcastedInvokeTransactionV1, + BroadcastedInvokeTransactionV3, BroadcastedTransaction, +}; use starknet_types_core::felt::Felt; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(tag = "type", rename_all = "SCREAMING_SNAKE_CASE")] #[serde(deny_unknown_fields)] pub enum UserTransaction { - DeclareV1(DeclareTransaction), - InvokeFunction(InvokeFunctionTransaction), - DeployAccount(DeployAccountTransaction), + DeclareV1(UserDeclareTransaction), + InvokeFunction(UserInvokeFunctionTransaction), + DeployAccount(UserDeployAccountTransaction), +} + +impl From for BroadcastedTransaction { + fn from(transaction: UserTransaction) -> Self { + match transaction { + UserTransaction::DeclareV1(v1) => BroadcastedTransaction::Declare(v1.into()), + UserTransaction::InvokeFunction(v1) => BroadcastedTransaction::Invoke(v1.into()), + UserTransaction::DeployAccount(v1) => BroadcastedTransaction::DeployAccount(v1.into()), + } + } } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(tag = "version")] -pub enum DeclareTransaction { +pub enum UserDeclareTransaction { #[serde(rename = "0x1")] - V1(DeclareV1Transaction), + V1(UserDeclareV1Transaction), #[serde(rename = "0x2")] - V2(DeclareV2Transaction), + V2(UserDeclareV2Transaction), #[serde(rename = "0x3")] - V3(DeclareV3Transaction), + V3(UserDeclareV3Transaction), +} + +impl From for BroadcastedDeclareTransaction { + fn from(transaction: UserDeclareTransaction) -> Self { + match transaction { + UserDeclareTransaction::V1(v1) => BroadcastedDeclareTransaction::V1(v1.into()), + UserDeclareTransaction::V2(v2) => BroadcastedDeclareTransaction::V2(v2.into()), + UserDeclareTransaction::V3(v3) => BroadcastedDeclareTransaction::V3(v3.into()), + } + } } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct DeclareV1Transaction { +pub struct UserDeclareV1Transaction { pub contract_class: CompressedLegacyContractClass, pub sender_address: Felt, pub max_fee: Felt, @@ -33,8 +61,21 @@ pub struct DeclareV1Transaction { pub is_query: bool, } +impl From for BroadcastedDeclareTransactionV1 { + fn from(transaction: UserDeclareV1Transaction) -> Self { + Self { + sender_address: transaction.sender_address, + max_fee: transaction.max_fee, + signature: transaction.signature, + nonce: transaction.nonce, + contract_class: Arc::new(transaction.contract_class.into()), + is_query: transaction.is_query, + } + } +} + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct DeclareV2Transaction { +pub struct UserDeclareV2Transaction { pub contract_class: FlattenedSierraClass, pub compiled_class_hash: Felt, pub sender_address: Felt, @@ -44,8 +85,22 @@ pub struct DeclareV2Transaction { pub is_query: bool, } +impl From for BroadcastedDeclareTransactionV2 { + fn from(transaction: UserDeclareV2Transaction) -> Self { + Self { + sender_address: transaction.sender_address, + compiled_class_hash: transaction.compiled_class_hash, + max_fee: transaction.max_fee, + signature: transaction.signature, + nonce: transaction.nonce, + contract_class: Arc::new(transaction.contract_class.into()), + is_query: transaction.is_query, + } + } +} + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct DeclareV3Transaction { +pub struct UserDeclareV3Transaction { pub contract_class: FlattenedSierraClass, pub compiled_class_hash: Felt, pub sender_address: Felt, @@ -60,17 +115,45 @@ pub struct DeclareV3Transaction { pub is_query: bool, } +impl From for BroadcastedDeclareTransactionV3 { + fn from(transaction: UserDeclareV3Transaction) -> Self { + Self { + sender_address: transaction.sender_address, + compiled_class_hash: transaction.compiled_class_hash, + signature: transaction.signature, + nonce: transaction.nonce, + nonce_data_availability_mode: transaction.nonce_data_availability_mode.into(), + fee_data_availability_mode: transaction.fee_data_availability_mode.into(), + resource_bounds: transaction.resource_bounds.into(), + tip: transaction.tip, + contract_class: Arc::new(transaction.contract_class.into()), + paymaster_data: transaction.paymaster_data, + account_deployment_data: transaction.account_deployment_data, + is_query: transaction.is_query, + } + } +} + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(tag = "version")] -pub enum InvokeFunctionTransaction { +pub enum UserInvokeFunctionTransaction { #[serde(rename = "0x1")] - V1(InvokeFunctionV1Transaction), + V1(UserInvokeFunctionV1Transaction), #[serde(rename = "0x3")] - V3(InvokeFunctionV3Transaction), + V3(UserInvokeFunctionV3Transaction), +} + +impl From for BroadcastedInvokeTransaction { + fn from(transaction: UserInvokeFunctionTransaction) -> Self { + match transaction { + UserInvokeFunctionTransaction::V1(v1) => BroadcastedInvokeTransaction::V1(v1.into()), + UserInvokeFunctionTransaction::V3(v3) => BroadcastedInvokeTransaction::V3(v3.into()), + } + } } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct InvokeFunctionV1Transaction { +pub struct UserInvokeFunctionV1Transaction { pub sender_address: Felt, pub calldata: Vec, pub signature: Vec, @@ -79,8 +162,21 @@ pub struct InvokeFunctionV1Transaction { pub is_query: bool, } +impl From for BroadcastedInvokeTransactionV1 { + fn from(transaction: UserInvokeFunctionV1Transaction) -> Self { + Self { + sender_address: transaction.sender_address, + calldata: transaction.calldata, + signature: transaction.signature, + max_fee: transaction.max_fee, + nonce: transaction.nonce, + is_query: transaction.is_query, + } + } +} + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct InvokeFunctionV3Transaction { +pub struct UserInvokeFunctionV3Transaction { pub sender_address: Felt, pub calldata: Vec, pub signature: Vec, @@ -94,17 +190,44 @@ pub struct InvokeFunctionV3Transaction { pub is_query: bool, } +impl From for BroadcastedInvokeTransactionV3 { + fn from(transaction: UserInvokeFunctionV3Transaction) -> Self { + Self { + sender_address: transaction.sender_address, + calldata: transaction.calldata, + signature: transaction.signature, + nonce: transaction.nonce, + nonce_data_availability_mode: transaction.nonce_data_availability_mode.into(), + fee_data_availability_mode: transaction.fee_data_availability_mode.into(), + resource_bounds: transaction.resource_bounds.into(), + tip: transaction.tip, + paymaster_data: transaction.paymaster_data, + account_deployment_data: transaction.account_deployment_data, + is_query: transaction.is_query, + } + } +} + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(tag = "version")] -pub enum DeployAccountTransaction { +pub enum UserDeployAccountTransaction { #[serde(rename = "0x1")] - V1(DeployAccountV1Transaction), + V1(UserDeployAccountV1Transaction), #[serde(rename = "0x3")] - V3(DeployAccountV3Transaction), + V3(UserDeployAccountV3Transaction), +} + +impl From for BroadcastedDeployAccountTransaction { + fn from(transaction: UserDeployAccountTransaction) -> Self { + match transaction { + UserDeployAccountTransaction::V1(v1) => BroadcastedDeployAccountTransaction::V1(v1.into()), + UserDeployAccountTransaction::V3(v3) => BroadcastedDeployAccountTransaction::V3(v3.into()), + } + } } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct DeployAccountV1Transaction { +pub struct UserDeployAccountV1Transaction { pub class_hash: Felt, pub contract_address_salt: Felt, pub constructor_calldata: Vec, @@ -114,8 +237,22 @@ pub struct DeployAccountV1Transaction { pub is_query: bool, } +impl From for BroadcastedDeployAccountTransactionV1 { + fn from(transaction: UserDeployAccountV1Transaction) -> Self { + Self { + class_hash: transaction.class_hash, + contract_address_salt: transaction.contract_address_salt, + constructor_calldata: transaction.constructor_calldata, + max_fee: transaction.max_fee, + signature: transaction.signature, + nonce: transaction.nonce, + is_query: transaction.is_query, + } + } +} + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct DeployAccountV3Transaction { +pub struct UserDeployAccountV3Transaction { pub class_hash: Felt, pub contract_address_salt: Felt, pub constructor_calldata: Vec, @@ -128,3 +265,21 @@ pub struct DeployAccountV3Transaction { pub paymaster_data: Vec, pub is_query: bool, } + +impl From for BroadcastedDeployAccountTransactionV3 { + fn from(transaction: UserDeployAccountV3Transaction) -> Self { + Self { + class_hash: transaction.class_hash, + contract_address_salt: transaction.contract_address_salt, + constructor_calldata: transaction.constructor_calldata, + signature: transaction.signature, + nonce: transaction.nonce, + nonce_data_availability_mode: transaction.nonce_data_availability_mode.into(), + fee_data_availability_mode: transaction.fee_data_availability_mode.into(), + resource_bounds: transaction.resource_bounds.into(), + tip: transaction.tip, + paymaster_data: transaction.paymaster_data, + is_query: transaction.is_query, + } + } +}