mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
chore(tree): minor Chain modifications (#5487)
This commit is contained in:
@ -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.
|
||||
@ -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 })
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
@ -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
|
||||
@ -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,
|
||||
@ -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(())
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
@ -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 {
|
||||
@ -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()
|
||||
@ -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(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user