reth_bench/bench/context.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
//! This contains the [`BenchContext`], which is information that all replay-based benchmarks need.
//! The initialization code is also the same, so this can be shared across benchmark commands.
use crate::{authenticated_transport::AuthenticatedTransportConnect, bench_mode::BenchMode};
use alloy_eips::BlockNumberOrTag;
use alloy_provider::{network::AnyNetwork, Provider, ProviderBuilder, RootProvider};
use alloy_rpc_client::ClientBuilder;
use alloy_rpc_types_engine::JwtSecret;
use alloy_transport::BoxTransport;
use alloy_transport_http::Http;
use reqwest::{Client, Url};
use reth_node_core::args::BenchmarkArgs;
use tracing::info;
/// This is intended to be used by benchmarks that replay blocks from an RPC.
///
/// It contains an authenticated provider for engine API queries, a block provider for block
/// queries, a [`BenchMode`] to determine whether the benchmark should run for a closed or open
/// range of blocks, and the next block to fetch.
pub(crate) struct BenchContext {
/// The auth provider is used for engine API queries.
pub(crate) auth_provider: RootProvider<BoxTransport, AnyNetwork>,
/// The block provider is used for block queries.
pub(crate) block_provider: RootProvider<Http<Client>, AnyNetwork>,
/// The benchmark mode, which defines whether the benchmark should run for a closed or open
/// range of blocks.
pub(crate) benchmark_mode: BenchMode,
/// The next block to fetch.
pub(crate) next_block: u64,
}
impl BenchContext {
/// This is the initialization code for most benchmarks, taking in a [`BenchmarkArgs`] and
/// returning the providers needed to run a benchmark.
pub(crate) async fn new(bench_args: &BenchmarkArgs, rpc_url: String) -> eyre::Result<Self> {
info!("Running benchmark using data from RPC URL: {}", rpc_url);
// Ensure that output directory is a directory
if let Some(output) = &bench_args.output {
if output.is_file() {
return Err(eyre::eyre!("Output path must be a directory"));
}
}
// set up alloy client for blocks
let block_provider =
ProviderBuilder::new().network::<AnyNetwork>().on_http(rpc_url.parse()?);
// If neither `--from` nor `--to` are provided, we will run the benchmark continuously,
// starting at the latest block.
let mut benchmark_mode = BenchMode::new(bench_args.from, bench_args.to)?;
// construct the authenticated provider
let auth_jwt = bench_args
.auth_jwtsecret
.clone()
.ok_or_else(|| eyre::eyre!("--jwtsecret must be provided for authenticated RPC"))?;
// fetch jwt from file
//
// the jwt is hex encoded so we will decode it after
let jwt = std::fs::read_to_string(auth_jwt)?;
let jwt = JwtSecret::from_hex(jwt)?;
// get engine url
let auth_url = Url::parse(&bench_args.engine_rpc_url)?;
// construct the authed transport
info!("Connecting to Engine RPC at {} for replay", auth_url);
let auth_transport = AuthenticatedTransportConnect::new(auth_url, jwt);
let client = ClientBuilder::default().connect_boxed(auth_transport).await?;
let auth_provider = RootProvider::<_, AnyNetwork>::new(client);
let first_block = match benchmark_mode {
BenchMode::Continuous => {
// fetch Latest block
block_provider
.get_block_by_number(BlockNumberOrTag::Latest, true.into())
.await?
.unwrap()
}
BenchMode::Range(ref mut range) => {
match range.next() {
Some(block_number) => {
// fetch first block in range
block_provider
.get_block_by_number(block_number.into(), true.into())
.await?
.unwrap()
}
None => {
return Err(eyre::eyre!(
"Benchmark mode range is empty, please provide a larger range"
));
}
}
}
};
let next_block = first_block.header.number + 1;
Ok(Self { auth_provider, block_provider, benchmark_mode, next_block })
}
}