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