diff --git a/Cargo.lock b/Cargo.lock index 8c89261f6..f1d3064a3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1994,6 +1994,7 @@ dependencies = [ "hex", "hyper 1.4.1", "jsonrpsee", + "parking_lot", "reth-chainspec", "reth-db", "reth-primitives", @@ -2811,6 +2812,7 @@ dependencies = [ "citrea-evm", "citrea-primitives", "jsonrpsee", + "parking_lot", "proptest", "reth-primitives", "reth-rpc-eth-types", diff --git a/Cargo.toml b/Cargo.toml index c545496ad..de7111a43 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -92,6 +92,7 @@ hex = { version = "0.4.3", default-features = false, features = ["alloc", "serde lazy_static = { version = "1.5.0" } log-panics = { version = "2", features = ["with-backtrace"] } once_cell = { version = "1.19.0", default-features = false, features = ["alloc"] } +parking_lot = { version = "0.12.3" } prometheus = { version = "0.13.3", default-features = false } proptest = { version = "1.3.1", default-features = false, features = ["alloc"] } proptest-derive = "0.4.0" diff --git a/crates/ethereum-rpc/Cargo.toml b/crates/ethereum-rpc/Cargo.toml index 456dcf74c..bd579bb70 100644 --- a/crates/ethereum-rpc/Cargo.toml +++ b/crates/ethereum-rpc/Cargo.toml @@ -12,29 +12,30 @@ readme = "README.md" resolver = "2" [dependencies] +# 3rd-party dependencies anyhow = { workspace = true } +borsh = { workspace = true } citrea-evm = { path = "../evm", features = ["native"] } citrea-primitives = { path = "../primitives" } jsonrpsee = { workspace = true, features = ["http-client", "server"] } +parking_lot = { workspace = true } rustc_version_runtime = { workspace = true } +schnellru = "0.2.1" sequencer-client = { path = "../sequencer-client" } -tracing = { workspace = true } - -borsh = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } +tokio = { workspace = true } +tracing = { workspace = true } +# Reth deps reth-primitives = { workspace = true } reth-rpc-eth-types = { workspace = true } reth-rpc-types = { workspace = true } reth-rpc-types-compat = { workspace = true } -schnellru = "0.2.1" -tokio = { workspace = true } - -sov-rollup-interface = { path = "../sovereign-sdk/rollup-interface", features = ["native"] } - +# Sovereign-SDK deps sov-modules-api = { path = "../sovereign-sdk/module-system/sov-modules-api", default-features = false } +sov-rollup-interface = { path = "../sovereign-sdk/rollup-interface", features = ["native"] } [dev-dependencies] proptest = { workspace = true } diff --git a/crates/ethereum-rpc/src/ethereum.rs b/crates/ethereum-rpc/src/ethereum.rs index 556878ae3..24fc9ea04 100644 --- a/crates/ethereum-rpc/src/ethereum.rs +++ b/crates/ethereum-rpc/src/ethereum.rs @@ -80,12 +80,8 @@ impl Ethereum { } #[instrument(level = "trace", skip_all)] - pub(crate) async fn max_fee_per_gas(&self, working_set: &mut WorkingSet) -> (U256, U256) { - let suggested_tip = self - .gas_price_oracle - .suggest_tip_cap(working_set) - .await - .unwrap(); + pub(crate) fn max_fee_per_gas(&self, working_set: &mut WorkingSet) -> (U256, U256) { + let suggested_tip = self.gas_price_oracle.suggest_tip_cap(working_set).unwrap(); let evm = Evm::::default(); let base_fee = evm diff --git a/crates/ethereum-rpc/src/gas_price/gas_oracle.rs b/crates/ethereum-rpc/src/gas_price/gas_oracle.rs index e82b67bea..8f3384314 100644 --- a/crates/ethereum-rpc/src/gas_price/gas_oracle.rs +++ b/crates/ethereum-rpc/src/gas_price/gas_oracle.rs @@ -5,13 +5,13 @@ use citrea_evm::{Evm, SYSTEM_SIGNER}; use citrea_primitives::basefee::calculate_next_block_base_fee; +use parking_lot::Mutex; use reth_primitives::constants::GWEI_TO_WEI; use reth_primitives::{BlockNumberOrTag, B256, U256}; use reth_rpc_eth_types::error::{EthApiError, EthResult, RpcInvalidTransactionError}; use reth_rpc_types::{BlockTransactions, FeeHistory}; use serde::{Deserialize, Serialize}; use sov_modules_api::WorkingSet; -use tokio::sync::Mutex; use tracing::warn; use super::cache::BlockCache; @@ -137,7 +137,7 @@ impl GasPriceOracle { } /// Reports the fee history - pub async fn fee_history( + pub fn fee_history( &self, mut block_count: u64, newest_block: BlockNumberOrTag, @@ -193,7 +193,7 @@ impl GasPriceOracle { let mut rewards: Vec> = Vec::new(); let (fee_entries, resolution) = { - let mut fee_history_cache = self.fee_history_cache.lock().await; + let mut fee_history_cache = self.fee_history_cache.lock(); ( fee_history_cache.get_history(start_block, end_block, working_set), @@ -239,7 +239,7 @@ impl GasPriceOracle { } /// Suggests a gas price estimate based on recent blocks, using the configured percentile. - pub async fn suggest_tip_cap(&self, working_set: &mut WorkingSet) -> EthResult { + pub fn suggest_tip_cap(&self, working_set: &mut WorkingSet) -> EthResult { let header = &self .provider .get_block_by_number(None, None, working_set) @@ -247,7 +247,7 @@ impl GasPriceOracle { .unwrap() .header; - let mut last_price = self.last_price.lock().await; + let mut last_price = self.last_price.lock(); // if we have stored a last price, then we check whether or not it was for the same head if last_price.block_hash == header.hash.unwrap() { @@ -274,8 +274,7 @@ impl GasPriceOracle { for _ in 0..max_blocks { let (parent_hash, block_values) = self - .get_block_values(current_hash, SAMPLE_NUMBER as usize, working_set) - .await? + .get_block_values(current_hash, SAMPLE_NUMBER as usize, working_set)? .ok_or(EthApiError::UnknownBlockNumber)?; if block_values.is_empty() { @@ -324,7 +323,7 @@ impl GasPriceOracle { /// If the block cannot be found, then this will return `None`. /// /// This method also returns the parent hash for the given block. - async fn get_block_values( + fn get_block_values( &self, block_hash: B256, limit: usize, @@ -332,7 +331,7 @@ impl GasPriceOracle { ) -> EthResult)>> { // check the cache (this will hit the disk if the block is not cached) let block_hit = { - let mut cache = self.fee_history_cache.lock().await; + let mut cache = self.fee_history_cache.lock(); cache.block_cache.get_block(block_hash, working_set)? }; let block = match block_hit { diff --git a/crates/ethereum-rpc/src/lib.rs b/crates/ethereum-rpc/src/lib.rs index 205f89266..d6e81ee77 100644 --- a/crates/ethereum-rpc/src/lib.rs +++ b/crates/ethereum-rpc/src/lib.rs @@ -89,7 +89,7 @@ fn register_rpc_methods( Ok::<_, ErrorObjectOwned>(ethereum.web3_client_version.clone()) })?; - rpc.register_async_method("web3_sha3", |params, _, _| async move { + rpc.register_blocking_method("web3_sha3", move |params, _, _| { info!("eth module: web3_sha3"); let data: Bytes = params.one()?; @@ -98,12 +98,12 @@ fn register_rpc_methods( Ok::<_, ErrorObjectOwned>(hash) })?; - rpc.register_async_method("eth_gasPrice", |_, ethereum, _| async move { + rpc.register_blocking_method("eth_gasPrice", move |_, ethereum, _| { info!("eth module: eth_gasPrice"); let price = { let mut working_set = WorkingSet::::new(ethereum.storage.clone()); - let (base_fee, suggested_tip) = ethereum.max_fee_per_gas(&mut working_set).await; + let (base_fee, suggested_tip) = ethereum.max_fee_per_gas(&mut working_set); suggested_tip + base_fee }; @@ -111,12 +111,12 @@ fn register_rpc_methods( Ok::(price) })?; - rpc.register_async_method("eth_maxFeePerGas", |_, ethereum, _| async move { + rpc.register_blocking_method("eth_maxFeePerGas", move |_, ethereum, _| { info!("eth module: eth_maxFeePerGas"); let max_fee_per_gas = { let mut working_set = WorkingSet::::new(ethereum.storage.clone()); - let (base_fee, suggested_tip) = ethereum.max_fee_per_gas(&mut working_set).await; + let (base_fee, suggested_tip) = ethereum.max_fee_per_gas(&mut working_set); suggested_tip + base_fee }; @@ -124,12 +124,12 @@ fn register_rpc_methods( Ok::(max_fee_per_gas) })?; - rpc.register_async_method("eth_maxPriorityFeePerGas", |_, ethereum, _| async move { + rpc.register_blocking_method("eth_maxPriorityFeePerGas", move |_, ethereum, _| { info!("eth module: eth_maxPriorityFeePerGas"); let max_priority_fee = { let mut working_set = WorkingSet::::new(ethereum.storage.clone()); - let (_base_fee, suggested_tip) = ethereum.max_fee_per_gas(&mut working_set).await; + let (_base_fee, suggested_tip) = ethereum.max_fee_per_gas(&mut working_set); suggested_tip }; @@ -137,7 +137,7 @@ fn register_rpc_methods( Ok::(max_priority_fee) })?; - rpc.register_async_method("eth_feeHistory", |params, ethereum, _| async move { + rpc.register_blocking_method("eth_feeHistory", move |params, ethereum, _| { info!("eth module: eth_feeHistory"); let mut params = params.sequence(); @@ -151,15 +151,12 @@ fn register_rpc_methods( let fee_history = { let mut working_set = WorkingSet::::new(ethereum.storage.clone()); - ethereum - .gas_price_oracle - .fee_history( - block_count, - newest_block, - reward_percentiles, - &mut working_set, - ) - .await? + ethereum.gas_price_oracle.fee_history( + block_count, + newest_block, + reward_percentiles, + &mut working_set, + )? }; Ok::(fee_history) @@ -396,9 +393,9 @@ fn register_rpc_methods( // Ok::<_, ErrorObjectOwned>(tx_hash) // })?; - rpc.register_async_method::, ErrorObjectOwned>, _, _>( + rpc.register_blocking_method::, ErrorObjectOwned>, _>( "debug_traceBlockByHash", - |parameters, ethereum, _| async move { + move |parameters, ethereum, _| { info!("eth module: debug_traceBlockByHash"); let mut params = parameters.sequence(); @@ -420,9 +417,9 @@ fn register_rpc_methods( }, )?; - rpc.register_async_method::, ErrorObjectOwned>, _, _>( + rpc.register_blocking_method::, ErrorObjectOwned>, _>( "debug_traceBlockByNumber", - |parameters, ethereum, _| async move { + move |parameters, ethereum, _| { info!("eth module: debug_traceBlockByNumber"); let mut params = parameters.sequence(); @@ -442,9 +439,9 @@ fn register_rpc_methods( }, )?; - rpc.register_async_method::, _, _>( + rpc.register_blocking_method::, _>( "debug_traceTransaction", - |parameters, ethereum, _| async move { + move |parameters, ethereum, _| { // the main rpc handler for debug_traceTransaction // Checks the cache in ethereum struct if the trace exists // if found; returns the trace diff --git a/crates/evm/src/query.rs b/crates/evm/src/query.rs index 02f4e1587..003c249ce 100644 --- a/crates/evm/src/query.rs +++ b/crates/evm/src/query.rs @@ -613,7 +613,7 @@ impl Evm { /// Handler for: `eth_call` //https://github.com/paradigmxyz/reth/blob/f577e147807a783438a3f16aad968b4396274483/crates/rpc/rpc/src/eth/api/transactions.rs#L502 //https://github.com/paradigmxyz/reth/blob/main/crates/rpc/rpc-types/src/eth/call.rs#L7 - #[rpc_method(name = "eth_call")] + #[rpc_method(name = "eth_call", blocking)] pub fn get_call( &self, request: reth_rpc_types::TransactionRequest, @@ -712,7 +712,7 @@ impl Evm { } /// Handler for `eth_createAccessList` - #[rpc_method(name = "eth_createAccessList")] + #[rpc_method(name = "eth_createAccessList", blocking)] pub fn create_access_list( &self, request: reth_rpc_types::TransactionRequest, @@ -902,7 +902,7 @@ impl Evm { /// Handler for: `eth_estimateGas` // https://github.com/paradigmxyz/reth/blob/main/crates/rpc/rpc/src/eth/api/call.rs#L172 - #[rpc_method(name = "eth_estimateGas")] + #[rpc_method(name = "eth_estimateGas", blocking)] pub fn eth_estimate_gas( &self, request: reth_rpc_types::TransactionRequest, @@ -916,7 +916,7 @@ impl Evm { } /// Handler for: `eth_estimateDiffSize` - #[rpc_method(name = "eth_estimateDiffSize")] + #[rpc_method(name = "eth_estimateDiffSize", blocking)] pub fn eth_estimate_diff_size( &self, request: reth_rpc_types::TransactionRequest, diff --git a/crates/sequencer/Cargo.toml b/crates/sequencer/Cargo.toml index c0146665d..c2568445e 100644 --- a/crates/sequencer/Cargo.toml +++ b/crates/sequencer/Cargo.toml @@ -23,6 +23,7 @@ futures = { workspace = true } hex = { workspace = true } hyper = { workspace = true } jsonrpsee = { workspace = true, features = ["http-client", "server"] } +parking_lot = { workspace = true } rs_merkle = { workspace = true } schnellru = "0.2.1" serde = { workspace = true } diff --git a/crates/sequencer/src/rpc.rs b/crates/sequencer/src/rpc.rs index 8c5f6b999..2f385bec2 100644 --- a/crates/sequencer/src/rpc.rs +++ b/crates/sequencer/src/rpc.rs @@ -5,13 +5,13 @@ use futures::channel::mpsc::UnboundedSender; use jsonrpsee::types::error::{INTERNAL_ERROR_CODE, INTERNAL_ERROR_MSG}; use jsonrpsee::types::ErrorObjectOwned; use jsonrpsee::RpcModule; +use parking_lot::Mutex; use reth_primitives::{Bytes, IntoRecoveredTransaction, B256}; use reth_rpc_eth_types::error::EthApiError; use reth_rpc_types_compat::transaction::from_recovered; use reth_transaction_pool::{EthPooledTransaction, PoolTransaction}; use sov_db::ledger_db::SequencerLedgerOps; use sov_modules_api::WorkingSet; -use tokio::sync::Mutex; use tracing::{debug, error}; use crate::deposit_data_mempool::DepositDataMempool; @@ -80,46 +80,39 @@ pub(crate) fn create_rpc_module< })?; } - rpc.register_async_method( - "eth_getTransactionByHash", - |parameters, ctx, _| async move { - let mut params = parameters.sequence(); - let hash: B256 = params.next()?; - let mempool_only: Result, ErrorObjectOwned> = params.optional_next(); - debug!( - "Sequencer: eth_getTransactionByHash({}, {:?})", - hash, mempool_only - ); - - match ctx.mempool.get(&hash) { - Some(tx) => { - let tx_signed_ec_recovered = tx.to_recovered_transaction(); // tx signed ec recovered - let tx: reth_rpc_types::Transaction = from_recovered(tx_signed_ec_recovered); - Ok::, ErrorObjectOwned>(Some(tx)) - } - None => match mempool_only { - Ok(Some(true)) => { - Ok::, ErrorObjectOwned>(None) - } - _ => { - let evm = Evm::::default(); - let mut working_set = WorkingSet::::new(ctx.storage.clone()); - - match evm.get_transaction_by_hash(hash, &mut working_set) { - Ok(tx) => { - Ok::, ErrorObjectOwned>(tx) - } - Err(e) => Err(e), - } - } - }, + rpc.register_blocking_method("eth_getTransactionByHash", move |parameters, ctx, _| { + let mut params = parameters.sequence(); + let hash: B256 = params.next()?; + let mempool_only: Result, ErrorObjectOwned> = params.optional_next(); + debug!( + "Sequencer: eth_getTransactionByHash({}, {:?})", + hash, mempool_only + ); + + match ctx.mempool.get(&hash) { + Some(tx) => { + let tx_signed_ec_recovered = tx.to_recovered_transaction(); // tx signed ec recovered + let tx: reth_rpc_types::Transaction = from_recovered(tx_signed_ec_recovered); + Ok::, ErrorObjectOwned>(Some(tx)) } - }, - )?; + None => match mempool_only { + Ok(Some(true)) => Ok::, ErrorObjectOwned>(None), + _ => { + let evm = Evm::::default(); + let mut working_set = WorkingSet::::new(ctx.storage.clone()); + + match evm.get_transaction_by_hash(hash, &mut working_set) { + Ok(tx) => Ok::, ErrorObjectOwned>(tx), + Err(e) => Err(e), + } + } + }, + } + })?; - rpc.register_async_method( + rpc.register_blocking_method( "citrea_sendRawDepositTransaction", - |parameters, ctx, _| async move { + move |parameters, ctx, _| { let mut params = parameters.sequence(); let deposit: Bytes = params.next()?; @@ -131,7 +124,6 @@ pub(crate) fn create_rpc_module< let dep_tx = ctx .deposit_mempool .lock() - .await .make_deposit_tx_from_data(deposit.clone().into()); let tx_res = evm.get_call(dep_tx, None, None, None, &mut working_set); @@ -139,10 +131,7 @@ pub(crate) fn create_rpc_module< match tx_res { Ok(hex_res) => { tracing::debug!("Deposit tx processed successfully {}", hex_res); - ctx.deposit_mempool - .lock() - .await - .add_deposit_tx(deposit.to_vec()); + ctx.deposit_mempool.lock().add_deposit_tx(deposit.to_vec()); } Err(e) => { error!("Error processing deposit tx: {:?}", e); diff --git a/crates/sequencer/src/sequencer.rs b/crates/sequencer/src/sequencer.rs index 2c46529d2..bf3779670 100644 --- a/crates/sequencer/src/sequencer.rs +++ b/crates/sequencer/src/sequencer.rs @@ -21,6 +21,7 @@ use futures::StreamExt; use hyper::Method; use jsonrpsee::server::{BatchRequestConfig, ServerBuilder}; use jsonrpsee::RpcModule; +use parking_lot::Mutex; use reth_primitives::{Address, IntoRecoveredTransaction, TxHash}; use reth_provider::{AccountReader, BlockReaderIdExt}; use reth_transaction_pool::{ @@ -46,7 +47,7 @@ use sov_rollup_interface::storage::HierarchicalStorageManager; use sov_rollup_interface::zk::ZkvmHost; use sov_stf_runner::{InitVariant, RollupPublicKeys, RpcConfig}; use tokio::sync::oneshot::channel as oneshot_channel; -use tokio::sync::{broadcast, mpsc, Mutex}; +use tokio::sync::{broadcast, mpsc}; use tokio::time::{sleep, Instant}; use tower_http::cors::{Any, CorsLayer}; use tracing::{debug, error, info, instrument, trace, warn}; @@ -384,7 +385,6 @@ where let deposit_data = self .deposit_mempool .lock() - .await .fetch_deposits(self.config.deposit_mempool_fetch_limit); let batch_info = HookSoftConfirmationInfo { diff --git a/crates/sovereign-sdk/full-node/sov-ledger-rpc/src/server.rs b/crates/sovereign-sdk/full-node/sov-ledger-rpc/src/server.rs index e7742fc2c..19dabafee 100644 --- a/crates/sovereign-sdk/full-node/sov-ledger-rpc/src/server.rs +++ b/crates/sovereign-sdk/full-node/sov-ledger-rpc/src/server.rs @@ -39,51 +39,51 @@ where { let mut rpc = RpcModule::new(ledger); - rpc.register_async_method( + rpc.register_blocking_method( "ledger_getSoftConfirmationByHash", - |params, ledger, _| async move { + move |params, ledger, _| { let args: HexHash = params.one()?; ledger .get_soft_confirmation_by_hash::(&args.0) .map_err(|e| to_jsonrpsee_error_object(LEDGER_RPC_ERROR, e)) }, )?; - rpc.register_async_method( + rpc.register_blocking_method( "ledger_getSoftConfirmationByNumber", - |params, ledger, _| async move { + move |params, ledger, _| { let args: u64 = params.one()?; ledger .get_soft_confirmation_by_number::(args) .map_err(|e| to_jsonrpsee_error_object(LEDGER_RPC_ERROR, e)) }, )?; - rpc.register_async_method( + rpc.register_blocking_method( "ledger_getSoftConfirmationRange", - |params, ledger, _| async move { + move |params, ledger, _| { let args: (u64, u64) = params.parse()?; ledger .get_soft_confirmations_range(args.0, args.1) .map_err(|e| to_jsonrpsee_error_object(LEDGER_RPC_ERROR, e)) }, )?; - rpc.register_async_method( + rpc.register_blocking_method( "ledger_getSoftConfirmationStatus", - |params, ledger, _| async move { + move |params, ledger, _| { let args: u64 = params.one()?; ledger .get_soft_confirmation_status(args) .map_err(|e| to_jsonrpsee_error_object(LEDGER_RPC_ERROR, e)) }, )?; - rpc.register_async_method("prover_getLastScannedL1Slot", |_, ledger, _| async move { + rpc.register_blocking_method("prover_getLastScannedL1Slot", move |_, ledger, _| { ledger .get_prover_last_scanned_l1_height() .map_err(|e| to_jsonrpsee_error_object(LEDGER_RPC_ERROR, e)) })?; - rpc.register_async_method( + rpc.register_blocking_method( "ledger_getSequencerCommitmentsOnSlotByNumber", - |params, ledger, _| async move { + move |params, ledger, _| { // Returns commitments on DA slot with given height. let height: u64 = params.one()?; @@ -93,9 +93,9 @@ where }, )?; - rpc.register_async_method( + rpc.register_blocking_method( "ledger_getSequencerCommitmentsOnSlotByHash", - |params, ledger, _| async move { + move |params, ledger, _| { // Returns commitments on DA slot with given hash. let hash: [u8; 32] = params.one()?; let height = ledger @@ -110,37 +110,31 @@ where }, )?; - rpc.register_async_method( - "ledger_getProofBySlotHeight", - |params, ledger, _| async move { - // Returns proof on DA slot with given height - let height: u64 = params.one()?; - ledger - .get_proof_data_by_l1_height(height) - .map_err(|e| to_jsonrpsee_error_object(LEDGER_RPC_ERROR, e)) - }, - )?; + rpc.register_blocking_method("ledger_getProofBySlotHeight", move |params, ledger, _| { + // Returns proof on DA slot with given height + let height: u64 = params.one()?; + ledger + .get_proof_data_by_l1_height(height) + .map_err(|e| to_jsonrpsee_error_object(LEDGER_RPC_ERROR, e)) + })?; - rpc.register_async_method( - "ledger_getProofBySlotHash", - |params, ledger, _| async move { - // Returns proof on DA slot with given height - let hash: [u8; 32] = params.one()?; - let height = ledger - .get_slot_number_by_hash(hash) - .map_err(|e| to_jsonrpsee_error_object(LEDGER_RPC_ERROR, e))?; - match height { - Some(height) => ledger - .get_proof_data_by_l1_height(height) - .map_err(|e| to_jsonrpsee_error_object(LEDGER_RPC_ERROR, e)), - None => Ok(None), - } - }, - )?; + rpc.register_blocking_method("ledger_getProofBySlotHash", move |params, ledger, _| { + // Returns proof on DA slot with given height + let hash: [u8; 32] = params.one()?; + let height = ledger + .get_slot_number_by_hash(hash) + .map_err(|e| to_jsonrpsee_error_object(LEDGER_RPC_ERROR, e))?; + match height { + Some(height) => ledger + .get_proof_data_by_l1_height(height) + .map_err(|e| to_jsonrpsee_error_object(LEDGER_RPC_ERROR, e)), + None => Ok(None), + } + })?; - rpc.register_async_method( + rpc.register_blocking_method( "ledger_getVerifiedProofsBySlotHeight", - |params, ledger, _| async move { + move |params, ledger, _| { // Returns proof on DA slot with given height let height: u64 = params.one()?; ledger @@ -149,25 +143,22 @@ where }, )?; - rpc.register_async_method("ledger_getLastVerifiedProof", |_, ledger, _| async move { + rpc.register_blocking_method("ledger_getLastVerifiedProof", move |_, ledger, _| { // Returns latest proof data ledger .get_last_verified_proof() .map_err(|e| to_jsonrpsee_error_object(LEDGER_RPC_ERROR, e)) })?; - rpc.register_async_method( - "ledger_getHeadSoftConfirmation", - |_, ledger, _| async move { - ledger - .get_head_soft_confirmation() - .map_err(|e: anyhow::Error| to_jsonrpsee_error_object(LEDGER_RPC_ERROR, e)) - }, - )?; + rpc.register_blocking_method("ledger_getHeadSoftConfirmation", move |_, ledger, _| { + ledger + .get_head_soft_confirmation() + .map_err(|e: anyhow::Error| to_jsonrpsee_error_object(LEDGER_RPC_ERROR, e)) + })?; - rpc.register_async_method( + rpc.register_blocking_method( "ledger_getHeadSoftConfirmationHeight", - |_, ledger, _| async move { + move |_, ledger, _| { ledger .get_head_soft_confirmation_height() .map_err(|e| to_jsonrpsee_error_object(LEDGER_RPC_ERROR, e)) diff --git a/crates/sovereign-sdk/module-system/sov-modules-macros/src/rpc/rpc_gen.rs b/crates/sovereign-sdk/module-system/sov-modules-macros/src/rpc/rpc_gen.rs index e3dba3f1d..59a135c48 100644 --- a/crates/sovereign-sdk/module-system/sov-modules-macros/src/rpc/rpc_gen.rs +++ b/crates/sovereign-sdk/module-system/sov-modules-macros/src/rpc/rpc_gen.rs @@ -87,6 +87,8 @@ impl RpcImplBlock { let impl_trait_name = format_ident!("{}RpcImpl", self.type_name); + let mut async_methods_count = 0; + for method in self.methods.iter() { // Extract the names of the formal arguments let arg_values = method @@ -125,10 +127,20 @@ impl RpcImplBlock { signature.inputs = inputs.into_iter().collect(); - quote! { - #( #docs )* - #signature { - <#type_name #ty_generics as ::std::default::Default>::default().#method_name(#(#pre_working_set_args,)* &mut Self::get_working_set(self), #(#post_working_set_args),* ) + if method.method_signature.asyncness.is_some() { + async_methods_count += 1; + quote! { + #( #docs )* + #signature { + <#type_name #ty_generics as ::std::default::Default>::default().#method_name(#(#pre_working_set_args,)* &mut Self::get_working_set(self), #(#post_working_set_args),* ).await + } + } + } else { + quote! { + #( #docs )* + #signature { + <#type_name #ty_generics as ::std::default::Default>::default().#method_name(#(#pre_working_set_args,)* &mut Self::get_working_set(self), #(#post_working_set_args),* ) + } } } } else { @@ -136,30 +148,60 @@ impl RpcImplBlock { let arg_values = arg_values .clone() .filter(|arg| arg.to_string() != quote! { self }.to_string()); - quote! { - #signature { - <#type_name #ty_generics as ::std::default::Default>::default().#method_name(#(#arg_values),*) + + if method.method_signature.asyncness.is_some() { + async_methods_count += 1; + quote! { + #signature { + <#type_name #ty_generics as ::std::default::Default>::default().#method_name(#(#arg_values),*).await + } + } + } else { + quote! { + #signature { + <#type_name #ty_generics as ::std::default::Default>::default().#method_name(#(#arg_values),*) + } } } }; impl_trait_methods.push(impl_trait_method); + #[allow(clippy::collapsible_else_if)] let blanket_impl_method = if let Some(idx) = method.idx_of_working_set_arg { // If necessary, adjust the signature to remove the working set argument. let pre_working_set_args = arg_values.clone().take(idx); let post_working_set_args = arg_values.clone().skip(idx + 1); - quote! { - #( #docs )* - #signature { - ::#method_name(#(#pre_working_set_args,)* #(#post_working_set_args),* ) + + if method.method_signature.asyncness.is_some() { + quote! { + #( #docs )* + #signature { + ::#method_name(#(#pre_working_set_args,)* #(#post_working_set_args),* ).await + } + } + } else { + quote! { + #( #docs )* + #signature { + ::#method_name(#(#pre_working_set_args,)* #(#post_working_set_args),* ) + } } } } else { - quote! { - #( #docs )* - #signature { - ::#method_name(#(#arg_values),*) + if method.method_signature.asyncness.is_some() { + quote! { + #( #docs )* + #signature { + ::#method_name(#(#arg_values),*).await + } + } + } else { + quote! { + #( #docs )* + #signature { + ::#method_name(#(#arg_values),*) + } } } }; @@ -167,10 +209,18 @@ impl RpcImplBlock { blanket_impl_methods.push(blanket_impl_method); } + let mut async_trait_marker = None; + if async_methods_count > 0 { + async_trait_marker = Some(quote! { + #[async_trait::async_trait] + }) + } + let rpc_impl_trait = if let Some(ref working_set_type) = self.working_set_type { quote! { /// Allows a Runtime to be converted into a functional RPC server by simply implementing the two required methods - /// `get_backing_impl(&self) -> MyModule` and `get_working_set(&self) -> ::sov_modules_api::WorkingSet` + #async_trait_marker pub trait #impl_trait_name #generics #where_clause { /// Get a clean working set on top of the latest state fn get_working_set(&self) -> #working_set_type; @@ -181,6 +231,7 @@ impl RpcImplBlock { quote! { /// Allows a Runtime to be converted into a functional RPC server by simply implementing the two required methods - /// `get_backing_impl(&self) -> MyModule` and `get_working_set(&self) -> ::sov_modules_api::WorkingSet` + #async_trait_marker pub trait #impl_trait_name #generics #where_clause { #(#impl_trait_methods)* } @@ -197,6 +248,7 @@ impl RpcImplBlock { .expect("Failed to parse generics without braces as token stream"); let rpc_server_trait_name = format_ident!("{}RpcServer", self.type_name); let blanket_impl = quote! { + #async_trait_marker impl