Skip to main content

reth_node_core/
utils.rs

1//! Utility functions for node startup and shutdown, for example path parsing and retrieving single
2//! blocks from the network.
3
4use alloy_consensus::BlockHeader;
5use alloy_eips::BlockHashOrNumber;
6use alloy_rpc_types_engine::{JwtError, JwtSecret};
7use eyre::Result;
8use reth_consensus::Consensus;
9use reth_network_p2p::{
10    bodies::client::BodiesClient, headers::client::HeadersClient, priority::Priority,
11};
12use reth_primitives_traits::{Block, SealedBlock, SealedHeader};
13use std::path::{Path, PathBuf};
14use tracing::{debug, info};
15
16/// Parses a user-specified path into a [`PathBuf`].
17pub fn parse_path(value: &str) -> PathBuf {
18    PathBuf::from(value)
19}
20
21/// Attempts to retrieve or create a JWT secret from the specified path.
22pub fn get_or_create_jwt_secret_from_path(path: &Path) -> Result<JwtSecret, JwtError> {
23    if path.exists() {
24        debug!(target: "reth::cli", ?path, "Reading JWT auth secret file");
25        JwtSecret::from_file(path)
26    } else {
27        info!(target: "reth::cli", ?path, "Creating JWT auth secret file");
28        JwtSecret::try_create_random(path)
29    }
30}
31
32/// Get a single header from the network
33pub async fn get_single_header<Client>(
34    client: Client,
35    id: BlockHashOrNumber,
36) -> Result<SealedHeader<Client::Header>>
37where
38    Client: HeadersClient<Header: reth_primitives_traits::BlockHeader>,
39{
40    let (peer_id, response) = client.get_header_with_priority(id, Priority::High).await?.split();
41
42    let Some(header) = response else {
43        client.report_bad_message(peer_id);
44        eyre::bail!("Invalid number of headers received. Expected: 1. Received: 0")
45    };
46
47    let header = SealedHeader::seal_slow(header);
48
49    let valid = match id {
50        BlockHashOrNumber::Hash(hash) => header.hash() == hash,
51        BlockHashOrNumber::Number(number) => header.number() == number,
52    };
53
54    if !valid {
55        client.report_bad_message(peer_id);
56        eyre::bail!(
57            "Received invalid header. Received: {:?}. Expected: {:?}",
58            header.num_hash(),
59            id
60        );
61    }
62
63    Ok(header)
64}
65
66/// Get a body from the network based on header
67pub async fn get_single_body<B, Client>(
68    client: Client,
69    header: SealedHeader<B::Header>,
70    consensus: impl Consensus<B>,
71) -> Result<SealedBlock<B>>
72where
73    B: Block,
74    Client: BodiesClient<Body = B::Body>,
75{
76    let (peer_id, response) = client.get_block_body(header.hash()).await?.split();
77
78    let Some(body) = response else {
79        client.report_bad_message(peer_id);
80        eyre::bail!("Invalid number of bodies received. Expected: 1. Received: 0")
81    };
82
83    let block = SealedBlock::from_sealed_parts(header, body);
84    consensus.validate_block_pre_execution(&block)?;
85
86    Ok(block)
87}