Skip to content

Commit

Permalink
Enable blocking RPC methods (#1032)
Browse files Browse the repository at this point in the history
* Enable blocking RPC methods

* Only add async trait marker if there are async methods

* Remove async from method

* Remove blocking marker

* Revert Cargo.lock files

* Silence clippy

* Convert async RPC into blocking RPC (#1042)

* Use parking_lot instead of tokio Mutex

* Register blocking methods

* Turn async into blocking in sequencer

* Ledger RPC are definitely blocking

* Fix Mutex type
  • Loading branch information
rakanalh authored Aug 27, 2024
1 parent ebbdbeb commit fa1d68d
Show file tree
Hide file tree
Showing 12 changed files with 191 additions and 162 deletions.
2 changes: 2 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 @@ -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"
Expand Down
17 changes: 9 additions & 8 deletions crates/ethereum-rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down
8 changes: 2 additions & 6 deletions crates/ethereum-rpc/src/ethereum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,8 @@ impl<C: sov_modules_api::Context, Da: DaService> Ethereum<C, Da> {
}

#[instrument(level = "trace", skip_all)]
pub(crate) async fn max_fee_per_gas(&self, working_set: &mut WorkingSet<C>) -> (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<C>) -> (U256, U256) {
let suggested_tip = self.gas_price_oracle.suggest_tip_cap(working_set).unwrap();

let evm = Evm::<C>::default();
let base_fee = evm
Expand Down
17 changes: 8 additions & 9 deletions crates/ethereum-rpc/src/gas_price/gas_oracle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -137,7 +137,7 @@ impl<C: sov_modules_api::Context> GasPriceOracle<C> {
}

/// Reports the fee history
pub async fn fee_history(
pub fn fee_history(
&self,
mut block_count: u64,
newest_block: BlockNumberOrTag,
Expand Down Expand Up @@ -193,7 +193,7 @@ impl<C: sov_modules_api::Context> GasPriceOracle<C> {
let mut rewards: Vec<Vec<u128>> = 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),
Expand Down Expand Up @@ -239,15 +239,15 @@ impl<C: sov_modules_api::Context> GasPriceOracle<C> {
}

/// Suggests a gas price estimate based on recent blocks, using the configured percentile.
pub async fn suggest_tip_cap(&self, working_set: &mut WorkingSet<C>) -> EthResult<u128> {
pub fn suggest_tip_cap(&self, working_set: &mut WorkingSet<C>) -> EthResult<u128> {
let header = &self
.provider
.get_block_by_number(None, None, working_set)
.unwrap()
.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() {
Expand All @@ -274,8 +274,7 @@ impl<C: sov_modules_api::Context> GasPriceOracle<C> {

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() {
Expand Down Expand Up @@ -324,15 +323,15 @@ impl<C: sov_modules_api::Context> GasPriceOracle<C> {
/// 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,
working_set: &mut WorkingSet<C>,
) -> EthResult<Option<(B256, Vec<u128>)>> {
// 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 {
Expand Down
43 changes: 20 additions & 23 deletions crates/ethereum-rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ fn register_rpc_methods<C: sov_modules_api::Context, Da: DaService>(
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()?;

Expand All @@ -98,46 +98,46 @@ fn register_rpc_methods<C: sov_modules_api::Context, Da: DaService>(
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::<C>::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
};

Ok::<U256, ErrorObjectOwned>(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::<C>::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
};

Ok::<U256, ErrorObjectOwned>(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::<C>::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
};

Ok::<U256, ErrorObjectOwned>(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();

Expand All @@ -151,15 +151,12 @@ fn register_rpc_methods<C: sov_modules_api::Context, Da: DaService>(
let fee_history = {
let mut working_set = WorkingSet::<C>::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::<FeeHistory, ErrorObjectOwned>(fee_history)
Expand Down Expand Up @@ -396,9 +393,9 @@ fn register_rpc_methods<C: sov_modules_api::Context, Da: DaService>(
// Ok::<_, ErrorObjectOwned>(tx_hash)
// })?;

rpc.register_async_method::<Result<Vec<GethTrace>, ErrorObjectOwned>, _, _>(
rpc.register_blocking_method::<Result<Vec<GethTrace>, ErrorObjectOwned>, _>(
"debug_traceBlockByHash",
|parameters, ethereum, _| async move {
move |parameters, ethereum, _| {
info!("eth module: debug_traceBlockByHash");

let mut params = parameters.sequence();
Expand All @@ -420,9 +417,9 @@ fn register_rpc_methods<C: sov_modules_api::Context, Da: DaService>(
},
)?;

rpc.register_async_method::<Result<Vec<GethTrace>, ErrorObjectOwned>, _, _>(
rpc.register_blocking_method::<Result<Vec<GethTrace>, ErrorObjectOwned>, _>(
"debug_traceBlockByNumber",
|parameters, ethereum, _| async move {
move |parameters, ethereum, _| {
info!("eth module: debug_traceBlockByNumber");

let mut params = parameters.sequence();
Expand All @@ -442,9 +439,9 @@ fn register_rpc_methods<C: sov_modules_api::Context, Da: DaService>(
},
)?;

rpc.register_async_method::<Result<GethTrace, ErrorObjectOwned>, _, _>(
rpc.register_blocking_method::<Result<GethTrace, ErrorObjectOwned>, _>(
"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
Expand Down
8 changes: 4 additions & 4 deletions crates/evm/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,7 @@ impl<C: sov_modules_api::Context> Evm<C> {
/// 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,
Expand Down Expand Up @@ -712,7 +712,7 @@ impl<C: sov_modules_api::Context> Evm<C> {
}

/// 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,
Expand Down Expand Up @@ -902,7 +902,7 @@ impl<C: sov_modules_api::Context> Evm<C> {

/// 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,
Expand All @@ -916,7 +916,7 @@ impl<C: sov_modules_api::Context> Evm<C> {
}

/// 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,
Expand Down
1 change: 1 addition & 0 deletions crates/sequencer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down
Loading

0 comments on commit fa1d68d

Please sign in to comment.