From 908429c53ab0e332bf364a7ca30cea182a3767da Mon Sep 17 00:00:00 2001 From: Wodann Date: Thu, 16 Nov 2023 10:53:55 +0000 Subject: [PATCH 1/2] refactor: remove async-trait --- Cargo.lock | 2 - crates/edr_evm/Cargo.toml | 1 - crates/edr_evm/src/block.rs | 8 +- crates/edr_evm/src/block/local.rs | 4 +- crates/edr_evm/src/block/remote.rs | 27 ++- crates/edr_evm/src/blockchain.rs | 42 ++-- crates/edr_evm/src/blockchain/forked.rs | 136 ++++++------ crates/edr_evm/src/blockchain/local.rs | 50 ++--- crates/edr_evm/src/blockchain/remote.rs | 17 +- crates/edr_evm/src/miner.rs | 3 +- crates/edr_evm/src/runtime.rs | 12 +- crates/edr_evm/src/state.rs | 12 +- crates/edr_evm/tests/blockchain.rs | 199 ++++++------------ crates/edr_napi/Cargo.toml | 1 - crates/edr_napi/index.d.ts | 10 +- crates/edr_napi/src/block.rs | 4 +- crates/edr_napi/src/block/builder.rs | 162 +++++++------- crates/edr_napi/src/blockchain.rs | 160 +++++++++----- crates/edr_napi/src/debug_trace.rs | 79 ++++--- crates/edr_napi/src/mempool.rs | 156 +++++++++----- crates/edr_napi/src/miner.rs | 90 ++++---- crates/edr_napi/src/provider.rs | 12 +- crates/edr_napi/src/runtime.rs | 109 ++++++---- crates/edr_napi/src/state.rs | 89 ++++---- crates/edr_napi/src/state/overrides.rs | 8 +- crates/edr_napi/src/transaction/pending.rs | 4 +- crates/edr_provider/src/data.rs | 167 ++++++--------- crates/edr_provider/src/lib.rs | 85 +++----- .../src/requests/eth/blockchain.rs | 11 +- crates/edr_provider/src/requests/eth/evm.rs | 8 +- crates/edr_provider/src/requests/eth/state.rs | 10 +- .../src/requests/eth/transactions.rs | 16 +- .../src/requests/hardhat/miner.rs | 4 +- .../src/requests/hardhat/state.rs | 16 +- .../provider/vm/block-builder/edr.ts | 2 +- 35 files changed, 855 insertions(+), 861 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 230c622a6c..de12c4c0a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -743,7 +743,6 @@ name = "edr_evm" version = "0.2.0-dev" dependencies = [ "async-rwlock", - "async-trait", "auto_impl", "cita_trie", "criterion", @@ -774,7 +773,6 @@ dependencies = [ name = "edr_napi" version = "0.2.0-dev" dependencies = [ - "async-trait", "crossbeam-channel", "edr_defaults", "edr_eth", diff --git a/crates/edr_evm/Cargo.toml b/crates/edr_evm/Cargo.toml index a193bb9885..8bd70a8183 100644 --- a/crates/edr_evm/Cargo.toml +++ b/crates/edr_evm/Cargo.toml @@ -8,7 +8,6 @@ edition = "2021" [dependencies] async-rwlock = { version = "1.3.0", default-features = false } -async-trait = { version = "0.1.73", default-features = false } auto_impl = { version = "1.0.1", default-features = false } cita_trie = { git = "https://github.com/Wodann/cita-trie", rev = "60efef5", version = "4.0.0", default-features = false } dyn-clone = { version = "1.0.13", default-features = false } diff --git a/crates/edr_evm/src/block.rs b/crates/edr_evm/src/block.rs index b020ed2c42..7466801237 100644 --- a/crates/edr_evm/src/block.rs +++ b/crates/edr_evm/src/block.rs @@ -4,7 +4,6 @@ mod remote; use std::{fmt::Debug, sync::Arc}; -use async_trait::async_trait; use auto_impl::auto_impl; use edr_eth::{block, receipt::BlockReceipt, transaction::SignedTransaction, Address, B256}; @@ -15,7 +14,6 @@ pub use self::{ }; /// Trait for implementations of an Ethereum block. -#[async_trait] #[auto_impl(Arc)] pub trait Block: Debug { /// The blockchain error type. @@ -34,10 +32,10 @@ pub trait Block: Debug { fn transaction_callers(&self) -> &[Address]; /// Returns the receipts of the block's transactions. - async fn transaction_receipts(&self) -> Result>, Self::Error>; + fn transaction_receipts(&self) -> Result>, Self::Error>; } /// Trait that meets all requirements for a synchronous block. -pub trait SyncBlock: Block + Send + Sync + 'static {} +pub trait SyncBlock: Block + Send + Sync {} -impl SyncBlock for BlockT where BlockT: Block + Send + Sync + 'static {} +impl SyncBlock for BlockT where BlockT: Block + Send + Sync {} diff --git a/crates/edr_evm/src/block/local.rs b/crates/edr_evm/src/block/local.rs index 21f3a7c90e..fb231cff97 100644 --- a/crates/edr_evm/src/block/local.rs +++ b/crates/edr_evm/src/block/local.rs @@ -1,6 +1,5 @@ use std::sync::Arc; -use async_trait::async_trait; use edr_eth::{ block::{self, Header, PartialHeader}, log::{FullBlockLog, Log, ReceiptLog}, @@ -94,7 +93,6 @@ impl LocalBlock { } } -#[async_trait] impl Block for LocalBlock { type Error = BlockchainError; @@ -114,7 +112,7 @@ impl Block for LocalBlock { &self.transaction_callers } - async fn transaction_receipts(&self) -> Result>, Self::Error> { + fn transaction_receipts(&self) -> Result>, Self::Error> { Ok(self.transaction_receipts.clone()) } } diff --git a/crates/edr_evm/src/block/remote.rs b/crates/edr_evm/src/block/remote.rs index 01c52d6026..2e5a57dbf5 100644 --- a/crates/edr_evm/src/block/remote.rs +++ b/crates/edr_evm/src/block/remote.rs @@ -1,6 +1,5 @@ use std::sync::{Arc, OnceLock}; -use async_trait::async_trait; use edr_eth::{ block::{BlobGas, Header}, receipt::BlockReceipt, @@ -12,6 +11,7 @@ use edr_eth::{ withdrawal::Withdrawal, Address, B256, B64, }; +use tokio::runtime; use crate::{blockchain::BlockchainError, Block, SyncBlock}; @@ -51,6 +51,7 @@ pub struct RemoteBlock { hash: B256, // The RPC client is needed to lazily fetch receipts rpc_client: Arc, + runtime: runtime::Handle, } impl RemoteBlock { @@ -58,6 +59,7 @@ impl RemoteBlock { pub fn new( block: eth::Block, rpc_client: Arc, + runtime: runtime::Handle, ) -> Result { let header = Header { parent_hash: block.parent_hash, @@ -104,11 +106,11 @@ impl RemoteBlock { _withdrawals: block.withdrawals, hash, rpc_client, + runtime, }) } } -#[async_trait] impl Block for RemoteBlock { type Error = BlockchainError; @@ -128,19 +130,22 @@ impl Block for RemoteBlock { &self.callers } - async fn transaction_receipts(&self) -> Result>, Self::Error> { + fn transaction_receipts(&self) -> Result>, Self::Error> { if let Some(receipts) = self.receipts.get() { return Ok(receipts.clone()); } - let receipts: Vec> = self - .rpc_client - .get_transaction_receipts(self.transactions.iter().map(SignedTransaction::hash)) - .await? - .expect("All receipts of the block should exist") - .into_iter() - .map(Arc::new) - .collect(); + let receipts: Vec> = tokio::task::block_in_place(|| { + self.runtime.block_on( + self.rpc_client.get_transaction_receipts( + self.transactions.iter().map(SignedTransaction::hash), + ), + ) + })? + .expect("All receipts of the block should exist") + .into_iter() + .map(Arc::new) + .collect(); self.receipts .set(receipts.clone()) diff --git a/crates/edr_evm/src/blockchain.rs b/crates/edr_evm/src/blockchain.rs index 68471a486c..a232742c81 100644 --- a/crates/edr_evm/src/blockchain.rs +++ b/crates/edr_evm/src/blockchain.rs @@ -6,7 +6,6 @@ pub mod storage; use std::{fmt::Debug, sync::Arc}; -use async_trait::async_trait; use edr_eth::{ receipt::BlockReceipt, remote::RpcClientError, spec::HardforkActivations, B256, U256, }; @@ -75,7 +74,6 @@ pub enum BlockchainError { } /// Trait for implementations of an Ethereum blockchain. -#[async_trait] pub trait Blockchain { /// The blockchain's error type type BlockchainError; @@ -84,74 +82,70 @@ pub trait Blockchain { type StateError; /// Retrieves the block with the provided hash, if it exists. - async fn block_by_hash( + #[allow(clippy::type_complexity)] + fn block_by_hash( &self, hash: &B256, ) -> Result>>, Self::BlockchainError>; /// Retrieves the block with the provided number, if it exists. - async fn block_by_number( + #[allow(clippy::type_complexity)] + fn block_by_number( &self, number: u64, ) -> Result>>, Self::BlockchainError>; /// Retrieves the block that contains a transaction with the provided hash, /// if it exists. - async fn block_by_transaction_hash( + #[allow(clippy::type_complexity)] + fn block_by_transaction_hash( &self, transaction_hash: &B256, ) -> Result>>, Self::BlockchainError>; /// Retrieves the instances chain ID. - async fn chain_id(&self) -> u64; + fn chain_id(&self) -> u64; /// Retrieves the last block in the blockchain. - async fn last_block( + fn last_block( &self, ) -> Result>, Self::BlockchainError>; /// Retrieves the last block number in the blockchain. - async fn last_block_number(&self) -> u64; + fn last_block_number(&self) -> u64; /// Retrieves the receipt of the transaction with the provided hash, if it /// exists. - async fn receipt_by_transaction_hash( + fn receipt_by_transaction_hash( &self, transaction_hash: &B256, ) -> Result>, Self::BlockchainError>; /// Retrieves the hardfork specification of the block at the provided /// number. - async fn spec_at_block_number( - &self, - block_number: u64, - ) -> Result; + fn spec_at_block_number(&self, block_number: u64) -> Result; /// Retrieves the hardfork specification used for new blocks. fn spec_id(&self) -> SpecId; /// Retrieves the state at a given block - async fn state_at_block_number( + fn state_at_block_number( &self, block_number: u64, ) -> Result>, Self::BlockchainError>; /// Retrieves the total difficulty at the block with the provided hash. - async fn total_difficulty_by_hash( - &self, - hash: &B256, - ) -> Result, Self::BlockchainError>; + fn total_difficulty_by_hash(&self, hash: &B256) -> Result, Self::BlockchainError>; } /// Trait for implementations of a mutable Ethereum blockchain -#[async_trait] pub trait BlockchainMut { /// The blockchain's error type type Error; /// Inserts the provided block into the blockchain, returning a reference to /// the inserted block. - async fn insert_block( + fn insert_block( &mut self, block: LocalBlock, state_diff: StateDiff, @@ -159,11 +153,11 @@ pub trait BlockchainMut { /// Reserves the provided number of blocks, starting from the next block /// number. - async fn reserve_blocks(&mut self, additional: u64, interval: u64) -> Result<(), Self::Error>; + fn reserve_blocks(&mut self, additional: u64, interval: u64) -> Result<(), Self::Error>; /// Reverts to the block with the provided number, deleting all later /// blocks. - async fn revert_to_block(&mut self, block_number: u64) -> Result<(), Self::Error>; + fn revert_to_block(&mut self, block_number: u64) -> Result<(), Self::Error>; } /// Trait that meets all requirements for a synchronous blockchain. @@ -174,7 +168,6 @@ pub trait SyncBlockchain: + Send + Sync + Debug - + 'static where BlockchainErrorT: Debug + Send, { @@ -188,8 +181,7 @@ where + BlockHashRef + Send + Sync - + Debug - + 'static, + + Debug, BlockchainErrorT: Debug + Send, { } diff --git a/crates/edr_evm/src/blockchain/forked.rs b/crates/edr_evm/src/blockchain/forked.rs index 75168582d3..b94037f7c8 100644 --- a/crates/edr_evm/src/blockchain/forked.rs +++ b/crates/edr_evm/src/blockchain/forked.rs @@ -1,6 +1,5 @@ use std::{num::NonZeroU64, sync::Arc}; -use async_trait::async_trait; use edr_eth::{ block::{largest_safe_block_number, safe_block_depth, LargestSafeBlockNumberArgs}, receipt::BlockReceipt, @@ -58,7 +57,6 @@ pub struct ForkedBlockchain { remote: RemoteBlockchain>, true>, // The state at the time of forking fork_state: ForkState, - runtime: runtime::Handle, fork_block_number: u64, chain_id: u64, _network_id: U256, @@ -155,9 +153,8 @@ impl ForkedBlockchain { Ok(Self { local_storage: ReservableSparseBlockchainStorage::empty(fork_block_number), - remote: RemoteBlockchain::new(rpc_client), + remote: RemoteBlockchain::new(rpc_client, runtime), fork_state, - runtime, fork_block_number, chain_id, _network_id: network_id, @@ -165,6 +162,10 @@ impl ForkedBlockchain { hardfork_activations, }) } + + fn runtime(&self) -> &runtime::Handle { + self.remote.runtime() + } } impl BlockHashRef for ForkedBlockchain { @@ -177,7 +178,7 @@ impl BlockHashRef for ForkedBlockchain { if number <= self.fork_block_number { tokio::task::block_in_place(move || { - self.runtime.block_on(self.remote.block_by_number(number)) + self.runtime().block_on(self.remote.block_by_number(number)) }) .map_or_else( |e| Err(BlockchainError::JsonRpcError(e)), @@ -192,14 +193,14 @@ impl BlockHashRef for ForkedBlockchain { } } -#[async_trait] impl Blockchain for ForkedBlockchain { type BlockchainError = BlockchainError; type StateError = StateError; #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] - async fn block_by_hash( + #[allow(clippy::type_complexity)] + fn block_by_hash( &self, hash: &B256, ) -> Result>>, Self::BlockchainError> @@ -207,21 +208,26 @@ impl Blockchain for ForkedBlockchain { if let Some(block) = self.local_storage.block_by_hash(hash) { Ok(Some(block)) } else { - self.remote - .block_by_hash(hash) - .await - .map_err(BlockchainError::JsonRpcError) + tokio::task::block_in_place(move || { + self.runtime() + .block_on(self.remote.block_by_hash(hash)) + .map_err(BlockchainError::JsonRpcError) + }) } } #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] - async fn block_by_number( + #[allow(clippy::type_complexity)] + fn block_by_number( &self, number: u64, ) -> Result>>, Self::BlockchainError> { if number <= self.fork_block_number { - self.remote.block_by_number(number).await.map_or_else( + tokio::task::block_in_place(move || { + self.runtime().block_on(self.remote.block_by_number(number)) + }) + .map_or_else( |e| Err(BlockchainError::JsonRpcError(e)), |block| Ok(Some(block)), ) @@ -231,7 +237,8 @@ impl Blockchain for ForkedBlockchain { } #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] - async fn block_by_transaction_hash( + #[allow(clippy::type_complexity)] + fn block_by_transaction_hash( &self, transaction_hash: &B256, ) -> Result>>, Self::BlockchainError> @@ -242,41 +249,43 @@ impl Blockchain for ForkedBlockchain { { Ok(Some(block)) } else { - self.remote - .block_by_transaction_hash(transaction_hash) - .await - .map_err(BlockchainError::JsonRpcError) + tokio::task::block_in_place(move || { + self.runtime() + .block_on(self.remote.block_by_transaction_hash(transaction_hash)) + }) + .map_err(BlockchainError::JsonRpcError) } } - async fn chain_id(&self) -> u64 { + fn chain_id(&self) -> u64 { self.chain_id } #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] - async fn last_block( + fn last_block( &self, ) -> Result>, Self::BlockchainError> { - let last_block_number = self.last_block_number().await; + let last_block_number = self.last_block_number(); if self.fork_block_number < last_block_number { Ok(self .local_storage .block_by_number(last_block_number) .expect("Block must exist")) } else { - self.remote - .block_by_number(self.fork_block_number) - .await - .map_err(BlockchainError::JsonRpcError) + tokio::task::block_in_place(move || { + self.runtime() + .block_on(self.remote.block_by_number(self.fork_block_number)) + }) + .map_err(BlockchainError::JsonRpcError) } } - async fn last_block_number(&self) -> u64 { + fn last_block_number(&self) -> u64 { self.local_storage.last_block_number() } #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] - async fn receipt_by_transaction_hash( + fn receipt_by_transaction_hash( &self, transaction_hash: &B256, ) -> Result>, Self::BlockchainError> { @@ -286,24 +295,26 @@ impl Blockchain for ForkedBlockchain { { Ok(Some(receipt)) } else { - self.remote - .receipt_by_transaction_hash(transaction_hash) - .await - .map_err(BlockchainError::JsonRpcError) + tokio::task::block_in_place(move || { + self.runtime() + .block_on(self.remote.receipt_by_transaction_hash(transaction_hash)) + }) + .map_err(BlockchainError::JsonRpcError) } } #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] - async fn spec_at_block_number( - &self, - block_number: u64, - ) -> Result { - if block_number > self.last_block_number().await { + fn spec_at_block_number(&self, block_number: u64) -> Result { + if block_number > self.last_block_number() { return Err(BlockchainError::UnknownBlockNumber); } if block_number <= self.fork_block_number { - self.remote.block_by_number(block_number).await.map_or_else( + tokio::task::block_in_place(move || { + self.runtime() + .block_on(self.remote.block_by_number(block_number)) + }) + .map_or_else( |e| Err(BlockchainError::JsonRpcError(e)), |block| { if let Some(hardfork_activations) = &self.hardfork_activations { @@ -331,25 +342,27 @@ impl Blockchain for ForkedBlockchain { } #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] - async fn state_at_block_number( + fn state_at_block_number( &self, block_number: u64, ) -> Result>, Self::BlockchainError> { - if block_number > self.last_block_number().await { + if block_number > self.last_block_number() { return Err(BlockchainError::UnknownBlockNumber); } let state = match block_number.cmp(&self.fork_block_number) { std::cmp::Ordering::Less => { // We don't apply account overrides to pre-fork states - ForkState::new( - self.runtime.clone(), - self.remote.client().clone(), - self.fork_state.state_root_generator().clone(), - block_number, - HashMap::new(), - ) - .await? + + tokio::task::block_in_place(move || { + self.runtime().block_on(ForkState::new( + self.runtime().clone(), + self.remote.client().clone(), + self.fork_state.state_root_generator().clone(), + block_number, + HashMap::new(), + )) + })? } std::cmp::Ordering::Equal => self.fork_state.clone(), std::cmp::Ordering::Greater => { @@ -363,38 +376,34 @@ impl Blockchain for ForkedBlockchain { } #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] - async fn total_difficulty_by_hash( - &self, - hash: &B256, - ) -> Result, Self::BlockchainError> { + fn total_difficulty_by_hash(&self, hash: &B256) -> Result, Self::BlockchainError> { if let Some(difficulty) = self.local_storage.total_difficulty_by_hash(hash) { Ok(Some(difficulty)) } else { - self.remote - .total_difficulty_by_hash(hash) - .await - .map_err(BlockchainError::JsonRpcError) + tokio::task::block_in_place(move || { + self.runtime() + .block_on(self.remote.total_difficulty_by_hash(hash)) + }) + .map_err(BlockchainError::JsonRpcError) } } } -#[async_trait] impl BlockchainMut for ForkedBlockchain { type Error = BlockchainError; #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] - async fn insert_block( + fn insert_block( &mut self, block: LocalBlock, state_diff: StateDiff, ) -> Result>, Self::Error> { - let last_block = self.last_block().await?; + let last_block = self.last_block()?; validate_next_block(self.spec_id, &last_block, &block)?; let previous_total_difficulty = self .total_difficulty_by_hash(last_block.hash()) - .await .expect("No error can occur as it is stored locally") .expect("Must exist as its block is stored"); @@ -411,17 +420,16 @@ impl BlockchainMut for ForkedBlockchain { } #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] - async fn reserve_blocks(&mut self, additional: u64, interval: u64) -> Result<(), Self::Error> { + fn reserve_blocks(&mut self, additional: u64, interval: u64) -> Result<(), Self::Error> { let additional = if let Some(additional) = NonZeroU64::new(additional) { additional } else { return Ok(()); // nothing to do }; - let last_block = self.last_block().await?; + let last_block = self.last_block()?; let previous_total_difficulty = self - .total_difficulty_by_hash(last_block.hash()) - .await? + .total_difficulty_by_hash(last_block.hash())? .expect("Must exist as its block is stored"); let last_header = last_block.header(); @@ -438,7 +446,7 @@ impl BlockchainMut for ForkedBlockchain { } #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] - async fn revert_to_block(&mut self, block_number: u64) -> Result<(), Self::Error> { + fn revert_to_block(&mut self, block_number: u64) -> Result<(), Self::Error> { match block_number.cmp(&self.fork_block_number) { std::cmp::Ordering::Less => Err(BlockchainError::CannotDeleteRemote), std::cmp::Ordering::Equal => { diff --git a/crates/edr_evm/src/blockchain/local.rs b/crates/edr_evm/src/blockchain/local.rs index f042196ec4..527269d019 100644 --- a/crates/edr_evm/src/blockchain/local.rs +++ b/crates/edr_evm/src/blockchain/local.rs @@ -5,7 +5,6 @@ use std::{ time::{SystemTime, UNIX_EPOCH}, }; -use async_trait::async_trait; use edr_eth::{block::PartialHeader, trie::KECCAK_NULL_RLP, Bytes, B256, B64, U256}; use revm::{db::BlockHashRef, primitives::SpecId}; @@ -170,14 +169,14 @@ impl LocalBlockchain { } } -#[async_trait] impl Blockchain for LocalBlockchain { type BlockchainError = BlockchainError; type StateError = StateError; #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] - async fn block_by_hash( + #[allow(clippy::type_complexity)] + fn block_by_hash( &self, hash: &B256, ) -> Result>>, Self::BlockchainError> @@ -186,7 +185,8 @@ impl Blockchain for LocalBlockchain { } #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] - async fn block_by_number( + #[allow(clippy::type_complexity)] + fn block_by_number( &self, number: u64, ) -> Result>>, Self::BlockchainError> @@ -195,7 +195,8 @@ impl Blockchain for LocalBlockchain { } #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] - async fn block_by_transaction_hash( + #[allow(clippy::type_complexity)] + fn block_by_transaction_hash( &self, transaction_hash: &B256, ) -> Result>>, Self::BlockchainError> @@ -203,12 +204,12 @@ impl Blockchain for LocalBlockchain { Ok(self.storage.block_by_transaction_hash(transaction_hash)) } - async fn chain_id(&self) -> u64 { + fn chain_id(&self) -> u64 { self.chain_id } #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] - async fn last_block( + fn last_block( &self, ) -> Result>, Self::BlockchainError> { Ok(self @@ -217,12 +218,12 @@ impl Blockchain for LocalBlockchain { .expect("Block must exist")) } - async fn last_block_number(&self) -> u64 { + fn last_block_number(&self) -> u64 { self.storage.last_block_number() } #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] - async fn receipt_by_transaction_hash( + fn receipt_by_transaction_hash( &self, transaction_hash: &B256, ) -> Result>, Self::BlockchainError> { @@ -230,11 +231,8 @@ impl Blockchain for LocalBlockchain { } #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] - async fn spec_at_block_number( - &self, - block_number: u64, - ) -> Result { - if block_number > self.last_block_number().await { + fn spec_at_block_number(&self, block_number: u64) -> Result { + if block_number > self.last_block_number() { return Err(BlockchainError::UnknownBlockNumber); } @@ -246,11 +244,11 @@ impl Blockchain for LocalBlockchain { } #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] - async fn state_at_block_number( + fn state_at_block_number( &self, block_number: u64, ) -> Result>, Self::BlockchainError> { - if block_number > self.last_block_number().await { + if block_number > self.last_block_number() { return Err(BlockchainError::UnknownBlockNumber); } @@ -263,31 +261,26 @@ impl Blockchain for LocalBlockchain { } #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] - async fn total_difficulty_by_hash( - &self, - hash: &B256, - ) -> Result, Self::BlockchainError> { + fn total_difficulty_by_hash(&self, hash: &B256) -> Result, Self::BlockchainError> { Ok(self.storage.total_difficulty_by_hash(hash)) } } -#[async_trait] impl BlockchainMut for LocalBlockchain { type Error = BlockchainError; #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] - async fn insert_block( + fn insert_block( &mut self, block: LocalBlock, state_diff: StateDiff, ) -> Result>, Self::Error> { - let last_block = self.last_block().await?; + let last_block = self.last_block()?; validate_next_block(self.spec_id, &last_block, &block)?; let previous_total_difficulty = self .total_difficulty_by_hash(last_block.hash()) - .await .expect("No error can occur as it is stored locally") .expect("Must exist as its block is stored"); @@ -304,17 +297,16 @@ impl BlockchainMut for LocalBlockchain { } #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] - async fn reserve_blocks(&mut self, additional: u64, interval: u64) -> Result<(), Self::Error> { + fn reserve_blocks(&mut self, additional: u64, interval: u64) -> Result<(), Self::Error> { let additional = if let Some(additional) = NonZeroU64::new(additional) { additional } else { return Ok(()); // nothing to do }; - let last_block = self.last_block().await?; + let last_block = self.last_block()?; let previous_total_difficulty = self - .total_difficulty_by_hash(last_block.hash()) - .await? + .total_difficulty_by_hash(last_block.hash())? .expect("Must exist as its block is stored"); let last_header = last_block.header(); @@ -332,7 +324,7 @@ impl BlockchainMut for LocalBlockchain { } #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] - async fn revert_to_block(&mut self, block_number: u64) -> Result<(), Self::Error> { + fn revert_to_block(&mut self, block_number: u64) -> Result<(), Self::Error> { if self.storage.revert_to_block(block_number) { Ok(()) } else { diff --git a/crates/edr_evm/src/blockchain/remote.rs b/crates/edr_evm/src/blockchain/remote.rs index 40cec82e36..821c050337 100644 --- a/crates/edr_evm/src/blockchain/remote.rs +++ b/crates/edr_evm/src/blockchain/remote.rs @@ -6,6 +6,7 @@ use edr_eth::{ remote::{self, BlockSpec, RpcClient, RpcClientError}, B256, U256, }; +use tokio::runtime; use super::storage::SparseBlockchainStorage; use crate::{Block, RemoteBlock}; @@ -14,16 +15,18 @@ use crate::{Block, RemoteBlock}; pub struct RemoteBlockchain { client: Arc, cache: RwLock>, + runtime: runtime::Handle, } impl, const FORCE_CACHING: bool> RemoteBlockchain { /// Constructs a new instance with the provided RPC client. - pub fn new(client: Arc) -> Self { + pub fn new(client: Arc, runtime: runtime::Handle) -> Self { Self { client, cache: RwLock::new(SparseBlockchainStorage::default()), + runtime, } } @@ -129,6 +132,11 @@ impl, const FORCE_CACHING: bool> } } + /// Retrieves the blockchain's runtime. + pub fn runtime(&self) -> &runtime::Handle { + &self.runtime + } + /// Retrieves the total difficulty at the block with the provided hash. #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] pub async fn total_difficulty_by_hash( @@ -167,7 +175,7 @@ impl, const FORCE_CACHING: bool> .total_difficulty .expect("Must be present as this is not a pending block"); - let block = RemoteBlock::new(block, self.client.clone()) + let block = RemoteBlock::new(block, self.client.clone(), self.runtime.clone()) .expect("Conversion must succeed, as we're not retrieving a pending block"); let is_cacheable = FORCE_CACHING @@ -206,7 +214,10 @@ mod tests { // Latest block number is always unsafe to cache let block_number = rpc_client.block_number().await.unwrap(); - let remote = RemoteBlockchain::::new(Arc::new(rpc_client)); + let remote = RemoteBlockchain::::new( + Arc::new(rpc_client), + runtime::Handle::current(), + ); let _ = remote.block_by_number(block_number).await.unwrap(); assert!(remote diff --git a/crates/edr_evm/src/miner.rs b/crates/edr_evm/src/miner.rs index 2650cb3483..ef162c6e92 100644 --- a/crates/edr_evm/src/miner.rs +++ b/crates/edr_evm/src/miner.rs @@ -75,7 +75,7 @@ pub enum MineBlockError { /// Mines a block using as many transactions as can fit in it. #[allow(clippy::too_many_arguments)] #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] -pub async fn mine_block( +pub fn mine_block( blockchain: &dyn SyncBlockchain, mut state: Box>, mem_pool: &MemPool, @@ -95,7 +95,6 @@ where { let parent_block = blockchain .last_block() - .await .map_err(MineBlockError::Blockchain)?; let parent_header = parent_block.header(); diff --git a/crates/edr_evm/src/runtime.rs b/crates/edr_evm/src/runtime.rs index ea082ead04..d001827842 100644 --- a/crates/edr_evm/src/runtime.rs +++ b/crates/edr_evm/src/runtime.rs @@ -20,7 +20,7 @@ pub type SyncDatabase<'blockchain, 'state, BlockchainErrorT, StateErrorT> = Data /// Runs a transaction without committing the state. #[cfg_attr(feature = "tracing", tracing::instrument)] -pub async fn dry_run( +pub fn dry_run( blockchain: &dyn SyncBlockchain, state: &dyn SyncState, state_overrides: &StateOverrides, @@ -43,7 +43,7 @@ where .expect("Block numbers cannot be larger than u64::MAX"); if transaction.gas_priority_fee.is_some() - && blockchain.spec_at_block_number(block_number).await? < SpecId::LONDON + && blockchain.spec_at_block_number(block_number)? < SpecId::LONDON { return Err(TransactionError::Eip1559Unsupported); } @@ -58,7 +58,7 @@ where /// Runs a transaction without committing the state, while disabling balance /// checks and creating accounts for new addresses. #[cfg_attr(feature = "tracing", tracing::instrument)] -pub async fn guaranteed_dry_run( +pub fn guaranteed_dry_run( blockchain: &dyn SyncBlockchain, state: &dyn SyncState, state_overrides: &StateOverrides, @@ -81,12 +81,11 @@ where block, inspector, ) - .await } /// Runs a transaction, committing the state in the process. #[cfg_attr(feature = "tracing", tracing::instrument)] -pub async fn run( +pub fn run( blockchain: &dyn SyncBlockchain, state: &mut dyn SyncState, cfg: CfgEnv, @@ -109,8 +108,7 @@ where transaction, block, inspector, - ) - .await?; + )?; state.commit(changes); diff --git a/crates/edr_evm/src/state.rs b/crates/edr_evm/src/state.rs index 0f57494903..d988468087 100644 --- a/crates/edr_evm/src/state.rs +++ b/crates/edr_evm/src/state.rs @@ -53,14 +53,7 @@ pub enum StateError { /// Trait that meets all requirements for a synchronous database pub trait SyncState: - StateRef - + DatabaseCommit - + StateDebug - + Debug - + DynClone - + Send - + Sync - + 'static + StateRef + DatabaseCommit + StateDebug + Debug + DynClone + Send + Sync where E: Debug + Send, { @@ -83,8 +76,7 @@ where + Debug + DynClone + Send - + Sync - + 'static, + + Sync, E: Debug + Send, { } diff --git a/crates/edr_evm/tests/blockchain.rs b/crates/edr_evm/tests/blockchain.rs index 68d0e399fd..8162127dc8 100644 --- a/crates/edr_evm/tests/blockchain.rs +++ b/crates/edr_evm/tests/blockchain.rs @@ -71,35 +71,31 @@ async fn create_dummy_blockchains() -> Vec, -) -> LocalBlock { - let block_number = blockchain.last_block_number().await + 1; +fn create_dummy_block(blockchain: &dyn SyncBlockchain) -> LocalBlock { + let block_number = blockchain.last_block_number() + 1; - create_dummy_block_with_number(blockchain, block_number).await + create_dummy_block_with_number(blockchain, block_number) } -async fn create_dummy_block_with_number( +fn create_dummy_block_with_number( blockchain: &dyn SyncBlockchain, number: u64, ) -> LocalBlock { let parent_hash = *blockchain .last_block() - .await .expect("Failed to retrieve last block") .hash(); create_dummy_block_with_hash(number, parent_hash) } -async fn create_dummy_block_with_difficulty( +fn create_dummy_block_with_difficulty( blockchain: &dyn SyncBlockchain, number: u64, difficulty: u64, ) -> LocalBlock { let parent_hash = *blockchain .last_block() - .await .expect("Failed to retrieve last block") .hash(); @@ -152,41 +148,35 @@ fn create_dummy_transaction() -> SignedTransaction { SignedTransaction::PostEip155Legacy(transaction.sign(&secret_key).expect("signs transaction")) } -#[tokio::test] +#[tokio::test(flavor = "multi_thread")] #[serial] -async fn test_get_last_block() { +async fn get_last_block() { let blockchains = create_dummy_blockchains().await; for mut blockchain in blockchains { - let next_block = create_dummy_block(blockchain.as_ref()).await; + let next_block = create_dummy_block(blockchain.as_ref()); let expected = blockchain .insert_block(next_block, StateDiff::default()) - .await .expect("Failed to insert block"); - assert_eq!( - blockchain.last_block().await.unwrap().hash(), - expected.hash() - ); + assert_eq!(blockchain.last_block().unwrap().hash(), expected.hash()); } } -#[tokio::test] +#[tokio::test(flavor = "multi_thread")] #[serial] -async fn test_get_block_by_hash_some() { +async fn get_block_by_hash_some() { let blockchains = create_dummy_blockchains().await; for mut blockchain in blockchains { - let next_block = create_dummy_block(blockchain.as_ref()).await; + let next_block = create_dummy_block(blockchain.as_ref()); let expected = blockchain .insert_block(next_block, StateDiff::default()) - .await .expect("Failed to insert block"); assert_eq!( blockchain .block_by_hash(expected.hash()) - .await .unwrap() .unwrap() .hash(), @@ -195,36 +185,30 @@ async fn test_get_block_by_hash_some() { } } -#[tokio::test] +#[tokio::test(flavor = "multi_thread")] #[serial] -async fn test_get_block_by_hash_none() { +async fn get_block_by_hash_none() { let blockchains = create_dummy_blockchains().await; for blockchain in blockchains { - assert!(blockchain - .block_by_hash(&B256::zero()) - .await - .unwrap() - .is_none()); + assert!(blockchain.block_by_hash(&B256::zero()).unwrap().is_none()); } } -#[tokio::test] +#[tokio::test(flavor = "multi_thread")] #[serial] -async fn test_get_block_by_number_some() { +async fn get_block_by_number_some() { let blockchains = create_dummy_blockchains().await; for mut blockchain in blockchains { - let next_block = create_dummy_block(blockchain.as_ref()).await; + let next_block = create_dummy_block(blockchain.as_ref()); let expected = blockchain .insert_block(next_block, StateDiff::default()) - .await .expect("Failed to insert block"); assert_eq!( blockchain .block_by_number(expected.header().number) - .await .unwrap() .unwrap() .hash(), @@ -235,41 +219,33 @@ async fn test_get_block_by_number_some() { #[tokio::test] #[serial] -async fn test_get_block_by_number_none() { +async fn get_block_by_number_none() { let blockchains = create_dummy_blockchains().await; for blockchain in blockchains { - let next_block_number = blockchain.last_block_number().await + 1; + let next_block_number = blockchain.last_block_number() + 1; assert!(blockchain .block_by_number(next_block_number) - .await .unwrap() .is_none()); } } -#[tokio::test] +#[tokio::test(flavor = "multi_thread")] #[serial] -async fn test_insert_block_multiple() { +async fn insert_block_multiple() { let blockchains = create_dummy_blockchains().await; for mut blockchain in blockchains { - let one = create_dummy_block(blockchain.as_ref()).await; - let one = blockchain - .insert_block(one, StateDiff::default()) - .await - .unwrap(); + let one = create_dummy_block(blockchain.as_ref()); + let one = blockchain.insert_block(one, StateDiff::default()).unwrap(); - let two = create_dummy_block(blockchain.as_ref()).await; - let two = blockchain - .insert_block(two, StateDiff::default()) - .await - .unwrap(); + let two = create_dummy_block(blockchain.as_ref()); + let two = blockchain.insert_block(two, StateDiff::default()).unwrap(); assert_eq!( blockchain .block_by_number(one.header().number) - .await .unwrap() .unwrap() .hash(), @@ -278,7 +254,6 @@ async fn test_insert_block_multiple() { assert_eq!( blockchain .block_by_number(two.header().number) - .await .unwrap() .unwrap() .hash(), @@ -287,20 +262,19 @@ async fn test_insert_block_multiple() { } } -#[tokio::test] +#[tokio::test(flavor = "multi_thread")] #[serial] -async fn test_insert_block_invalid_block_number() { +async fn insert_block_invalid_block_number() { let blockchains = create_dummy_blockchains().await; for mut blockchain in blockchains { - let next_block_number = blockchain.last_block_number().await + 1; + let next_block_number = blockchain.last_block_number() + 1; let invalid_block_number = next_block_number + 1; let invalid_block = - create_dummy_block_with_number(blockchain.as_ref(), invalid_block_number).await; + create_dummy_block_with_number(blockchain.as_ref(), invalid_block_number); let error = blockchain .insert_block(invalid_block, StateDiff::default()) - .await .expect_err("Should fail to insert block"); if let BlockchainError::InvalidBlockNumber { actual, expected } = error { @@ -312,65 +286,53 @@ async fn test_insert_block_invalid_block_number() { } } -#[tokio::test] +#[tokio::test(flavor = "multi_thread")] #[serial] -async fn test_insert_block_invalid_parent_hash() { +async fn insert_block_invalid_parent_hash() { let blockchains = create_dummy_blockchains().await; for mut blockchain in blockchains { const INVALID_BLOCK_HASH: B256 = B256::zero(); - let next_block_number = blockchain.last_block_number().await + 1; + let next_block_number = blockchain.last_block_number() + 1; let one = create_dummy_block_with_hash(next_block_number, INVALID_BLOCK_HASH); let error = blockchain .insert_block(one, StateDiff::default()) - .await .expect_err("Should fail to insert block"); if let BlockchainError::InvalidParentHash { actual, expected } = error { assert_eq!(actual, INVALID_BLOCK_HASH); - assert_eq!(expected, *blockchain.last_block().await.unwrap().hash()); + assert_eq!(expected, *blockchain.last_block().unwrap().hash()); } else { panic!("Unexpected error: {error:?}"); } } } -#[tokio::test] +#[tokio::test(flavor = "multi_thread")] #[serial] -async fn test_revert_to_block() { +async fn revert_to_block() { let blockchains = create_dummy_blockchains().await; for mut blockchain in blockchains { - let last_block = blockchain.last_block().await.unwrap(); + let last_block = blockchain.last_block().unwrap(); - let one = create_dummy_block(blockchain.as_ref()).await; - let one = blockchain - .insert_block(one, StateDiff::default()) - .await - .unwrap(); + let one = create_dummy_block(blockchain.as_ref()); + let one = blockchain.insert_block(one, StateDiff::default()).unwrap(); - let two = create_dummy_block(blockchain.as_ref()).await; - let two = blockchain - .insert_block(two, StateDiff::default()) - .await - .unwrap(); + let two = create_dummy_block(blockchain.as_ref()); + let two = blockchain.insert_block(two, StateDiff::default()).unwrap(); blockchain .revert_to_block(last_block.header().number) - .await .unwrap(); // Last block still exists - assert_eq!( - blockchain.last_block().await.unwrap().hash(), - last_block.hash() - ); + assert_eq!(blockchain.last_block().unwrap().hash(), last_block.hash()); assert_eq!( blockchain .block_by_hash(last_block.hash()) - .await .unwrap() .unwrap() .hash(), @@ -380,39 +342,28 @@ async fn test_revert_to_block() { // Blocks 1 and 2 are gone assert!(blockchain .block_by_number(one.header().number) - .await .unwrap() .is_none()); assert!(blockchain .block_by_number(two.header().number) - .await .unwrap() .is_none()); - assert!(blockchain - .block_by_hash(one.hash()) - .await - .unwrap() - .is_none()); - assert!(blockchain - .block_by_hash(two.hash()) - .await - .unwrap() - .is_none()); + assert!(blockchain.block_by_hash(one.hash()).unwrap().is_none()); + assert!(blockchain.block_by_hash(two.hash()).unwrap().is_none()); } } #[tokio::test] #[serial] -async fn test_revert_to_block_invalid_number() { +async fn revert_to_block_invalid_number() { let blockchains = create_dummy_blockchains().await; for mut blockchain in blockchains { - let next_block_number = blockchain.last_block_number().await + 1; + let next_block_number = blockchain.last_block_number() + 1; let error = blockchain .revert_to_block(next_block_number) - .await .expect_err("Should fail to insert block"); if let BlockchainError::UnknownBlockNumber = error { @@ -422,101 +373,76 @@ async fn test_revert_to_block_invalid_number() { } } -#[tokio::test] +#[tokio::test(flavor = "multi_thread")] #[serial] -async fn test_block_total_difficulty_by_hash() { +async fn block_total_difficulty_by_hash() { let blockchains: Vec>> = create_dummy_blockchains().await; for mut blockchain in blockchains { - let last_block = blockchain.last_block().await.unwrap(); + let last_block = blockchain.last_block().unwrap(); let last_block_header = last_block.header(); let one = create_dummy_block_with_difficulty( blockchain.as_ref(), last_block_header.number + 1, 1000, - ) - .await; - let one = blockchain - .insert_block(one, StateDiff::default()) - .await - .unwrap(); + ); + let one = blockchain.insert_block(one, StateDiff::default()).unwrap(); let two = create_dummy_block_with_difficulty( blockchain.as_ref(), last_block_header.number + 2, 2000, - ) - .await; - let two = blockchain - .insert_block(two, StateDiff::default()) - .await - .unwrap(); + ); + let two = blockchain.insert_block(two, StateDiff::default()).unwrap(); let last_block_difficulty = blockchain .total_difficulty_by_hash(last_block.hash()) - .await .unwrap() .expect("total difficulty must exist"); assert_eq!( - blockchain - .total_difficulty_by_hash(one.hash()) - .await - .unwrap(), + blockchain.total_difficulty_by_hash(one.hash()).unwrap(), Some(last_block_difficulty + one.header().difficulty) ); assert_eq!( - blockchain - .total_difficulty_by_hash(two.hash()) - .await - .unwrap(), + blockchain.total_difficulty_by_hash(two.hash()).unwrap(), Some(last_block_difficulty + one.header().difficulty + two.header().difficulty) ); - blockchain - .revert_to_block(one.header().number) - .await - .unwrap(); + blockchain.revert_to_block(one.header().number).unwrap(); // Block 1 has a total difficulty assert_eq!( - blockchain - .total_difficulty_by_hash(one.hash()) - .await - .unwrap(), + blockchain.total_difficulty_by_hash(one.hash()).unwrap(), Some(last_block_difficulty + one.header().difficulty) ); // Block 2 no longer stores a total difficulty assert!(blockchain .total_difficulty_by_hash(two.hash()) - .await .unwrap() .is_none()); } } -#[tokio::test] +#[tokio::test(flavor = "multi_thread")] #[serial] -async fn test_block_total_difficulty_by_hash_invalid_hash() { +async fn block_total_difficulty_by_hash_invalid_hash() { let blockchains = create_dummy_blockchains().await; for blockchain in blockchains { - let difficulty = blockchain - .total_difficulty_by_hash(&B256::zero()) - .await - .unwrap(); + let difficulty = blockchain.total_difficulty_by_hash(&B256::zero()).unwrap(); assert!(difficulty.is_none()); } } -#[tokio::test] +#[tokio::test(flavor = "multi_thread")] #[serial] -async fn test_transaction_by_hash() { +async fn transaction_by_hash() { let blockchains = create_dummy_blockchains().await; for blockchain in blockchains { @@ -524,7 +450,6 @@ async fn test_transaction_by_hash() { let block = blockchain .block_by_transaction_hash(transaction.hash()) - .await .unwrap(); assert!(block.is_none()); diff --git a/crates/edr_napi/Cargo.toml b/crates/edr_napi/Cargo.toml index bd99322887..151f3962a4 100644 --- a/crates/edr_napi/Cargo.toml +++ b/crates/edr_napi/Cargo.toml @@ -7,7 +7,6 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -async-trait = { version = "0.1.73", default-features = false } crossbeam-channel = { version = "0.5.6", default-features = false } k256 = { version = "0.13.1", default-features = false, features = ["arithmetic", "ecdsa", "pkcs8", "precomputed-tables", "std"] } # when napi is pinned, be sure to pin napi-derive to the same version diff --git a/crates/edr_napi/index.d.ts b/crates/edr_napi/index.d.ts index 1a200d8f3f..40ede26e64 100644 --- a/crates/edr_napi/index.d.ts +++ b/crates/edr_napi/index.d.ts @@ -171,9 +171,9 @@ export interface ConfigOptions { disableEip3607?: boolean } /** Get trace output for `debug_traceTransaction` */ -export function debugTraceTransaction(blockchain: Blockchain, stateManager: State, evmConfig: ConfigOptions, traceConfig: DebugTraceConfig, blockConfig: BlockConfig, transactions: Array, transactionHash: Buffer): Promise +export function debugTraceTransaction(blockchain: Blockchain, state: State, evmConfig: ConfigOptions, traceConfig: DebugTraceConfig, blockConfig: BlockConfig, transactions: Array, transactionHash: Buffer): Promise /** Get trace output for `debug_traceTransaction` */ -export function debugTraceCall(blockchain: Blockchain, stateManager: State, evmConfig: ConfigOptions, traceConfig: DebugTraceConfig, blockConfig: BlockConfig, transaction: TransactionRequest): Promise +export function debugTraceCall(blockchain: Blockchain, state: State, evmConfig: ConfigOptions, traceConfig: DebugTraceConfig, blockConfig: BlockConfig, transaction: TransactionRequest): Promise export interface DebugTraceConfig { disableStorage?: boolean disableMemory?: boolean @@ -222,7 +222,7 @@ export const enum MineOrdering { Priority = 'Priority' } /** Mines a block using as many transactions as can fit in it. */ -export function mineBlock(blockchain: Blockchain, stateManager: State, memPool: MemPool, config: ConfigOptions, timestamp: bigint, beneficiary: Buffer, minGasPrice: bigint, mineOrdering: MineOrdering, reward: bigint, baseFee?: bigint | undefined | null, prevrandao?: Buffer | undefined | null, tracer?: Tracer | undefined | null): Promise +export function mineBlock(blockchain: Blockchain, state: State, memPool: MemPool, config: ConfigOptions, timestamp: bigint, beneficiary: Buffer, minGasPrice: bigint, mineOrdering: MineOrdering, reward: bigint, baseFee?: bigint | undefined | null, prevrandao?: Buffer | undefined | null, tracer?: Tracer | undefined | null): Promise /** Configuration for forking a blockchain */ export interface ForkConfig { /** The URL of the JSON-RPC endpoint to fork from */ @@ -527,7 +527,7 @@ export interface Withdrawal { amount: bigint } export class BlockBuilder { - static create(blockchain: Blockchain, stateManager: State, config: ConfigOptions, parent: BlockHeader, block: BlockOptions): Promise + constructor(blockchain: Blockchain, stateManager: State, config: ConfigOptions, parent: BlockHeader, block: BlockOptions) /** Retrieves the amount of gas used by the builder. */ get gasUsed(): Promise addTransaction(transaction: PendingTransaction, withTrace: boolean): Promise @@ -617,7 +617,7 @@ export class Log { /**Returns the index of the transaction the log is included in. */ get transactionIndex(): bigint | null } -/** The mempool contains transactions pending inclusion in the blockchain. */ +/** The mem pool contains transactions pending inclusion in the blockchain. */ export class MemPool { /**Constructs a new [`MemPool`]. */ constructor(blockGasLimit: bigint) diff --git a/crates/edr_napi/src/block.rs b/crates/edr_napi/src/block.rs index 921a8823e0..6a78f54141 100644 --- a/crates/edr_napi/src/block.rs +++ b/crates/edr_napi/src/block.rs @@ -400,8 +400,8 @@ impl Block { #[doc = "Retrieves the transactions' receipts."] #[napi] - pub async fn receipts(&self) -> napi::Result> { - self.inner.transaction_receipts().await.map_or_else( + pub fn receipts(&self) -> napi::Result> { + self.inner.transaction_receipts().map_or_else( |error| Err(napi::Error::new(Status::InvalidArg, error.to_string())), |receipts: Vec>| { Ok(receipts.into_iter().map(Receipt::from).collect()) diff --git a/crates/edr_napi/src/block/builder.rs b/crates/edr_napi/src/block/builder.rs index 991cf1f674..44a0288d48 100644 --- a/crates/edr_napi/src/block/builder.rs +++ b/crates/edr_napi/src/block/builder.rs @@ -8,11 +8,12 @@ use edr_evm::{ BlockTransactionError, CfgEnv, InvalidTransaction, SyncBlock, SyncInspector, }; use napi::{ - bindgen_prelude::{BigInt, Buffer, Env}, - tokio::{runtime, sync::RwLock}, - JsObject, Status, + bindgen_prelude::{BigInt, Buffer}, + tokio::runtime, + Status, }; use napi_derive::napi; +use parking_lot::RwLock; use super::{Block, BlockHeader, BlockOptions}; use crate::{ @@ -32,18 +33,15 @@ pub struct BlockBuilder { #[napi] impl BlockBuilder { - // TODO: There seems to be a limitation in napi-rs that prevents us from - // creating a #[napi(factory)] with an async fn - #[napi(ts_return_type = "Promise")] + #[napi(constructor)] #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] - pub fn create( - env: Env, + pub fn new( blockchain: &Blockchain, state_manager: &State, config: ConfigOptions, parent: BlockHeader, block: BlockOptions, - ) -> napi::Result { + ) -> napi::Result { let parent = Header::try_from(parent)?; let block = edr_eth::block::BlockOptions::try_from(block)?; @@ -51,64 +49,59 @@ impl BlockBuilder { let blockchain = (*blockchain).clone(); let state = (*state_manager).clone(); - let (deferred, promise) = env.create_deferred()?; - runtime::Handle::current().spawn(async move { - let result = edr_evm::BlockBuilder::new(config, &parent, block).map_or_else( - |e| Err(napi::Error::new(Status::GenericFailure, e.to_string())), - |builder| { - Ok(Self { - builder: Arc::new(RwLock::new(Some(builder))), - blockchain, - state, - }) - }, - ); - - deferred.resolve(|_| result); - }); - - Ok(promise) + edr_evm::BlockBuilder::new(config, &parent, block).map_or_else( + |e| Err(napi::Error::new(Status::GenericFailure, e.to_string())), + |builder| { + Ok(Self { + builder: Arc::new(RwLock::new(Some(builder))), + blockchain, + state, + }) + }, + ) } /// Retrieves the amount of gas used by the builder. #[napi(getter)] pub async fn gas_used(&self) -> napi::Result { - let builder = self.builder.read().await; - if let Some(builder) = builder.as_ref() { - Ok(BigInt::from(builder.gas_used())) - } else { - Err(napi::Error::new( - Status::InvalidArg, - "`this` has been moved in Rust".to_owned(), - )) - } + let builder = self.builder.clone(); + runtime::Handle::current() + .spawn_blocking(move || { + let builder = builder.read(); + if let Some(builder) = builder.as_ref() { + Ok(BigInt::from(builder.gas_used())) + } else { + Err(napi::Error::new( + Status::InvalidArg, + "`this` has been moved in Rust".to_owned(), + )) + } + }) + .await + .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))? } #[napi] - #[napi(ts_return_type = "Promise")] #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] - pub fn add_transaction( + pub async fn add_transaction( &self, - env: Env, transaction: &PendingTransaction, with_trace: bool, - ) -> napi::Result { - let builder = self.builder.clone(); - let transaction = (*transaction).clone(); - + ) -> napi::Result { let blockchain = self.blockchain.clone(); + let builder = self.builder.clone(); let state = self.state.clone(); + let transaction = (*transaction).clone(); - let (deferred, promise) = env.create_deferred()?; - runtime::Handle::current().spawn(async move { - let mut builder = builder.write().await; - let result = if let Some(builder) = builder.as_mut() { + runtime::Handle::current().spawn_blocking(move || { + let mut builder = builder.write(); + if let Some(builder) = builder.as_mut() { let mut tracer = TraceCollector::default(); let inspector: Option<&mut dyn SyncInspector> = if with_trace { Some(&mut tracer) } else { None }; builder - .add_transaction(&*blockchain.read().await, &mut *state.write().await, transaction, inspector) + .add_transaction(&*blockchain.read(), &mut *state.write(), transaction, inspector) .map_or_else( |e| Err(napi::Error::new(Status::GenericFailure, match e { BlockTransactionError::InvalidTransaction( @@ -131,12 +124,9 @@ impl BlockBuilder { Status::InvalidArg, "`this` has been moved in Rust".to_owned(), )) - }; - - deferred.resolve(|_| result); - }); - - Ok(promise) + } + }) + .await.map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))? } /// This call consumes the [`BlockBuilder`] object in Rust. Afterwards, you @@ -148,35 +138,43 @@ impl BlockBuilder { rewards: Vec<(Buffer, BigInt)>, timestamp: Option, ) -> napi::Result { - let mut builder = self.builder.write().await; - if let Some(builder) = builder.take() { - let rewards = rewards - .into_iter() - .map(|(address, reward)| { - TryCast::::try_cast(reward) - .map(|reward| (Address::from_slice(&address), reward)) - }) - .collect::>>()?; - - let timestamp: Option = timestamp.map_or(Ok(None), |timestamp| { - BigInt::try_cast(timestamp).map(Option::Some) - })?; + let builder = self.builder.clone(); + let state = self.state.clone(); - builder - .finalize(&mut *self.state.write().await, rewards, timestamp) - .map_or_else( - |e| Err(napi::Error::new(Status::GenericFailure, e.to_string())), - |result| { - let block: Arc> = - Arc::new(result.block); - Ok(Block::from(block)) - }, - ) - } else { - Err(napi::Error::new( - Status::InvalidArg, - "The BlockBuilder object has been moved in Rust".to_owned(), - )) - } + runtime::Handle::current() + .spawn_blocking(move || { + let mut builder = builder.write(); + if let Some(builder) = builder.take() { + let rewards = rewards + .into_iter() + .map(|(address, reward)| { + TryCast::::try_cast(reward) + .map(|reward| (Address::from_slice(&address), reward)) + }) + .collect::>>()?; + + let timestamp: Option = timestamp.map_or(Ok(None), |timestamp| { + BigInt::try_cast(timestamp).map(Option::Some) + })?; + + builder + .finalize(&mut *state.write(), rewards, timestamp) + .map_or_else( + |e| Err(napi::Error::new(Status::GenericFailure, e.to_string())), + |result| { + let block: Arc> = + Arc::new(result.block); + Ok(Block::from(block)) + }, + ) + } else { + Err(napi::Error::new( + Status::InvalidArg, + "The BlockBuilder object has been moved in Rust".to_owned(), + )) + } + }) + .await + .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))? } } diff --git a/crates/edr_napi/src/blockchain.rs b/crates/edr_napi/src/blockchain.rs index 96be70ab68..9f2dfdbb94 100644 --- a/crates/edr_napi/src/blockchain.rs +++ b/crates/edr_napi/src/blockchain.rs @@ -8,10 +8,11 @@ use edr_evm::{ }; use napi::{ bindgen_prelude::{BigInt, Buffer, ObjectFinalize}, - tokio::{runtime, sync::RwLock}, + tokio::runtime, Env, JsObject, Status, }; use napi_derive::napi; +use parking_lot::RwLock; use crate::{ account::{genesis_accounts, GenesisAccount}, @@ -37,7 +38,7 @@ pub struct Blockchain { impl Blockchain { fn with_blockchain(env: &mut Env, blockchain: BlockchainT) -> napi::Result where - BlockchainT: SyncBlockchain, + BlockchainT: SyncBlockchain + 'static, { // Signal that memory was externally allocated env.adjust_external_memory(BLOCKCHAIN_MEMORY_SIZE)?; @@ -129,19 +130,20 @@ impl Blockchain { let runtime = runtime::Handle::current(); let (deferred, promise) = env.create_deferred()?; - runtime.clone().spawn(async move { + runtime.clone().spawn_blocking(move || { let rpc_client = RpcClient::new(&remote_url, cache_dir); - let result = edr_evm::blockchain::ForkedBlockchain::new( - runtime, - spec_id, - rpc_client, - fork_block_number, - state_root_generator, - accounts, - hardfork_activation_overrides, - ) - .await - .map_err(|e| napi::Error::new(Status::GenericFailure, e.to_string())); + let result = runtime + .clone() + .block_on(edr_evm::blockchain::ForkedBlockchain::new( + runtime, + spec_id, + rpc_client, + fork_block_number, + state_root_generator, + accounts, + hardfork_activation_overrides, + )) + .map_err(|e| napi::Error::new(Status::GenericFailure, e.to_string())); deferred.resolve(|mut env| { result.map(|blockchain| Self::with_blockchain(&mut env, blockchain)) @@ -157,10 +159,15 @@ impl Blockchain { pub async fn block_by_hash(&self, hash: Buffer) -> napi::Result> { let hash = TryCast::::try_cast(hash)?; - self.read().await.block_by_hash(&hash).await.map_or_else( - |e| Err(napi::Error::new(Status::GenericFailure, e.to_string())), - |block| Ok(block.map(Block::from)), - ) + let blockchain = self.inner.clone(); + runtime::Handle::current() + .spawn_blocking(move || blockchain.read().block_by_hash(&hash)) + .await + .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))? + .map_or_else( + |e| Err(napi::Error::new(Status::GenericFailure, e.to_string())), + |block| Ok(block.map(Block::from)), + ) } #[doc = "Retrieves the block with the provided number, if it exists."] @@ -169,10 +176,15 @@ impl Blockchain { pub async fn block_by_number(&self, number: BigInt) -> napi::Result> { let number: u64 = BigInt::try_cast(number)?; - self.read().await.block_by_number(number).await.map_or_else( - |e| Err(napi::Error::new(Status::GenericFailure, e.to_string())), - |block| Ok(block.map(Block::from)), - ) + let blockchain = self.inner.clone(); + runtime::Handle::current() + .spawn_blocking(move || blockchain.read().block_by_number(number)) + .await + .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))? + .map_or_else( + |e| Err(napi::Error::new(Status::GenericFailure, e.to_string())), + |block| Ok(block.map(Block::from)), + ) } #[doc = "Retrieves the block that contains a transaction with the provided hash, if it exists."] @@ -184,10 +196,15 @@ impl Blockchain { ) -> napi::Result> { let transaction_hash = TryCast::::try_cast(transaction_hash)?; - self.read() - .await - .block_by_transaction_hash(&transaction_hash) + let blockchain = self.inner.clone(); + runtime::Handle::current() + .spawn_blocking(move || { + blockchain + .read() + .block_by_transaction_hash(&transaction_hash) + }) .await + .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))? .map_or_else( |e| Err(napi::Error::new(Status::GenericFailure, e.to_string())), |block| Ok(block.map(Block::from)), @@ -197,10 +214,14 @@ impl Blockchain { #[doc = "Retrieves the instance's chain ID."] #[napi] #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] - pub async fn chain_id(&self) -> BigInt { - let chain_id = self.read().await.chain_id().await; + pub async fn chain_id(&self) -> napi::Result { + let blockchain = self.inner.clone(); + let chain_id = runtime::Handle::current() + .spawn_blocking(move || blockchain.read().chain_id()) + .await + .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))?; - BigInt::from(chain_id) + Ok(BigInt::from(chain_id)) } // #[napi] @@ -221,19 +242,29 @@ impl Blockchain { #[napi] #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] pub async fn last_block(&self) -> napi::Result { - self.read().await.last_block().await.map_or_else( - |e| Err(napi::Error::new(Status::GenericFailure, e.to_string())), - |block| Ok(Block::from(block)), - ) + let blockchain = self.inner.clone(); + runtime::Handle::current() + .spawn_blocking(move || blockchain.read().last_block()) + .await + .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))? + .map_or_else( + |e| Err(napi::Error::new(Status::GenericFailure, e.to_string())), + |block| Ok(Block::from(block)), + ) } #[doc = "Retrieves the number of the last block in the blockchain."] #[napi] #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] - pub async fn last_block_number(&self) -> BigInt { - let block_number = self.read().await.last_block_number().await; - - BigInt::from(block_number) + pub async fn last_block_number(&self) -> napi::Result { + let blockchain = self.inner.clone(); + runtime::Handle::current() + .spawn_blocking(move || blockchain.read().last_block_number()) + .await + .map_or_else( + |e| Err(napi::Error::new(Status::GenericFailure, e.to_string())), + |block_number| Ok(BigInt::from(block_number)), + ) } #[doc = "Retrieves the receipt of the transaction with the provided hash, if it exists."] @@ -245,10 +276,15 @@ impl Blockchain { ) -> napi::Result> { let transaction_hash = TryCast::::try_cast(transaction_hash)?; - self.read() - .await - .receipt_by_transaction_hash(&transaction_hash) + let blockchain = self.inner.clone(); + runtime::Handle::current() + .spawn_blocking(move || { + blockchain + .read() + .receipt_by_transaction_hash(&transaction_hash) + }) .await + .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))? .map_or_else( |e| Err(napi::Error::new(Status::GenericFailure, e.to_string())), |receipt| Ok(receipt.map(Into::into)), @@ -262,10 +298,11 @@ impl Blockchain { let additional: u64 = BigInt::try_cast(additional)?; let interval: u64 = BigInt::try_cast(interval)?; - self.write() - .await - .reserve_blocks(additional, interval) + let blockchain = self.inner.clone(); + runtime::Handle::current() + .spawn_blocking(move || blockchain.write().reserve_blocks(additional, interval)) .await + .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))? .map_err(|e| napi::Error::new(Status::GenericFailure, e.to_string())) } @@ -275,10 +312,11 @@ impl Blockchain { pub async fn revert_to_block(&self, block_number: BigInt) -> napi::Result<()> { let block_number: u64 = BigInt::try_cast(block_number)?; - self.write() - .await - .revert_to_block(block_number) + let blockchain = self.inner.clone(); + runtime::Handle::current() + .spawn_blocking(move || blockchain.write().revert_to_block(block_number)) .await + .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))? .map_err(|e| napi::Error::new(Status::GenericFailure, e.to_string())) } @@ -288,10 +326,11 @@ impl Blockchain { pub async fn spec_at_block_number(&self, block_number: BigInt) -> napi::Result { let block_number: u64 = BigInt::try_cast(block_number)?; - self.read() - .await - .spec_at_block_number(block_number) + let blockchain = self.inner.clone(); + runtime::Handle::current() + .spawn_blocking(move || blockchain.read().spec_at_block_number(block_number)) .await + .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))? .map_or_else( |error| Err(napi::Error::new(Status::GenericFailure, error.to_string())), |spec_id| Ok(SpecId::from(spec_id)), @@ -301,8 +340,15 @@ impl Blockchain { #[doc = "Retrieves the hardfork specification used for new blocks."] #[napi] #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] - pub async fn spec_id(&self) -> SpecId { - SpecId::from(self.read().await.spec_id()) + pub async fn spec_id(&self) -> napi::Result { + let blockchain = self.inner.clone(); + runtime::Handle::current() + .spawn_blocking(move || blockchain.read().spec_id()) + .await + .map_or_else( + |error| Err(napi::Error::new(Status::GenericFailure, error.to_string())), + |spec_id| Ok(spec_id.into()), + ) } #[doc = "Retrieves the state at the block with the provided number."] @@ -311,10 +357,11 @@ impl Blockchain { pub async fn state_at_block_number(&self, block_number: BigInt) -> napi::Result { let block_number: u64 = BigInt::try_cast(block_number)?; - self.read() - .await - .state_at_block_number(block_number) + let blockchain = self.inner.clone(); + runtime::Handle::current() + .spawn_blocking(move || blockchain.read().state_at_block_number(block_number)) .await + .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))? .map_or_else( |e| Err(napi::Error::new(Status::GenericFailure, e.to_string())), |state| Ok(State::from(state)), @@ -327,10 +374,11 @@ impl Blockchain { pub async fn total_difficulty_by_hash(&self, hash: Buffer) -> napi::Result> { let hash = TryCast::::try_cast(hash)?; - self.read() - .await - .total_difficulty_by_hash(&hash) + let blockchain = self.inner.clone(); + runtime::Handle::current() + .spawn_blocking(move || blockchain.read().total_difficulty_by_hash(&hash)) .await + .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))? .map_or_else( |e| Err(napi::Error::new(Status::GenericFailure, e.to_string())), |value| { diff --git a/crates/edr_napi/src/debug_trace.rs b/crates/edr_napi/src/debug_trace.rs index 459ea7ae20..8fb14212bc 100644 --- a/crates/edr_napi/src/debug_trace.rs +++ b/crates/edr_napi/src/debug_trace.rs @@ -6,6 +6,7 @@ use edr_evm::{ }; use napi::{ bindgen_prelude::{BigInt, Buffer}, + tokio::runtime, Status, }; use napi_derive::napi; @@ -24,7 +25,7 @@ use crate::{ #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] pub async fn debug_trace_transaction( blockchain: &Blockchain, - state_manager: &State, + state: &State, evm_config: ConfigOptions, trace_config: DebugTraceConfig, block_config: BlockConfig, @@ -39,20 +40,27 @@ pub async fn debug_trace_transaction( let transactions: Vec = transactions.into_iter().map(|tx| (*tx).clone()).collect(); - let state = { state_manager.read().await.clone() }; - - let result = edr_evm::debug_trace_transaction( - &*blockchain.read().await, - state, - evm_config, - trace_config.into(), - block_env, - transactions, - &transaction_hash, - ) - .map_err(|e| napi::Error::new(Status::GenericFailure, e.to_string()))? - .try_into()?; - Ok(result) + let blockchain = (*blockchain).clone(); + let state = (*state).clone(); + + runtime::Handle::current() + .spawn_blocking(move || { + edr_evm::debug_trace_transaction( + &*blockchain.read(), + state.read().clone(), + evm_config, + trace_config.into(), + block_env, + transactions, + &transaction_hash, + ) + .map_or_else( + |error| Err(napi::Error::new(Status::GenericFailure, error.to_string())), + TryInto::try_into, + ) + }) + .await + .map_err(|e| napi::Error::new(Status::GenericFailure, e.to_string()))? } /// Get trace output for `debug_traceTransaction` @@ -60,7 +68,7 @@ pub async fn debug_trace_transaction( #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] pub async fn debug_trace_call( blockchain: &Blockchain, - state_manager: &State, + state: &State, evm_config: ConfigOptions, trace_config: DebugTraceConfig, block_config: BlockConfig, @@ -72,22 +80,29 @@ pub async fn debug_trace_call( let mut tracer = TracerEip3155::new(trace_config.into()); - let ResultAndState { - result: execution_result, - .. - } = edr_evm::guaranteed_dry_run( - &*blockchain.read().await, - &*state_manager.read().await, - &edr_evm::state::StateOverrides::default(), - evm_config, - transaction, - block, - Some(&mut tracer), - ) - .await - .map_err(|e| napi::Error::new(Status::GenericFailure, e.to_string()))?; - - execution_result_to_debug_result(execution_result, tracer).try_into() + let blockchain = (*blockchain).clone(); + let state = (*state).clone(); + + runtime::Handle::current() + .spawn_blocking(move || { + let ResultAndState { + result: execution_result, + .. + } = edr_evm::guaranteed_dry_run( + &*blockchain.read(), + &*state.read(), + &edr_evm::state::StateOverrides::default(), + evm_config, + transaction, + block, + Some(&mut tracer), + ) + .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))?; + + execution_result_to_debug_result(execution_result, tracer).try_into() + }) + .await + .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))? } #[napi(object)] diff --git a/crates/edr_napi/src/mempool.rs b/crates/edr_napi/src/mempool.rs index 4867e5bfca..ddabb873b5 100644 --- a/crates/edr_napi/src/mempool.rs +++ b/crates/edr_napi/src/mempool.rs @@ -3,10 +3,11 @@ use std::{ops::Deref, sync::Arc}; use edr_eth::{Address, B256}; use napi::{ bindgen_prelude::{BigInt, Buffer}, - tokio::sync::RwLock, + tokio::runtime, Status, }; use napi_derive::napi; +use parking_lot::RwLock; use crate::{ cast::TryCast, @@ -14,7 +15,7 @@ use crate::{ transaction::{OrderedTransaction, PendingTransaction}, }; -/// The mempool contains transactions pending inclusion in the blockchain. +/// The mem pool contains transactions pending inclusion in the blockchain. #[napi] pub struct MemPool { inner: Arc>, @@ -43,20 +44,28 @@ impl MemPool { #[doc = "Creates a deep clone of the [`MemPool`]."] #[napi] #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] - pub async fn deep_clone(&self) -> Self { - let mem_pool = self.read().await; - - Self { - inner: Arc::new(RwLock::new(mem_pool.clone())), - } + pub async fn deep_clone(&self) -> napi::Result { + let mem_pool = self.inner.clone(); + runtime::Handle::current() + .spawn_blocking(move || { + let mem_pool = mem_pool.read(); + + Self { + inner: Arc::new(RwLock::new(mem_pool.clone())), + } + }) + .await + .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string())) } #[doc = "Retrieves the instance's block gas limit."] #[napi] - pub async fn block_gas_limit(&self) -> BigInt { - let mem_pool = self.read().await; - - BigInt::from(mem_pool.block_gas_limit()) + pub async fn block_gas_limit(&self) -> napi::Result { + let mem_pool = self.inner.clone(); + runtime::Handle::current() + .spawn_blocking(move || BigInt::from(mem_pool.read().block_gas_limit())) + .await + .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string())) } #[doc = "Sets the instance's block gas limit."] @@ -68,24 +77,30 @@ impl MemPool { ) -> napi::Result<()> { let block_gas_limit: u64 = block_gas_limit.try_cast()?; - let state = state.read().await; - self.write() + let state = (*state).clone(); + let mem_pool = self.inner.clone(); + runtime::Handle::current() + .spawn_blocking(move || { + let state = state.read(); + mem_pool + .write() + .set_block_gas_limit(&*state, block_gas_limit) + .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string())) + }) .await - .set_block_gas_limit(&*state, block_gas_limit) - .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))?; - - Ok(()) + .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))? } #[doc = "Retrieves the last pending nonce of the account corresponding to the specified address, if it exists."] #[napi] - pub async fn last_pending_nonce(&self, address: Buffer) -> Option { + pub async fn last_pending_nonce(&self, address: Buffer) -> napi::Result> { let address = Address::from_slice(&address); - self.read() + let mem_pool = self.inner.clone(); + runtime::Handle::current() + .spawn_blocking(move || mem_pool.read().last_pending_nonce(&address).map(From::from)) .await - .last_pending_nonce(&address) - .map(From::from) + .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string())) } #[doc = "Tries to add the provided transaction to the instance."] @@ -95,12 +110,21 @@ impl MemPool { state: &State, transaction: &PendingTransaction, ) -> napi::Result<()> { - let state = state.read().await; - - self.write() + let mem_pool = self.inner.clone(); + let state = (*state).clone(); + let transaction = (*transaction).clone(); + + runtime::Handle::current() + .spawn_blocking(move || { + let state = state.read(); + + mem_pool + .write() + .add_transaction(&*state, transaction) + .map_err(|e| napi::Error::new(Status::GenericFailure, e.to_string())) + }) .await - .add_transaction(&*state, (*transaction).clone()) - .map_err(|e| napi::Error::new(Status::GenericFailure, e.to_string())) + .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))? } #[doc = "Removes the transaction corresponding to the provided hash, if it exists."] @@ -108,42 +132,69 @@ impl MemPool { pub async fn remove_transaction(&self, hash: Buffer) -> napi::Result { let hash = TryCast::::try_cast(hash)?; - Ok(self.write().await.remove_transaction(&hash).is_some()) + let mem_pool = self.inner.clone(); + runtime::Handle::current() + .spawn_blocking(move || mem_pool.write().remove_transaction(&hash).is_some()) + .await + .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string())) } #[doc = "Updates the instance, moving any future transactions to the pending status, if their nonces are high enough."] #[napi] pub async fn update(&self, state: &State) -> napi::Result<()> { - let state = state.read().await; - - self.write() + let mem_pool = self.inner.clone(); + let state = (*state).clone(); + + runtime::Handle::current() + .spawn_blocking(move || { + let state = state.read(); + + mem_pool + .write() + .update(&*state) + .map_err(|e| napi::Error::new(Status::GenericFailure, e.to_string())) + }) .await - .update(&*state) - .map_err(|e| napi::Error::new(Status::GenericFailure, e.to_string())) + .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))? } #[doc = "Returns all transactions in the mem pool."] #[napi] - pub async fn transactions(&self) -> Vec { - let mempool = self.read().await; - - mempool - .transactions() - .cloned() - .map(PendingTransaction::from) - .collect() + pub async fn transactions(&self) -> napi::Result> { + let mem_pool = self.inner.clone(); + runtime::Handle::current() + .spawn_blocking(move || { + mem_pool + .read() + .transactions() + .cloned() + .map(PendingTransaction::from) + .collect() + }) + .await + .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string())) } #[doc = "Returns whether the [`MemPool`] contains any future transactions."] #[napi] - pub async fn has_future_transactions(&self) -> bool { - self.read().await.has_future_transactions() + pub async fn has_future_transactions(&self) -> napi::Result { + let mem_pool = self.inner.clone(); + + runtime::Handle::current() + .spawn_blocking(move || mem_pool.read().has_future_transactions()) + .await + .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string())) } #[doc = "Returns whether the [`MemPool`] contains any pending transactions."] #[napi] - pub async fn has_pending_transactions(&self) -> bool { - self.read().await.has_pending_transactions() + pub async fn has_pending_transactions(&self) -> napi::Result { + let mem_pool = self.inner.clone(); + + runtime::Handle::current() + .spawn_blocking(move || mem_pool.read().has_pending_transactions()) + .await + .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string())) } #[doc = "Returns the transaction corresponding to the provided hash, if it exists."] @@ -154,11 +205,16 @@ impl MemPool { ) -> napi::Result> { let hash = TryCast::::try_cast(hash)?; - Ok(self - .read() + let mem_pool = self.inner.clone(); + runtime::Handle::current() + .spawn_blocking(move || { + mem_pool + .read() + .transaction_by_hash(&hash) + .cloned() + .map(OrderedTransaction::from) + }) .await - .transaction_by_hash(&hash) - .cloned() - .map(OrderedTransaction::from)) + .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string())) } } diff --git a/crates/edr_napi/src/miner.rs b/crates/edr_napi/src/miner.rs index b6b23b7122..ac0529dc52 100644 --- a/crates/edr_napi/src/miner.rs +++ b/crates/edr_napi/src/miner.rs @@ -7,6 +7,7 @@ use edr_eth::{Address, B256, U256}; use edr_evm::{BlockTransactionError, CfgEnv, InvalidTransaction, MineBlockError}; use napi::{ bindgen_prelude::{BigInt, Buffer}, + tokio::runtime, Status, }; use napi_derive::napi; @@ -23,7 +24,7 @@ use crate::{ #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] pub async fn mine_block( blockchain: &Blockchain, - state_manager: &State, + state: &State, mem_pool: &MemPool, config: ConfigOptions, timestamp: BigInt, @@ -45,49 +46,56 @@ pub async fn mine_block( base_fee.map_or(Ok(None), |base_fee| BigInt::try_cast(base_fee).map(Some))?; let prevrandao: Option = prevrandao.map(TryCast::::try_cast).transpose()?; - let mut state = state_manager.write().await; - let mut blockchain = blockchain.write().await; - let mut mem_pool = mem_pool.write().await; + let blockchain = (*blockchain).clone(); + let mem_pool = (*mem_pool).clone(); + let state = (*state).clone(); + let inspector = tracer.map(Tracer::as_dyn_inspector); - let result = edr_evm::mine_block( - &*blockchain, - state.clone(), - &mem_pool, - &config, - timestamp, - beneficiary, - min_gas_price, - mine_ordering, - reward, - base_fee, - prevrandao, - tracer.map(Tracer::as_dyn_inspector) - ) - .await - .map_err( - |e| napi::Error::new(Status::GenericFailure, - match e { - MineBlockError::BlockTransaction( - BlockTransactionError::InvalidTransaction( - InvalidTransaction::LackOfFundForMaxFee { fee, balance } - )) => format!("sender doesn't have enough funds to send tx. The max upfront cost is: {fee} and the sender's account only has: {balance}"), - e => e.to_string(), - }))?; + runtime::Handle::current().spawn_blocking(move || { + let mut blockchain = blockchain.write(); + let mut state = state.write(); + let mut mem_pool = mem_pool.write(); - let block = blockchain - .insert_block(result.block, result.state_diff) - .await - .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))?; + let result = edr_evm::mine_block( + &*blockchain, + state.clone(), + &mem_pool, + &config, + timestamp, + beneficiary, + min_gas_price, + mine_ordering, + reward, + base_fee, + prevrandao, + inspector + ) + .map_err( + |e| napi::Error::new(Status::GenericFailure, + match e { + MineBlockError::BlockTransaction( + BlockTransactionError::InvalidTransaction( + InvalidTransaction::LackOfFundForMaxFee { fee, balance } + )) => format!("sender doesn't have enough funds to send tx. The max upfront cost is: {fee} and the sender's account only has: {balance}"), + e => e.to_string(), + }))?; + + let block = blockchain + .insert_block(result.block, result.state_diff) + .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))?; - mem_pool - .update(&result.state) - .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))?; + mem_pool + .update(&result.state) + .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))?; - *state = result.state; + *state = result.state; - Ok(MineBlockResult::from(edr_evm::MineBlockResult { - block, - transaction_results: result.transaction_results, - transaction_traces: result.transaction_traces, - })) + Ok(MineBlockResult::from(edr_evm::MineBlockResult { + block, + transaction_results: result.transaction_results, + transaction_traces: result.transaction_traces, + })) + }) + .await + .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))? } diff --git a/crates/edr_napi/src/provider.rs b/crates/edr_napi/src/provider.rs index 5f7e2d7b91..22096bc634 100644 --- a/crates/edr_napi/src/provider.rs +++ b/crates/edr_napi/src/provider.rs @@ -50,11 +50,15 @@ impl Provider { ) })?; - let response = self - .provider - .handle_request(request) + let provider = self.provider.clone(); + let response = runtime::Handle::current() + .spawn_blocking(move || { + provider + .handle_request(request) + .map_err(|e| napi::Error::new(Status::GenericFailure, e.to_string())) + }) .await - .map_err(|e| napi::Error::new(Status::GenericFailure, e.to_string()))?; + .map_err(|e| napi::Error::new(Status::GenericFailure, e.to_string()))??; serde_json::to_string(&response) .map_err(|e| napi::Error::new(Status::GenericFailure, e.to_string())) diff --git a/crates/edr_napi/src/runtime.rs b/crates/edr_napi/src/runtime.rs index b183e79f53..e83679445f 100644 --- a/crates/edr_napi/src/runtime.rs +++ b/crates/edr_napi/src/runtime.rs @@ -4,7 +4,7 @@ use edr_evm::{ trace::TraceCollector, BlockEnv, CfgEnv, InspectorContainer, InvalidTransaction, ResultAndState, TransactionError, TxEnv, }; -use napi::Status; +use napi::{tokio::runtime, Status}; use napi_derive::napi; use crate::{ @@ -35,21 +35,28 @@ pub async fn dry_run( let block = BlockEnv::try_from(block)?; let mut container = InspectorContainer::new(with_trace, tracer.map(Tracer::as_dyn_inspector)); + let blockchain = (*blockchain).clone(); + let state = (*state).clone(); + let state_overrides = state_overrides.as_inner().clone(); - let ResultAndState { result, state } = edr_evm::dry_run( - &*blockchain.read().await, - &*state.read().await, - state_overrides.as_inner(), - cfg, - transaction, - block, - container.as_dyn_inspector(), - ) - .await - .map_err(|e| napi::Error::new(Status::GenericFailure, e.to_string()))?; + runtime::Handle::current() + .spawn_blocking(move || { + let ResultAndState { result, state } = edr_evm::dry_run( + &*blockchain.read(), + &*state.read(), + &state_overrides, + cfg, + transaction, + block, + container.as_dyn_inspector(), + ) + .map_err(|e| napi::Error::new(Status::GenericFailure, e.to_string()))?; - let trace = container.into_tracer().map(TraceCollector::into_trace); - Ok(TransactionResult::new(result, Some(state), trace)) + let trace = container.into_tracer().map(TraceCollector::into_trace); + Ok(TransactionResult::new(result, Some(state), trace)) + }) + .await + .map_err(|e| napi::Error::new(Status::GenericFailure, e.to_string()))? } /// Executes the provided transaction without changing state, ignoring @@ -72,21 +79,28 @@ pub async fn guaranteed_dry_run( let block = BlockEnv::try_from(block)?; let mut container = InspectorContainer::new(with_trace, tracer.map(Tracer::as_dyn_inspector)); + let blockchain = (*blockchain).clone(); + let state = (*state).clone(); + let state_overrides = state_overrides.as_inner().clone(); - let ResultAndState { result, state } = edr_evm::guaranteed_dry_run( - &*blockchain.read().await, - &*state.read().await, - state_overrides.as_inner(), - cfg, - transaction, - block, - container.as_dyn_inspector(), - ) - .await - .map_err(|e| napi::Error::new(Status::GenericFailure, e.to_string()))?; + runtime::Handle::current() + .spawn_blocking(move || { + let ResultAndState { result, state } = edr_evm::guaranteed_dry_run( + &*blockchain.read(), + &*state.read(), + &state_overrides, + cfg, + transaction, + block, + container.as_dyn_inspector(), + ) + .map_err(|e| napi::Error::new(Status::GenericFailure, e.to_string()))?; - let trace = container.into_tracer().map(TraceCollector::into_trace); - Ok(TransactionResult::new(result, Some(state), trace)) + let trace = container.into_tracer().map(TraceCollector::into_trace); + Ok(TransactionResult::new(result, Some(state), trace)) + }) + .await + .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))? } /// Executes the provided transaction, changing state in the process. @@ -94,7 +108,7 @@ pub async fn guaranteed_dry_run( #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] pub async fn run( blockchain: &Blockchain, - state_manager: &State, + state: &State, cfg: ConfigOptions, transaction: TransactionRequest, block: BlockConfig, @@ -106,23 +120,30 @@ pub async fn run( let block = BlockEnv::try_from(block)?; let mut container = InspectorContainer::new(with_trace, tracer.map(Tracer::as_dyn_inspector)); + let blockchain = (*blockchain).clone(); + let state = (*state).clone(); - let result = edr_evm::run( - &*blockchain.read().await, - &mut *state_manager.write().await, - cfg, transaction, block, container.as_dyn_inspector()).await - .map_err(|e| { - napi::Error::new( - Status::GenericFailure, - match e { - TransactionError::InvalidTransaction( - InvalidTransaction::LackOfFundForMaxFee { fee, balance } - ) => format!("sender doesn't have enough funds to send tx. The max upfront cost is: {fee} and the sender's account only has: {balance}"), - e => e.to_string(), - }, + runtime::Handle::current().spawn_blocking(move || { + let result = edr_evm::run( + &*blockchain.read(), + &mut *state.write(), + cfg, transaction, block, container.as_dyn_inspector() ) - })?; + .map_err(|e| { + napi::Error::new( + Status::GenericFailure, + match e { + TransactionError::InvalidTransaction( + InvalidTransaction::LackOfFundForMaxFee { fee, balance } + ) => format!("sender doesn't have enough funds to send tx. The max upfront cost is: {fee} and the sender's account only has: {balance}"), + e => e.to_string(), + }, + ) + })?; - let trace = container.into_tracer().map(TraceCollector::into_trace); - Ok(TransactionResult::new(result, None, trace)) + let trace = container.into_tracer().map(TraceCollector::into_trace); + Ok(TransactionResult::new(result, None, trace)) + }) + .await + .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))? } diff --git a/crates/edr_napi/src/state.rs b/crates/edr_napi/src/state.rs index 0823e308c8..6aeaeaec8e 100644 --- a/crates/edr_napi/src/state.rs +++ b/crates/edr_napi/src/state.rs @@ -17,11 +17,12 @@ use edr_evm::{ }; use napi::{ bindgen_prelude::{BigInt, Buffer, ObjectFinalize}, - tokio::{runtime, sync::RwLock}, + tokio::runtime, Env, JsFunction, JsObject, NapiRaw, Status, }; use napi_derive::napi; pub use overrides::*; +use parking_lot::RwLock; use crate::{ account::{genesis_accounts, Account, GenesisAccount}, @@ -70,7 +71,7 @@ impl State { #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] fn with_state(env: &mut Env, state: S) -> napi::Result where - S: SyncState, + S: SyncState + 'static, { // Signal that memory was externally allocated env.adjust_external_memory(STATE_MEMORY_SIZE)?; @@ -141,18 +142,19 @@ impl State { let state_root_generator = context.state_root_generator.clone(); let (deferred, promise) = env.create_deferred()?; - runtime.clone().spawn(async move { + runtime.clone().spawn_blocking(move || { let rpc_client = RpcClient::new(&remote_node_url, cache_dir); - let result = ForkState::new( - runtime.clone(), - Arc::new(rpc_client), - state_root_generator, - fork_block_number, - account_overrides, - ) - .await - .map_err(|e| napi::Error::new(Status::GenericFailure, e.to_string())); + let result = runtime + .clone() + .block_on(ForkState::new( + runtime, + Arc::new(rpc_client), + state_root_generator, + fork_block_number, + account_overrides, + )) + .map_err(|e| napi::Error::new(Status::GenericFailure, e.to_string())); deferred.resolve(|mut env| result.map(|state| Self::with_state(&mut env, state))); }); @@ -163,12 +165,19 @@ impl State { #[doc = "Clones the state"] #[napi] #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))] - pub async fn deep_clone(&self) -> Self { - let state = self.state.read().await.clone(); + pub async fn deep_clone(&self) -> napi::Result { + let state = self.state.clone(); - Self { - state: Arc::new(RwLock::new(state)), - } + runtime::Handle::current() + .spawn_blocking(move || { + let state = state.read().clone(); + + Self { + state: Arc::new(RwLock::new(state)), + } + }) + .await + .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string())) } /// Retrieves the account corresponding to the specified address. @@ -179,8 +188,8 @@ impl State { let state = self.state.clone(); runtime::Handle::current() - .spawn(async move { - let state = state.read().await; + .spawn_blocking(move || { + let state = state.read(); state.basic(address).and_then(|account_info| { account_info.map_or(Ok(None), |mut account_info| { @@ -208,10 +217,7 @@ impl State { let state = self.state.clone(); runtime::Handle::current() - .spawn(async move { - let state = state.read().await; - state.account_storage_root(&address) - }) + .spawn_blocking(move || state.read().account_storage_root(&address)) .await .unwrap() .map_or_else( @@ -233,10 +239,7 @@ impl State { let state = self.state.clone(); runtime::Handle::current() - .spawn(async move { - let state = state.read().await; - state.storage(address, index) - }) + .spawn_blocking(move || state.read().storage(address, index)) .await .unwrap() .map_or_else( @@ -256,10 +259,7 @@ impl State { pub async fn get_state_root(&self) -> napi::Result { let state = self.state.clone(); runtime::Handle::current() - .spawn(async move { - let state = state.read().await; - state.state_root() - }) + .spawn_blocking(move || state.read().state_root()) .await .unwrap() .map_or_else( @@ -277,10 +277,7 @@ impl State { let state = self.state.clone(); runtime::Handle::current() - .spawn(async move { - let mut state = state.write().await; - state.insert_account(address, account_info) - }) + .spawn_blocking(move || state.write().insert_account(address, account_info)) .await .unwrap() .map_err(|e| napi::Error::new(Status::GenericFailure, e.to_string())) @@ -372,10 +369,9 @@ impl State { let (deferred, promise) = env.create_deferred()?; let state = self.state.clone(); - runtime::Handle::current().spawn(async move { - let mut state = state.write().await; - + runtime::Handle::current().spawn_blocking(move || { let result = state + .write() .modify_account( address, AccountModifierFn::new(Box::new( @@ -423,10 +419,7 @@ impl State { let state = self.state.clone(); runtime::Handle::current() - .spawn(async move { - let mut state = state.write().await; - state.remove_account(address) - }) + .spawn_blocking(move || state.write().remove_account(address)) .await .unwrap() .map_or_else( @@ -441,10 +434,7 @@ impl State { pub async fn serialize(&self) -> String { let state = self.state.clone(); runtime::Handle::current() - .spawn(async move { - let state = state.read().await; - state.serialize() - }) + .spawn_blocking(move || state.read().serialize()) .await .unwrap() } @@ -465,9 +455,10 @@ impl State { let state = self.state.clone(); runtime::Handle::current() - .spawn(async move { - let mut state = state.write().await; - state.set_account_storage_slot(address, index, value) + .spawn_blocking(move || { + state + .write() + .set_account_storage_slot(address, index, value) }) .await .unwrap() diff --git a/crates/edr_napi/src/state/overrides.rs b/crates/edr_napi/src/state/overrides.rs index 874f0726be..0c4b424e56 100644 --- a/crates/edr_napi/src/state/overrides.rs +++ b/crates/edr_napi/src/state/overrides.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use edr_eth::{Address, Bytes}; use edr_evm::HashMap; use napi::bindgen_prelude::{BigInt, Buffer}; @@ -65,12 +67,12 @@ impl TryCast for AccountOverride { #[napi] pub struct StateOverrides { - inner: edr_evm::state::StateOverrides, + inner: Arc, } impl StateOverrides { /// Returns a reference to the inner state overrides. - pub fn as_inner(&self) -> &edr_evm::state::StateOverrides { + pub fn as_inner(&self) -> &Arc { &self.inner } } @@ -91,7 +93,7 @@ impl StateOverrides { .collect::>()?; Ok(Self { - inner: edr_evm::state::StateOverrides::new(account_overrides), + inner: Arc::new(edr_evm::state::StateOverrides::new(account_overrides)), }) } } diff --git a/crates/edr_napi/src/transaction/pending.rs b/crates/edr_napi/src/transaction/pending.rs index e5b669948a..58bbf89dde 100644 --- a/crates/edr_napi/src/transaction/pending.rs +++ b/crates/edr_napi/src/transaction/pending.rs @@ -49,8 +49,8 @@ impl PendingTransaction { let state = (*state_manager).clone(); let (deferred, promise) = env.create_deferred()?; - runtime::Handle::current().spawn(async move { - let state = state.read().await; + runtime::Handle::current().spawn_blocking(move || { + let state = state.read(); let result = if let Some(caller) = caller { let caller = Address::from_slice(&caller); diff --git a/crates/edr_provider/src/data.rs b/crates/edr_provider/src/data.rs index 8ee0fde436..046d5c39f7 100644 --- a/crates/edr_provider/src/data.rs +++ b/crates/edr_provider/src/data.rs @@ -107,7 +107,7 @@ impl ProviderData { self.local_accounts.keys() } - pub async fn balance( + pub fn balance( &self, address: Address, block_spec: Option<&BlockSpec>, @@ -116,39 +116,36 @@ impl ProviderData { Ok(state .basic(address)? .map_or(U256::ZERO, |account| account.balance)) - }) - .await? + })? } - pub async fn block_number(&self) -> u64 { - self.blockchain.last_block_number().await + pub fn block_number(&self) -> u64 { + self.blockchain.last_block_number() } /// Fetch a block by block spec. /// Returns `None` if the block spec is `pending`. /// Returns `ProviderError::InvalidBlockSpec` if the block spec is a number /// or a hash and the block isn't found. - pub async fn block_by_block_spec( + pub fn block_by_block_spec( &self, block_spec: &BlockSpec, ) -> Result>>, ProviderError> { let result = match block_spec { BlockSpec::Number(block_number) => Some( self.blockchain - .block_by_number(*block_number) - .await? + .block_by_number(*block_number)? .ok_or_else(|| ProviderError::InvalidBlockNumberOrHash(block_spec.clone()))?, ), BlockSpec::Tag(BlockTag::Earliest) => Some( self.blockchain - .block_by_number(0) - .await? + .block_by_number(0)? .expect("genesis block should always exist"), ), // Matching Hardhat behaviour by returning the last block for finalized and safe. // https://github.com/NomicFoundation/hardhat/blob/b84baf2d9f5d3ea897c06e0ecd5e7084780d8b6c/packages/hardhat-core/src/internal/hardhat-network/provider/modules/eth.ts#L1395 BlockSpec::Tag(BlockTag::Finalized | BlockTag::Safe | BlockTag::Latest) => { - Some(self.blockchain.last_block().await?) + Some(self.blockchain.last_block()?) } BlockSpec::Tag(BlockTag::Pending) => None, BlockSpec::Eip1898(Eip1898BlockSpec::Hash { @@ -156,14 +153,12 @@ impl ProviderData { require_canonical: _, }) => Some( self.blockchain - .block_by_hash(block_hash) - .await? + .block_by_hash(block_hash)? .ok_or_else(|| ProviderError::InvalidBlockNumberOrHash(block_spec.clone()))?, ), BlockSpec::Eip1898(Eip1898BlockSpec::Number { block_number }) => Some( self.blockchain - .block_by_number(*block_number) - .await? + .block_by_number(*block_number)? .ok_or_else(|| ProviderError::InvalidBlockNumberOrHash(block_spec.clone()))?, ), }; @@ -171,25 +166,24 @@ impl ProviderData { Ok(result) } - pub async fn block_by_hash( + pub fn block_by_hash( &self, block_hash: &B256, ) -> Result>>, ProviderError> { self.blockchain .block_by_hash(block_hash) - .await .map_err(ProviderError::Blockchain) } - pub async fn chain_id(&self) -> u64 { - self.blockchain.chain_id().await + pub fn chain_id(&self) -> u64 { + self.blockchain.chain_id() } pub fn coinbase(&self) -> Address { self.beneficiary } - pub async fn get_code( + pub fn get_code( &self, address: Address, block_spec: Option<&BlockSpec>, @@ -204,8 +198,7 @@ impl ProviderData { })?; Ok(code) - }) - .await? + })? } pub fn get_filter_changes(&mut self, filter_id: &U256) -> Option { @@ -232,7 +225,7 @@ impl ProviderData { .transpose() } - pub async fn get_storage_at( + pub fn get_storage_at( &self, address: Address, index: U256, @@ -240,11 +233,10 @@ impl ProviderData { ) -> Result { self.execute_in_block_state::>(block_spec, move |state| { Ok(state.storage(address, index)?) - }) - .await? + })? } - pub async fn get_transaction_count( + pub fn get_transaction_count( &self, address: Address, block_spec: Option<&BlockSpec>, @@ -255,8 +247,7 @@ impl ProviderData { .map_or(0, |account_info| account_info.nonce); Ok(nonce) - }) - .await? + })? } pub fn impersonate_account(&mut self, address: Address) { @@ -272,18 +263,18 @@ impl ProviderData { &self.logger } - pub async fn mine_and_commit_block( + pub fn mine_and_commit_block( &mut self, timestamp: Option, ) -> Result, ProviderError> { - let (block_timestamp, new_offset) = self.next_block_timestamp(timestamp).await?; + let (block_timestamp, new_offset) = self.next_block_timestamp(timestamp)?; let prevrandao = if self.blockchain.spec_id() >= SpecId::MERGE { Some(self.prevrandao_generator.next_value()) } else { None }; - let result = self.mine_block(block_timestamp, prevrandao).await?; + let result = self.mine_block(block_timestamp, prevrandao)?; if let Some(new_offset) = new_offset { self.block_time_offset_seconds = new_offset; @@ -295,7 +286,6 @@ impl ProviderData { let block = self .blockchain .insert_block(result.block, result.state_diff) - .await .map_err(ProviderError::Blockchain)?; self.mem_pool @@ -353,11 +343,7 @@ impl ProviderData { self.add_pending_transaction(pending_transaction) } - pub async fn set_balance( - &mut self, - address: Address, - balance: U256, - ) -> Result<(), ProviderError> { + pub fn set_balance(&mut self, address: Address, balance: U256) -> Result<(), ProviderError> { self.state.modify_account( address, AccountModifierFn::new(Box::new(move |account_balance, _, _| { @@ -373,7 +359,7 @@ impl ProviderData { }, )?; - let block_number = self.blockchain.last_block_number().await; + let block_number = self.blockchain.last_block_number(); let state = self.state.clone(); self.irregular_state.insert_state(block_number, state); @@ -382,7 +368,7 @@ impl ProviderData { Ok(()) } - pub async fn set_code(&mut self, address: Address, code: Bytes) -> Result<(), ProviderError> { + pub fn set_code(&mut self, address: Address, code: Bytes) -> Result<(), ProviderError> { let default_code = code.clone(); self.state.modify_account( address, @@ -399,7 +385,7 @@ impl ProviderData { }, )?; - let block_number = self.blockchain.last_block_number().await; + let block_number = self.blockchain.last_block_number(); let state = self.state.clone(); self.irregular_state.insert_state(block_number, state); @@ -407,10 +393,10 @@ impl ProviderData { } /// Set the next block timestamp. - pub async fn set_next_block_timestamp(&mut self, timestamp: u64) -> Result { + pub fn set_next_block_timestamp(&mut self, timestamp: u64) -> Result { use std::cmp::Ordering; - let latest_block = self.blockchain.last_block().await?; + let latest_block = self.blockchain.last_block()?; let latest_block_header = latest_block.header(); match timestamp.cmp(&latest_block_header.timestamp) { @@ -428,7 +414,7 @@ impl ProviderData { } } - pub async fn set_nonce(&mut self, address: Address, nonce: u64) -> Result<(), ProviderError> { + pub fn set_nonce(&mut self, address: Address, nonce: u64) -> Result<(), ProviderError> { self.state.modify_account( address, AccountModifierFn::new(Box::new(move |_, account_nonce, _| *account_nonce = nonce)), @@ -442,7 +428,7 @@ impl ProviderData { }, )?; - let block_number = self.blockchain.last_block_number().await; + let block_number = self.blockchain.last_block_number(); let state = self.state.clone(); self.irregular_state.insert_state(block_number, state); @@ -451,7 +437,7 @@ impl ProviderData { Ok(()) } - pub async fn set_account_storage_slot( + pub fn set_account_storage_slot( &mut self, address: Address, index: U256, @@ -459,7 +445,7 @@ impl ProviderData { ) -> Result<(), ProviderError> { self.state.set_account_storage_slot(address, index, value)?; - let block_number = self.blockchain.last_block_number().await; + let block_number = self.blockchain.last_block_number(); let state = self.state.clone(); self.irregular_state.insert_state(block_number, state); @@ -487,7 +473,7 @@ impl ProviderData { /// Get a transaction by hash from the blockchain or from the mempool if /// it's not mined yet. - pub async fn transaction_by_hash( + pub fn transaction_by_hash( &self, hash: &B256, ) -> Result, ProviderError> { @@ -499,11 +485,10 @@ impl ProviderData { spec_id: self.blockchain.spec_id(), block_metadata: None, }) - } else if let Some(tx_block) = self.blockchain.block_by_transaction_hash(hash).await? { + } else if let Some(tx_block) = self.blockchain.block_by_transaction_hash(hash)? { let tx_index = self .blockchain - .receipt_by_transaction_hash(hash) - .await? + .receipt_by_transaction_hash(hash)? .expect("If the transaction was inserted in a block, it must have a receipt") .transaction_index; @@ -536,9 +521,9 @@ impl ProviderData { Ok(transaction_hash) } - async fn create_evm_config(&self) -> CfgEnv { + fn create_evm_config(&self) -> CfgEnv { let mut evm_config = CfgEnv::default(); - evm_config.chain_id = self.blockchain.chain_id().await; + evm_config.chain_id = self.blockchain.chain_id(); evm_config.spec_id = self.blockchain.spec_id(); evm_config.limit_contract_code_size = if self.allow_unlimited_contract_size { Some(usize::MAX) @@ -548,12 +533,12 @@ impl ProviderData { evm_config } - async fn execute_in_block_state( + fn execute_in_block_state( &self, block_spec: Option<&BlockSpec>, function: impl FnOnce(Box>) -> T, ) -> Result { - let contextual_state = self.state_by_block_spec(block_spec).await?; + let contextual_state = self.state_by_block_spec(block_spec)?; // Execute function in the requested block context. let result = function(contextual_state); @@ -562,7 +547,7 @@ impl ProviderData { } /// Mine a block at a specific timestamp - async fn mine_block( + fn mine_block( &self, timestamp: u64, prevrandao: Option, @@ -576,7 +561,7 @@ impl ProviderData { // TODO: https://github.com/NomicFoundation/edr/issues/156 let reward = U256::ZERO; - let evm_config = self.create_evm_config().await; + let evm_config = self.create_evm_config(); let result = mine_block( &*self.blockchain, @@ -592,8 +577,7 @@ impl ProviderData { base_fee, prevrandao, None, - ) - .await?; + )?; // TODO: when we support hardhat_setNextBlockBaseFeePerGas, reset the user // provided next block base fee per gas to `None` @@ -603,26 +587,24 @@ impl ProviderData { } /// Mines a pending block, without modifying any values. - pub async fn mine_pending_block( - &self, - ) -> Result, ProviderError> { - let (block_timestamp, _new_offset) = self.next_block_timestamp(None).await?; + pub fn mine_pending_block(&self) -> Result, ProviderError> { + let (block_timestamp, _new_offset) = self.next_block_timestamp(None)?; let prevrandao = if self.blockchain.spec_id() >= SpecId::MERGE { Some(self.prevrandao_generator.seed()) } else { None }; - self.mine_block(block_timestamp, prevrandao).await + self.mine_block(block_timestamp, prevrandao) } /// Get the timestamp for the next block. /// Ported from - async fn next_block_timestamp( + fn next_block_timestamp( &self, timestamp: Option, ) -> Result<(u64, Option), ProviderError> { - let latest_block = self.blockchain.last_block().await?; + let latest_block = self.blockchain.last_block()?; let latest_block_header = latest_block.header(); let current_timestamp = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs(); @@ -702,20 +684,20 @@ impl ProviderData { } } - async fn state_by_block_spec( + fn state_by_block_spec( &self, block_spec: Option<&BlockSpec>, ) -> Result>, ProviderError> { let block = if let Some(block_spec) = block_spec { - if let Some(block) = self.block_by_block_spec(block_spec).await? { + if let Some(block) = self.block_by_block_spec(block_spec)? { block } else { // Block spec is pending - let result = self.mine_pending_block().await?; + let result = self.mine_pending_block()?; return Ok(result.state); } } else { - self.blockchain.last_block().await? + self.blockchain.last_block()? }; let block_header = block.header(); @@ -727,9 +709,7 @@ impl ProviderData { { irregular_state } else { - self.blockchain - .state_at_block_number(block_header.number) - .await? + self.blockchain.state_at_block_number(block_header.number)? }; Ok(contextual_state) @@ -795,11 +775,10 @@ async fn create_blockchain_and_state( ) .await?; - let fork_block_number = blockchain.last_block_number().await; + let fork_block_number = blockchain.last_block_number(); let state = blockchain .state_at_block_number(fork_block_number) - .await .expect("Fork state must exist"); Ok(BlockchainAndState { @@ -825,7 +804,6 @@ async fn create_blockchain_and_state( let state = blockchain .state_at_block_number(0) - .await .expect("Genesis state must exist"); Ok(BlockchainAndState { @@ -1011,8 +989,7 @@ mod tests { let block = fixture .provider_data - .block_by_block_spec(&block_spec) - .await? + .block_by_block_spec(&block_spec)? .context("block should exist")?; assert_eq!(block.header().number, 0); @@ -1025,8 +1002,8 @@ mod tests { let mut fixture = ProviderTestFixture::new().await?; // Mine a block to make sure we're not getting the genesis block - fixture.provider_data.mine_and_commit_block(None).await?; - let last_block_number = fixture.provider_data.block_number().await; + fixture.provider_data.mine_and_commit_block(None)?; + let last_block_number = fixture.provider_data.block_number(); // Sanity check assert!(last_block_number > 0); @@ -1036,8 +1013,7 @@ mod tests { let block = fixture .provider_data - .block_by_block_spec(&block_spec) - .await? + .block_by_block_spec(&block_spec)? .context("block should exist")?; assert_eq!(block.header().number, last_block_number); @@ -1052,10 +1028,7 @@ mod tests { let block_spec = BlockSpec::Tag(BlockTag::Pending); - let block = fixture - .provider_data - .block_by_block_spec(&block_spec) - .await?; + let block = fixture.provider_data.block_by_block_spec(&block_spec)?; assert!(block.is_none()); @@ -1066,7 +1039,7 @@ mod tests { async fn chain_id() -> anyhow::Result<()> { let fixture = ProviderTestFixture::new().await?; - let chain_id = fixture.provider_data.chain_id().await; + let chain_id = fixture.provider_data.chain_id(); assert_eq!(chain_id, fixture.config.chain_id); Ok(()) @@ -1107,8 +1080,7 @@ mod tests { fixture .provider_data - .set_balance(fixture.impersonated_account, U256::from(100)) - .await?; + .set_balance(fixture.impersonated_account, U256::from(100))?; assert!(fixture .provider_data @@ -1126,8 +1098,7 @@ mod tests { // Artificially raise the nonce, to ensure the transaction is not rejected fixture .provider_data - .set_nonce(fixture.impersonated_account, 1) - .await?; + .set_nonce(fixture.impersonated_account, 1)?; let transaction = { let mut request = fixture.dummy_transaction_request(); @@ -1153,8 +1124,7 @@ mod tests { // Lower the nonce, to ensure the transaction is not rejected fixture .provider_data - .set_nonce(fixture.impersonated_account, 0) - .await?; + .set_nonce(fixture.impersonated_account, 0)?; assert!(fixture .provider_data @@ -1174,10 +1144,7 @@ mod tests { async fn transaction_by_invalid_hash() -> anyhow::Result<()> { let fixture = ProviderTestFixture::new().await?; - let non_existing_tx = fixture - .provider_data - .transaction_by_hash(&B256::zero()) - .await?; + let non_existing_tx = fixture.provider_data.transaction_by_hash(&B256::zero())?; assert_eq!(non_existing_tx, None); @@ -1195,8 +1162,7 @@ mod tests { let transaction_result = fixture .provider_data - .transaction_by_hash(&transaction_hash) - .await? + .transaction_by_hash(&transaction_hash)? .context("transaction not found")?; assert_eq!( @@ -1216,7 +1182,7 @@ mod tests { .provider_data .add_pending_transaction(transaction_request)?; - let results = fixture.provider_data.mine_and_commit_block(None).await?; + let results = fixture.provider_data.mine_and_commit_block(None)?; // Make sure transaction was mined successfully. assert!(results @@ -1229,8 +1195,7 @@ mod tests { let transaction_result = fixture .provider_data - .transaction_by_hash(&transaction_hash) - .await? + .transaction_by_hash(&transaction_hash)? .context("transaction not found")?; assert_eq!( diff --git a/crates/edr_provider/src/lib.rs b/crates/edr_provider/src/lib.rs index 04b09962dd..e6f2f3e2d6 100644 --- a/crates/edr_provider/src/lib.rs +++ b/crates/edr_provider/src/lib.rs @@ -9,11 +9,12 @@ mod requests; pub mod test_utils; use data::{CreationError, ProviderData}; +use parking_lot::Mutex; use requests::{ eth::{self, handle_evm_mine_request}, hardhat, }; -use tokio::{runtime, sync::Mutex}; +use tokio::runtime; use self::requests::{EthRequest, Request}; pub use self::{ @@ -69,48 +70,48 @@ impl Provider { }) } - pub async fn handle_request( + pub fn handle_request( &self, request: ProviderRequest, ) -> Result { - let mut data = self.data.lock().await; + let mut data = self.data.lock(); // TODO: resolve deserialization defaults using data // Will require changes to `ProviderRequest` to receive `json_serde::Value` match request { - ProviderRequest::Single(request) => handle_single_request(&mut data, request).await, - ProviderRequest::Batch(requests) => handle_batch_request(&mut data, requests).await, + ProviderRequest::Single(request) => handle_single_request(&mut data, request), + ProviderRequest::Batch(requests) => handle_batch_request(&mut data, requests), } } } /// Handles a JSON request for an execution provider. -async fn handle_single_request( +fn handle_single_request( data: &mut ProviderData, request: Request, ) -> Result { match request { - Request::Eth(request) => handle_eth_request(data, request).await, - Request::Hardhat(request) => handle_hardhat_request(data, request).await, + Request::Eth(request) => handle_eth_request(data, request), + Request::Hardhat(request) => handle_hardhat_request(data, request), } } /// Handles a batch of JSON requests for an execution provider. -async fn handle_batch_request( +fn handle_batch_request( data: &mut ProviderData, request: Vec, ) -> Result { let mut results = Vec::new(); for req in request { - results.push(handle_single_request(data, req).await?); + results.push(handle_single_request(data, req)?); } serde_json::to_value(results).map_err(ProviderError::Serialization) } -async fn handle_eth_request( +fn handle_eth_request( data: &mut ProviderData, request: EthRequest, ) -> Result { @@ -118,19 +119,15 @@ async fn handle_eth_request( #[allow(clippy::match_same_arms)] match request { EthRequest::Accounts() => eth::handle_accounts_request(data).and_then(to_json), - EthRequest::BlockNumber() => eth::handle_block_number_request(data) - .await - .and_then(to_json), + EthRequest::BlockNumber() => eth::handle_block_number_request(data).and_then(to_json), EthRequest::Call(_, _) => Err(ProviderError::Unimplemented("".to_string())), - EthRequest::ChainId() => eth::handle_chain_id_request(data).await.and_then(to_json), + EthRequest::ChainId() => eth::handle_chain_id_request(data).and_then(to_json), EthRequest::Coinbase() => eth::handle_coinbase_request(data).and_then(to_json), EthRequest::EstimateGas(_, _) => Err(ProviderError::Unimplemented("".to_string())), EthRequest::FeeHistory(_, _, _) => Err(ProviderError::Unimplemented("".to_string())), EthRequest::GasPrice() => Err(ProviderError::Unimplemented("".to_string())), EthRequest::GetBalance(address, block_spec) => { - eth::handle_get_balance_request(data, address, block_spec) - .await - .and_then(to_json) + eth::handle_get_balance_request(data, address, block_spec).and_then(to_json) } EthRequest::GetBlockByNumber(_, _) => Err(ProviderError::Unimplemented("".to_string())), EthRequest::GetBlockByHash(_, _) => Err(ProviderError::Unimplemented("".to_string())), @@ -141,9 +138,7 @@ async fn handle_eth_request( Err(ProviderError::Unimplemented("".to_string())) } EthRequest::GetCode(address, block_spec) => { - eth::handle_get_code_request(data, address, block_spec) - .await - .and_then(to_json) + eth::handle_get_code_request(data, address, block_spec).and_then(to_json) } EthRequest::GetFilterChanges(filter_id) => { eth::handle_get_filter_changes_request(data, filter_id).and_then(to_json) @@ -153,29 +148,21 @@ async fn handle_eth_request( } EthRequest::GetLogs(_) => Err(ProviderError::Unimplemented("".to_string())), EthRequest::GetStorageAt(address, index, block_spec) => { - eth::handle_get_storage_at_request(data, address, index, block_spec) - .await - .and_then(to_json) + eth::handle_get_storage_at_request(data, address, index, block_spec).and_then(to_json) } EthRequest::GetTransactionByBlockHashAndIndex(block_hash, index) => { eth::handle_get_transaction_by_block_hash_and_index(data, block_hash, index) - .await .and_then(to_json) } EthRequest::GetTransactionByBlockNumberAndIndex(block_spec, index) => { eth::handle_get_transaction_by_block_spec_and_index(data, block_spec, index) - .await .and_then(to_json) } EthRequest::GetTransactionByHash(transaction_hash) => { - eth::handle_get_transaction_by_hash(data, transaction_hash) - .await - .and_then(to_json) + eth::handle_get_transaction_by_hash(data, transaction_hash).and_then(to_json) } EthRequest::GetTransactionCount(address, block_spec) => { - eth::handle_get_transaction_count_request(data, address, block_spec) - .await - .and_then(to_json) + eth::handle_get_transaction_count_request(data, address, block_spec).and_then(to_json) } EthRequest::GetTransactionReceipt(_) => Err(ProviderError::Unimplemented("".to_string())), EthRequest::Mining() => Err(ProviderError::Unimplemented("".to_string())), @@ -213,21 +200,19 @@ async fn handle_eth_request( EthRequest::EvmIncreaseTime(increment) => { eth::handle_evm_increase_time_request(data, increment).and_then(to_json) } - EthRequest::EvmMine(timestamp) => handle_evm_mine_request(data, timestamp) - .await - .and_then(to_json), + EthRequest::EvmMine(timestamp) => { + handle_evm_mine_request(data, timestamp).and_then(to_json) + } EthRequest::EvmSetAutomine(_) => Err(ProviderError::Unimplemented("".to_string())), EthRequest::EvmSetIntervalMining(_) => Err(ProviderError::Unimplemented("".to_string())), EthRequest::EvmSetNextBlockTimestamp(timestamp) => { - eth::handle_evm_set_next_block_timestamp(data, timestamp) - .await - .and_then(to_json) + eth::handle_evm_set_next_block_timestamp(data, timestamp).and_then(to_json) } EthRequest::EvmSnapshot() => Err(ProviderError::Unimplemented("".to_string())), } } -async fn handle_hardhat_request( +fn handle_hardhat_request( data: &mut ProviderData, request: rpc_hardhat::Request, ) -> Result { @@ -247,21 +232,17 @@ async fn handle_hardhat_request( rpc_hardhat::Request::ImpersonateAccount(address) => { hardhat::handle_impersonate_account_request(data, address).and_then(to_json) } - rpc_hardhat::Request::IntervalMine() => hardhat::handle_interval_mine_request(data) - .await - .and_then(to_json), + rpc_hardhat::Request::IntervalMine() => { + hardhat::handle_interval_mine_request(data).and_then(to_json) + } rpc_hardhat::Request::Metadata() => Err(ProviderError::Unimplemented("".to_string())), rpc_hardhat::Request::Mine(_, _) => Err(ProviderError::Unimplemented("".to_string())), rpc_hardhat::Request::Reset(_) => Err(ProviderError::Unimplemented("".to_string())), rpc_hardhat::Request::SetBalance(address, balance) => { - hardhat::handle_set_balance(data, address, balance) - .await - .and_then(to_json) + hardhat::handle_set_balance(data, address, balance).and_then(to_json) } rpc_hardhat::Request::SetCode(address, code) => { - hardhat::handle_set_code(data, address, code) - .await - .and_then(to_json) + hardhat::handle_set_code(data, address, code).and_then(to_json) } rpc_hardhat::Request::SetCoinbase(_) => Err(ProviderError::Unimplemented("".to_string())), rpc_hardhat::Request::SetLoggingEnabled(_) => { @@ -274,15 +255,11 @@ async fn handle_hardhat_request( Err(ProviderError::Unimplemented("".to_string())) } rpc_hardhat::Request::SetNonce(address, nonce) => { - hardhat::handle_set_nonce(data, address, nonce) - .await - .and_then(to_json) + hardhat::handle_set_nonce(data, address, nonce).and_then(to_json) } rpc_hardhat::Request::SetPrevRandao(_) => Err(ProviderError::Unimplemented("".to_string())), rpc_hardhat::Request::SetStorageAt(address, index, value) => { - hardhat::handle_set_storage_at(data, address, index, value) - .await - .and_then(to_json) + hardhat::handle_set_storage_at(data, address, index, value).and_then(to_json) } rpc_hardhat::Request::StopImpersonatingAccount(address) => { hardhat::handle_stop_impersonating_account_request(data, address).and_then(to_json) diff --git a/crates/edr_provider/src/requests/eth/blockchain.rs b/crates/edr_provider/src/requests/eth/blockchain.rs index 074761230d..f988858c81 100644 --- a/crates/edr_provider/src/requests/eth/blockchain.rs +++ b/crates/edr_provider/src/requests/eth/blockchain.rs @@ -2,20 +2,19 @@ use edr_eth::{remote::BlockSpec, Address, U256, U64}; use crate::{data::ProviderData, ProviderError}; -pub async fn handle_block_number_request(data: &ProviderData) -> Result { - Ok(U64::from(data.block_number().await)) +pub fn handle_block_number_request(data: &ProviderData) -> Result { + Ok(U64::from(data.block_number())) } -pub async fn handle_chain_id_request(data: &ProviderData) -> Result { - Ok(U64::from(data.chain_id().await)) +pub fn handle_chain_id_request(data: &ProviderData) -> Result { + Ok(U64::from(data.chain_id())) } -pub async fn handle_get_transaction_count_request( +pub fn handle_get_transaction_count_request( data: &ProviderData, address: Address, block_spec: Option, ) -> Result { data.get_transaction_count(address, block_spec.as_ref()) - .await .map(U256::from) } diff --git a/crates/edr_provider/src/requests/eth/evm.rs b/crates/edr_provider/src/requests/eth/evm.rs index c25b989d8a..6a0e26dfad 100644 --- a/crates/edr_provider/src/requests/eth/evm.rs +++ b/crates/edr_provider/src/requests/eth/evm.rs @@ -13,23 +13,23 @@ pub fn handle_evm_increase_time_request( Ok(new_block_time.to_string()) } -pub async fn handle_evm_mine_request( +pub fn handle_evm_mine_request( data: &mut ProviderData, timestamp: Option, ) -> Result { let timestamp: Option = timestamp.map(U64OrUsize::into); - let mine_block_result = data.mine_and_commit_block(timestamp).await?; + let mine_block_result = data.mine_and_commit_block(timestamp)?; log_block(&mine_block_result)?; Ok(String::from("0")) } -pub async fn handle_evm_set_next_block_timestamp( +pub fn handle_evm_set_next_block_timestamp( data: &mut ProviderData, timestamp: U64OrUsize, ) -> Result { - let new_timestamp = data.set_next_block_timestamp(timestamp.into()).await?; + let new_timestamp = data.set_next_block_timestamp(timestamp.into())?; // This RPC call is an exception: it returns a number as a string decimal Ok(new_timestamp.to_string()) diff --git a/crates/edr_provider/src/requests/eth/state.rs b/crates/edr_provider/src/requests/eth/state.rs index f2b855c628..261e0f73ca 100644 --- a/crates/edr_provider/src/requests/eth/state.rs +++ b/crates/edr_provider/src/requests/eth/state.rs @@ -2,30 +2,28 @@ use edr_eth::{remote::BlockSpec, serde::ZeroXPrefixedBytes, Address, U256}; use crate::{data::ProviderData, ProviderError}; -pub async fn handle_get_balance_request( +pub fn handle_get_balance_request( data: &ProviderData, address: Address, block_spec: Option, ) -> Result { - data.balance(address, block_spec.as_ref()).await + data.balance(address, block_spec.as_ref()) } -pub async fn handle_get_code_request( +pub fn handle_get_code_request( data: &ProviderData, address: Address, block_spec: Option, ) -> Result { data.get_code(address, block_spec.as_ref()) - .await .map(ZeroXPrefixedBytes::from) } -pub async fn handle_get_storage_at_request( +pub fn handle_get_storage_at_request( data: &ProviderData, address: Address, index: U256, block_spec: Option, ) -> Result { data.get_storage_at(address, index, block_spec.as_ref()) - .await } diff --git a/crates/edr_provider/src/requests/eth/transactions.rs b/crates/edr_provider/src/requests/eth/transactions.rs index 822dd18360..1c9ffcefa0 100644 --- a/crates/edr_provider/src/requests/eth/transactions.rs +++ b/crates/edr_provider/src/requests/eth/transactions.rs @@ -18,32 +18,31 @@ use crate::{ const FIRST_HARDFORK_WITH_TRANSACTION_TYPE: SpecId = SpecId::BERLIN; -pub async fn handle_get_transaction_by_block_hash_and_index( +pub fn handle_get_transaction_by_block_hash_and_index( data: &ProviderData, block_hash: B256, index: U256, ) -> Result, ProviderError> { let index = rpc_index_to_usize(&index)?; - data.block_by_hash(&block_hash) - .await? + data.block_by_hash(&block_hash)? .and_then(|block| transaction_from_block(&block, index, data.spec_id())) .map(get_transaction_result_to_rpc_result) .transpose() } -pub async fn handle_get_transaction_by_block_spec_and_index( +pub fn handle_get_transaction_by_block_spec_and_index( data: &ProviderData, block_spec: PreEip1898BlockSpec, index: U256, ) -> Result, ProviderError> { let index = rpc_index_to_usize(&index)?; - match data.block_by_block_spec(&block_spec.into()).await { + match data.block_by_block_spec(&block_spec.into()) { Ok(Some(block)) => Some(block), // Pending block requested Ok(None) => { - let result = data.mine_pending_block().await?; + let result = data.mine_pending_block()?; let block: Arc> = Arc::new(result.block); Some(block) } @@ -62,12 +61,11 @@ fn rpc_index_to_usize(index: &U256) -> Result { .map_err(|_err| ProviderError::InvalidTransactionIndex(*index)) } -pub async fn handle_get_transaction_by_hash( +pub fn handle_get_transaction_by_hash( data: &ProviderData, transaction_hash: B256, ) -> Result, ProviderError> { - data.transaction_by_hash(&transaction_hash) - .await? + data.transaction_by_hash(&transaction_hash)? .map(get_transaction_result_to_rpc_result) .transpose() } diff --git a/crates/edr_provider/src/requests/hardhat/miner.rs b/crates/edr_provider/src/requests/hardhat/miner.rs index 6d2c8f02df..6905916653 100644 --- a/crates/edr_provider/src/requests/hardhat/miner.rs +++ b/crates/edr_provider/src/requests/hardhat/miner.rs @@ -1,7 +1,7 @@ use crate::{data::ProviderData, ProviderError}; -pub async fn handle_interval_mine_request(data: &mut ProviderData) -> Result { - let mine_block_result = data.mine_and_commit_block(None).await?; +pub fn handle_interval_mine_request(data: &mut ProviderData) -> Result { + let mine_block_result = data.mine_and_commit_block(None)?; if mine_block_result.block.transactions().is_empty() { data.logger() .log_interval_mined_block(&mine_block_result, Vec::new()); diff --git a/crates/edr_provider/src/requests/hardhat/state.rs b/crates/edr_provider/src/requests/hardhat/state.rs index bf131a46d4..14fbb3a8b0 100644 --- a/crates/edr_provider/src/requests/hardhat/state.rs +++ b/crates/edr_provider/src/requests/hardhat/state.rs @@ -2,43 +2,43 @@ use edr_eth::{serde::ZeroXPrefixedBytes, Address, U256}; use crate::{data::ProviderData, ProviderError}; -pub async fn handle_set_balance( +pub fn handle_set_balance( data: &mut ProviderData, address: Address, balance: U256, ) -> Result { - data.set_balance(address, balance).await?; + data.set_balance(address, balance)?; Ok(true) } -pub async fn handle_set_code( +pub fn handle_set_code( data: &mut ProviderData, address: Address, code: ZeroXPrefixedBytes, ) -> Result { - data.set_code(address, code.into()).await?; + data.set_code(address, code.into())?; Ok(true) } -pub async fn handle_set_nonce( +pub fn handle_set_nonce( data: &mut ProviderData, address: Address, nonce: u64, ) -> Result { - data.set_nonce(address, nonce).await?; + data.set_nonce(address, nonce)?; Ok(true) } -pub async fn handle_set_storage_at( +pub fn handle_set_storage_at( data: &mut ProviderData, address: Address, index: U256, value: U256, ) -> Result { - data.set_account_storage_slot(address, index, value).await?; + data.set_account_storage_slot(address, index, value)?; Ok(true) } diff --git a/packages/hardhat-core/src/internal/hardhat-network/provider/vm/block-builder/edr.ts b/packages/hardhat-core/src/internal/hardhat-network/provider/vm/block-builder/edr.ts index ae70f077c2..cf6fbc8325 100644 --- a/packages/hardhat-core/src/internal/hardhat-network/provider/vm/block-builder/edr.ts +++ b/packages/hardhat-core/src/internal/hardhat-network/provider/vm/block-builder/edr.ts @@ -50,7 +50,7 @@ export class EdrBlockBuilder implements BlockBuilderAdapter { disableEip3607: true, }; - const blockBuilder = await BlockBuilder.create( + const blockBuilder = new BlockBuilder( blockchain, clonedState, config, From 43a158d35d35355ba5b54f2c9958bdab2e6ae3b2 Mon Sep 17 00:00:00 2001 From: Wodann Date: Fri, 17 Nov 2023 04:23:32 +0000 Subject: [PATCH 2/2] fix: linter --- crates/edr_napi/index.d.ts | 4 ++-- crates/edr_napi/src/block.rs | 2 +- .../src/internal/hardhat-network/provider/blockchain/edr.ts | 2 +- .../src/internal/hardhat-network/provider/miner/edr.ts | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/edr_napi/index.d.ts b/crates/edr_napi/index.d.ts index 40ede26e64..7713f5af1f 100644 --- a/crates/edr_napi/index.d.ts +++ b/crates/edr_napi/index.d.ts @@ -274,7 +274,7 @@ export function dryRun(blockchain: Blockchain, state: State, stateOverrides: Sta */ export function guaranteedDryRun(blockchain: Blockchain, state: State, stateOverrides: StateOverrides, cfg: ConfigOptions, transaction: TransactionRequest, block: BlockConfig, withTrace: boolean, tracer?: Tracer | undefined | null): Promise /** Executes the provided transaction, changing state in the process. */ -export function run(blockchain: Blockchain, stateManager: State, cfg: ConfigOptions, transaction: TransactionRequest, block: BlockConfig, withTrace: boolean, tracer?: Tracer | undefined | null): Promise +export function run(blockchain: Blockchain, state: State, cfg: ConfigOptions, transaction: TransactionRequest, block: BlockConfig, withTrace: boolean, tracer?: Tracer | undefined | null): Promise export interface Signature { /** R value */ r: bigint @@ -547,7 +547,7 @@ export class Block { /**Retrieves the callers of the block's transactions */ get callers(): Array /**Retrieves the transactions' receipts. */ - receipts(): Promise> + get receipts(): Array } /** The EDR blockchain */ export class Blockchain { diff --git a/crates/edr_napi/src/block.rs b/crates/edr_napi/src/block.rs index 6a78f54141..4002f6826c 100644 --- a/crates/edr_napi/src/block.rs +++ b/crates/edr_napi/src/block.rs @@ -399,7 +399,7 @@ impl Block { } #[doc = "Retrieves the transactions' receipts."] - #[napi] + #[napi(getter)] pub fn receipts(&self) -> napi::Result> { self.inner.transaction_receipts().map_or_else( |error| Err(napi::Error::new(Status::InvalidArg, error.to_string())), diff --git a/packages/hardhat-core/src/internal/hardhat-network/provider/blockchain/edr.ts b/packages/hardhat-core/src/internal/hardhat-network/provider/blockchain/edr.ts index c347b1b8a7..acf24c778e 100644 --- a/packages/hardhat-core/src/internal/hardhat-network/provider/blockchain/edr.ts +++ b/packages/hardhat-core/src/internal/hardhat-network/provider/blockchain/edr.ts @@ -99,7 +99,7 @@ export class EdrBlockchain implements BlockchainAdapter { ) { continue; } - const receipts = await block.receipts(); + const receipts = block.receipts; for (const receipt of receipts) { logs.push( ...filterLogs( diff --git a/packages/hardhat-core/src/internal/hardhat-network/provider/miner/edr.ts b/packages/hardhat-core/src/internal/hardhat-network/provider/miner/edr.ts index df2b59c189..02da0dd75c 100644 --- a/packages/hardhat-core/src/internal/hardhat-network/provider/miner/edr.ts +++ b/packages/hardhat-core/src/internal/hardhat-network/provider/miner/edr.ts @@ -123,7 +123,7 @@ export class EdrMiner implements BlockMinerAdapter { traces.push({ trace, error }); } - const receipts = await mineResult.block.receipts(); + const receipts = mineResult.block.receipts; const totalDifficultyAfterBlock = await this._blockchain.getTotalDifficultyByHash(mineResult.block.hash());