diff --git a/tests/cli_util/Cargo.toml b/tests/cli_util/Cargo.toml index b868f1541a..6fd2119705 100644 --- a/tests/cli_util/Cargo.toml +++ b/tests/cli_util/Cargo.toml @@ -8,6 +8,7 @@ edition = "2018" [dependencies] clap = "2.33" +hex = "0.3" log = "0.4" serde = "1.0" serde_yaml = "0.8" diff --git a/tests/cli_util/src/main.rs b/tests/cli_util/src/main.rs index e03febca6d..ef2848578e 100644 --- a/tests/cli_util/src/main.rs +++ b/tests/cli_util/src/main.rs @@ -1,9 +1,11 @@ #[macro_use] extern crate log; +mod parse_hex; mod transition_blocks; use clap::{App, Arg, SubCommand}; +use parse_hex::run_parse_hex; use std::fs::File; use std::path::PathBuf; use std::time::{SystemTime, UNIX_EPOCH}; @@ -85,6 +87,27 @@ fn main() { .help("Path to output a SSZ file."), ), ) + .subcommand( + SubCommand::with_name("pretty-hex") + .about("Parses some SSZ as encoded as ASCII 0x-prefixed hex") + .version("0.1.0") + .author("Paul Hauner ") + .arg( + Arg::with_name("type") + .value_name("TYPE") + .takes_value(true) + .required(true) + .possible_values(&["block"]) + .help("The schema of the supplied SSZ."), + ) + .arg( + Arg::with_name("hex_ssz") + .value_name("HEX") + .takes_value(true) + .required(true) + .help("SSZ encoded as 0x-prefixed hex"), + ), + ) .get_matches(); match matches.subcommand() { @@ -128,6 +151,9 @@ fn main() { } ("transition-blocks", Some(matches)) => run_transition_blocks(matches) .unwrap_or_else(|e| error!("Failed to transition blocks: {}", e)), + ("pretty-hex", Some(matches)) => { + run_parse_hex(matches).unwrap_or_else(|e| error!("Failed to pretty print hex: {}", e)) + } (other, _) => error!("Unknown subcommand supplied: {}", other), } } diff --git a/tests/cli_util/src/parse_hex.rs b/tests/cli_util/src/parse_hex.rs new file mode 100644 index 0000000000..a74e9a645c --- /dev/null +++ b/tests/cli_util/src/parse_hex.rs @@ -0,0 +1,47 @@ +use clap::ArgMatches; +use serde::Serialize; +use ssz::{Decode, Encode}; +use state_processing::{per_block_processing, per_slot_processing, BlockSignatureStrategy}; +use std::fs::File; +use std::io::prelude::*; +use std::path::PathBuf; +use types::{BeaconBlock, BeaconState, EthSpec, MinimalEthSpec}; + +pub fn run_parse_hex(matches: &ArgMatches) -> Result<(), String> { + let type_str = matches + .value_of("type") + .ok_or_else(|| "No type supplied".to_string())?; + let mut hex: String = matches + .value_of("hex_ssz") + .ok_or_else(|| "No hex ssz supplied".to_string())? + .to_string(); + + if hex.starts_with("0x") { + hex = hex[2..].to_string(); + } + + let hex = hex::decode(&hex).map_err(|e| format!("Failed to parse hex: {:?}", e))?; + + info!("Using minimal spec"); + info!("Type: {:?}", type_str); + + match type_str.as_ref() { + "block" => decode_and_print::>(&hex)?, + "state" => decode_and_print::>(&hex)?, + other => return Err(format!("Unknown type: {}", other)), + }; + + Ok(()) +} + +fn decode_and_print(bytes: &[u8]) -> Result<(), String> { + let item = T::from_ssz_bytes(&bytes).map_err(|e| format!("Ssz decode failed: {:?}", e))?; + + println!( + "{}", + serde_yaml::to_string(&item) + .map_err(|e| format!("Unable to write object to YAML: {:?}", e))? + ); + + Ok(()) +}