Skip to content

Commit

Permalink
fix: ensure parent hash and number match (paradigmxyz#2546)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattsse authored May 3, 2023
1 parent 9c74fb8 commit 010b600
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 4 deletions.
15 changes: 14 additions & 1 deletion crates/blockchain-tree/src/block_indices.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,11 +337,24 @@ impl BlockIndices {
lose_chains
}

/// get canonical hash
/// Returns the block hash of the canonical block with the given number.
pub fn canonical_hash(&self, block_number: BlockNumber) -> Option<BlockHash> {
self.canonical_chain.get(&block_number).cloned()
}

/// Returns the block number of the canonical block with the given hash.
pub fn canonical_number(&self, block_hash: BlockHash) -> Option<BlockNumber> {
self.canonical_chain.iter().find_map(
|(number, hash)| {
if *hash == block_hash {
Some(*number)
} else {
None
}
},
)
}

/// get canonical tip
pub fn canonical_tip(&self) -> BlockNumHash {
self.canonical_chain
Expand Down
24 changes: 21 additions & 3 deletions crates/blockchain-tree/src/blockchain_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ use crate::{
};
use reth_db::{cursor::DbCursorRO, database::Database, tables, transaction::DbTx};
use reth_interfaces::{
blockchain_tree::BlockStatus, consensus::Consensus, executor::Error as ExecError, Error,
blockchain_tree::BlockStatus,
consensus::{Consensus, ConsensusError},
executor::Error as ExecError,
Error,
};
use reth_primitives::{
BlockHash, BlockNumHash, BlockNumber, ForkBlock, Hardfork, SealedBlock, SealedBlockWithSenders,
Expand Down Expand Up @@ -309,8 +312,10 @@ impl<DB: Database, C: Consensus, EF: ExecutorFactory> BlockchainTree<DB, C, EF>
return status
}

let canonical_parent_block = self.block_indices.canonical_hash(parent.number);

// if not found, check if the parent can be found inside canonical chain.
if Some(parent.hash) == self.block_indices.canonical_hash(parent.number) {
if Some(parent.hash) == canonical_parent_block {
// create new chain that points to that block
//return self.fork_canonical_chain(block.clone());
// TODO save pending block to database
Expand Down Expand Up @@ -354,14 +359,27 @@ impl<DB: Database, C: Consensus, EF: ExecutorFactory> BlockchainTree<DB, C, EF>
return Ok(block_status)
}

// this is another check to ensure that if the block points to a canonical block its block
// is valid
if let Some(canonical_parent_number) =
self.block_indices.canonical_number(block.parent_hash)
{
// we found the parent block in canonical chain
if canonical_parent_number != parent.number {
return Err(Error::Consensus(ConsensusError::ParentBlockNumberMismatch {
parent_block_number: canonical_parent_number,
block_number: block.number,
}))
}
}

// if there is a parent inside the buffer, validate against it.
if let Some(buffered_parent) = self.buffered_blocks.block(parent) {
self.externals.consensus.validate_header_against_parent(&block, buffered_parent)?
}

// insert block inside unconnected block buffer. Delaying it execution.
self.buffered_blocks.insert_block(block);

Ok(BlockStatus::Disconnected)
}

Expand Down
3 changes: 3 additions & 0 deletions crates/rpc/rpc-types/src/eth/engine/payload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,9 @@ pub enum PayloadValidationError {
/// Thrown when a forkchoice update's head links to a previously rejected payload.
#[error("links to previously rejected block")]
LinksToRejectedPayload,
/// Thrown when a new payload contains a wrong block number.
#[error("invalid block number")]
InvalidBlockNumber,
}

#[cfg(test)]
Expand Down

0 comments on commit 010b600

Please sign in to comment.