Skip to content

Commit

Permalink
chore(tree): minor Chain modifications (#5487)
Browse files Browse the repository at this point in the history
  • Loading branch information
rkrasiuk authored Nov 18, 2023
1 parent 6e6e873 commit 49d69c6
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 45 deletions.
21 changes: 10 additions & 11 deletions crates/blockchain-tree/src/blockchain_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -546,8 +546,9 @@ impl<DB: Database, EF: ExecutorFactory> BlockchainTree<DB, EF> {
let Some(chain) = self.state.chains.get(&chain_id) else { return hashes };
hashes.extend(chain.blocks().values().map(|b| (b.number, b.hash())));

let fork_block = chain.fork_block_hash();
if let Some(next_chain_id) = self.block_indices().get_blocks_chain_id(&fork_block) {
let fork_block = chain.fork_block();
if let Some(next_chain_id) = self.block_indices().get_blocks_chain_id(&fork_block.hash)
{
chain_id = next_chain_id;
} else {
// if there is no fork block that point to other chains, break the loop.
Expand Down Expand Up @@ -794,7 +795,7 @@ impl<DB: Database, EF: ExecutorFactory> BlockchainTree<DB, EF> {
// check unconnected block buffer for childs of the chains
let mut all_chain_blocks = Vec::new();
for (_, chain) in self.state.chains.iter() {
for (&number, blocks) in chain.blocks.iter() {
for (&number, blocks) in chain.blocks().iter() {
all_chain_blocks.push(BlockNumHash { number, hash: blocks.hash })
}
}
Expand Down Expand Up @@ -946,18 +947,16 @@ impl<DB: Database, EF: ExecutorFactory> BlockchainTree<DB, EF> {
let canonical = self.split_chain(chain_id, chain, ChainSplitTarget::Hash(*block_hash));
durations_recorder.record_relative(MakeCanonicalAction::SplitChain);

let mut block_fork = canonical.fork_block();
let mut block_fork_number = canonical.fork_block_number();
let mut fork_block = canonical.fork_block();
let mut chains_to_promote = vec![canonical];

// loop while fork blocks are found in Tree.
while let Some(chain_id) = self.block_indices().get_blocks_chain_id(&block_fork.hash) {
let chain = self.state.chains.remove(&chain_id).expect("To fork to be present");
block_fork = chain.fork_block();
while let Some(chain_id) = self.block_indices().get_blocks_chain_id(&fork_block.hash) {
let chain = self.state.chains.remove(&chain_id).expect("fork is present");
// canonical chain is lower part of the chain.
let canonical =
self.split_chain(chain_id, chain, ChainSplitTarget::Number(block_fork_number));
block_fork_number = canonical.fork_block_number();
self.split_chain(chain_id, chain, ChainSplitTarget::Number(fork_block.number));
fork_block = canonical.fork_block();
chains_to_promote.push(canonical);
}
durations_recorder.record_relative(MakeCanonicalAction::SplitChainForks);
Expand Down Expand Up @@ -989,7 +988,7 @@ impl<DB: Database, EF: ExecutorFactory> BlockchainTree<DB, EF> {
);

// if joins to the tip;
if new_canon_chain.fork_block_hash() == old_tip.hash {
if new_canon_chain.fork_block().hash == old_tip.hash {
chain_notification =
CanonStateNotification::Commit { new: Arc::new(new_canon_chain.clone()) };
// append to database
Expand Down
14 changes: 5 additions & 9 deletions crates/blockchain-tree/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ impl AppendableChain {
)
})?;

let mut state = self.state.clone();
let mut state = self.state().clone();

// Revert state to the state after execution of the parent block
state.revert_to(parent.number);
Expand All @@ -169,11 +169,8 @@ impl AppendableChain {
.map_err(|err| InsertBlockError::new(block.block.clone(), err.into()))?;
state.extend(block_state);

let chain =
Self { chain: Chain { state, blocks: BTreeMap::from([(block.number, block)]) } };

// If all is okay, return new chain back. Present chain is not modified.
Ok(chain)
Ok(Self { chain: Chain::from_block(block, state) })
}

/// Validate and execute the given block that _extends the canonical chain_, validating its
Expand Down Expand Up @@ -280,10 +277,10 @@ impl AppendableChain {
DB: Database,
EF: ExecutorFactory,
{
let (_, parent_block) = self.blocks.last_key_value().expect("Chain has at least one block");
let parent_block = self.chain.tip();

let post_state_data = BundleStateDataRef {
state: &self.state,
state: self.state(),
sidechain_block_hashes: &side_chain_block_hashes,
canonical_block_hashes,
canonical_fork,
Expand All @@ -299,8 +296,7 @@ impl AppendableChain {
)
.map_err(|err| InsertBlockError::new(block.block.clone(), err.into()))?;
// extend the state.
self.state.extend(block_state);
self.blocks.insert(block.number, block);
self.chain.append_block(block, block_state);
Ok(())
}
}
Expand Down
54 changes: 29 additions & 25 deletions crates/storage/provider/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,29 @@ use std::{borrow::Cow, collections::BTreeMap, fmt};
/// Used inside the BlockchainTree.
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct Chain {
/// All blocks in this chain.
blocks: BTreeMap<BlockNumber, SealedBlockWithSenders>,
/// The state of all accounts after execution of the _all_ blocks in this chain's range from
/// [Chain::first] to [Chain::tip], inclusive.
///
/// This state also contains the individual changes that lead to the current state.
pub state: BundleStateWithReceipts,
/// All blocks in this chain.
pub blocks: BTreeMap<BlockNumber, SealedBlockWithSenders>,
state: BundleStateWithReceipts,
}

impl Chain {
/// Create new Chain from blocks and state.
pub fn new(
blocks: impl IntoIterator<Item = SealedBlockWithSenders>,
state: BundleStateWithReceipts,
) -> Self {
Self { blocks: BTreeMap::from_iter(blocks.into_iter().map(|b| (b.number, b))), state }
}

/// Create new Chain from a single block and its state.
pub fn from_block(block: SealedBlockWithSenders, state: BundleStateWithReceipts) -> Self {
Self::new([block], state)
}

/// Get the blocks in this chain.
pub fn blocks(&self) -> &BTreeMap<BlockNumber, SealedBlockWithSenders> {
&self.blocks
Expand Down Expand Up @@ -96,18 +109,6 @@ impl Chain {
ForkBlock { number: first.number.saturating_sub(1), hash: first.parent_hash }
}

/// Get the block number at which this chain forked.
#[track_caller]
pub fn fork_block_number(&self) -> BlockNumber {
self.first().number.saturating_sub(1)
}

/// Get the block hash at which this chain forked.
#[track_caller]
pub fn fork_block_hash(&self) -> BlockHash {
self.first().parent_hash
}

/// Get the first block in this chain.
#[track_caller]
pub fn first(&self) -> &SealedBlockWithSenders {
Expand All @@ -124,11 +125,6 @@ impl Chain {
self.blocks.last_key_value().expect("Chain should have at least one block").1
}

/// Create new chain with given blocks and post state.
pub fn new(blocks: Vec<SealedBlockWithSenders>, state: BundleStateWithReceipts) -> Self {
Self { state, blocks: blocks.into_iter().map(|b| (b.number, b)).collect() }
}

/// Returns length of the chain.
pub fn len(&self) -> usize {
self.blocks.len()
Expand Down Expand Up @@ -160,22 +156,30 @@ impl Chain {
receipt_attch
}

/// Append a single block with state to the chain.
/// This method assumes that blocks attachment to the chain has already been validated.
pub fn append_block(&mut self, block: SealedBlockWithSenders, state: BundleStateWithReceipts) {
self.blocks.insert(block.number, block);
self.state.extend(state);
}

/// Merge two chains by appending the given chain into the current one.
///
/// The state of accounts for this chain is set to the state of the newest chain.
pub fn append_chain(&mut self, chain: Chain) -> RethResult<()> {
pub fn append_chain(&mut self, other: Chain) -> RethResult<()> {
let chain_tip = self.tip();
if chain_tip.hash != chain.fork_block_hash() {
let other_fork_block = other.fork_block();
if chain_tip.hash != other_fork_block.hash {
return Err(BlockExecutionError::AppendChainDoesntConnect {
chain_tip: Box::new(chain_tip.num_hash()),
other_chain_fork: Box::new(chain.fork_block()),
other_chain_fork: Box::new(other_fork_block),
}
.into())
}

// Insert blocks from other chain
self.blocks.extend(chain.blocks);
self.state.extend(chain.state);
self.blocks.extend(other.blocks);
self.state.extend(other.state);

Ok(())
}
Expand Down

0 comments on commit 49d69c6

Please sign in to comment.