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]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
mod block_root;
|
||||||
mod change_genesis_time;
|
mod change_genesis_time;
|
||||||
mod check_deposit_data;
|
mod check_deposit_data;
|
||||||
mod create_payload_header;
|
mod create_payload_header;
|
||||||
@ -714,6 +715,42 @@ fn main() {
|
|||||||
.help("List of Attestations to convert to indexed form (JSON)"),
|
.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();
|
.get_matches();
|
||||||
|
|
||||||
let result = matches
|
let result = matches
|
||||||
@ -799,6 +836,8 @@ fn run<T: EthSpec>(
|
|||||||
.map_err(|e| format!("Failed to run insecure-validators command: {}", e)),
|
.map_err(|e| format!("Failed to run insecure-validators command: {}", e)),
|
||||||
("indexed-attestations", Some(matches)) => indexed_attestations::run::<T>(matches)
|
("indexed-attestations", Some(matches)) => indexed_attestations::run::<T>(matches)
|
||||||
.map_err(|e| format!("Failed to run indexed-attestations command: {}", e)),
|
.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)),
|
(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
|
//! 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.
|
//! 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
|
//! ## Examples
|
||||||
//!
|
//!
|
||||||
//! ### Run using a block from a beaconAPI
|
//! ### 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)
|
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) => {
|
(Some(pre_state_path), Some(block_path), None) => {
|
||||||
info!("Block path: {:?}", pre_state_path);
|
info!("Block path: {:?}", block_path);
|
||||||
info!("Pre-state 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 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)?;
|
let block = load_from_ssz_with(&block_path, spec, SignedBeaconBlock::from_ssz_bytes)?;
|
||||||
(pre_state, None, block)
|
(pre_state, None, block)
|
||||||
|
Loading…
Reference in New Issue
Block a user