Add password option for submitting deposits

This commit is contained in:
Paul Hauner
2019-11-25 11:38:40 +11:00
parent 140a0517a7
commit 8347ddda96
2 changed files with 68 additions and 3 deletions

View File

@@ -18,6 +18,7 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
.arg( .arg(
Arg::with_name("eth1-endpoint") Arg::with_name("eth1-endpoint")
.short("e") .short("e")
.long("eth1-endpoint")
.value_name("HTTP_SERVER") .value_name("HTTP_SERVER")
.takes_value(true) .takes_value(true)
.requires("send-deposits") .requires("send-deposits")
@@ -27,6 +28,7 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
.arg( .arg(
Arg::with_name("deposit-contract") Arg::with_name("deposit-contract")
.short("c") .short("c")
.long("deposit-contract")
.value_name("ADDRESS") .value_name("ADDRESS")
.takes_value(true) .takes_value(true)
.requires("send-deposits") .requires("send-deposits")
@@ -36,12 +38,22 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
.arg( .arg(
Arg::with_name("account-index") Arg::with_name("account-index")
.short("i") .short("i")
.long("account-index")
.value_name("INDEX") .value_name("INDEX")
.takes_value(true) .takes_value(true)
.requires("send-deposits") .requires("send-deposits")
.default_value("0") .default_value("0")
.help("The eth1 accounts[] index which will send the transaction"), .help("The eth1 accounts[] index which will send the transaction"),
) )
.arg(
Arg::with_name("password")
.short("p")
.long("password")
.value_name("FILE")
.takes_value(true)
.requires("send-deposits")
.help("The password file to unlock the eth1 account (see --index)"),
)
.arg( .arg(
Arg::with_name("testnet-dir") Arg::with_name("testnet-dir")
.long("testnet-dir") .long("testnet-dir")

View File

@@ -4,10 +4,12 @@ use clap::ArgMatches;
use deposit_contract::DEPOSIT_GAS; use deposit_contract::DEPOSIT_GAS;
use environment::{Environment, RuntimeContext}; use environment::{Environment, RuntimeContext};
use eth2_testnet::Eth2TestnetDir; use eth2_testnet::Eth2TestnetDir;
use futures::{stream::unfold, Future, IntoFuture, Stream}; use futures::{future, stream::unfold, Future, IntoFuture, Stream};
use rayon::prelude::*; use rayon::prelude::*;
use slog::{crit, error, info, Logger}; use slog::{crit, error, info, Logger};
use std::fs; use std::fs;
use std::fs::File;
use std::io::prelude::*;
use std::path::PathBuf; use std::path::PathBuf;
use types::{ChainSpec, EthSpec}; use types::{ChainSpec, EthSpec};
use validator_client::validator_directory::{ValidatorDirectory, ValidatorDirectoryBuilder}; use validator_client::validator_directory::{ValidatorDirectory, ValidatorDirectoryBuilder};
@@ -132,6 +134,29 @@ fn run_new_validator_subcommand<T: EthSpec>(
.parse::<usize>() .parse::<usize>()
.map_err(|e| format!("Unable to parse account-index: {}", e))?; .map_err(|e| format!("Unable to parse account-index: {}", e))?;
let password = if let Some(password_path) = matches.value_of("password") {
Some(
File::open(password_path)
.map_err(|e| format!("Unable to open password file: {:?}", e))
.and_then(|mut file| {
let mut password = String::new();
file.read_to_string(&mut password)
.map_err(|e| format!("Unable to read password file to string: {:?}", e))
.map(|_| password)
})
.map(|password| {
// Trim the linefeed from the end.
if password.ends_with("\n") {
password[0..password.len() - 1].to_string()
} else {
password
}
})?,
)
} else {
None
};
info!( info!(
log, log,
"Submitting validator deposits"; "Submitting validator deposits";
@@ -166,10 +191,11 @@ fn run_new_validator_subcommand<T: EthSpec>(
deposit_contract, deposit_contract,
validators.clone(), validators.clone(),
account_index, account_index,
password,
)) { )) {
error!( error!(
log, log,
"Failed to deposit validators"; "Created validators but could not submit deposits";
) )
} else { } else {
info!( info!(
@@ -195,6 +221,7 @@ fn deposit_validators<E: EthSpec>(
deposit_contract: Address, deposit_contract: Address,
validators: Vec<ValidatorDirectory>, validators: Vec<ValidatorDirectory>,
account_index: usize, account_index: usize,
password: Option<String>,
) -> impl Future<Item = (), Error = ()> { ) -> impl Future<Item = (), Error = ()> {
let deposit_amount = context.eth2_config.spec.max_effective_balance; let deposit_amount = context.eth2_config.spec.max_effective_balance;
let log_1 = context.log.clone(); let log_1 = context.log.clone();
@@ -215,6 +242,7 @@ fn deposit_validators<E: EthSpec>(
unfold(validators.into_iter(), move |mut validators| { unfold(validators.into_iter(), move |mut validators| {
let web3 = web3.clone(); let web3 = web3.clone();
let log = log_2.clone(); let log = log_2.clone();
let password = password.clone();
validators.next().map(move |validator| { validators.next().map(move |validator| {
deposit_validator( deposit_validator(
@@ -223,6 +251,7 @@ fn deposit_validators<E: EthSpec>(
&validator, &validator,
deposit_amount, deposit_amount,
account_index, account_index,
password,
log, log,
) )
.map(|()| ((), validators)) .map(|()| ((), validators))
@@ -241,9 +270,11 @@ fn deposit_validator(
validator: &ValidatorDirectory, validator: &ValidatorDirectory,
deposit_amount: u64, deposit_amount: u64,
account_index: usize, account_index: usize,
password_opt: Option<String>,
log: Logger, log: Logger,
) -> impl Future<Item = (), Error = ()> { ) -> impl Future<Item = (), Error = ()> {
let web3_1 = web3.clone(); let web3_1 = web3.clone();
let web3_2 = web3.clone();
let log_1 = log.clone(); let log_1 = log.clone();
let log_2 = log.clone(); let log_2 = log.clone();
@@ -269,6 +300,28 @@ fn deposit_validator(
.cloned() .cloned()
.ok_or_else(|| "Insufficient accounts for deposit".to_string()) .ok_or_else(|| "Insufficient accounts for deposit".to_string())
}) })
.and_then(move |from_address| {
let future: Box<dyn Future<Item = Address, Error = String> + Send> =
if let Some(password) = password_opt {
// Unlock for only a single transaction.
let duration = None;
let future = web3_1
.personal()
.unlock_account(from_address, &password, duration)
.then(move |result| match result {
Ok(true) => Ok(from_address),
Ok(false) => Err("Eth1 node refused to unlock account".to_string()),
Err(e) => Err(format!("Eth1 unlock request failed: {:?}", e)),
});
Box::new(future)
} else {
Box::new(future::ok(from_address))
};
future
})
.and_then(move |from| { .and_then(move |from| {
let tx_request = TransactionRequest { let tx_request = TransactionRequest {
from, from,
@@ -281,7 +334,7 @@ fn deposit_validator(
condition: None, condition: None,
}; };
web3_1 web3_2
.eth() .eth()
.send_transaction(tx_request) .send_transaction(tx_request)
.map_err(|e| format!("Failed to call deposit fn: {:?}", e)) .map_err(|e| format!("Failed to call deposit fn: {:?}", e))