Add lcli block-root
tool (#3580)
## Issue Addressed NA ## Proposed Changes Adds a simple tool for computing the block root of some block from a beacon-API or a file. This is useful for benchmarking. ## Additional Info NA
This commit is contained in:
parent
2cd3e3a768
commit
bde3c168e2
103
lcli/src/block_root.rs
Normal file
103
lcli/src/block_root.rs
Normal file
@ -0,0 +1,103 @@
|
||||
//! # Block Root
|
||||
//!
|
||||
//! Use this tool to compute the canonical root of a `SignedBeaconBlock`. This is most likely only
|
||||
//! useful for benchmarking with tools like `flamegraph`.
|
||||
//!
|
||||
//! It can load a block from a SSZ file or download it from a beaconAPI.
|
||||
//!
|
||||
//! Logging output is controlled via the `RUST_LOG` environment variable. For example, `export
|
||||
//! RUST_LOG=debug`.
|
||||
//!
|
||||
//! ## Examples
|
||||
//!
|
||||
//! Download a block and re-compute the canonical root 5,000 times.
|
||||
//!
|
||||
//! ```ignore
|
||||
//! lcli block-root \
|
||||
//! --beacon-url http://localhost:5052 \
|
||||
//! --block-id 0x3d887d30ee25c9c1ce7621ec30a7b49b07d6a03200df9c7206faca52a533f432 \
|
||||
//! --runs 5000
|
||||
//! ```
|
||||
//!
|
||||
//! Load a block from SSZ and compute the canonical root once.
|
||||
//!
|
||||
//! ```ignore
|
||||
//! lcli block-root \
|
||||
//! --block-path /tmp/block.ssz \
|
||||
//! --runs 1
|
||||
//! ```
|
||||
use crate::transition_blocks::load_from_ssz_with;
|
||||
use clap::ArgMatches;
|
||||
use clap_utils::{parse_optional, parse_required};
|
||||
use environment::Environment;
|
||||
use eth2::{types::BlockId, BeaconNodeHttpClient, SensitiveUrl, Timeouts};
|
||||
use std::path::PathBuf;
|
||||
use std::time::{Duration, Instant};
|
||||
use types::{EthSpec, FullPayload, SignedBeaconBlock};
|
||||
|
||||
const HTTP_TIMEOUT: Duration = Duration::from_secs(5);
|
||||
|
||||
pub fn run<T: EthSpec>(mut env: Environment<T>, matches: &ArgMatches) -> Result<(), String> {
|
||||
let spec = &T::default_spec();
|
||||
let executor = env.core_context().executor;
|
||||
|
||||
/*
|
||||
* Parse (most) CLI arguments.
|
||||
*/
|
||||
|
||||
let block_path: Option<PathBuf> = parse_optional(matches, "block-path")?;
|
||||
let beacon_url: Option<SensitiveUrl> = parse_optional(matches, "beacon-url")?;
|
||||
let runs: usize = parse_required(matches, "runs")?;
|
||||
|
||||
info!("Using {} spec", T::spec_name());
|
||||
info!("Doing {} runs", runs);
|
||||
|
||||
/*
|
||||
* Load the block and pre-state from disk or beaconAPI URL.
|
||||
*/
|
||||
|
||||
let block: SignedBeaconBlock<T, FullPayload<T>> = match (block_path, beacon_url) {
|
||||
(Some(block_path), None) => {
|
||||
info!("Block path: {:?}", block_path);
|
||||
load_from_ssz_with(&block_path, spec, SignedBeaconBlock::from_ssz_bytes)?
|
||||
}
|
||||
(None, Some(beacon_url)) => {
|
||||
let block_id: BlockId = parse_required(matches, "block-id")?;
|
||||
let client = BeaconNodeHttpClient::new(beacon_url, Timeouts::set_all(HTTP_TIMEOUT));
|
||||
executor
|
||||
.handle()
|
||||
.ok_or("shutdown in progress")?
|
||||
.block_on(async move {
|
||||
let block = client
|
||||
.get_beacon_blocks(block_id)
|
||||
.await
|
||||
.map_err(|e| format!("Failed to download block: {:?}", e))?
|
||||
.ok_or_else(|| format!("Unable to locate block at {:?}", block_id))?
|
||||
.data;
|
||||
Ok::<_, String>(block)
|
||||
})
|
||||
.map_err(|e| format!("Failed to complete task: {:?}", e))?
|
||||
}
|
||||
_ => return Err("must supply --block-path *or* --beacon-url".into()),
|
||||
};
|
||||
|
||||
/*
|
||||
* Perform the core "runs".
|
||||
*/
|
||||
|
||||
let mut block_root = None;
|
||||
for i in 0..runs {
|
||||
let start = Instant::now();
|
||||
|
||||
block_root = Some(block.canonical_root());
|
||||
|
||||
let duration = Instant::now().duration_since(start);
|
||||
info!("Run {}: {:?}", i, duration);
|
||||
}
|
||||
|
||||
if let Some(block_root) = block_root {
|
||||
info!("Block root is {:?}", block_root);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
mod block_root;
|
||||
mod change_genesis_time;
|
||||
mod check_deposit_data;
|
||||
mod create_payload_header;
|
||||
@ -714,6 +715,42 @@ fn main() {
|
||||
.help("List of Attestations to convert to indexed form (JSON)"),
|
||||
)
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("block-root")
|
||||
.about("Computes the block root of some block")
|
||||
.arg(
|
||||
Arg::with_name("block-path")
|
||||
.long("block-path")
|
||||
.value_name("PATH")
|
||||
.takes_value(true)
|
||||
.conflicts_with("beacon-url")
|
||||
.requires("pre-state-path")
|
||||
.help("Path to load a SignedBeaconBlock from file as SSZ."),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("beacon-url")
|
||||
.long("beacon-url")
|
||||
.value_name("URL")
|
||||
.takes_value(true)
|
||||
.help("URL to a beacon-API provider."),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("block-id")
|
||||
.long("block-id")
|
||||
.value_name("BLOCK_ID")
|
||||
.takes_value(true)
|
||||
.requires("beacon-url")
|
||||
.help("Identifier for a block as per beacon-API standards (slot, root, etc.)"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("runs")
|
||||
.long("runs")
|
||||
.value_name("INTEGER")
|
||||
.takes_value(true)
|
||||
.default_value("1")
|
||||
.help("Number of repeat runs, useful for benchmarking."),
|
||||
)
|
||||
)
|
||||
.get_matches();
|
||||
|
||||
let result = matches
|
||||
@ -799,6 +836,8 @@ fn run<T: EthSpec>(
|
||||
.map_err(|e| format!("Failed to run insecure-validators command: {}", e)),
|
||||
("indexed-attestations", Some(matches)) => indexed_attestations::run::<T>(matches)
|
||||
.map_err(|e| format!("Failed to run indexed-attestations command: {}", e)),
|
||||
("block-root", Some(matches)) => block_root::run::<T>(env, matches)
|
||||
.map_err(|e| format!("Failed to run block-root command: {}", e)),
|
||||
(other, _) => Err(format!("Unknown subcommand {}. See --help.", other)),
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,9 @@
|
||||
//! It can load states and blocks from file or pull them from a beaconAPI. Objects pulled from a
|
||||
//! beaconAPI can be saved to disk to reduce future calls to that server.
|
||||
//!
|
||||
//! Logging output is controlled via the `RUST_LOG` environment variable. For example, `export
|
||||
//! RUST_LOG=debug`.
|
||||
//!
|
||||
//! ## Examples
|
||||
//!
|
||||
//! ### Run using a block from a beaconAPI
|
||||
@ -124,8 +127,8 @@ pub fn run<T: EthSpec>(mut env: Environment<T>, matches: &ArgMatches) -> Result<
|
||||
let (mut pre_state, mut state_root_opt, block) = match (pre_state_path, block_path, beacon_url)
|
||||
{
|
||||
(Some(pre_state_path), Some(block_path), None) => {
|
||||
info!("Block path: {:?}", pre_state_path);
|
||||
info!("Pre-state path: {:?}", block_path);
|
||||
info!("Block path: {:?}", block_path);
|
||||
info!("Pre-state path: {:?}", pre_state_path);
|
||||
let pre_state = load_from_ssz_with(&pre_state_path, spec, BeaconState::from_ssz_bytes)?;
|
||||
let block = load_from_ssz_with(&block_path, spec, SignedBeaconBlock::from_ssz_bytes)?;
|
||||
(pre_state, None, block)
|
||||
|
Loading…
Reference in New Issue
Block a user