diff --git a/Cargo.lock b/Cargo.lock index 8c89261f6..d42148848 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1837,6 +1837,7 @@ dependencies = [ "alloy-rlp", "alloy-sol-types", "anyhow", + "async-trait", "borsh", "bytes", "citrea-primitives", @@ -1868,6 +1869,7 @@ dependencies = [ "sov-state", "tempfile", "thiserror", + "tokio", "tracing", "tracing-subscriber 0.3.18", "walkdir", @@ -7391,6 +7393,7 @@ name = "soft-confirmation-rule-enforcer" version = "0.4.0-rc.3" dependencies = [ "anyhow", + "async-trait", "borsh", "chrono", "jsonrpsee", @@ -7425,6 +7428,7 @@ dependencies = [ name = "sov-accessory-state" version = "0.4.0-rc.3" dependencies = [ + "async-trait", "borsh", "jsonrpsee", "serde", @@ -7440,6 +7444,7 @@ version = "0.4.0-rc.3" dependencies = [ "anyhow", "arbitrary", + "async-trait", "borsh", "clap", "jsonrpsee", @@ -7460,6 +7465,7 @@ name = "sov-bank" version = "0.4.0-rc.3" dependencies = [ "anyhow", + "async-trait", "borsh", "clap", "jsonrpsee", @@ -7844,6 +7850,7 @@ version = "0.4.0-rc.3" dependencies = [ "anyhow", "arbitrary", + "async-trait", "borsh", "clap", "jsonrpsee", @@ -7926,6 +7933,7 @@ name = "sov-value-setter" version = "0.4.0-rc.3" dependencies = [ "anyhow", + "async-trait", "borsh", "clap", "jsonrpsee", @@ -7944,6 +7952,7 @@ name = "sov-vec-setter" version = "0.4.0-rc.3" dependencies = [ "anyhow", + "async-trait", "borsh", "clap", "jsonrpsee", diff --git a/bin/citrea/provers/risc0/guest-bitcoin/Cargo.lock b/bin/citrea/provers/risc0/guest-bitcoin/Cargo.lock index 6ff0d9744..969302284 100644 --- a/bin/citrea/provers/risc0/guest-bitcoin/Cargo.lock +++ b/bin/citrea/provers/risc0/guest-bitcoin/Cargo.lock @@ -900,6 +900,7 @@ dependencies = [ "alloy-primitives", "alloy-sol-types", "anyhow", + "async-trait", "borsh", "citrea-primitives", "hex", @@ -2799,6 +2800,7 @@ name = "soft-confirmation-rule-enforcer" version = "0.4.0-rc.3" dependencies = [ "anyhow", + "async-trait", "borsh", "serde", "sov-modules-api", @@ -2811,6 +2813,7 @@ name = "sov-accounts" version = "0.4.0-rc.3" dependencies = [ "anyhow", + "async-trait", "borsh", "serde", "sov-modules-api", diff --git a/bin/citrea/provers/risc0/guest-mock/Cargo.lock b/bin/citrea/provers/risc0/guest-mock/Cargo.lock index d7add3b1e..b1f3a49f1 100644 --- a/bin/citrea/provers/risc0/guest-mock/Cargo.lock +++ b/bin/citrea/provers/risc0/guest-mock/Cargo.lock @@ -759,6 +759,7 @@ dependencies = [ "alloy-primitives", "alloy-sol-types", "anyhow", + "async-trait", "borsh", "citrea-primitives", "hex", @@ -2536,6 +2537,7 @@ name = "soft-confirmation-rule-enforcer" version = "0.4.0-rc.3" dependencies = [ "anyhow", + "async-trait", "borsh", "serde", "sov-modules-api", @@ -2548,6 +2550,7 @@ name = "sov-accounts" version = "0.4.0-rc.3" dependencies = [ "anyhow", + "async-trait", "borsh", "serde", "sov-modules-api", diff --git a/bin/citrea/src/rollup/bitcoin.rs b/bin/citrea/src/rollup/bitcoin.rs index a2b362a3c..e06bc2025 100644 --- a/bin/citrea/src/rollup/bitcoin.rs +++ b/bin/citrea/src/rollup/bitcoin.rs @@ -71,7 +71,6 @@ impl RollupBlueprint for BitcoinRollup { // unused inside register RPC let sov_sequencer = Address::new([0; 32]); - #[allow(unused_mut)] let mut rpc_methods = sov_modules_rollup_blueprint::register_rpc::< Self::NativeRuntime, Self::NativeContext, diff --git a/crates/ethereum-rpc/src/ethereum.rs b/crates/ethereum-rpc/src/ethereum.rs index 556878ae3..b67487100 100644 --- a/crates/ethereum-rpc/src/ethereum.rs +++ b/crates/ethereum-rpc/src/ethereum.rs @@ -90,6 +90,7 @@ impl Ethereum { let evm = Evm::::default(); let base_fee = evm .get_block_by_number(None, None, working_set) + .await .unwrap() .unwrap() .header diff --git a/crates/ethereum-rpc/src/gas_price/cache.rs b/crates/ethereum-rpc/src/gas_price/cache.rs index 323d7b5e3..4a5ec7b18 100644 --- a/crates/ethereum-rpc/src/gas_price/cache.rs +++ b/crates/ethereum-rpc/src/gas_price/cache.rs @@ -21,7 +21,7 @@ impl BlockCache { } /// Gets block from cache or from provider - pub fn get_block( + pub async fn get_block( &mut self, block_hash: B256, working_set: &mut WorkingSet, @@ -38,6 +38,7 @@ impl BlockCache { let block = self .provider .get_block_by_hash(block_hash, Some(true), working_set) + .await .unwrap_or(None); // Add block to cache if it exists @@ -52,7 +53,7 @@ impl BlockCache { } /// Gets block from cache or from provider by block number - pub fn get_block_by_number( + pub async fn get_block_by_number( &mut self, block_number: u64, working_set: &mut WorkingSet, @@ -70,6 +71,7 @@ impl BlockCache { Some(true), working_set, ) + .await .unwrap_or(None); // Add block to cache if it exists @@ -84,26 +86,28 @@ impl BlockCache { Ok(block) } - pub fn get_block_with_receipts( + pub async fn get_block_with_receipts( &mut self, block_number: u64, working_set: &mut WorkingSet, ) -> EthResult, Vec)>> { // if height not in cache, get hash from provider and call get_block - let block = self.get_block_by_number(block_number, working_set)?; + let block = self.get_block_by_number(block_number, working_set).await?; if let Some(block) = block { // Receipts are not added to cache but their fee history will be kept in cache in fee_history.rs let receipts: Vec<_> = match &block.transactions { BlockTransactions::Full(transactions) => { - transactions - .iter() - .map(|tx| { - self.provider - .get_transaction_receipt(tx.hash, working_set) - .unwrap() - .unwrap() // There is no way to get None here - }) - .collect() + let mut receipts = vec![]; + for tx in transactions { + let receipt = self + .provider + .get_transaction_receipt(tx.hash, working_set) + .await + .unwrap() + .unwrap(); // There is no way to get None here + receipts.push(receipt); + } + receipts } _ => unreachable!(), }; diff --git a/crates/ethereum-rpc/src/gas_price/fee_history.rs b/crates/ethereum-rpc/src/gas_price/fee_history.rs index 76adb44a7..9859fabfe 100644 --- a/crates/ethereum-rpc/src/gas_price/fee_history.rs +++ b/crates/ethereum-rpc/src/gas_price/fee_history.rs @@ -100,7 +100,7 @@ impl FeeHistoryCache { /// If the requested range (start_block to end_block) is within the cache bounds, /// it returns the corresponding entries. /// Otherwise it returns None. - pub fn get_history( + pub async fn get_history( &mut self, start_block: u64, end_block: u64, @@ -122,15 +122,18 @@ impl FeeHistoryCache { } // Get blocks from cache (fallback rpc) and receipts from rpc - let blocks_with_receipts = empty_blocks - .clone() - .into_iter() - .filter_map(|block_number| { - self.block_cache - .get_block_with_receipts(block_number, working_set) - .unwrap_or(None) - }) - .collect(); + let mut blocks_with_receipts = vec![]; + for block_number in empty_blocks.iter() { + let Some(block_with_receipt) = self + .block_cache + .get_block_with_receipts(*block_number, working_set) + .await + .unwrap_or(None) + else { + continue; + }; + blocks_with_receipts.push(block_with_receipt); + } // Insert blocks with receipts into cache self.insert_blocks(blocks_with_receipts); diff --git a/crates/ethereum-rpc/src/gas_price/gas_oracle.rs b/crates/ethereum-rpc/src/gas_price/gas_oracle.rs index e82b67bea..4bf9704ad 100644 --- a/crates/ethereum-rpc/src/gas_price/gas_oracle.rs +++ b/crates/ethereum-rpc/src/gas_price/gas_oracle.rs @@ -161,7 +161,8 @@ impl GasPriceOracle { let end_block = self .provider - .block_number_for_id(&newest_block, working_set)?; + .block_number_for_id(&newest_block, working_set) + .await?; // need to add 1 to the end block to get the correct (inclusive) range let end_block_plus = end_block + 1; @@ -196,7 +197,9 @@ impl GasPriceOracle { let mut fee_history_cache = self.fee_history_cache.lock().await; ( - fee_history_cache.get_history(start_block, end_block, working_set), + fee_history_cache + .get_history(start_block, end_block, working_set) + .await, fee_history_cache.resolution(), ) }; @@ -223,7 +226,10 @@ impl GasPriceOracle { last_entry.gas_used as u128, last_entry.gas_limit as u128, Some(last_entry.base_fee_per_gas), - self.provider.get_chain_config(working_set).base_fee_params, + self.provider + .get_chain_config(working_set) + .await + .base_fee_params, ) .unwrap() as u128, ); @@ -243,6 +249,7 @@ impl GasPriceOracle { let header = &self .provider .get_block_by_number(None, None, working_set) + .await .unwrap() .unwrap() .header; @@ -333,7 +340,7 @@ impl GasPriceOracle { // 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; - cache.block_cache.get_block(block_hash, working_set)? + cache.block_cache.get_block(block_hash, working_set).await? }; let block = match block_hit { Some(block) => block, diff --git a/crates/ethereum-rpc/src/lib.rs b/crates/ethereum-rpc/src/lib.rs index 205f89266..5a66237f6 100644 --- a/crates/ethereum-rpc/src/lib.rs +++ b/crates/ethereum-rpc/src/lib.rs @@ -408,15 +408,18 @@ fn register_rpc_methods( let mut working_set = WorkingSet::::new(ethereum.storage.clone()); let opts: Option = params.optional_next()?; - let block_number = - match evm.get_block_number_by_block_hash(block_hash, &mut working_set) { - Some(block_number) => block_number, - None => { - return Err(EthApiError::UnknownBlockNumber.into()); - } - }; + let block_number = match evm + .get_block_number_by_block_hash(block_hash, &mut working_set) + .await + { + Some(block_number) => block_number, + None => { + return Err(EthApiError::UnknownBlockNumber.into()); + } + }; debug_trace_by_block_number(block_number, None, ðereum, &evm, &mut working_set, opts) + .await }, )?; @@ -430,15 +433,16 @@ fn register_rpc_methods( let block_number: BlockNumberOrTag = params.next()?; let opts: Option = params.optional_next()?; - let mut working_set = WorkingSet::::new(ethereum.storage.clone()); + let working_set = WorkingSet::::new(ethereum.storage.clone()); let evm = Evm::::default(); let block_number = match block_number { BlockNumberOrTag::Number(block_number) => block_number, - BlockNumberOrTag::Latest => evm.block_number(&mut working_set)?.saturating_to(), + BlockNumberOrTag::Latest => evm.block_number(working_set).await?.saturating_to(), _ => return Err(EthApiError::Unsupported("Earliest, pending, safe and finalized are not supported for debug_traceBlockByNumber").into()), }; - debug_trace_by_block_number(block_number, None, ðereum, &evm, &mut working_set, opts) + let mut working_set = WorkingSet::::new(ethereum.storage.clone()); + debug_trace_by_block_number(block_number, None, ðereum, &evm, &mut working_set, opts).await }, )?; @@ -462,6 +466,7 @@ fn register_rpc_methods( let tx = evm .get_transaction_by_hash(tx_hash, &mut working_set) + .await .unwrap() .ok_or_else(|| EthApiError::UnknownBlockOrTxIndex)?; let trace_idx: u64 = tx @@ -481,7 +486,8 @@ fn register_rpc_methods( &evm, &mut working_set, opts, - )?; + ) + .await?; Ok(traces[0].clone()) }, )?; @@ -572,7 +578,7 @@ fn register_rpc_methods( // if mempool_only is not true ask evm first then sequencer let evm = Evm::::default(); let mut working_set = WorkingSet::::new(ethereum.storage.clone()); - match evm.get_transaction_by_hash(hash, &mut working_set) { + match evm.get_transaction_by_hash(hash, &mut working_set).await { Ok(Some(tx)) => Ok(Some(tx)), Ok(None) => { // if not found in evm then ask to sequencer mempool @@ -627,8 +633,9 @@ fn register_rpc_methods( let evm = Evm::::default(); let mut working_set = WorkingSet::::new(ethereum.storage.clone()); - let block = - evm.get_block_by_number(Some(BlockNumberOrTag::Latest), None, &mut working_set); + let block = evm + .get_block_by_number(Some(BlockNumberOrTag::Latest), None, &mut working_set) + .await; let synced_block_number = match block { Ok(Some(block)) => block.header.number.unwrap(), diff --git a/crates/ethereum-rpc/src/subscription.rs b/crates/ethereum-rpc/src/subscription.rs index bd414db17..709d2a569 100644 --- a/crates/ethereum-rpc/src/subscription.rs +++ b/crates/ethereum-rpc/src/subscription.rs @@ -39,6 +39,7 @@ impl SubscriptionManager { None, &mut working_set, ) + .await .expect("Error querying block from evm") .expect("Received signal but evm block is not found"); @@ -55,6 +56,7 @@ impl SubscriptionManager { height, height, ) + .await .expect("Error getting logs in block range"); // Only possible error is no receiver diff --git a/crates/ethereum-rpc/src/trace.rs b/crates/ethereum-rpc/src/trace.rs index 2fa2ee9e3..c489c18b5 100644 --- a/crates/ethereum-rpc/src/trace.rs +++ b/crates/ethereum-rpc/src/trace.rs @@ -45,10 +45,11 @@ pub async fn handle_debug_trace_chain::new(ethereum.storage.clone()); + let working_set = WorkingSet::::new(ethereum.storage.clone()); let evm = Evm::::default(); let latest_block_number: u64 = evm - .block_number(&mut working_set) + .block_number(working_set) + .await .expect("Expected at least one block") .saturating_to(); let end_block = match end_block { @@ -92,7 +93,8 @@ pub async fn handle_debug_trace_chain { let msg = SubscriptionMessage::new( @@ -125,7 +127,7 @@ pub async fn handle_debug_trace_chain( +pub async fn debug_trace_by_block_number( block_number: u64, trace_idx: Option, ethereum: &Ethereum, @@ -135,8 +137,9 @@ pub fn debug_trace_by_block_number( ) -> Result, ErrorObjectOwned> { // If opts is None or if opts.tracer is None, then do not check cache or insert cache, just perform the operation if opts.as_ref().map_or(true, |o| o.tracer.is_none()) { - let traces = - evm.trace_block_transactions_by_number(block_number, opts, trace_idx, working_set)?; + let traces = evm + .trace_block_transactions_by_number(block_number, opts, trace_idx, working_set) + .await?; return match trace_idx { Some(idx) => Ok(vec![traces[idx].clone()]), None => Ok(traces), @@ -159,12 +162,9 @@ pub fn debug_trace_by_block_number( } let cache_options = create_trace_cache_opts(); - let traces = evm.trace_block_transactions_by_number( - block_number, - Some(cache_options), - None, - working_set, - )?; + let traces = evm + .trace_block_transactions_by_number(block_number, Some(cache_options), None, working_set) + .await?; ethereum .trace_cache .lock() diff --git a/crates/evm/Cargo.toml b/crates/evm/Cargo.toml index b26e08347..eb04132d8 100644 --- a/crates/evm/Cargo.toml +++ b/crates/evm/Cargo.toml @@ -19,6 +19,7 @@ sov-state = { path = "../sovereign-sdk/module-system/sov-state" } citrea-primitives = { path = "../primitives" } anyhow = { workspace = true } +async-trait = { workspace = true } borsh = { workspace = true, features = ["rc"] } clap = { workspace = true, optional = true } hex = { workspace = true } @@ -27,6 +28,7 @@ schemars = { workspace = true, optional = true } serde = { workspace = true } serde_json = { workspace = true, optional = true } thiserror = { workspace = true } +tokio = { workspace = true, optional = true } tracing = { workspace = true, optional = true } alloy-consensus = { workspace = true } @@ -76,6 +78,7 @@ native = [ "reth-provider", "alloy-rlp", + "tokio", "jsonrpsee", "schemars", "clap", diff --git a/crates/evm/src/query.rs b/crates/evm/src/query.rs index 02f4e1587..9e9e61f96 100644 --- a/crates/evm/src/query.rs +++ b/crates/evm/src/query.rs @@ -91,13 +91,13 @@ pub struct EstimatedDiffSize { impl Evm { /// Handler for `net_version` #[rpc_method(name = "net_version")] - pub fn net_version(&self, working_set: &mut WorkingSet) -> RpcResult { + pub async fn net_version(&self, mut working_set: WorkingSet) -> RpcResult { debug!("evm module: net_version"); // Network ID is the same as chain ID for most networks let chain_id = self .cfg - .get(working_set) + .get(&mut working_set) .expect("EVM config must be set at genesis") .chain_id; @@ -106,12 +106,12 @@ impl Evm { /// Handler for: `eth_chainId` #[rpc_method(name = "eth_chainId")] - pub fn chain_id(&self, working_set: &mut WorkingSet) -> RpcResult> { + pub async fn chain_id(&self, mut working_set: WorkingSet) -> RpcResult> { tracing::debug!("evm module: eth_chainId"); let chain_id = reth_primitives::U64::from( self.cfg - .get(working_set) + .get(&mut working_set) .expect("EVM config must be set at genesis") .chain_id, ); @@ -122,125 +122,36 @@ impl Evm { /// Handler for `eth_getBlockByHash` #[rpc_method(name = "eth_getBlockByHash")] - pub fn get_block_by_hash( + pub async fn _get_block_by_hash( &self, block_hash: reth_primitives::B256, details: Option, - working_set: &mut WorkingSet, + mut working_set: WorkingSet, ) -> RpcResult> { debug!("evm module: eth_getBlockByHash"); - - // if block hash is not known, return None - let block_number = match self - .block_hashes - .get(&block_hash, &mut working_set.accessory_state()) - { - Some(block_number) => block_number, - None => return Ok(None), - }; - - self.get_block_by_number( - Some(BlockNumberOrTag::Number(block_number)), - details, - working_set, - ) + self.get_block_by_hash(block_hash, details, &mut working_set) + .await } /// Handler for: `eth_getBlockByNumber` #[rpc_method(name = "eth_getBlockByNumber")] - pub fn get_block_by_number( + pub async fn _get_block_by_number( &self, block_number: Option, details: Option, - working_set: &mut WorkingSet, + mut working_set: WorkingSet, ) -> RpcResult> { debug!("evm module: eth_getBlockByNumber"); - - let sealed_block = match self.get_sealed_block_by_number(block_number, working_set)? { - Some(sealed_block) => sealed_block, - None => return Ok(None), // if block doesn't exist return null - }; - - // Build rpc header response - let mut header = from_primitive_with_hash(sealed_block.header.clone()); - header.total_difficulty = Some(header.difficulty); - // Collect transactions with ids from db - let transactions: Vec = sealed_block - .transactions - .clone() - .map(|id| { - self.transactions - .get(id as usize, &mut working_set.accessory_state()) - .expect("Transaction must be set") - }) - .collect(); - - let block = Block { - header: sealed_block.header.header().clone(), - body: transactions - .iter() - .map(|tx| tx.signed_transaction.clone()) - .collect(), - ommers: Default::default(), - withdrawals: Default::default(), - requests: None, - }; - - let size = block.length(); - - // Build rpc transactions response - let transactions = match details { - Some(true) => reth_rpc_types::BlockTransactions::Full( - transactions - .iter() - .enumerate() - .map(|(id, tx)| { - reth_rpc_types_compat::transaction::from_recovered_with_block_context( - tx.clone().into(), - header.hash.expect("Block must be already sealed"), - header.number.expect("Block must be already sealed"), - header.base_fee_per_gas.map(|bfpg| bfpg.try_into().unwrap()), // u64 max is 18446744073 gwei, for the conversion to fail the base fee per gas would have to be higher than that - id, - ) - }) - .collect::>(), - ), - _ => reth_rpc_types::BlockTransactions::Hashes({ - transactions - .iter() - .map(|tx| tx.signed_transaction.hash) - .collect::>() - }), - }; - - // Build rpc block response - let block = reth_rpc_types::Block { - header, - size: Some(U256::from(size)), - uncles: Default::default(), - transactions, - withdrawals: Default::default(), - other: OtherFields::new(BTreeMap::::from([ - ( - "l1FeeRate".to_string(), - serde_json::json!(sealed_block.l1_fee_rate), - ), - ( - "l1Hash".to_string(), - serde_json::json!(sealed_block.l1_hash), - ), - ])), - }; - - Ok(Some(block.into())) + self.get_block_by_number(block_number, details, &mut working_set) + .await } /// Handler for: `eth_getBlockReceipts` #[rpc_method(name = "eth_getBlockReceipts")] - pub fn get_block_receipts( + pub async fn get_block_receipts( &self, block_number_or_hash: BlockId, - working_set: &mut WorkingSet, + mut working_set: WorkingSet, ) -> RpcResult>> { debug!("evm module: eth_getBlockReceipts"); @@ -260,7 +171,7 @@ impl Evm { .expect("Block must be set") } BlockId::Number(block_number) => { - match self.get_sealed_block_by_number(Some(block_number), working_set)? { + match self.get_sealed_block_by_number(Some(block_number), &mut working_set)? { Some(block) => block, None => return Ok(None), // if block doesn't exist return null } @@ -290,11 +201,11 @@ impl Evm { /// Handler for: `eth_getBalance` #[rpc_method(name = "eth_getBalance")] - pub fn get_balance( + pub async fn get_balance( &self, address: reth_primitives::Address, block_number: Option, - working_set: &mut WorkingSet, + mut working_set: WorkingSet, ) -> RpcResult { debug!("evm module: eth_getBalance"); @@ -311,12 +222,12 @@ impl Evm { if num > curr_block_number { return Err(EthApiError::UnknownBlockNumber.into()); } - set_state_to_end_of_evm_block(num, working_set); + set_state_to_end_of_evm_block(num, &mut working_set); } // Working state here is already at the latest state, so no need to anything Some(BlockNumberOrTag::Latest) | Some(BlockNumberOrTag::Pending) | None => {} Some(BlockNumberOrTag::Earliest) => { - set_state_to_end_of_evm_block(0, working_set); + set_state_to_end_of_evm_block(0, &mut working_set); } _ => { return Err(EthApiError::InvalidParams( @@ -328,7 +239,7 @@ impl Evm { let balance = self .accounts - .get(&address, working_set) + .get(&address, &mut working_set) .map(|account| account.info.balance) .unwrap_or_default(); @@ -337,12 +248,12 @@ impl Evm { /// Handler for: `eth_getStorageAt` #[rpc_method(name = "eth_getStorageAt")] - pub fn get_storage_at( + pub async fn get_storage_at( &self, address: reth_primitives::Address, index: reth_primitives::U256, block_number: Option, - working_set: &mut WorkingSet, + mut working_set: WorkingSet, ) -> RpcResult { debug!("evm module: eth_getStorageAt"); @@ -359,12 +270,12 @@ impl Evm { if num > curr_block_number { return Err(EthApiError::UnknownBlockNumber.into()); } - set_state_to_end_of_evm_block(num, working_set); + set_state_to_end_of_evm_block(num, &mut working_set); } // Working state here is already at the latest state, so no need to anything Some(BlockNumberOrTag::Latest) | Some(BlockNumberOrTag::Pending) | None => {} Some(BlockNumberOrTag::Earliest) => { - set_state_to_end_of_evm_block(0, working_set); + set_state_to_end_of_evm_block(0, &mut working_set); } _ => { return Err(EthApiError::InvalidParams( @@ -376,8 +287,8 @@ impl Evm { let storage_slot = self .accounts - .get(&address, working_set) - .and_then(|account| account.storage.get(&index, working_set)) + .get(&address, &mut working_set) + .and_then(|account| account.storage.get(&index, &mut working_set)) .unwrap_or_default(); Ok(storage_slot.into()) @@ -385,11 +296,11 @@ impl Evm { /// Handler for: `eth_getTransactionCount` #[rpc_method(name = "eth_getTransactionCount")] - pub fn get_transaction_count( + pub async fn get_transaction_count( &self, address: reth_primitives::Address, block_number: Option, - working_set: &mut WorkingSet, + mut working_set: WorkingSet, ) -> RpcResult { debug!("evm module: eth_getTransactionCount"); @@ -406,12 +317,12 @@ impl Evm { if num > curr_block_number { return Err(EthApiError::UnknownBlockNumber.into()); } - set_state_to_end_of_evm_block(num, working_set); + set_state_to_end_of_evm_block(num, &mut working_set); } // Working state here is already at the latest state, so no need to anything Some(BlockNumberOrTag::Latest) | Some(BlockNumberOrTag::Pending) | None => {} Some(BlockNumberOrTag::Earliest) => { - set_state_to_end_of_evm_block(0, working_set); + set_state_to_end_of_evm_block(0, &mut working_set); } _ => { return Err(EthApiError::InvalidParams( @@ -423,7 +334,7 @@ impl Evm { let nonce = self .accounts - .get(&address, working_set) + .get(&address, &mut working_set) .map(|account| account.info.nonce) .unwrap_or_default(); @@ -432,11 +343,11 @@ impl Evm { /// Handler for: `eth_getCode` #[rpc_method(name = "eth_getCode")] - pub fn get_code( + pub async fn get_code( &self, address: reth_primitives::Address, block_number: Option, - working_set: &mut WorkingSet, + mut working_set: WorkingSet, ) -> RpcResult { debug!("evm module: eth_getCode"); @@ -452,12 +363,12 @@ impl Evm { if num > curr_block_number { return Err(EthApiError::UnknownBlockNumber.into()); } - set_state_to_end_of_evm_block(num, working_set); + set_state_to_end_of_evm_block(num, &mut working_set); } // Working state here is already at the latest state, so no need to anything Some(BlockNumberOrTag::Latest) | Some(BlockNumberOrTag::Pending) | None => {} Some(BlockNumberOrTag::Earliest) => { - set_state_to_end_of_evm_block(0, working_set); + set_state_to_end_of_evm_block(0, &mut working_set); } // Is this the way? // Note that reth works for all types of BlockNumberOrTag @@ -471,8 +382,8 @@ impl Evm { let code = self .accounts - .get(&address, working_set) - .and_then(|account| self.code.get(&account.info.code_hash, working_set)) + .get(&address, &mut working_set) + .and_then(|account| self.code.get(&account.info.code_hash, &mut working_set)) .unwrap_or_default(); Ok(code.original_bytes()) @@ -480,11 +391,11 @@ impl Evm { /// Handler for: `eth_getTransactionByBlockHashAndIndex` #[rpc_method(name = "eth_getTransactionByBlockHashAndIndex")] - pub fn get_transaction_by_block_hash_and_index( + pub async fn get_transaction_by_block_hash_and_index( &self, block_hash: reth_primitives::B256, index: reth_primitives::U64, - working_set: &mut WorkingSet, + mut working_set: WorkingSet, ) -> RpcResult> { debug!("evm module: eth_getTransactionByBlockHashAndIndex"); @@ -530,15 +441,18 @@ impl Evm { /// Handler for: `eth_getTransactionByBlockNumberAndIndex` #[rpc_method(name = "eth_getTransactionByBlockNumberAndIndex")] - pub fn get_transaction_by_block_number_and_index( + pub async fn get_transaction_by_block_number_and_index( &self, block_number: BlockNumberOrTag, index: reth_primitives::U64, - working_set: &mut WorkingSet, + mut working_set: WorkingSet, ) -> RpcResult> { debug!("evm module: eth_getTransactionByBlockNumberAndIndex"); - let block_number = match self.block_number_for_id(&block_number, working_set) { + let block_number = match self + .block_number_for_id(&block_number, &mut working_set) + .await + { Ok(block_number) => block_number, Err(EthApiError::UnknownBlockNumber) => return Ok(None), Err(err) => return Err(err.into()), @@ -579,127 +493,110 @@ impl Evm { /// Handler for: `eth_getTransactionReceipt` #[rpc_method(name = "eth_getTransactionReceipt")] - pub fn get_transaction_receipt( + pub async fn _get_transaction_receipt( &self, hash: reth_primitives::B256, - working_set: &mut WorkingSet, + mut working_set: WorkingSet, ) -> RpcResult> { debug!("evm module: eth_getTransactionReceipt"); - let mut accessory_state = working_set.accessory_state(); - - let tx_number = self.transaction_hashes.get(&hash, &mut accessory_state); - - let receipt = tx_number.map(|number| { - let tx = self - .transactions - .get(number as usize, &mut accessory_state) - .expect("Transaction with known hash must be set"); - let block = self - .blocks - .get(tx.block_number as usize, &mut accessory_state) - .expect("Block number for known transaction must be set"); - - let receipt = self - .receipts - .get(number as usize, &mut accessory_state) - .expect("Receipt for known transaction must be set"); - - build_rpc_receipt(&block, tx, number, receipt) - }); - - Ok(receipt) + self.get_transaction_receipt(hash, &mut working_set).await } /// 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")] - pub fn get_call( + pub async fn get_call( &self, request: reth_rpc_types::TransactionRequest, block_number: Option, _state_overrides: Option, _block_overrides: Option>, - working_set: &mut WorkingSet, + mut working_set: WorkingSet, ) -> RpcResult { - debug!("evm module: eth_call"); - let mut block_env = match block_number { - None | Some(BlockNumberOrTag::Pending | BlockNumberOrTag::Latest) => { - // if no block is produced yet, should default to genesis block env, else just return the lates - self.block_env.get(working_set).unwrap_or_else(|| { - BlockEnv::from( - &self - .get_sealed_block_by_number( + let s = self.clone(); + tokio::task::spawn_blocking(move || { + debug!("evm module: eth_call"); + let mut block_env = match block_number { + None | Some(BlockNumberOrTag::Pending | BlockNumberOrTag::Latest) => { + // if no block is produced yet, should default to genesis block env, else just return the lates + s.block_env.get(&mut working_set).unwrap_or_else(|| { + BlockEnv::from( + &s.get_sealed_block_by_number( Some(BlockNumberOrTag::Earliest), - working_set, + &mut working_set, ) .unwrap() .expect("Genesis block must be set"), - ) - }) - } - _ => { - let block = match self.get_sealed_block_by_number(block_number, working_set)? { - Some(block) => block, - None => return Err(EthApiError::UnknownBlockNumber.into()), - }; - - set_state_to_end_of_evm_block(block.header.number, working_set); - - BlockEnv::from(&block) - } - }; + ) + }) + } + _ => { + let block = + match s.get_sealed_block_by_number(block_number, &mut working_set)? { + Some(block) => block, + None => return Err(EthApiError::UnknownBlockNumber.into()), + }; - let cfg = self - .cfg - .get(working_set) - .expect("EVM chain config should be set"); - let mut cfg_env = get_cfg_env(&block_env, cfg); + set_state_to_end_of_evm_block(block.header.number, &mut working_set); - // set endpoint specific params - cfg_env.disable_eip3607 = true; - cfg_env.disable_base_fee = true; - // set higher block gas limit than usual - // but still cap it to prevent DoS - block_env.gas_limit = 100_000_000; + BlockEnv::from(&block) + } + }; - let mut evm_db = self.get_db(working_set); - let mut tx_env = prepare_call_env( - &block_env, - request.clone(), - Some( - evm_db - .basic(request.from.unwrap_or_default()) - .unwrap() - .unwrap_or_default() - .balance, - ), - )?; + let cfg = s + .cfg + .get(&mut working_set) + .expect("EVM chain config should be set"); + let mut cfg_env = get_cfg_env(&block_env, cfg); + + // set endpoint specific params + cfg_env.disable_eip3607 = true; + cfg_env.disable_base_fee = true; + // set higher block gas limit than usual + // but still cap it to prevent DoS + block_env.gas_limit = 100_000_000; + + let mut evm_db = s.get_db(&mut working_set); + let mut tx_env = prepare_call_env( + &block_env, + request.clone(), + Some( + evm_db + .basic(request.from.unwrap_or_default()) + .unwrap() + .unwrap_or_default() + .balance, + ), + )?; - // https://github.com/paradigmxyz/reth/issues/6574 - tx_env.nonce = None; + // https://github.com/paradigmxyz/reth/issues/6574 + tx_env.nonce = None; - let result = match inspect( - evm_db, - cfg_env, - block_env, - tx_env, - TracingInspector::new(TracingInspectorConfig::all()), - ) { - Ok(result) => result.result, - Err(err) => { - return Err(EthApiError::from(err).into()); - } - }; + let result = match inspect( + evm_db, + cfg_env, + block_env, + tx_env, + TracingInspector::new(TracingInspectorConfig::all()), + ) { + Ok(result) => result.result, + Err(err) => { + return Err(EthApiError::from(err).into()); + } + }; - Ok(ensure_success(result)?) + Ok(ensure_success(result)?) + }) + .await + .map_err(|_| EthApiError::EvmCustom("Could not process transaction".to_owned()))? } /// Handler for: `eth_blockNumber` #[rpc_method(name = "eth_blockNumber")] - pub fn block_number( + pub async fn block_number( &self, - working_set: &mut WorkingSet, + mut working_set: WorkingSet, ) -> RpcResult { debug!("evm module: eth_blockNumber"); @@ -713,11 +610,11 @@ impl Evm { /// Handler for `eth_createAccessList` #[rpc_method(name = "eth_createAccessList")] - pub fn create_access_list( + pub async fn create_access_list( &self, request: reth_rpc_types::TransactionRequest, block_number: Option, - working_set: &mut WorkingSet, + mut working_set: WorkingSet, ) -> RpcResult { debug!("evm module: eth_createAccessList"); @@ -727,14 +624,14 @@ impl Evm { None | Some(BlockNumberOrTag::Pending | BlockNumberOrTag::Latest) => { // so we don't unnecessarily set archival version // if no block was produced yet, the l1 fee rate can unwrap to 0, we don't care, else just return the latest - let l1_fee_rate = self.l1_fee_rate.get(working_set).unwrap_or_default(); + let l1_fee_rate = self.l1_fee_rate.get(&mut working_set).unwrap_or_default(); // if no block is produced yet, should default to genesis block env, else just return the lates - let block_env = self.block_env.get(working_set).unwrap_or_else(|| { + let block_env = self.block_env.get(&mut working_set).unwrap_or_else(|| { BlockEnv::from( &self .get_sealed_block_by_number( Some(BlockNumberOrTag::Earliest), - working_set, + &mut working_set, ) .unwrap() .expect("Genesis block must be set"), @@ -743,12 +640,12 @@ impl Evm { (l1_fee_rate, block_env) } _ => { - let block = match self.get_sealed_block_by_number(block_number, working_set)? { + let block = match self.get_sealed_block_by_number(block_number, &mut working_set)? { Some(block) => block, None => return Err(EthApiError::UnknownBlockNumber.into()), }; - set_state_to_end_of_evm_block(block.header.number, working_set); + set_state_to_end_of_evm_block(block.header.number, &mut working_set); let l1_fee_rate = block.l1_fee_rate; let block_env = BlockEnv::from(&block); (l1_fee_rate, block_env) @@ -757,7 +654,7 @@ impl Evm { let cfg = self .cfg - .get(working_set) + .get(&mut working_set) .expect("EVM chain config should be set"); let mut cfg_env = get_cfg_env(&block_env, cfg); @@ -768,7 +665,7 @@ impl Evm { // but still cap it to prevent DoS block_env.gas_limit = 100_000_000; - let mut evm_db = self.get_db(working_set); + let mut evm_db = self.get_db(&mut working_set); let mut tx_env = prepare_call_env( &block_env, @@ -829,7 +726,7 @@ impl Evm { block_env, cfg_env, &mut tx_env, - working_set, + &mut working_set, )?; Ok(AccessListWithGasUsed { @@ -903,31 +800,31 @@ 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")] - pub fn eth_estimate_gas( + pub async fn eth_estimate_gas( &self, request: reth_rpc_types::TransactionRequest, block_number: Option, - working_set: &mut WorkingSet, + mut working_set: WorkingSet, ) -> RpcResult { debug!("evm module: eth_estimateGas"); - let estimated = self.estimate_tx_expenses(request, block_number, working_set)?; + let estimated = self.estimate_tx_expenses(request, block_number, &mut working_set)?; Ok(estimated.gas_with_l1_overhead()) } /// Handler for: `eth_estimateDiffSize` #[rpc_method(name = "eth_estimateDiffSize")] - pub fn eth_estimate_diff_size( + pub async fn eth_estimate_diff_size( &self, request: reth_rpc_types::TransactionRequest, block_number: Option, - working_set: &mut WorkingSet, + mut working_set: WorkingSet, ) -> RpcResult { debug!("evm module: eth_estimateDiffSize"); if request.gas.is_none() { return Err(EthApiError::InvalidParams("gas must be set".into()))?; } - let estimated = self.estimate_tx_expenses(request, block_number, working_set)?; + let estimated = self.estimate_tx_expenses(request, block_number, &mut working_set)?; Ok(EstimatedDiffSize { gas: estimated.gas_used, @@ -938,14 +835,16 @@ impl Evm { /// Handler for: `eth_getBlockTransactionCountByHash` // https://github.com/paradigmxyz/reth/blob/main/crates/rpc/rpc/src/eth/api/call.rs#L172 #[rpc_method(name = "eth_getBlockTransactionCountByHash")] - pub fn eth_get_block_transaction_count_by_hash( + pub async fn eth_get_block_transaction_count_by_hash( &self, block_hash: reth_primitives::B256, - working_set: &mut WorkingSet, + mut working_set: WorkingSet, ) -> RpcResult> { debug!("evm module: eth_getBlockTransactionCountByHash"); // Get the number of transactions in a block given blockhash - let block = self.get_block_by_hash(block_hash, None, working_set)?; + let block = self + .get_block_by_hash(block_hash, None, &mut working_set) + .await?; match block { Some(block) => Ok(Some(U256::from(block.transactions.len()))), None => Ok(None), @@ -954,14 +853,16 @@ impl Evm { /// Handler for: `eth_getBlockTransactionCountByNumber` #[rpc_method(name = "eth_getBlockTransactionCountByNumber")] - pub fn eth_get_block_transaction_count_by_number( + pub async fn eth_get_block_transaction_count_by_number( &self, block_number: BlockNumberOrTag, - working_set: &mut WorkingSet, + mut working_set: WorkingSet, ) -> RpcResult> { debug!("evm module: eth_getBlockTransactionCountByNumber"); // Get the number of transactions in a block given block number - let block = self.get_block_by_number(Some(block_number), None, working_set)?; + let block = self + .get_block_by_number(Some(block_number), None, &mut working_set) + .await?; match block { Some(block) => Ok(Some(U256::from(block.transactions.len()))), None => Ok(None), @@ -1221,18 +1122,18 @@ impl Evm { /// /// Handler for `eth_getLogs` #[rpc_method(name = "eth_getLogs")] - pub fn eth_get_logs( + pub async fn eth_get_logs( &self, filter: Filter, - working_set: &mut WorkingSet, + mut working_set: WorkingSet, ) -> RpcResult> { // https://github.com/paradigmxyz/reth/blob/8892d04a88365ba507f28c3314d99a6b54735d3f/crates/rpc/rpc/src/eth/filter.rs#L302 - Ok(self.logs_for_filter(filter, working_set)?) + Ok(self.logs_for_filter(filter, &mut working_set).await?) } /// Handler for: `eth_getTransactionByHash` /// RPC method is moved to sequencer and ethereum-rpc modules - pub fn get_transaction_by_hash( + pub async fn get_transaction_by_hash( &self, hash: reth_primitives::B256, working_set: &mut WorkingSet, @@ -1271,7 +1172,7 @@ impl Evm { } /// Traces the entire block txs and returns the traces - pub fn trace_block_transactions_by_number( + pub async fn trace_block_transactions_by_number( &self, block_number: u64, opts: Option, @@ -1341,7 +1242,7 @@ impl Evm { } // https://github.com/paradigmxyz/reth/blob/8892d04a88365ba507f28c3314d99a6b54735d3f/crates/rpc/rpc/src/eth/filter.rs#L349 - fn logs_for_filter( + async fn logs_for_filter( &self, filter: Filter, working_set: &mut WorkingSet, @@ -1400,6 +1301,7 @@ impl Evm { from_block_number, to_block_number, ) + .await } } } @@ -1410,7 +1312,7 @@ impl Evm { /// Returns an error if: /// - underlying database error /// - amount of matches exceeds configured limit - pub fn get_logs_in_block_range( + pub async fn get_logs_in_block_range( &self, working_set: &mut WorkingSet, filter: &Filter, @@ -1519,14 +1421,14 @@ impl Evm { } /// Helper function to get chain config - pub fn get_chain_config(&self, working_set: &mut WorkingSet) -> EvmChainConfig { + pub async fn get_chain_config(&self, working_set: &mut WorkingSet) -> EvmChainConfig { self.cfg .get(working_set) .expect("EVM chain config should be set") } /// Helper function to get block hash from block number - pub fn block_hash_from_number( + pub async fn block_hash_from_number( &self, block_number: u64, working_set: &mut WorkingSet, @@ -1538,7 +1440,7 @@ impl Evm { } /// Helper function to get headers in range - pub fn sealed_headers_range( + pub async fn sealed_headers_range( &self, range: RangeInclusive, working_set: &mut WorkingSet, @@ -1556,7 +1458,7 @@ impl Evm { /// Helper function to check if the block number is valid /// If returns None, block doesn't exist - pub fn block_number_for_id( + pub async fn block_number_for_id( &self, block_id: &BlockNumberOrTag, working_set: &mut WorkingSet, @@ -1616,7 +1518,7 @@ impl Evm { /// Returns the block number given block hash /// If block not found returns None - pub fn get_block_number_by_block_hash( + pub async fn get_block_number_by_block_hash( &self, block_hash: reth_primitives::B256, working_set: &mut WorkingSet, @@ -1629,12 +1531,157 @@ impl Evm { /// Returns the cumulative gas used in pending transactions /// Used to calculate how much gas system transactions use at the beginning of the block - pub fn get_pending_txs_cumulative_gas_used(&self, working_set: &mut WorkingSet) -> u128 { + pub async fn get_pending_txs_cumulative_gas_used( + &self, + working_set: &mut WorkingSet, + ) -> u128 { self.pending_transactions .iter(working_set) .map(|tx| tx.receipt.gas_used) .sum::() } + + /// Returns the block at the provided number. + pub async fn get_block_by_number( + &self, + block_number: Option, + details: Option, + working_set: &mut WorkingSet, + ) -> RpcResult> { + let sealed_block = match self.get_sealed_block_by_number(block_number, working_set)? { + Some(sealed_block) => sealed_block, + None => return Ok(None), // if block doesn't exist return null + }; + + // Build rpc header response + let mut header = from_primitive_with_hash(sealed_block.header.clone()); + header.total_difficulty = Some(header.difficulty); + // Collect transactions with ids from db + let transactions: Vec = sealed_block + .transactions + .clone() + .map(|id| { + self.transactions + .get(id as usize, &mut working_set.accessory_state()) + .expect("Transaction must be set") + }) + .collect(); + + let block = Block { + header: sealed_block.header.header().clone(), + body: transactions + .iter() + .map(|tx| tx.signed_transaction.clone()) + .collect(), + ommers: Default::default(), + withdrawals: Default::default(), + requests: None, + }; + + let size = block.length(); + + // Build rpc transactions response + let transactions = match details { + Some(true) => reth_rpc_types::BlockTransactions::Full( + transactions + .iter() + .enumerate() + .map(|(id, tx)| { + reth_rpc_types_compat::transaction::from_recovered_with_block_context( + tx.clone().into(), + header.hash.expect("Block must be already sealed"), + header.number.expect("Block must be already sealed"), + header.base_fee_per_gas.map(|bfpg| bfpg.try_into().unwrap()), // u64 max is 18446744073 gwei, for the conversion to fail the base fee per gas would have to be higher than that + id, + ) + }) + .collect::>(), + ), + _ => reth_rpc_types::BlockTransactions::Hashes({ + transactions + .iter() + .map(|tx| tx.signed_transaction.hash) + .collect::>() + }), + }; + + // Build rpc block response + let block = reth_rpc_types::Block { + header, + size: Some(U256::from(size)), + uncles: Default::default(), + transactions, + withdrawals: Default::default(), + other: OtherFields::new(BTreeMap::::from([ + ( + "l1FeeRate".to_string(), + serde_json::json!(sealed_block.l1_fee_rate), + ), + ( + "l1Hash".to_string(), + serde_json::json!(sealed_block.l1_hash), + ), + ])), + }; + + Ok(Some(block.into())) + } + + /// Returns the block at the provided hash. + pub async fn get_block_by_hash( + &self, + block_hash: reth_primitives::B256, + details: Option, + working_set: &mut WorkingSet, + ) -> RpcResult> { + // if block hash is not known, return None + let block_number = match self + .block_hashes + .get(&block_hash, &mut working_set.accessory_state()) + { + Some(block_number) => block_number, + None => return Ok(None), + }; + + self.get_block_by_number( + Some(BlockNumberOrTag::Number(block_number)), + details, + working_set, + ) + .await + } + + /// Returns the transaction receipt by hash + pub async fn get_transaction_receipt( + &self, + hash: reth_primitives::B256, + working_set: &mut WorkingSet, + ) -> RpcResult> { + debug!("evm module: eth_getTransactionReceipt"); + let mut accessory_state = working_set.accessory_state(); + + let tx_number = self.transaction_hashes.get(&hash, &mut accessory_state); + + let receipt = tx_number.map(|number| { + let tx = self + .transactions + .get(number as usize, &mut accessory_state) + .expect("Transaction with known hash must be set"); + let block = self + .blocks + .get(tx.block_number as usize, &mut accessory_state) + .expect("Block number for known transaction must be set"); + + let receipt = self + .receipts + .get(number as usize, &mut accessory_state) + .expect("Receipt for known transaction must be set"); + + build_rpc_receipt(&block, tx, number, receipt) + }); + + Ok(receipt) + } } // modified from: https://github.com/paradigmxyz/reth/blob/cc576bc8690a3e16e6e5bf1cbbbfdd029e85e3d4/crates/rpc/rpc/src/eth/api/transactions.rs#L849 diff --git a/crates/sequencer/src/db_provider/mod.rs b/crates/sequencer/src/db_provider/mod.rs index 747ee95aa..9ed523606 100644 --- a/crates/sequencer/src/db_provider/mod.rs +++ b/crates/sequencer/src/db_provider/mod.rs @@ -32,14 +32,17 @@ impl DbProvider { Self { evm, storage } } - pub fn cfg(&self) -> EvmChainConfig { + pub async fn cfg(&self) -> EvmChainConfig { let mut working_set = WorkingSet::::new(self.storage.clone()); - self.evm.get_chain_config(&mut working_set) + self.evm.get_chain_config(&mut working_set).await } - pub fn last_block_tx_hashes(&self) -> RpcResult> { + pub async fn last_block_tx_hashes(&self) -> RpcResult> { let mut working_set = WorkingSet::::new(self.storage.clone()); - let rich_block = self.evm.get_block_by_number(None, None, &mut working_set)?; + let rich_block = self + .evm + .get_block_by_number(None, None, &mut working_set) + .await?; let hashes = rich_block.map(|b| b.inner.transactions); match hashes { Some(BlockTransactions::Hashes(hashes)) => Ok(hashes), @@ -47,19 +50,21 @@ impl DbProvider { } } - pub fn last_block(&self) -> RpcResult>> { + pub async fn last_block(&self) -> RpcResult>> { let mut working_set = WorkingSet::::new(self.storage.clone()); let rich_block = self .evm - .get_block_by_number(None, Some(true), &mut working_set)?; + .get_block_by_number(None, Some(true), &mut working_set) + .await?; Ok(rich_block) } - pub fn genesis_block(&self) -> RpcResult> { + pub async fn genesis_block(&self) -> RpcResult> { let mut working_set = WorkingSet::::new(self.storage.clone()); let rich_block = self .evm - .get_block_by_number(Some(BlockNumberOrTag::Earliest), None, &mut working_set)? + .get_block_by_number(Some(BlockNumberOrTag::Earliest), None, &mut working_set) + .await? .map(|b| b.inner); Ok(rich_block) } diff --git a/crates/sequencer/src/mempool.rs b/crates/sequencer/src/mempool.rs index 9f5d382b1..89f012fea 100644 --- a/crates/sequencer/src/mempool.rs +++ b/crates/sequencer/src/mempool.rs @@ -27,16 +27,17 @@ type Transaction = as TransactionPool>::Transaction; pub(crate) struct CitreaMempool(CitreaMempoolImpl); impl CitreaMempool { - pub(crate) fn new( + pub(crate) async fn new( client: DbProvider, mempool_conf: SequencerMempoolConfig, ) -> anyhow::Result { let blob_store = NoopBlobStore::default(); let genesis_block = client .genesis_block() + .await .map(|b| b.ok_or(anyhow!("Genesis block does not exist"))) .map_err(|e| anyhow!("{e}"))??; - let evm_config = client.cfg(); + let evm_config = client.cfg().await; let Some(nonce) = genesis_block.header.nonce else { bail!("Genesis nonce is not set"); }; diff --git a/crates/sequencer/src/rpc.rs b/crates/sequencer/src/rpc.rs index 8c5f6b999..eb8a43590 100644 --- a/crates/sequencer/src/rpc.rs +++ b/crates/sequencer/src/rpc.rs @@ -105,7 +105,7 @@ pub(crate) fn create_rpc_module< let evm = Evm::::default(); let mut working_set = WorkingSet::::new(ctx.storage.clone()); - match evm.get_transaction_by_hash(hash, &mut working_set) { + match evm.get_transaction_by_hash(hash, &mut working_set).await { Ok(tx) => { Ok::, ErrorObjectOwned>(tx) } @@ -126,7 +126,7 @@ pub(crate) fn create_rpc_module< debug!("Sequencer: citrea_sendRawDepositTransaction"); let evm = Evm::::default(); - let mut working_set = WorkingSet::::new(ctx.storage.clone()); + let working_set = WorkingSet::::new(ctx.storage.clone()); let dep_tx = ctx .deposit_mempool @@ -134,7 +134,7 @@ pub(crate) fn create_rpc_module< .await .make_deposit_tx_from_data(deposit.clone().into()); - let tx_res = evm.get_call(dep_tx, None, None, None, &mut working_set); + let tx_res = evm.get_call(dep_tx, None, None, None, working_set).await; match tx_res { Ok(hex_res) => { diff --git a/crates/sequencer/src/sequencer.rs b/crates/sequencer/src/sequencer.rs index 2c46529d2..e6a0ad7bd 100644 --- a/crates/sequencer/src/sequencer.rs +++ b/crates/sequencer/src/sequencer.rs @@ -17,6 +17,7 @@ use citrea_primitives::MAX_STATEDIFF_SIZE_COMMITMENT_THRESHOLD; use citrea_stf::runtime::Runtime; use digest::Digest; use futures::channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender}; +use futures::executor::block_on; use futures::StreamExt; use hyper::Method; use jsonrpsee::server::{BatchRequestConfig, ServerBuilder}; @@ -156,7 +157,10 @@ where // used as client of reth's mempool let db_provider = DbProvider::new(storage.clone()); - let pool = CitreaMempool::new(db_provider.clone(), config.mempool_conf.clone())?; + let pool = block_on(CitreaMempool::new( + db_provider.clone(), + config.mempool_conf.clone(), + ))?; let deposit_mempool = Arc::new(Mutex::new(DepositDataMempool::new())); @@ -280,7 +284,7 @@ where &mut signed_batch, ) { (Ok(()), mut working_set_to_discard) => { - let block_gas_limit = self.db_provider.cfg().block_gas_limit; + let block_gas_limit = self.db_provider.cfg().await.block_gas_limit; let evm = Evm::::default(); @@ -303,8 +307,9 @@ where let raw_message = as EncodeCall< citrea_evm::Evm, >>::encode_call(call_txs); - let signed_blob = - self.make_blob(raw_message, &mut working_set_to_discard)?; + let signed_blob = self + .make_blob(raw_message, &mut working_set_to_discard) + .await?; let txs = vec![signed_blob.clone()]; @@ -412,7 +417,7 @@ where let pub_key = signed_batch.pub_key().clone(); - let evm_txs = self.get_best_transactions()?; + let evm_txs = self.get_best_transactions().await?; // Dry running transactions would basically allow for figuring out a list of // all transactions that would fit into the current block and the list of transactions @@ -454,7 +459,7 @@ where as EncodeCall>>::encode_call( call_txs, ); - let signed_blob = self.make_blob(raw_message, &mut batch_workspace)?; + let signed_blob = self.make_blob(raw_message, &mut batch_workspace).await?; txs.push(signed_blob); (batch_workspace, tx_receipts) = self.stf.apply_soft_confirmation_txs( @@ -571,12 +576,12 @@ where self.state_root = next_state_root; self.batch_hash = signed_soft_confirmation.hash(); - let mut txs_to_remove = self.db_provider.last_block_tx_hashes()?; + let mut txs_to_remove = self.db_provider.last_block_tx_hashes().await?; txs_to_remove.extend(l1_fee_failed_txs); self.mempool.remove_transactions(txs_to_remove.clone()); - let account_updates = self.get_account_updates()?; + let account_updates = self.get_account_updates().await?; self.mempool.update_accounts(account_updates); @@ -1042,12 +1047,12 @@ where } } - fn get_best_transactions( + async fn get_best_transactions( &self, ) -> anyhow::Result< Box>>>, > { - let cfg = self.db_provider.cfg(); + let cfg = self.db_provider.cfg().await; let latest_header = self .db_provider .latest_header() @@ -1072,14 +1077,14 @@ where /// Signs batch of messages with sovereign priv key turns them into a sov blob /// Returns a single sovereign transaction made up of multiple ethereum transactions - fn make_blob( + async fn make_blob( &mut self, raw_message: Vec, working_set: &mut WorkingSet, ) -> anyhow::Result> { // if a batch failed need to refetch nonce // so sticking to fetching from state makes sense - let nonce = self.get_nonce(working_set)?; + let nonce = self.get_nonce(working_set).await?; // TODO: figure out what to do with sov-tx fields // chain id gas tip and gas limit @@ -1116,11 +1121,12 @@ where } /// Fetches nonce from state - fn get_nonce(&self, working_set: &mut WorkingSet) -> anyhow::Result { + async fn get_nonce(&self, working_set: &mut WorkingSet) -> anyhow::Result { let accounts = Accounts::::default(); match accounts .get_account(self.sov_tx_signer_priv_key.pub_key(), working_set) + .await .map_err(|e| anyhow!("Sequencer: Failed to get sov-account: {}", e))? { AccountExists { addr: _, nonce } => Ok(nonce), @@ -1165,10 +1171,11 @@ where Ok(()) } - fn get_account_updates(&self) -> Result, anyhow::Error> { + async fn get_account_updates(&self) -> Result, anyhow::Error> { let head = self .db_provider - .last_block()? + .last_block() + .await? .expect("Unrecoverable: Head must exist"); let addresses: HashSet
= match head.transactions { diff --git a/crates/soft-confirmation-rule-enforcer/Cargo.toml b/crates/soft-confirmation-rule-enforcer/Cargo.toml index edac26036..d66615a56 100644 --- a/crates/soft-confirmation-rule-enforcer/Cargo.toml +++ b/crates/soft-confirmation-rule-enforcer/Cargo.toml @@ -17,6 +17,7 @@ sov-rollup-interface = { path = "../sovereign-sdk/rollup-interface" } sov-state = { path = "../sovereign-sdk/module-system/sov-state" } anyhow = { workspace = true } +async-trait = { workspace = true } borsh = { workspace = true } jsonrpsee = { workspace = true, features = ["macros", "client-core", "server"], optional = true } serde = { workspace = true } diff --git a/crates/soft-confirmation-rule-enforcer/src/query.rs b/crates/soft-confirmation-rule-enforcer/src/query.rs index 87a53b835..3510c6888 100644 --- a/crates/soft-confirmation-rule-enforcer/src/query.rs +++ b/crates/soft-confirmation-rule-enforcer/src/query.rs @@ -10,7 +10,10 @@ use crate::SoftConfirmationRuleEnforcer; impl SoftConfirmationRuleEnforcer { #[rpc_method(name = "getMaxL2BlocksPerL1")] /// Get the account corresponding to the given public key. - pub fn get_max_l2_blocks_per_l1(&self, working_set: &mut WorkingSet) -> RpcResult { + pub async fn get_max_l2_blocks_per_l1( + &self, + working_set: &mut WorkingSet, + ) -> RpcResult { Ok(self .max_l2_blocks_per_l1 .get(working_set) @@ -19,7 +22,7 @@ impl SoftConfirmationRuleEnforcer { #[rpc_method(name = "getBlockCountByDaRootHash")] /// Get number of L2 blocks published for L1 block with the given DA root hash. - pub fn get_block_count_by_da_root_hash( + pub async fn get_block_count_by_da_root_hash( &self, da_root_hash: [u8; 32], working_set: &mut WorkingSet, @@ -32,7 +35,7 @@ impl SoftConfirmationRuleEnforcer { #[rpc_method(name = "getMaxL1FeeRateChangePercentage")] /// Get the maximum L1 fee rate change percentage. - pub fn get_max_l1_fee_rate_change_percentage( + pub async fn get_max_l1_fee_rate_change_percentage( &self, working_set: &mut WorkingSet, ) -> RpcResult { @@ -45,13 +48,13 @@ impl SoftConfirmationRuleEnforcer { #[rpc_method(name = "getLastL1FeeRate")] /// Get the last processed L1 fee rate. /// 0 at genesis. - pub fn get_last_l1_fee_rate(&self, working_set: &mut WorkingSet) -> RpcResult { + pub async fn get_last_l1_fee_rate(&self, working_set: &mut WorkingSet) -> RpcResult { Ok(self.last_l1_fee_rate.get(working_set).unwrap_or(0)) } #[rpc_method(name = "getLatestBlockTimestamp")] /// Get the latest block's timestamp. /// 0 at genesis. - pub fn get_last_timestamp(&self, working_set: &mut WorkingSet) -> RpcResult { + pub async fn get_last_timestamp(&self, working_set: &mut WorkingSet) -> RpcResult { Ok(self.last_timestamp.get(working_set).unwrap_or(0)) } diff --git a/crates/sovereign-sdk/full-node/sov-stf-runner/Cargo.toml b/crates/sovereign-sdk/full-node/sov-stf-runner/Cargo.toml index 8bdb6925a..fff456cef 100644 --- a/crates/sovereign-sdk/full-node/sov-stf-runner/Cargo.toml +++ b/crates/sovereign-sdk/full-node/sov-stf-runner/Cargo.toml @@ -62,4 +62,5 @@ native = [ "rand", "tower", "hyper", + "tokio", ] diff --git a/crates/sovereign-sdk/module-system/module-implementations/examples/sov-accessory-state/Cargo.toml b/crates/sovereign-sdk/module-system/module-implementations/examples/sov-accessory-state/Cargo.toml index e2df25e68..4ba57b436 100644 --- a/crates/sovereign-sdk/module-system/module-implementations/examples/sov-accessory-state/Cargo.toml +++ b/crates/sovereign-sdk/module-system/module-implementations/examples/sov-accessory-state/Cargo.toml @@ -7,20 +7,21 @@ license = { workspace = true } repository = { workspace = true } version = { workspace = true } -readme = "README.md" publish = false +readme = "README.md" resolver = "2" [dependencies] +async-trait = { workspace = true } +borsh = { workspace = true, features = ["rc"] } jsonrpsee = { workspace = true, features = ["macros", "client-core", "server"], optional = true } +serde = { workspace = true, optional = true } sov-modules-api = { path = "../../../sov-modules-api", default-features = false, features = ["macros"] } sov-state = { path = "../../../sov-state" } -serde = { workspace = true, optional = true } -borsh = { workspace = true, features = ["rc"] } [dev-dependencies] -tempfile = { workspace = true } sov-prover-storage-manager = { path = "../../../../full-node/sov-prover-storage-manager", features = ["test-utils"] } +tempfile = { workspace = true } [features] default = [] diff --git a/crates/sovereign-sdk/module-system/module-implementations/examples/sov-accessory-state/src/query.rs b/crates/sovereign-sdk/module-system/module-implementations/examples/sov-accessory-state/src/query.rs index b6f015e12..ff9761cc0 100644 --- a/crates/sovereign-sdk/module-system/module-implementations/examples/sov-accessory-state/src/query.rs +++ b/crates/sovereign-sdk/module-system/module-implementations/examples/sov-accessory-state/src/query.rs @@ -19,7 +19,7 @@ impl AccessorySetter { /// Returns the latest value set in the accessory state via /// [`CallMessage::SetValueAccessory`](crate::CallMessage::SetValueAccessory). #[rpc_method(name = "value")] - pub fn query_value(&self, working_set: &mut WorkingSet) -> RpcResult { + pub async fn query_value(&self, working_set: &mut WorkingSet) -> RpcResult { Ok(ValueResponse { value: self.accessory_value.get(&mut working_set.accessory_state()), }) diff --git a/crates/sovereign-sdk/module-system/module-implementations/examples/sov-value-setter/Cargo.toml b/crates/sovereign-sdk/module-system/module-implementations/examples/sov-value-setter/Cargo.toml index 9c60aa694..9873b9231 100644 --- a/crates/sovereign-sdk/module-system/module-implementations/examples/sov-value-setter/Cargo.toml +++ b/crates/sovereign-sdk/module-system/module-implementations/examples/sov-value-setter/Cargo.toml @@ -1,35 +1,34 @@ [package] name = "sov-value-setter" -description = "A Sovereign SDK example module for setting/reading value from state" authors = { workspace = true } edition = { workspace = true } homepage = { workspace = true } license = { workspace = true } repository = { workspace = true } +description = "A Sovereign SDK example module for setting/reading value from state" version = { workspace = true } +publish = false readme = "README.md" resolver = "2" -publish = false - [dev-dependencies] -tempfile = { workspace = true } sov-modules-api = { path = "../../../sov-modules-api", features = ["native"] } sov-prover-storage-manager = { path = "../../../../full-node/sov-prover-storage-manager", features = ["test-utils"] } - +tempfile = { workspace = true } [dependencies] anyhow = { workspace = true } -sov-modules-api = { path = "../../../sov-modules-api" } -sov-state = { path = "../../../sov-state" } +async-trait = { workspace = true } +borsh = { workspace = true, features = ["rc"] } +clap = { workspace = true, optional = true } +jsonrpsee = { workspace = true, features = ["macros", "client-core", "server"], optional = true } schemars = { workspace = true, optional = true } serde = { workspace = true } serde_json = { workspace = true, optional = true } +sov-modules-api = { path = "../../../sov-modules-api" } +sov-state = { path = "../../../sov-state" } thiserror = { workspace = true } -borsh = { workspace = true, features = ["rc"] } -jsonrpsee = { workspace = true, features = ["macros", "client-core", "server"], optional = true } -clap = { workspace = true, optional = true } [features] default = ["native"] diff --git a/crates/sovereign-sdk/module-system/module-implementations/examples/sov-value-setter/src/query.rs b/crates/sovereign-sdk/module-system/module-implementations/examples/sov-value-setter/src/query.rs index 098d1e118..ade862281 100644 --- a/crates/sovereign-sdk/module-system/module-implementations/examples/sov-value-setter/src/query.rs +++ b/crates/sovereign-sdk/module-system/module-implementations/examples/sov-value-setter/src/query.rs @@ -17,7 +17,7 @@ pub struct Response { impl ValueSetter { /// Queries the state of the module. #[rpc_method(name = "queryValue")] - pub fn query_value(&self, working_set: &mut WorkingSet) -> RpcResult { + pub async fn query_value(&self, working_set: &mut WorkingSet) -> RpcResult { Ok(Response { value: self.value.get(working_set), }) diff --git a/crates/sovereign-sdk/module-system/module-implementations/examples/sov-vec-setter/Cargo.toml b/crates/sovereign-sdk/module-system/module-implementations/examples/sov-vec-setter/Cargo.toml index 5219edf94..3687f28f7 100644 --- a/crates/sovereign-sdk/module-system/module-implementations/examples/sov-vec-setter/Cargo.toml +++ b/crates/sovereign-sdk/module-system/module-implementations/examples/sov-vec-setter/Cargo.toml @@ -1,33 +1,34 @@ [package] name = "sov-vec-setter" -description = "A Sovereign SDK example module for setting/reading vectors from state" authors = { workspace = true } edition = { workspace = true } homepage = { workspace = true } license = { workspace = true } repository = { workspace = true } +description = "A Sovereign SDK example module for setting/reading vectors from state" version = { workspace = true } +publish = false readme = "README.md" resolver = "2" -publish = false [dev-dependencies] -tempfile = { workspace = true } sov-modules-api = { path = "../../../sov-modules-api", features = ["native", "macros"] } sov-prover-storage-manager = { path = "../../../../full-node/sov-prover-storage-manager", features = ["test-utils"] } +tempfile = { workspace = true } [dependencies] anyhow = { workspace = true } -sov-modules-api = { path = "../../../sov-modules-api", default-features = false, features = ["macros"] } -sov-state = { path = "../../../sov-state", default-features = false } +async-trait = { workspace = true } +borsh = { workspace = true, features = ["rc"] } +clap = { workspace = true, optional = true } +jsonrpsee = { workspace = true, features = ["macros", "client-core", "server"], optional = true } schemars = { workspace = true, optional = true } serde = { workspace = true } serde_json = { workspace = true, optional = true } +sov-modules-api = { path = "../../../sov-modules-api", default-features = false, features = ["macros"] } +sov-state = { path = "../../../sov-state", default-features = false } thiserror = { workspace = true } -borsh = { workspace = true, features = ["rc"] } -jsonrpsee = { workspace = true, features = ["macros", "client-core", "server"], optional = true } -clap = { workspace = true, optional = true } [features] default = ["native"] diff --git a/crates/sovereign-sdk/module-system/module-implementations/examples/sov-vec-setter/src/query.rs b/crates/sovereign-sdk/module-system/module-implementations/examples/sov-vec-setter/src/query.rs index 3a4c7466b..8a9a9eb87 100644 --- a/crates/sovereign-sdk/module-system/module-implementations/examples/sov-vec-setter/src/query.rs +++ b/crates/sovereign-sdk/module-system/module-implementations/examples/sov-vec-setter/src/query.rs @@ -22,7 +22,7 @@ pub struct LenResponse { impl VecSetter { /// Queries the state vector of the module. #[rpc_method(name = "queryVec")] - pub fn query_vec( + pub async fn query_vec( &self, index: usize, working_set: &mut WorkingSet, @@ -33,7 +33,7 @@ impl VecSetter { } /// Queries the length of the vector #[rpc_method(name = "lenVec")] - pub fn len_vec(&self, working_set: &mut WorkingSet) -> RpcResult { + pub async fn len_vec(&self, working_set: &mut WorkingSet) -> RpcResult { Ok(LenResponse { value: self.vector.len(working_set), }) diff --git a/crates/sovereign-sdk/module-system/module-implementations/sov-accounts/Cargo.toml b/crates/sovereign-sdk/module-system/module-implementations/sov-accounts/Cargo.toml index fc9d18f2c..33e31d7c4 100644 --- a/crates/sovereign-sdk/module-system/module-implementations/sov-accounts/Cargo.toml +++ b/crates/sovereign-sdk/module-system/module-implementations/sov-accounts/Cargo.toml @@ -1,11 +1,11 @@ [package] name = "sov-accounts" -description = "A Sovereign SDK module for managing rollup state using accounts" authors = { workspace = true } edition = { workspace = true } homepage = { workspace = true } license = { workspace = true } repository = { workspace = true } +description = "A Sovereign SDK module for managing rollup state using accounts" version = { workspace = true } readme = "README.md" @@ -14,49 +14,41 @@ resolver = "2" [dependencies] anyhow = { workspace = true } arbitrary = { workspace = true, optional = true } +async-trait = { workspace = true } borsh = { workspace = true, features = ["rc"] } +clap = { workspace = true, optional = true } +jsonrpsee = { workspace = true, features = ["macros", "client-core", "server"], optional = true } proptest = { workspace = true, optional = true } proptest-derive = { workspace = true, optional = true } schemars = { workspace = true, optional = true } serde = { workspace = true } serde_json = { workspace = true, optional = true } thiserror = { workspace = true } -clap = { workspace = true, optional = true } -jsonrpsee = { workspace = true, features = [ - "macros", - "client-core", - "server", -], optional = true } -sov-modules-api = { path = "../../sov-modules-api", default-features = false, features = [ - "macros", -] } +sov-modules-api = { path = "../../sov-modules-api", default-features = false, features = ["macros"] } sov-state = { path = "../../sov-state" } - [dev-dependencies] +sov-prover-storage-manager = { path = "../../../full-node/sov-prover-storage-manager", features = ["test-utils"] } tempfile = { workspace = true } -sov-prover-storage-manager = { path = "../../../full-node/sov-prover-storage-manager", features = [ - "test-utils", -] } [features] default = ["native"] arbitrary = [ - "dep:arbitrary", - "dep:proptest", - "dep:proptest-derive", - "sov-state/arbitrary", - "sov-modules-api/arbitrary", - "sov-state/arbitrary", + "dep:arbitrary", + "dep:proptest", + "dep:proptest-derive", + "sov-state/arbitrary", + "sov-modules-api/arbitrary", + "sov-state/arbitrary", ] native = [ - "serde", - "serde_json", - "jsonrpsee", - "schemars", - "clap", - "sov-state/native", - "sov-modules-api/native", + "serde", + "serde_json", + "jsonrpsee", + "schemars", + "clap", + "sov-state/native", + "sov-modules-api/native", ] serde = [] diff --git a/crates/sovereign-sdk/module-system/module-implementations/sov-accounts/src/query.rs b/crates/sovereign-sdk/module-system/module-implementations/sov-accounts/src/query.rs index 23ff939e2..0ea52fbfc 100644 --- a/crates/sovereign-sdk/module-system/module-implementations/sov-accounts/src/query.rs +++ b/crates/sovereign-sdk/module-system/module-implementations/sov-accounts/src/query.rs @@ -27,7 +27,7 @@ pub enum Response { impl Accounts { #[rpc_method(name = "getAccount")] /// Get the account corresponding to the given public key. - pub fn get_account( + pub async fn get_account( &self, pub_key: C::PublicKey, working_set: &mut WorkingSet, diff --git a/crates/sovereign-sdk/module-system/module-implementations/sov-accounts/src/tests.rs b/crates/sovereign-sdk/module-system/module-implementations/sov-accounts/src/tests.rs index 84a2ac09a..92fbfd63f 100644 --- a/crates/sovereign-sdk/module-system/module-implementations/sov-accounts/src/tests.rs +++ b/crates/sovereign-sdk/module-system/module-implementations/sov-accounts/src/tests.rs @@ -9,7 +9,7 @@ use crate::{AccountConfig, Accounts}; type C = DefaultContext; #[test] -fn test_config_account() { +async fn test_config_account() { let priv_key = DefaultPrivateKey::generate(); let init_pub_key = priv_key.pub_key(); let init_pub_key_addr = init_pub_key.to_address::<::Address>(); @@ -24,7 +24,10 @@ fn test_config_account() { accounts.init_module(&account_config, working_set).unwrap(); - let query_response = accounts.get_account(init_pub_key, working_set).unwrap(); + let query_response = accounts + .get_account(init_pub_key, working_set) + .await + .unwrap(); assert_eq!( query_response, diff --git a/crates/sovereign-sdk/module-system/module-implementations/sov-bank/Cargo.toml b/crates/sovereign-sdk/module-system/module-implementations/sov-bank/Cargo.toml index 65033bfea..4296c2e31 100644 --- a/crates/sovereign-sdk/module-system/module-implementations/sov-bank/Cargo.toml +++ b/crates/sovereign-sdk/module-system/module-implementations/sov-bank/Cargo.toml @@ -1,11 +1,11 @@ [package] name = "sov-bank" -description = "A Sovereign SDK managing fungible tokens" authors = { workspace = true } edition = { workspace = true } homepage = { workspace = true } license = { workspace = true } repository = { workspace = true } +description = "A Sovereign SDK managing fungible tokens" version = { workspace = true } readme = "README.md" @@ -13,13 +13,10 @@ resolver = "2" [dependencies] anyhow = { workspace = true } +async-trait = { workspace = true } borsh = { workspace = true, features = ["rc"] } clap = { workspace = true, optional = true } -jsonrpsee = { workspace = true, features = [ - "macros", - "client-core", - "server", -], optional = true } +jsonrpsee = { workspace = true, features = ["macros", "client-core", "server"], optional = true } schemars = { workspace = true, optional = true } serde = { workspace = true } serde_json = { workspace = true, optional = true } @@ -28,24 +25,21 @@ thiserror = { workspace = true } sov-modules-api = { path = "../../sov-modules-api", default-features = false } sov-state = { path = "../../sov-state" } - [dev-dependencies] sov-bank = { path = ".", features = ["native", "test-utils"] } +sov-prover-storage-manager = { path = "../../../full-node/sov-prover-storage-manager", features = ["test-utils"] } tempfile = { workspace = true } -sov-prover-storage-manager = { path = "../../../full-node/sov-prover-storage-manager", features = [ - "test-utils", -] } [features] default = [] native = [ - "serde", - "serde_json", - "jsonrpsee", - "clap", - "schemars", - "sov-state/native", - "sov-modules-api/native", + "serde", + "serde_json", + "jsonrpsee", + "clap", + "schemars", + "sov-state/native", + "sov-modules-api/native", ] cli = ["native"] serde = [] diff --git a/crates/sovereign-sdk/module-system/module-implementations/sov-bank/src/query.rs b/crates/sovereign-sdk/module-system/module-implementations/sov-bank/src/query.rs index 70df33f09..3041d6b08 100644 --- a/crates/sovereign-sdk/module-system/module-implementations/sov-bank/src/query.rs +++ b/crates/sovereign-sdk/module-system/module-implementations/sov-bank/src/query.rs @@ -24,7 +24,7 @@ impl Bank { #[rpc_method(name = "balanceOf")] /// Rpc method that returns the balance of the user at the address `user_address` for the token /// stored at the address `token_address`. - pub fn balance_of( + pub async fn balance_of( &self, user_address: C::Address, token_address: C::Address, @@ -37,7 +37,7 @@ impl Bank { #[rpc_method(name = "supplyOf")] /// Rpc method that returns the supply of a token stored at the address `token_address`. - pub fn supply_of( + pub async fn supply_of( &self, token_address: C::Address, working_set: &mut WorkingSet, diff --git a/crates/sovereign-sdk/module-system/module-implementations/sov-sequencer-registry/Cargo.toml b/crates/sovereign-sdk/module-system/module-implementations/sov-sequencer-registry/Cargo.toml index bd49d0645..adc8ad2f1 100644 --- a/crates/sovereign-sdk/module-system/module-implementations/sov-sequencer-registry/Cargo.toml +++ b/crates/sovereign-sdk/module-system/module-implementations/sov-sequencer-registry/Cargo.toml @@ -1,11 +1,11 @@ [package] name = "sov-sequencer-registry" -description = "A Sovereign SDK module for registering rollup sequencers" authors = { workspace = true } edition = { workspace = true } homepage = { workspace = true } license = { workspace = true } repository = { workspace = true } +description = "A Sovereign SDK module for registering rollup sequencers" version = { workspace = true } readme = "README.md" @@ -15,62 +15,55 @@ resolver = "2" [dependencies] anyhow = { workspace = true } arbitrary = { workspace = true, optional = true } +async-trait = { workspace = true } +borsh = { workspace = true, features = ["rc"] } clap = { workspace = true, optional = true } +jsonrpsee = { workspace = true, features = ["macros", "client-core", "server"], optional = true } proptest = { workspace = true, optional = true } proptest-derive = { workspace = true, optional = true } -sov-bank = { path = "../sov-bank" } -sov-modules-api = { path = "../../sov-modules-api", default-features = false } -sov-state = { path = "../../sov-state" } +risc0-zkvm = { workspace = true, default-features = false, features = ["std"], optional = true } +risc0-zkvm-platform = { workspace = true, optional = true } schemars = { workspace = true, optional = true } serde = { workspace = true } serde_json = { workspace = true, optional = true } -borsh = { workspace = true, features = ["rc"] } -jsonrpsee = { workspace = true, features = [ - "macros", - "client-core", - "server", -], optional = true } +sov-bank = { path = "../sov-bank" } +sov-modules-api = { path = "../../sov-modules-api", default-features = false } +sov-state = { path = "../../sov-state" } sov-zk-cycle-macros = { path = "../../../utils/zk-cycle-macros", optional = true } -risc0-zkvm = { workspace = true, default-features = false, features = [ - "std", -], optional = true } -risc0-zkvm-platform = { workspace = true, optional = true } sov-zk-cycle-utils = { path = "../../../utils/zk-cycle-utils", optional = true } [dev-dependencies] -tempfile = { workspace = true } -sov-sequencer-registry = { path = ".", features = ["native"] } sov-mock-da = { path = "../../../adapters/mock-da", features = ["native"] } -sov-prover-storage-manager = { path = "../../../full-node/sov-prover-storage-manager", features = [ - "test-utils", -] } +sov-prover-storage-manager = { path = "../../../full-node/sov-prover-storage-manager", features = ["test-utils"] } +sov-sequencer-registry = { path = ".", features = ["native"] } +tempfile = { workspace = true } [features] bench = [ - "sov-zk-cycle-macros/bench", - "risc0-zkvm", - "risc0-zkvm-platform", - "sov-zk-cycle-utils", + "sov-zk-cycle-macros/bench", + "risc0-zkvm", + "risc0-zkvm-platform", + "sov-zk-cycle-utils", ] default = [] arbitrary = ["dep:arbitrary", "dep:proptest", "dep:proptest-derive"] native = [ - "serde", - "serde_json", - "jsonrpsee", - "schemars", - "clap", - "sov-state/native", - "sov-modules-api/native", - # This: - "sov-bank/native", + "serde", + "serde_json", + "jsonrpsee", + "schemars", + "clap", + "sov-state/native", + "sov-modules-api/native", + # This: + "sov-bank/native", ] serde = [] [package.metadata.cargo-udeps.ignore] normal = [ - "risc0-zkvm", - "risc0-zkvm-platform", - "sov-zk-cycle-macros", - "sov-zk-cycle-utils", + "risc0-zkvm", + "risc0-zkvm-platform", + "sov-zk-cycle-macros", + "sov-zk-cycle-utils", ] diff --git a/crates/sovereign-sdk/module-system/module-implementations/sov-sequencer-registry/src/query.rs b/crates/sovereign-sdk/module-system/module-implementations/sov-sequencer-registry/src/query.rs index a7c3ab2f2..41b1ca270 100644 --- a/crates/sovereign-sdk/module-system/module-implementations/sov-sequencer-registry/src/query.rs +++ b/crates/sovereign-sdk/module-system/module-implementations/sov-sequencer-registry/src/query.rs @@ -22,7 +22,7 @@ impl SequencerRegistry { /// /// The response only contains data if the sequencer is registered. #[rpc_method(name = "getSequencerAddress")] - pub fn sequencer_address( + pub async fn sequencer_address( &self, da_address: Da::Address, working_set: &mut WorkingSet, 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..641a4bdbf 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 @@ -43,7 +43,7 @@ fn jsonrpsee_rpc_macro_path() -> Path { } } -fn find_working_set_argument(sig: &Signature) -> Option<(usize, syn::Type)> { +fn find_working_set_argument(sig: &Signature) -> Option<(usize, syn::Type, WorkingSetPassType)> { for (idx, input) in sig.inputs.iter().enumerate() { if let FnArg::Typed(PatType { ty, .. }) = input { if let syn::Type::Reference(syn::TypeReference { elem, .. }) = *ty.clone() { @@ -51,20 +51,33 @@ fn find_working_set_argument(sig: &Signature) -> Option<(usize, syn::Type)> { if let Some(segment) = path.segments.last() { // TODO: enforce that the working set has exactly one angle bracketed argument if segment.ident == "WorkingSet" && !segment.arguments.is_empty() { - return Some((idx, *elem.clone())); + return Some((idx, *elem.clone(), WorkingSetPassType::RefMut)); } } } + } else if let syn::Type::Path(syn::TypePath { path, .. }) = *ty.clone() { + if let Some(segment) = path.segments.last() { + if segment.ident == "WorkingSet" { + return Some((idx, *ty.clone(), WorkingSetPassType::Owned)); + } + } } } } None } +#[derive(Clone)] +enum WorkingSetPassType { + RefMut, + Owned, +} + struct RpcImplBlock { pub(crate) type_name: Ident, pub(crate) methods: Vec, pub(crate) working_set_type: Option, + pub(crate) working_set_mutability: Option, pub(crate) generics: syn::Generics, } @@ -125,10 +138,26 @@ 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),* ) + match self + .working_set_mutability + .clone() + .expect("Working set mutability should be set") + { + WorkingSetPassType::RefMut => { + 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 + } + } + } + WorkingSetPassType::Owned => { + quote! { + #( #docs )* + #signature { + <#type_name #ty_generics as ::std::default::Default>::default().#method_name(#(#pre_working_set_args,)* Self::get_working_set(self), #(#post_working_set_args),* ).await + } + } } } } else { @@ -138,7 +167,7 @@ impl RpcImplBlock { .filter(|arg| arg.to_string() != quote! { self }.to_string()); quote! { #signature { - <#type_name #ty_generics as ::std::default::Default>::default().#method_name(#(#arg_values),*) + <#type_name #ty_generics as ::std::default::Default>::default().#method_name(#(#arg_values),*).await } } }; @@ -152,14 +181,14 @@ impl RpcImplBlock { quote! { #( #docs )* #signature { - ::#method_name(#(#pre_working_set_args,)* #(#post_working_set_args),* ) + ::#method_name(#(#pre_working_set_args,)* #(#post_working_set_args),* ).await } } } else { quote! { #( #docs )* #signature { - ::#method_name(#(#arg_values),*) + ::#method_name(#(#arg_values),*).await } } }; @@ -171,6 +200,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::async_trait] 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 +211,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::async_trait] pub trait #impl_trait_name #generics #where_clause { #(#impl_trait_methods)* } @@ -197,6 +228,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::async_trait] impl = intermediate_trait_inputs.into_iter().collect(); @@ -275,6 +308,7 @@ fn build_rpc_trait( // Store the type of the working set argument for later reference rpc_info.working_set_type = Some(ty); + rpc_info.working_set_mutability = Some(pass_ty); Some(idx) } else { None @@ -332,6 +366,7 @@ fn build_rpc_trait( #rpc_attribute #[doc = #doc_string] + #[async_trait::async_trait] pub trait #intermediate_trait_name #generics #where_clause { #(#intermediate_trait_items)*