From 7b1aee2d9c4e1d05a90c0340b87a225f94bed132 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Mon, 1 May 2023 21:08:43 +0200 Subject: [PATCH] feat: add helper for accessing pending block object (#2465) --- crates/blockchain-tree/src/block_indices.rs | 8 ++++++++ crates/blockchain-tree/src/blockchain_tree.rs | 6 ++++++ crates/blockchain-tree/src/shareable.rs | 10 +++++++--- crates/interfaces/src/blockchain_tree.rs | 7 ++++++- crates/storage/provider/src/providers/mod.rs | 15 ++++++++++----- 5 files changed, 37 insertions(+), 9 deletions(-) diff --git a/crates/blockchain-tree/src/block_indices.rs b/crates/blockchain-tree/src/block_indices.rs index dc523f80ad..3fe3c5e0bf 100644 --- a/crates/blockchain-tree/src/block_indices.rs +++ b/crates/blockchain-tree/src/block_indices.rs @@ -59,6 +59,14 @@ impl BlockIndices { &self.blocks_to_chain } + /// Returns the hash and number of the pending block (the first block in the + /// [Self::pending_blocks]) set. + pub fn pending_block_num_hash(&self) -> Option { + let canonical_tip = self.canonical_tip(); + let hash = self.fork_to_child.get(&canonical_tip.hash)?.iter().next().copied()?; + Some(BlockNumHash { number: canonical_tip.number + 1, hash }) + } + /// Return all pending block hashes. Pending blocks are considered blocks /// that are extending that canonical tip by one block number. pub fn pending_blocks(&self) -> (BlockNumber, Vec) { diff --git a/crates/blockchain-tree/src/blockchain_tree.rs b/crates/blockchain-tree/src/blockchain_tree.rs index 965dc7cfa4..bd5d5a59c2 100644 --- a/crates/blockchain-tree/src/blockchain_tree.rs +++ b/crates/blockchain-tree/src/blockchain_tree.rs @@ -163,6 +163,12 @@ impl BlockchainTree chain.block(block_hash) } + /// Returns the block that's considered the `Pending` block, if it exists. + pub fn pending_block(&self) -> Option<&SealedBlock> { + let b = self.block_indices.pending_block_num_hash()?; + self.block_by_hash(b.hash) + } + /// Return items needed to execute on the pending state. /// This includes: /// * `BlockHash` of canonical block that chain connects to. Needed for creating database diff --git a/crates/blockchain-tree/src/shareable.rs b/crates/blockchain-tree/src/shareable.rs index 6843514373..9830284600 100644 --- a/crates/blockchain-tree/src/shareable.rs +++ b/crates/blockchain-tree/src/shareable.rs @@ -102,10 +102,14 @@ impl BlockchainTreeViewer self.tree.read().block_indices().pending_blocks() } - fn pending_block(&self) -> Option { + fn pending_block_num_hash(&self) -> Option { trace!(target: "blockchain_tree", "Returning first pending block"); - let (number, blocks) = self.tree.read().block_indices().pending_blocks(); - blocks.first().map(|&hash| BlockNumHash { number, hash }) + self.tree.read().block_indices().pending_block_num_hash() + } + + fn pending_block(&self) -> Option { + trace!(target: "blockchain_tree", "Returning first pending block"); + self.tree.read().pending_block().cloned() } } diff --git a/crates/interfaces/src/blockchain_tree.rs b/crates/interfaces/src/blockchain_tree.rs index 37cd9fad74..85f27127b1 100644 --- a/crates/interfaces/src/blockchain_tree.rs +++ b/crates/interfaces/src/blockchain_tree.rs @@ -105,5 +105,10 @@ pub trait BlockchainTreeViewer: Send + Sync { /// Return block hashes that extends the canonical chain tip by one. /// /// If there is no such block, return `None`. - fn pending_block(&self) -> Option; + fn pending_block_num_hash(&self) -> Option; + + /// Returns the pending block if there is one. + fn pending_block(&self) -> Option { + self.block_by_hash(self.pending_block_num_hash()?.hash) + } } diff --git a/crates/storage/provider/src/providers/mod.rs b/crates/storage/provider/src/providers/mod.rs index 580ab3405d..ff0d16ceb5 100644 --- a/crates/storage/provider/src/providers/mod.rs +++ b/crates/storage/provider/src/providers/mod.rs @@ -109,7 +109,9 @@ where let num = match num { BlockNumberOrTag::Latest => self.chain_info()?.best_number, BlockNumberOrTag::Number(num) => num, - BlockNumberOrTag::Pending => return Ok(self.tree.pending_block().map(|b| b.number)), + BlockNumberOrTag::Pending => { + return Ok(self.tree.pending_block_num_hash().map(|b| b.number)) + } BlockNumberOrTag::Finalized => return Ok(self.chain_info()?.last_finalized), BlockNumberOrTag::Safe => return Ok(self.chain_info()?.safe_finalized), BlockNumberOrTag::Earliest => 0, @@ -122,7 +124,7 @@ where BlockId::Hash(hash) => Ok(Some(hash.into())), BlockId::Number(num) => match num { BlockNumberOrTag::Latest => Ok(Some(self.chain_info()?.best_hash)), - BlockNumberOrTag::Pending => Ok(self.tree.pending_block().map(|b| b.hash)), + BlockNumberOrTag::Pending => Ok(self.tree.pending_block_num_hash().map(|b| b.hash)), _ => self .convert_block_number(num)? .map(|num| self.block_hash(num)) @@ -162,6 +164,9 @@ where } fn block(&self, id: BlockId) -> Result> { + if id.is_pending() { + return Ok(self.tree.pending_block().map(SealedBlock::unseal)) + } self.database.block(id) } @@ -314,7 +319,7 @@ where fn pending(&self) -> Result> { trace!(target: "providers::blockchain", "Getting provider for pending state"); - if let Some(block) = self.tree.pending_block() { + if let Some(block) = self.tree.pending_block_num_hash() { let pending = self.tree.pending_state_provider(block.hash)?; return self.pending_with_provider(pending) } @@ -389,8 +394,8 @@ where self.tree.pending_blocks() } - fn pending_block(&self) -> Option { - self.tree.pending_block() + fn pending_block_num_hash(&self) -> Option { + self.tree.pending_block_num_hash() } }