From 2711178ee9b0e8408fce69e027bc7cec3ed50d1a Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Fri, 26 May 2023 18:59:39 +0200 Subject: [PATCH] perf: use single tx for converting hash to number (#2870) --- .../provider/src/providers/database.rs | 59 ++++++++++++++----- 1 file changed, 43 insertions(+), 16 deletions(-) diff --git a/crates/storage/provider/src/providers/database.rs b/crates/storage/provider/src/providers/database.rs index 710e815b1..6a76d9f9f 100644 --- a/crates/storage/provider/src/providers/database.rs +++ b/crates/storage/provider/src/providers/database.rs @@ -192,7 +192,7 @@ impl BlockNumProvider for ShareableDatabase { } fn block_number(&self, hash: H256) -> Result> { - self.db.view(|tx| tx.get::(hash))?.map_err(Into::into) + self.db.view(|tx| read_block_number(tx, hash))?.map_err(Into::into) } } @@ -206,10 +206,10 @@ impl BlockProvider for ShareableDatabase { } fn block(&self, id: BlockHashOrNumber) -> Result> { - if let Some(number) = self.convert_hash(id)? { + let tx = self.db.tx()?; + if let Some(number) = convert_hash_or_number(&tx, id)? { if let Some(header) = self.header_by_number(number)? { let id = BlockHashOrNumber::Number(number); - let tx = self.db.tx()?; let transactions = self .transactions_by_block(id)? .ok_or(ProviderError::BlockBodyIndicesNotFound(number))?; @@ -234,8 +234,8 @@ impl BlockProvider for ShareableDatabase { } fn ommers(&self, id: BlockHashOrNumber) -> Result>> { - if let Some(number) = self.convert_hash(id)? { - let tx = self.db.tx()?; + let tx = self.db.tx()?; + if let Some(number) = convert_hash_or_number(&tx, id)? { // TODO: this can be optimized to return empty Vec post-merge let ommers = tx.get::(number)?.map(|o| o.ommers); return Ok(ommers) @@ -328,8 +328,8 @@ impl TransactionsProvider for ShareableDatabase { &self, id: BlockHashOrNumber, ) -> Result>> { - if let Some(number) = self.convert_hash(id)? { - let tx = self.db.tx()?; + let tx = self.db.tx()?; + if let Some(number) = convert_hash_or_number(&tx, id)? { if let Some(body) = tx.get::(number)? { let tx_range = body.tx_num_range(); return if tx_range.is_empty() { @@ -391,8 +391,8 @@ impl ReceiptProvider for ShareableDatabase { } fn receipts_by_block(&self, block: BlockHashOrNumber) -> Result>> { - if let Some(number) = self.convert_hash(block)? { - let tx = self.db.tx()?; + let tx = self.db.tx()?; + if let Some(number) = convert_hash_or_number(&tx, block)? { if let Some(body) = tx.get::(number)? { let tx_range = body.tx_num_range(); return if tx_range.is_empty() { @@ -418,15 +418,15 @@ impl WithdrawalsProvider for ShareableDatabase { timestamp: u64, ) -> Result>> { if self.chain_spec.fork(Hardfork::Shanghai).active_at_timestamp(timestamp) { - if let Some(number) = self.convert_hash(id)? { + let tx = self.db.tx()?; + if let Some(number) = convert_hash_or_number(&tx, id)? { // If we are past shanghai, then all blocks should have a withdrawal list, even if // empty - return Ok(Some( - self.db - .view(|tx| tx.get::(number))?? - .map(|w| w.withdrawals) - .unwrap_or_default(), - )) + let withdrawals = tx + .get::(number)? + .map(|w| w.withdrawals) + .unwrap_or_default(); + return Ok(Some(withdrawals)) } } Ok(None) @@ -511,6 +511,33 @@ impl EvmEnvProvider for ShareableDatabase { } } +/// Returns the block number for the given block hash or number. +#[inline] +fn convert_hash_or_number<'a, TX>( + tx: &TX, + block: BlockHashOrNumber, +) -> std::result::Result, reth_interfaces::db::DatabaseError> +where + TX: DbTx<'a> + Send + Sync, +{ + match block { + BlockHashOrNumber::Hash(hash) => read_block_number(tx, hash), + BlockHashOrNumber::Number(number) => Ok(Some(number)), + } +} + +/// Reads the number for the given block hash. +#[inline] +fn read_block_number<'a, TX>( + tx: &TX, + hash: H256, +) -> std::result::Result, reth_interfaces::db::DatabaseError> +where + TX: DbTx<'a> + Send + Sync, +{ + tx.get::(hash) +} + /// Reads the hash for the given block number /// /// Returns an error if no matching entry is found.