Add lcli command to replace state pubkeys (#1999)
## Issue Addressed NA ## Proposed Changes Adds a command to replace all the pubkeys in a state with one generated from a mnemonic. ## Additional Info This is not production code, it's only for testing.
This commit is contained in:
parent
805e152f66
commit
46cb6e204c
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -3324,6 +3324,7 @@ dependencies = [
|
||||
name = "lcli"
|
||||
version = "1.0.6"
|
||||
dependencies = [
|
||||
"account_utils",
|
||||
"bls",
|
||||
"clap",
|
||||
"clap_utils",
|
||||
@ -3335,6 +3336,7 @@ dependencies = [
|
||||
"eth2_libp2p",
|
||||
"eth2_network_config",
|
||||
"eth2_ssz",
|
||||
"eth2_wallet",
|
||||
"futures 0.3.8",
|
||||
"genesis",
|
||||
"hex",
|
||||
|
@ -35,4 +35,6 @@ rand = "0.7.3"
|
||||
eth2_keystore = { path = "../crypto/eth2_keystore" }
|
||||
lighthouse_version = { path = "../common/lighthouse_version" }
|
||||
directory = { path = "../common/directory" }
|
||||
account_utils = { path = "../common/account_utils" }
|
||||
eth2_wallet = { path = "../crypto/eth2_wallet" }
|
||||
tokio-compat-02 = "0.1"
|
||||
|
@ -8,6 +8,7 @@ mod insecure_validators;
|
||||
mod interop_genesis;
|
||||
mod new_testnet;
|
||||
mod parse_hex;
|
||||
mod replace_state_pubkeys;
|
||||
mod skip_slots;
|
||||
mod transition_blocks;
|
||||
|
||||
@ -231,6 +232,35 @@ fn main() {
|
||||
.help("The value for state.genesis_time."),
|
||||
),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("replace-state-pubkeys")
|
||||
.about(
|
||||
"Loads a file with an SSZ-encoded BeaconState and replaces \
|
||||
all the validator pubkeys with ones derived from the mnemonic \
|
||||
such that validator indices correspond to EIP-2334 voting keypair \
|
||||
derivation paths.",
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("ssz-state")
|
||||
.index(1)
|
||||
.value_name("PATH")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.help("The path to the SSZ file"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("mnemonic")
|
||||
.index(2)
|
||||
.value_name("BIP39_MNENMONIC")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.default_value(
|
||||
"replace nephew blur decorate waste convince soup column \
|
||||
orient excite play baby",
|
||||
)
|
||||
.help("The mnemonic for key derivation."),
|
||||
),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("new-testnet")
|
||||
.about(
|
||||
@ -516,6 +546,8 @@ fn run<T: EthSpec>(
|
||||
.map_err(|e| format!("Failed to run interop-genesis command: {}", e)),
|
||||
("change-genesis-time", Some(matches)) => change_genesis_time::run::<T>(matches)
|
||||
.map_err(|e| format!("Failed to run change-genesis-time command: {}", e)),
|
||||
("replace-state-pubkeys", Some(matches)) => replace_state_pubkeys::run::<T>(matches)
|
||||
.map_err(|e| format!("Failed to run replace-state-pubkeys command: {}", e)),
|
||||
("new-testnet", Some(matches)) => new_testnet::run::<T>(matches)
|
||||
.map_err(|e| format!("Failed to run new_testnet command: {}", e)),
|
||||
("check-deposit-data", Some(matches)) => check_deposit_data::run::<T>(matches)
|
||||
|
55
lcli/src/replace_state_pubkeys.rs
Normal file
55
lcli/src/replace_state_pubkeys.rs
Normal file
@ -0,0 +1,55 @@
|
||||
use account_utils::{eth2_keystore::keypair_from_secret, mnemonic_from_phrase};
|
||||
use clap::ArgMatches;
|
||||
use eth2_wallet::bip39::Seed;
|
||||
use eth2_wallet::{recover_validator_secret_from_mnemonic, KeyType};
|
||||
use ssz::{Decode, Encode};
|
||||
use std::fs::File;
|
||||
use std::io::{Read, Write};
|
||||
use std::path::PathBuf;
|
||||
use types::{BeaconState, EthSpec};
|
||||
|
||||
pub fn run<T: EthSpec>(matches: &ArgMatches) -> Result<(), String> {
|
||||
let path = matches
|
||||
.value_of("ssz-state")
|
||||
.ok_or("ssz-state not specified")?
|
||||
.parse::<PathBuf>()
|
||||
.map_err(|e| format!("Unable to parse ssz-state: {}", e))?;
|
||||
|
||||
let mnemonic_phrase = matches
|
||||
.value_of("mnemonic")
|
||||
.ok_or("mnemonic not specified")?;
|
||||
|
||||
let mut state: BeaconState<T> = {
|
||||
let mut file = File::open(&path).map_err(|e| format!("Unable to open file: {}", e))?;
|
||||
|
||||
let mut ssz = vec![];
|
||||
|
||||
file.read_to_end(&mut ssz)
|
||||
.map_err(|e| format!("Unable to read file: {}", e))?;
|
||||
|
||||
BeaconState::from_ssz_bytes(&ssz).map_err(|e| format!("Unable to decode SSZ: {:?}", e))?
|
||||
};
|
||||
|
||||
let mnemonic = mnemonic_from_phrase(mnemonic_phrase)?;
|
||||
let seed = Seed::new(&mnemonic, "");
|
||||
|
||||
for (index, validator) in state.validators.iter_mut().enumerate() {
|
||||
let (secret, _) =
|
||||
recover_validator_secret_from_mnemonic(seed.as_bytes(), index as u32, KeyType::Voting)
|
||||
.map_err(|e| format!("Unable to generate validator key: {:?}", e))?;
|
||||
|
||||
let keypair = keypair_from_secret(secret.as_bytes())
|
||||
.map_err(|e| format!("Unable build keystore: {:?}", e))?;
|
||||
|
||||
eprintln!("{}: {}", index, keypair.pk);
|
||||
|
||||
validator.pubkey = keypair.pk.into();
|
||||
}
|
||||
|
||||
let mut file = File::create(path).map_err(|e| format!("Unable to create file: {}", e))?;
|
||||
|
||||
file.write_all(&state.as_ssz_bytes())
|
||||
.map_err(|e| format!("Unable to write to file: {}", e))?;
|
||||
|
||||
Ok(())
|
||||
}
|
Loading…
Reference in New Issue
Block a user