Add efforts to automate eth1 testnet deployment

This commit is contained in:
Paul Hauner
2019-11-24 18:51:37 +11:00
parent ad65d72814
commit 2fdd130f4c
12 changed files with 312 additions and 19 deletions

View File

@@ -22,3 +22,4 @@ eth1_test_rig = { path = "../tests/eth1_test_rig" }
futures = "0.1.25"
environment = { path = "../lighthouse/environment" }
web3 = "0.8.0"
eth2_testnet = { path = "../eth2/utils/eth2_testnet" }

View File

@@ -4,6 +4,7 @@ extern crate log;
mod deposit_contract;
mod parse_hex;
mod pycli;
mod testnet;
mod transition_blocks;
use clap::{App, Arg, SubCommand};
@@ -24,8 +25,6 @@ fn main() {
simple_logger::init_with_level(Level::Info).expect("logger should initialize");
let matches = App::new("Lighthouse CLI Tool")
.version("0.1.0")
.author("Paul Hauner <paul@sigmaprime.io>")
.about(
"Performs various testing-related tasks, modelled after zcli. \
by @protolambda.",
@@ -33,8 +32,6 @@ fn main() {
.subcommand(
SubCommand::with_name("genesis_yaml")
.about("Generates a genesis YAML file")
.version("0.1.0")
.author("Paul Hauner <paul@sigmaprime.io>")
.arg(
Arg::with_name("num_validators")
.short("n")
@@ -73,8 +70,6 @@ fn main() {
.subcommand(
SubCommand::with_name("transition-blocks")
.about("Performs a state transition given a pre-state and block")
.version("0.1.0")
.author("Paul Hauner <paul@sigmaprime.io>")
.arg(
Arg::with_name("pre-state")
.value_name("BEACON_STATE")
@@ -101,8 +96,6 @@ fn main() {
.subcommand(
SubCommand::with_name("pretty-hex")
.about("Parses SSZ encoded as ASCII 0x-prefixed hex")
.version("0.1.0")
.author("Paul Hauner <paul@sigmaprime.io>")
.arg(
Arg::with_name("type")
.value_name("TYPE")
@@ -124,8 +117,6 @@ fn main() {
.about(
"Uses an eth1 test rpc (e.g., ganache-cli) to simulate the deposit contract.",
)
.version("0.1.0")
.author("Paul Hauner <paul@sigmaprime.io>")
.arg(
Arg::with_name("count")
.short("c")
@@ -158,11 +149,46 @@ fn main() {
.help("The number of block confirmations before declaring the contract deployed."),
)
)
.subcommand(
SubCommand::with_name("testnet")
.about(
"Deploy an eth1 deposit contract and create files with testnet details.",
)
.arg(
Arg::with_name("output")
.short("o")
.value_name("PATH")
.takes_value(true)
.default_value("~/.lighthouse/testnet")
.help("The output directory."),
)
.arg(
Arg::with_name("min_genesis_time")
.short("t")
.value_name("UNIX_EPOCH_SECONDS")
.takes_value(true)
.default_value("0")
.help("The MIN_GENESIS_TIME constant."),
)
.arg(
Arg::with_name("endpoint")
.short("e")
.value_name("HTTP_SERVER")
.takes_value(true)
.default_value("http://localhost:8545")
.help("The URL to the eth1 JSON-RPC http API."),
)
.arg(
Arg::with_name("confirmations")
.value_name("INTEGER")
.takes_value(true)
.default_value("3")
.help("The number of block confirmations before declaring the contract deployed."),
)
)
.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")
@@ -231,6 +257,8 @@ fn main() {
.unwrap_or_else(|e| error!("Failed to run pycli: {}", e)),
("deposit-contract", Some(matches)) => run_deposit_contract::<LocalEthSpec>(env, matches)
.unwrap_or_else(|e| error!("Failed to run deposit contract sim: {}", e)),
("testnet", Some(matches)) => testnet::new_testnet::<LocalEthSpec>(env, matches)
.unwrap_or_else(|e| error!("Failed to run testnet commmand: {}", e)),
(other, _) => error!("Unknown subcommand {}. See --help.", other),
}
}

84
lcli/src/testnet.rs Normal file
View File

@@ -0,0 +1,84 @@
use clap::ArgMatches;
use environment::Environment;
use eth1_test_rig::DepositContract;
use eth2_testnet::Eth2TestnetDir;
use std::path::PathBuf;
use types::EthSpec;
use web3::{transports::Http, Web3};
pub fn new_testnet<T: EthSpec>(
mut env: Environment<T>,
matches: &ArgMatches,
) -> Result<(), String> {
let min_genesis_time = matches
.value_of("min_genesis_time")
.ok_or_else(|| "min_genesis_time not specified")?
.parse::<u64>()
.map_err(|e| format!("Failed to parse min_genesis_time: {}", e))?;
let confirmations = matches
.value_of("confirmations")
.ok_or_else(|| "Confirmations not specified")?
.parse::<usize>()
.map_err(|e| format!("Failed to parse confirmations: {}", e))?;
let output_dir = matches
.value_of("output")
.ok_or_else(|| "Output directory not specified")?
.parse::<PathBuf>()
.map_err(|e| format!("Failed to parse output directory: {}", e))?;
let endpoint = matches
.value_of("endpoint")
.ok_or_else(|| "Endpoint not specified")?;
let (_event_loop, transport) = Http::new(&endpoint).map_err(|e| {
format!(
"Failed to start HTTP transport connected to ganache: {:?}",
e
)
})?;
let web3 = Web3::new(transport);
if output_dir.exists() {
return Err("Output directory already exists".to_string());
}
// It's unlikely that this will be the _actual_ deployment block, however it'll be close
// enough to serve our purposes.
//
// We only need the deposit block to put a lower bound on the block number we need to search
// for deposit logs.
let deploy_block = env
.runtime()
.block_on(web3.eth().block_number())
.map_err(|e| format!("Failed to get block number: {}", e))?;
info!("Present eth1 block number is {}", deploy_block);
info!(
"Submitting deployment transaction, waiting for {} confirmations",
confirmations
);
let deposit_contract = env
.runtime()
.block_on(DepositContract::deploy_testnet(web3, confirmations))
.map_err(|e| format!("Failed to deploy contract: {}", e))?;
info!(
"Deposit contract deployed. address: {}, min_genesis_time: {}, deploy_block: {}",
deposit_contract.address(),
min_genesis_time,
deploy_block
);
Eth2TestnetDir::new(
output_dir,
format!("0x{}", deposit_contract.address()),
deploy_block.as_u64(),
min_genesis_time,
)?;
Ok(())
}