diff --git a/Cargo.toml b/Cargo.toml index 8c1ee8c4514c1..d7a0330b0a670 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -406,15 +406,15 @@ reth-trie-db = { path = "crates/trie/db" } reth-trie-parallel = { path = "crates/trie/parallel" } # revm -revm = { version = "14.0.3", features = [ +revm = { git = "https://github.com/risechain/revm", rev = "53cdccac81148ef5bbdedfc34c7d526a5fb7d494", features = [ "std", "secp256k1", "blst", ], default-features = false } -revm-inspectors = "0.8.1" -revm-primitives = { version = "10.0.0", features = [ +revm-primitives = { git = "https://github.com/risechain/revm", rev = "53cdccac81148ef5bbdedfc34c7d526a5fb7d494", features = [ "std", ], default-features = false } +revm-inspectors = { git = "https://github.com/risechain/revm-inspectors", rev = "ec5ba7d2ce40a7f7aeae1d869365f2e4b8d8df02" } # eth alloy-chains = "0.1.32" diff --git a/crates/ethereum/evm/Cargo.toml b/crates/ethereum/evm/Cargo.toml index 61ce0a23b904b..050f61d42f4a8 100644 --- a/crates/ethereum/evm/Cargo.toml +++ b/crates/ethereum/evm/Cargo.toml @@ -29,6 +29,8 @@ alloy-primitives.workspace = true alloy-eips.workspace = true alloy-sol-types.workspace = true +pevm = { git = "https://github.com/risechain/pevm", rev = "1955ff251c2c1eb38f878e4eb4444edc1df2a4e7" } + [dev-dependencies] reth-testing-utils.workspace = true reth-revm = { workspace = true, features = ["test-utils"] } diff --git a/crates/ethereum/evm/src/execute.rs b/crates/ethereum/evm/src/execute.rs index f1d7de115d575..ea1d647474e80 100644 --- a/crates/ethereum/evm/src/execute.rs +++ b/crates/ethereum/evm/src/execute.rs @@ -6,7 +6,8 @@ use crate::{ }; use alloc::{boxed::Box, sync::Arc, vec, vec::Vec}; use alloy_primitives::{BlockNumber, U256}; -use core::fmt::Display; +use core::{fmt::Display, num::NonZeroUsize}; +use pevm::{chain::PevmEthereum, Pevm}; use reth_chainspec::{ChainSpec, EthereumHardforks, MAINNET}; use reth_ethereum_consensus::validate_block_post_execution; use reth_evm::{ @@ -27,7 +28,7 @@ use reth_revm::{ Evm, }; use revm_primitives::{ - db::{Database, DatabaseCommit}, + db::{DatabaseCommit, DatabaseRef}, BlockEnv, CfgEnvWithHandlerCfg, EnvWithHandlerCfg, ResultAndState, }; @@ -63,12 +64,15 @@ where { fn eth_executor(&self, db: DB) -> EthBlockExecutor where - DB: Database>, + DB: DatabaseRef + Display> + Send + Sync, { EthBlockExecutor::new( self.chain_spec.clone(), self.evm_config.clone(), State::builder().with_database(db).with_bundle_update().without_state_clear().build(), + Pevm::default(), + PevmEthereum::mainnet(), + NonZeroUsize::new(8).unwrap(), ) } } @@ -77,22 +81,22 @@ impl BlockExecutorProvider for EthExecutorProvider where EvmConfig: ConfigureEvm
, { - type Executor + Display>> = + type Executor + Display> + Send + Sync> = EthBlockExecutor; - type BatchExecutor + Display>> = + type BatchExecutor + Display> + Send + Sync> = EthBatchExecutor; fn executor(&self, db: DB) -> Self::Executor where - DB: Database + Display>, + DB: DatabaseRef + Display> + Send + Sync, { self.eth_executor(db) } fn batch_executor(&self, db: DB) -> Self::BatchExecutor where - DB: Database + Display>, + DB: DatabaseRef + Display> + Send + Sync, { let executor = self.eth_executor(db); EthBatchExecutor { executor, batch_record: BlockBatchRecord::default() } @@ -130,14 +134,13 @@ where /// /// It does __not__ apply post-execution changes that do not require an [EVM](Evm), for that see /// [`EthBlockExecutor::post_execution`]. - fn execute_state_transitions( + fn _execute_state_transitions( &self, block: &BlockWithSenders, mut evm: Evm<'_, Ext, &mut State>, - ) -> Result + ) -> Result<(EthExecuteOutput, Vec), BlockExecutionError> where - DB: Database, - DB::Error: Into + Display, + DB: DatabaseRef + Display> + Send + Sync, { let mut system_caller = SystemCaller::new(&self.evm_config, &self.chain_spec); @@ -146,6 +149,7 @@ where // execute transactions let mut cumulative_gas_used = 0; let mut receipts = Vec::with_capacity(block.body.transactions.len()); + let mut results = Vec::with_capacity(block.body.transactions.len()); for (sender, transaction) in block.transactions_with_sender() { // The sum of the transaction’s gas limit, Tg, and the gas utilized in this block prior, // must be no greater than the block’s gasLimit. @@ -155,13 +159,13 @@ where transaction_gas_limit: transaction.gas_limit(), block_available_gas, } - .into()) + .into()); } self.evm_config.fill_tx_env(evm.tx_mut(), transaction, *sender); // Execute transaction. - let ResultAndState { result, state } = evm.transact().map_err(move |err| { + let result_and_state = evm.transact().map_err(move |err| { let new_err = err.map_db_err(|e| e.into()); // Ensure hash is calculated for error log, if not already done BlockValidationError::EVM { @@ -169,10 +173,11 @@ where error: Box::new(new_err), } })?; - evm.db_mut().commit(state); + results.push(result_and_state.clone()); + evm.db_mut().commit(result_and_state.state); // append gas used - cumulative_gas_used += result.gas_used(); + cumulative_gas_used += result_and_state.result.gas_used(); // Push transaction changeset and calculate header bloom filter for receipt. receipts.push( @@ -181,10 +186,10 @@ where tx_type: transaction.tx_type(), // Success flag was added in `EIP-658: Embedding transaction status code in // receipts`. - success: result.is_success(), + success: result_and_state.result.is_success(), cumulative_gas_used, // convert to reth log - logs: result.into_logs(), + logs: result_and_state.result.into_logs(), ..Default::default() }, ); @@ -202,7 +207,7 @@ where vec![] }; - Ok(EthExecuteOutput { receipts, requests, gas_used: cumulative_gas_used }) + Ok((EthExecuteOutput { receipts, requests, gas_used: cumulative_gas_used }, results)) } } @@ -217,12 +222,29 @@ pub struct EthBlockExecutor { executor: EthEvmExecutor, /// The state to use for execution state: State, + /// Parallel executor + pevm: Pevm, + chain: PevmEthereum, + concurrency_level: NonZeroUsize, } impl EthBlockExecutor { /// Creates a new Ethereum block executor. - pub const fn new(chain_spec: Arc, evm_config: EvmConfig, state: State) -> Self { - Self { executor: EthEvmExecutor { chain_spec, evm_config }, state } + pub const fn new( + chain_spec: Arc, + evm_config: EvmConfig, + state: State, + pevm: Pevm, + chain: PevmEthereum, + concurrency_level: NonZeroUsize, + ) -> Self { + Self { + executor: EthEvmExecutor { chain_spec, evm_config }, + state, + pevm, + chain, + concurrency_level, + } } #[inline] @@ -240,14 +262,14 @@ impl EthBlockExecutor { impl EthBlockExecutor where EvmConfig: ConfigureEvm
, - DB: Database + Display>, + DB: DatabaseRef + Display> + Send + Sync, { /// Configures a new evm configuration and block environment for the given block. /// /// # Caution /// /// This does not initialize the tx environment. - fn evm_env_for_block(&self, header: &Header, total_difficulty: U256) -> EnvWithHandlerCfg { + fn _evm_env_for_block(&self, header: &Header, total_difficulty: U256) -> EnvWithHandlerCfg { let mut cfg = CfgEnvWithHandlerCfg::new(Default::default(), Default::default()); let mut block_env = BlockEnv::default(); self.executor.evm_config.fill_cfg_and_block_env( @@ -275,16 +297,60 @@ where self.on_new_block(&block.header); // 2. configure the evm and execute - let env = self.evm_env_for_block(&block.header, total_difficulty); - let output = { - let evm = self.executor.evm_config.evm_with_env(&mut self.state, env); - self.executor.execute_state_transitions(block, evm) - }?; + let spec_id = crate::config::revm_spec( + self.chain_spec(), + &reth_chainspec::Head { + number: block.header.number, + timestamp: block.header.timestamp, + difficulty: block.header.difficulty, + total_difficulty, + hash: Default::default(), + }, + ); + let mut block_env = BlockEnv::default(); + self.executor.evm_config.fill_block_env( + &mut block_env, + &block.header, + spec_id >= revm_primitives::SpecId::MERGE, + ); + let mut tx_envs = Vec::with_capacity(block.body.transactions.len()); + for (sender, transaction) in block.transactions_with_sender() { + let mut tx_env = revm_primitives::TxEnv::default(); + self.executor.evm_config.fill_tx_env(&mut tx_env, transaction, *sender); + tx_envs.push(tx_env); + } + let results = + if tx_envs.len() < self.concurrency_level.into() || block.header.gas_used < 4_000_000 { + pevm::execute_revm_sequential(&self.state, &self.chain, spec_id, block_env, tx_envs) + } else { + self.pevm.execute_revm_parallel( + &self.state, + &self.chain, + spec_id, + block_env, + tx_envs, + self.concurrency_level, + ) + } + .unwrap_or_else(|err| panic!("{:?}", err)); + let mut cumulative_gas_used = 0; + let mut receipts = Vec::with_capacity(block.body.transactions.len()); + for (tx, ResultAndState { result, state }) in block.body.transactions().zip(results) { + cumulative_gas_used += result.gas_used(); + receipts.push(Receipt { + tx_type: tx.tx_type(), + success: result.is_success(), + cumulative_gas_used, + logs: result.into_logs(), + ..Default::default() + }); + self.state.commit(state); + } // 3. apply post execution changes self.post_execution(block, total_difficulty)?; - Ok(output) + Ok(EthExecuteOutput { receipts, requests: Vec::new(), gas_used: cumulative_gas_used }) } /// Apply settings before a new block is executed. @@ -329,7 +395,7 @@ where impl Executor for EthBlockExecutor where EvmConfig: ConfigureEvm
, - DB: Database + Display>, + DB: DatabaseRef + Display> + Send + Sync, { type Input<'a> = BlockExecutionInput<'a, BlockWithSenders>; type Output = BlockExecutionOutput; @@ -393,7 +459,7 @@ impl EthBatchExecutor { impl BatchExecutor for EthBatchExecutor where EvmConfig: ConfigureEvm
, - DB: Database + Display>, + DB: DatabaseRef + Display> + Send + Sync, { type Input<'a> = BlockExecutionInput<'a, BlockWithSenders>; type Output = ExecutionOutcome; diff --git a/crates/ethereum/payload/src/lib.rs b/crates/ethereum/payload/src/lib.rs index 5d2fcde2f7e5d..bd8df1cf3f353 100644 --- a/crates/ethereum/payload/src/lib.rs +++ b/crates/ethereum/payload/src/lib.rs @@ -199,12 +199,12 @@ where // which also removes all dependent transaction from the iterator before we can // continue best_txs.mark_invalid(&pool_tx); - continue + continue; } // check if the job was cancelled, if so we can exit early if cancel.is_cancelled() { - return Ok(BuildOutcome::Cancelled) + return Ok(BuildOutcome::Cancelled); } // convert tx to a signed transaction @@ -221,7 +221,7 @@ where // for regular transactions above. trace!(target: "payload_builder", tx=?tx.hash, ?sum_blob_gas_used, ?tx_blob_gas, "skipping blob transaction because it would exceed the max data gas per block"); best_txs.mark_invalid(&pool_tx); - continue + continue; } } @@ -249,11 +249,11 @@ where best_txs.mark_invalid(&pool_tx); } - continue + continue; } err => { // this is an error that we should treat as fatal for this attempt - return Err(PayloadBuilderError::EvmExecutionError(err)) + return Err(PayloadBuilderError::EvmExecutionError(err)); } } } @@ -303,7 +303,7 @@ where // check if we have a better block if !is_better_payload(best_payload.as_ref(), total_fees) { // can skip building the block - return Ok(BuildOutcome::Aborted { fees: total_fees, cached_reads }) + return Ok(BuildOutcome::Aborted { fees: total_fees, cached_reads }); } // calculate the requests and the requests root @@ -354,7 +354,7 @@ where // calculate the state root let hashed_state = HashedPostState::from_bundle_state(&execution_outcome.state().state); let (state_root, trie_output) = { - let state_provider = db.database.0.inner.borrow_mut(); + let state_provider = db.database.inner.borrow_mut(); state_provider.db.state_root_with_updates(hashed_state.clone()).inspect_err(|err| { warn!(target: "payload_builder", parent_hash=%parent_block.hash(), diff --git a/crates/evm/src/either.rs b/crates/evm/src/either.rs index a3fca50ec7eee..9d5f0e0888ec9 100644 --- a/crates/evm/src/either.rs +++ b/crates/evm/src/either.rs @@ -9,7 +9,7 @@ use reth_execution_types::{BlockExecutionInput, BlockExecutionOutput, ExecutionO use reth_primitives::{BlockWithSenders, Receipt}; use reth_prune_types::PruneModes; use reth_storage_errors::provider::ProviderError; -use revm_primitives::db::Database; +use revm::DatabaseRef; // re-export Either pub use futures_util::future::Either; @@ -20,15 +20,15 @@ where A: BlockExecutorProvider, B: BlockExecutorProvider, { - type Executor + Display>> = + type Executor + Display> + Send + Sync> = Either, B::Executor>; - type BatchExecutor + Display>> = + type BatchExecutor + Display> + Send + Sync> = Either, B::BatchExecutor>; fn executor(&self, db: DB) -> Self::Executor where - DB: Database + Display>, + DB: DatabaseRef + Display> + Send + Sync, { match self { Self::Left(a) => Either::Left(a.executor(db)), @@ -38,7 +38,7 @@ where fn batch_executor(&self, db: DB) -> Self::BatchExecutor where - DB: Database + Display>, + DB: DatabaseRef + Display> + Send + Sync, { match self { Self::Left(a) => Either::Left(a.batch_executor(db)), @@ -61,7 +61,7 @@ where Output = BlockExecutionOutput, Error = BlockExecutionError, >, - DB: Database + Display>, + DB: DatabaseRef + Display>, { type Input<'a> = BlockExecutionInput<'a, BlockWithSenders>; type Output = BlockExecutionOutput; @@ -103,7 +103,7 @@ where Output = ExecutionOutcome, Error = BlockExecutionError, >, - DB: Database + Display>, + DB: DatabaseRef + Display>, { type Input<'a> = BlockExecutionInput<'a, BlockWithSenders>; type Output = ExecutionOutcome; diff --git a/crates/evm/src/execute.rs b/crates/evm/src/execute.rs index ffc08469dc8d6..144b7b533a4d2 100644 --- a/crates/evm/src/execute.rs +++ b/crates/evm/src/execute.rs @@ -10,7 +10,7 @@ use core::fmt::Display; use reth_primitives::{BlockWithSenders, Receipt}; use reth_prune_types::PruneModes; use revm::State; -use revm_primitives::db::Database; +use revm_primitives::db::DatabaseRef; /// A general purpose executor trait that executes an input (e.g. block) and produces an output /// (e.g. state changes and receipts). @@ -118,7 +118,7 @@ pub trait BlockExecutorProvider: Send + Sync + Clone + Unpin + 'static { /// /// It is not expected to validate the state trie root, this must be done by the caller using /// the returned state. - type Executor + Display>>: for<'a> Executor< + type Executor + Display> + Send + Sync>: for<'a> Executor< DB, Input<'a> = BlockExecutionInput<'a, BlockWithSenders>, Output = BlockExecutionOutput, @@ -126,7 +126,7 @@ pub trait BlockExecutorProvider: Send + Sync + Clone + Unpin + 'static { >; /// An executor that can execute a batch of blocks given a database. - type BatchExecutor + Display>>: for<'a> BatchExecutor< + type BatchExecutor + Display> + Send + Sync>: for<'a> BatchExecutor< DB, Input<'a> = BlockExecutionInput<'a, BlockWithSenders>, Output = ExecutionOutcome, @@ -138,7 +138,7 @@ pub trait BlockExecutorProvider: Send + Sync + Clone + Unpin + 'static { /// This is used to execute a single block and get the changed state. fn executor(&self, db: DB) -> Self::Executor where - DB: Database + Display>; + DB: DatabaseRef + Display> + Send + Sync; /// Creates a new batch executor with the given database and pruning modes. /// @@ -146,7 +146,7 @@ pub trait BlockExecutorProvider: Send + Sync + Clone + Unpin + 'static { /// during historical sync which involves executing multiple blocks in sequence. fn batch_executor(&self, db: DB) -> Self::BatchExecutor where - DB: Database + Display>; + DB: DatabaseRef + Display> + Send + Sync; } #[cfg(test)] @@ -160,19 +160,21 @@ mod tests { struct TestExecutorProvider; impl BlockExecutorProvider for TestExecutorProvider { - type Executor + Display>> = TestExecutor; - type BatchExecutor + Display>> = TestExecutor; + type Executor + Display> + Send + Sync> = + TestExecutor; + type BatchExecutor + Display> + Send + Sync> = + TestExecutor; - fn executor(&self, _db: DB) -> Self::Executor + fn executor(&self, _db: DB) -> Self::Executor where - DB: Database + Display>, + DB: DatabaseRef + Display>, { TestExecutor(PhantomData) } - fn batch_executor(&self, _db: DB) -> Self::BatchExecutor + fn batch_executor(&self, _db: DB) -> Self::BatchExecutor where - DB: Database + Display>, + DB: DatabaseRef + Display>, { TestExecutor(PhantomData) } diff --git a/crates/evm/src/noop.rs b/crates/evm/src/noop.rs index 392bfd0bd722d..45e8cfdeb4e29 100644 --- a/crates/evm/src/noop.rs +++ b/crates/evm/src/noop.rs @@ -8,7 +8,7 @@ use reth_primitives::{BlockWithSenders, Receipt}; use reth_prune_types::PruneModes; use reth_storage_errors::provider::ProviderError; use revm::State; -use revm_primitives::db::Database; +use revm_primitives::db::DatabaseRef; use crate::execute::{BatchExecutor, BlockExecutorProvider, Executor}; @@ -20,20 +20,20 @@ const UNAVAILABLE_FOR_NOOP: &str = "execution unavailable for noop"; pub struct NoopBlockExecutorProvider; impl BlockExecutorProvider for NoopBlockExecutorProvider { - type Executor + Display>> = Self; + type Executor + Display> + Send + Sync> = Self; - type BatchExecutor + Display>> = Self; + type BatchExecutor + Display> + Send + Sync> = Self; fn executor(&self, _: DB) -> Self::Executor where - DB: Database + Display>, + DB: DatabaseRef + Display> + Send + Sync, { Self } fn batch_executor(&self, _: DB) -> Self::BatchExecutor where - DB: Database + Display>, + DB: DatabaseRef + Display> + Send + Sync, { Self } diff --git a/crates/evm/src/test_utils.rs b/crates/evm/src/test_utils.rs index cf45930aece94..bdf2d75b5ff76 100644 --- a/crates/evm/src/test_utils.rs +++ b/crates/evm/src/test_utils.rs @@ -10,8 +10,7 @@ use reth_execution_types::ExecutionOutcome; use reth_primitives::{BlockWithSenders, Receipt}; use reth_prune_types::PruneModes; use reth_storage_errors::provider::ProviderError; -use revm::State; -use revm_primitives::db::Database; +use revm::{DatabaseRef, State}; use std::{fmt::Display, sync::Arc}; /// A [`BlockExecutorProvider`] that returns mocked execution results. @@ -28,20 +27,20 @@ impl MockExecutorProvider { } impl BlockExecutorProvider for MockExecutorProvider { - type Executor + Display>> = Self; + type Executor + Display> + Send + Sync> = Self; - type BatchExecutor + Display>> = Self; + type BatchExecutor + Display> + Send + Sync> = Self; fn executor(&self, _: DB) -> Self::Executor where - DB: Database + Display>, + DB: DatabaseRef + Display> + Send + Sync, { self.clone() } fn batch_executor(&self, _: DB) -> Self::BatchExecutor where - DB: Database + Display>, + DB: DatabaseRef + Display> + Send + Sync, { self.clone() } diff --git a/crates/payload/basic/src/lib.rs b/crates/payload/basic/src/lib.rs index f9487ec784ca3..57771636b9166 100644 --- a/crates/payload/basic/src/lib.rs +++ b/crates/payload/basic/src/lib.rs @@ -27,7 +27,7 @@ use reth_provider::{ use reth_revm::state_change::post_block_withdrawals_balance_increments; use reth_tasks::TaskSpawner; use reth_transaction_pool::TransactionPool; -use revm::{Database, State}; +use revm::{DatabaseRef, State}; use std::{ fmt, future::Future, @@ -399,7 +399,7 @@ where // check if the deadline is reached if this.deadline.as_mut().poll(cx).is_ready() { trace!(target: "payload_builder", "payload building deadline reached"); - return Poll::Ready(Ok(())) + return Poll::Ready(Ok(())); } // check if the interval is reached @@ -457,7 +457,7 @@ where fn best_payload(&self) -> Result { if let Some(ref payload) = self.best_payload { - return Ok(payload.clone()) + return Ok(payload.clone()); } // No payload has been built yet, but we need to return something that the CL then can // deliver, so we need to return an empty payload. @@ -575,14 +575,14 @@ where this.maybe_better = None; if let Ok(BuildOutcome::Better { payload, .. }) = res { debug!(target: "payload_builder", "resolving better payload"); - return Poll::Ready(Ok(payload)) + return Poll::Ready(Ok(payload)); } } } if let Some(best) = this.best_payload.take() { debug!(target: "payload_builder", "resolving best payload"); - return Poll::Ready(Ok(best)) + return Poll::Ready(Ok(best)); } if let Some(fut) = Pin::new(&mut this.empty_payload).as_pin_mut() { @@ -598,12 +598,12 @@ where Poll::Ready(res) } Err(err) => Poll::Ready(Err(err.into())), - } + }; } } if this.is_empty() { - return Poll::Ready(Err(PayloadBuilderError::MissingPayload)) + return Poll::Ready(Err(PayloadBuilderError::MissingPayload)); } Poll::Pending @@ -900,18 +900,18 @@ impl WithdrawalsOutcome { /// Returns the withdrawals root. /// /// Returns `None` values pre shanghai -pub fn commit_withdrawals>( +pub fn commit_withdrawals>( db: &mut State, chain_spec: &ChainSpec, timestamp: u64, withdrawals: Withdrawals, ) -> Result { if !chain_spec.is_shanghai_active_at_timestamp(timestamp) { - return Ok(WithdrawalsOutcome::pre_shanghai()) + return Ok(WithdrawalsOutcome::pre_shanghai()); } if withdrawals.is_empty() { - return Ok(WithdrawalsOutcome::empty()) + return Ok(WithdrawalsOutcome::empty()); } let balance_increments = diff --git a/crates/rpc/rpc/src/debug.rs b/crates/rpc/rpc/src/debug.rs index 1e57607689909..445a63821260e 100644 --- a/crates/rpc/rpc/src/debug.rs +++ b/crates/rpc/rpc/src/debug.rs @@ -630,10 +630,12 @@ where .cache .contracts .iter() - .map(|(hash, code)| (*hash, code.bytes())) + .map(|r| (*r.key(), r.value().bytes())) .collect(); - for (address, account) in &statedb.cache.accounts { + for r in &statedb.cache.accounts { + let address = r.key(); + let account = r.value(); let hashed_address = keccak256(address); hashed_state.accounts.insert( hashed_address, diff --git a/crates/storage/libmdbx-rs/src/transaction.rs b/crates/storage/libmdbx-rs/src/transaction.rs index 88236ebe99144..497d66f7b0539 100644 --- a/crates/storage/libmdbx-rs/src/transaction.rs +++ b/crates/storage/libmdbx-rs/src/transaction.rs @@ -524,7 +524,7 @@ impl Transaction { /// Begins a new nested transaction inside of this transaction. pub fn begin_nested_txn(&mut self) -> Result { if self.inner.env.is_write_map() { - return Err(Error::NestedTransactionsUnsupportedWithWriteMap) + return Err(Error::NestedTransactionsUnsupportedWithWriteMap); } self.txn_execute(|txn| { let (tx, rx) = sync_channel(0); @@ -580,12 +580,12 @@ impl TransactionPtr { if let Some(lock) = self.lock.try_lock() { lock } else { - tracing::debug!( - target: "libmdbx", - txn = %self.txn as usize, - backtrace = %std::backtrace::Backtrace::force_capture(), - "Transaction lock is already acquired, blocking..." - ); + // tracing::debug!( + // target: "libmdbx", + // txn = %self.txn as usize, + // backtrace = %std::backtrace::Backtrace::force_capture(), + // "Transaction lock is already acquired, blocking..." + // ); self.lock.lock() } } @@ -605,7 +605,7 @@ impl TransactionPtr { // to the `mdbx_txn_reset`. #[cfg(feature = "read-tx-timeouts")] if self.is_timed_out() { - return Err(Error::ReadTransactionTimeout) + return Err(Error::ReadTransactionTimeout); } Ok((f)(self.txn))