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" }
|
types = { path = "../eth2/types" }
|
||||||
state_processing = { path = "../eth2/state_processing" }
|
state_processing = { path = "../eth2/state_processing" }
|
||||||
eth2_ssz = { path = "../eth2/utils/ssz" }
|
eth2_ssz = { path = "../eth2/utils/ssz" }
|
||||||
|
regex = "1.3"
|
||||||
|
@ -2,16 +2,20 @@
|
|||||||
extern crate log;
|
extern crate log;
|
||||||
|
|
||||||
mod parse_hex;
|
mod parse_hex;
|
||||||
|
mod pycli;
|
||||||
mod transition_blocks;
|
mod transition_blocks;
|
||||||
|
|
||||||
use clap::{App, Arg, SubCommand};
|
use clap::{App, Arg, SubCommand};
|
||||||
use parse_hex::run_parse_hex;
|
use parse_hex::run_parse_hex;
|
||||||
|
use pycli::run_pycli;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::time::{SystemTime, UNIX_EPOCH};
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
use transition_blocks::run_transition_blocks;
|
use transition_blocks::run_transition_blocks;
|
||||||
use types::{test_utils::TestingBeaconStateBuilder, EthSpec, MainnetEthSpec, MinimalEthSpec};
|
use types::{test_utils::TestingBeaconStateBuilder, EthSpec, MainnetEthSpec, MinimalEthSpec};
|
||||||
|
|
||||||
|
type LocalEthSpec = MinimalEthSpec;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
simple_logger::init().expect("logger should initialize");
|
simple_logger::init().expect("logger should initialize");
|
||||||
|
|
||||||
@ -111,6 +115,21 @@ fn main() {
|
|||||||
.help("SSZ encoded as 0x-prefixed hex"),
|
.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();
|
.get_matches();
|
||||||
|
|
||||||
match matches.subcommand() {
|
match matches.subcommand() {
|
||||||
@ -157,6 +176,8 @@ fn main() {
|
|||||||
("pretty-hex", Some(matches)) => {
|
("pretty-hex", Some(matches)) => {
|
||||||
run_parse_hex(matches).unwrap_or_else(|e| error!("Failed to pretty print hex: {}", e))
|
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),
|
(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