Skip to main content

ethrex_p2p/
backend.rs

1use ethrex_common::types::ForkId;
2use ethrex_storage::{Store, error::StoreError};
3
4use crate::rlpx::{error::PeerConnectionError, eth::status::StatusMessage, p2p::Capability};
5
6pub async fn validate_status<ST: StatusMessage>(
7    msg_data: ST,
8    storage: &Store,
9    eth_capability: &Capability,
10) -> Result<(), PeerConnectionError> {
11    //Check networkID
12    let chain_config = storage.get_chain_config();
13    if msg_data.get_network_id() != chain_config.chain_id {
14        return Err(PeerConnectionError::HandshakeError(
15            "Network Id does not match".to_string(),
16        ));
17    }
18    //Check Protocol Version
19    if msg_data.get_eth_version() != eth_capability.version {
20        return Err(PeerConnectionError::HandshakeError(
21            "Eth protocol version does not match".to_string(),
22        ));
23    }
24    //Check Genesis
25    let genesis_header = storage
26        .get_block_header(0)?
27        .ok_or(PeerConnectionError::NotFound("Genesis Block".to_string()))?;
28    let genesis_hash = genesis_header.hash();
29    if msg_data.get_genesis() != genesis_hash {
30        return Err(PeerConnectionError::HandshakeError(
31            "Genesis does not match".to_string(),
32        ));
33    }
34    // Check ForkID
35    if !is_fork_id_valid(storage, &msg_data.get_fork_id()).await? {
36        return Err(PeerConnectionError::HandshakeError(
37            "Invalid Fork Id".to_string(),
38        ));
39    }
40    Ok(())
41}
42
43/// Validates the fork id from a remote node is valid.
44pub async fn is_fork_id_valid(
45    storage: &Store,
46    remote_fork_id: &ForkId,
47) -> Result<bool, StoreError> {
48    let chain_config = storage.get_chain_config();
49    let genesis_header = storage
50        .get_block_header(0)?
51        .ok_or(StoreError::Custom("Latest block not in DB".to_string()))?;
52    let latest_block_number = storage.get_latest_block_number().await?;
53    let latest_block_header = storage
54        .get_block_header(latest_block_number)?
55        .ok_or(StoreError::Custom("Latest block not in DB".to_string()))?;
56    let local_fork_id = ForkId::new(
57        chain_config,
58        genesis_header.clone(),
59        latest_block_header.timestamp,
60        latest_block_number,
61    );
62    Ok(local_fork_id.is_valid(
63        remote_fork_id.clone(),
64        latest_block_number,
65        latest_block_header.timestamp,
66        chain_config,
67        genesis_header,
68    ))
69}