Add unfinished pycli integration
This commit is contained in:
parent
2676c8a62d
commit
e1f6052d5e
@ -17,3 +17,4 @@ simple_logger = "1.0"
|
||||
types = { path = "../eth2/types" }
|
||||
state_processing = { path = "../eth2/state_processing" }
|
||||
eth2_ssz = { path = "../eth2/utils/ssz" }
|
||||
regex = "1.3"
|
||||
|
@ -2,16 +2,20 @@
|
||||
extern crate log;
|
||||
|
||||
mod parse_hex;
|
||||
mod pycli;
|
||||
mod transition_blocks;
|
||||
|
||||
use clap::{App, Arg, SubCommand};
|
||||
use parse_hex::run_parse_hex;
|
||||
use pycli::run_pycli;
|
||||
use std::fs::File;
|
||||
use std::path::PathBuf;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
use transition_blocks::run_transition_blocks;
|
||||
use types::{test_utils::TestingBeaconStateBuilder, EthSpec, MainnetEthSpec, MinimalEthSpec};
|
||||
|
||||
type LocalEthSpec = MinimalEthSpec;
|
||||
|
||||
fn main() {
|
||||
simple_logger::init().expect("logger should initialize");
|
||||
|
||||
@ -111,6 +115,21 @@ fn main() {
|
||||
.help("SSZ encoded as 0x-prefixed hex"),
|
||||
),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("pycli")
|
||||
.about("TODO")
|
||||
.version("0.1.0")
|
||||
.author("Paul Hauner <paul@sigmaprime.io>")
|
||||
.arg(
|
||||
Arg::with_name("pycli-path")
|
||||
.long("pycli-path")
|
||||
.short("p")
|
||||
.value_name("PATH")
|
||||
.takes_value(true)
|
||||
.default_value("../../pycli")
|
||||
.help("Path to the pycli repository."),
|
||||
),
|
||||
)
|
||||
.get_matches();
|
||||
|
||||
match matches.subcommand() {
|
||||
@ -157,6 +176,8 @@ fn main() {
|
||||
("pretty-hex", Some(matches)) => {
|
||||
run_parse_hex(matches).unwrap_or_else(|e| error!("Failed to pretty print hex: {}", e))
|
||||
}
|
||||
("pycli", Some(matches)) => run_pycli::<LocalEthSpec>(matches)
|
||||
.unwrap_or_else(|e| error!("Failed to run pycli: {}", e)),
|
||||
(other, _) => error!("Unknown subcommand {}. See --help.", other),
|
||||
}
|
||||
}
|
||||
|
123
lcli/src/pycli.rs
Normal file
123
lcli/src/pycli.rs
Normal file
@ -0,0 +1,123 @@
|
||||
use clap::ArgMatches;
|
||||
use ssz::Decode;
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
use types::{BeaconState, EthSpec};
|
||||
|
||||
pub fn run_pycli<T: EthSpec>(matches: &ArgMatches) -> Result<(), String> {
|
||||
let cmd_path = matches
|
||||
.value_of("pycli-path")
|
||||
.ok_or_else(|| "No pycli-path supplied")?;
|
||||
|
||||
let pycli = PyCli::new(cmd_path.to_string())?;
|
||||
|
||||
let block_path = PathBuf::from("/tmp/trinity/block_16.ssz");
|
||||
let pre_state_path = PathBuf::from("/tmp/trinity/state_15.ssz");
|
||||
|
||||
pycli
|
||||
.transition_blocks::<T>(block_path, pre_state_path)
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: loading from file.
|
||||
*
|
||||
use regex::Regex;
|
||||
use std::collections::HashMap;
|
||||
use std::ffi::OsString;
|
||||
|
||||
const BLOCK_PREFIX: &str = "block_";
|
||||
const PRE_PREFIX: &str = "state_pre_";
|
||||
const POST_PREFIX: &str = "state_post_";
|
||||
|
||||
struct Case<T: EthSpec> {
|
||||
pre: Option<BeaconState<T>>,
|
||||
post: Option<BeaconState<T>>,
|
||||
block: Option<BeaconBlock<T>>,
|
||||
}
|
||||
|
||||
fn get_sets<T: EthSpec>(dir: PathBuf) -> Result<(), String> {
|
||||
let map: HashMap<String, Case<T>> = HashMap::new();
|
||||
|
||||
fs::read_dir(dir)
|
||||
.map_err(|e| format!("Unable to read source directory: {:?}", e))?
|
||||
.filter_map(Result::ok)
|
||||
.map(|f| f.file_name().into_string())
|
||||
.filter_map(Result::ok)
|
||||
.try_for_each(|filename| {
|
||||
if filename.starts_with(BLOCK_PREFIX) {
|
||||
let regex = Regex::new(r".*root0x(.........)")
|
||||
.map_err(|e| format!("Failed to compile block regex: {:?}", e))?;
|
||||
let captures = regex.captures(&filename).
|
||||
// block
|
||||
} else if filename.starts_with(PRE_PREFIX) {
|
||||
dbg!("pre state");
|
||||
} else if filename.starts_with(POST_PREFIX) {
|
||||
dbg!("post state");
|
||||
} else {
|
||||
dbg!("unknown file");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
*/
|
||||
|
||||
/// A wrapper around Danny Ryan's `pycli` utility:
|
||||
///
|
||||
/// https://github.com/djrtwo/pycli
|
||||
///
|
||||
/// Provides functions for testing consensus logic against the executable Python spec.
|
||||
pub struct PyCli {
|
||||
cmd_path: PathBuf,
|
||||
}
|
||||
|
||||
impl PyCli {
|
||||
/// Create a new instance, parsing the given `cmd_path` as a canonical path.
|
||||
pub fn new(cmd_path: String) -> Result<Self, String> {
|
||||
Ok(Self {
|
||||
cmd_path: fs::canonicalize(cmd_path)
|
||||
.map_err(|e| format!("Failed to canonicalize pycli path: {:?}", e))?,
|
||||
})
|
||||
}
|
||||
|
||||
/// Performs block processing on the state at the given `pre_state_path`, using the block at
|
||||
/// `block_path`.
|
||||
///
|
||||
/// Returns an SSZ-encoded `BeaconState` on success.
|
||||
pub fn transition_blocks<T: EthSpec>(
|
||||
&self,
|
||||
block_path: PathBuf,
|
||||
pre_state_path: PathBuf,
|
||||
) -> Result<BeaconState<T>, String> {
|
||||
let output = Command::new("python")
|
||||
.current_dir(self.cmd_path.clone())
|
||||
.arg("pycli.py")
|
||||
.arg("transition")
|
||||
.arg("blocks")
|
||||
.arg(format!("--pre={}", path_string(pre_state_path)?))
|
||||
.arg(path_string(block_path)?)
|
||||
.output()
|
||||
.map_err(|e| format!("Failed to run command: {:?}", e))?;
|
||||
|
||||
if output.status.success() {
|
||||
let state = BeaconState::from_ssz_bytes(&output.stdout)
|
||||
.map_err(|e| format!("Failed to parse SSZ: {:?}", e))?;
|
||||
Ok(state)
|
||||
} else {
|
||||
Err(format!("pycli returned an error: {:?}", output))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn path_string(path: PathBuf) -> Result<String, String> {
|
||||
let path =
|
||||
fs::canonicalize(path).map_err(|e| format!("Unable to canonicalize path: {:?}", e))?;
|
||||
|
||||
path.into_os_string()
|
||||
.into_string()
|
||||
.map_err(|p| format!("Unable to stringify path: {:?}", p))
|
||||
}
|
Loading…
Reference in New Issue
Block a user