Add lcli indexed-attestations
(#3221)
## Proposed Changes It's reasonably often that we want to manually convert an attestation to indexed form. This PR adds an `lcli` command for doing this, using an SSZ state and a list of JSON attestations (as extracted from a JSON block) as input.
This commit is contained in:
parent
af5da1244e
commit
ee18f6a9f7
48
lcli/src/indexed_attestations.rs
Normal file
48
lcli/src/indexed_attestations.rs
Normal file
@ -0,0 +1,48 @@
|
||||
use clap::ArgMatches;
|
||||
use clap_utils::parse_required;
|
||||
use state_processing::common::get_indexed_attestation;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::path::{Path, PathBuf};
|
||||
use types::*;
|
||||
|
||||
fn read_file_bytes(filename: &Path) -> Result<Vec<u8>, String> {
|
||||
let mut bytes = vec![];
|
||||
let mut file = File::open(filename)
|
||||
.map_err(|e| format!("Unable to open {}: {}", filename.display(), e))?;
|
||||
file.read_to_end(&mut bytes)
|
||||
.map_err(|e| format!("Unable to read {}: {}", filename.display(), e))?;
|
||||
Ok(bytes)
|
||||
}
|
||||
|
||||
pub fn run<T: EthSpec>(matches: &ArgMatches) -> Result<(), String> {
|
||||
let spec = &T::default_spec();
|
||||
|
||||
let state_file: PathBuf = parse_required(matches, "state")?;
|
||||
let attestations_file: PathBuf = parse_required(matches, "attestations")?;
|
||||
|
||||
let mut state = BeaconState::<T>::from_ssz_bytes(&read_file_bytes(&state_file)?, spec)
|
||||
.map_err(|e| format!("Invalid state: {:?}", e))?;
|
||||
state
|
||||
.build_all_committee_caches(spec)
|
||||
.map_err(|e| format!("{:?}", e))?;
|
||||
|
||||
let attestations: Vec<Attestation<T>> =
|
||||
serde_json::from_slice(&read_file_bytes(&attestations_file)?)
|
||||
.map_err(|e| format!("Invalid attestation list: {:?}", e))?;
|
||||
|
||||
let indexed_attestations = attestations
|
||||
.into_iter()
|
||||
.map(|att| {
|
||||
let committee = state.get_beacon_committee(att.data.slot, att.data.index)?;
|
||||
get_indexed_attestation(committee.committee, &att)
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.map_err(|e| format!("Error constructing indexed attestation: {:?}", e))?;
|
||||
|
||||
let string_output = serde_json::to_string_pretty(&indexed_attestations)
|
||||
.map_err(|e| format!("Unable to convert to JSON: {:?}", e))?;
|
||||
println!("{}", string_output);
|
||||
|
||||
Ok(())
|
||||
}
|
@ -6,6 +6,7 @@ mod create_payload_header;
|
||||
mod deploy_deposit_contract;
|
||||
mod eth1_genesis;
|
||||
mod generate_bootnode_enr;
|
||||
mod indexed_attestations;
|
||||
mod insecure_validators;
|
||||
mod interop_genesis;
|
||||
mod new_testnet;
|
||||
@ -598,6 +599,26 @@ fn main() {
|
||||
.help("The number of nodes to divide the validator keys to"),
|
||||
)
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("indexed-attestations")
|
||||
.about("Convert attestations to indexed form, using the committees from a state.")
|
||||
.arg(
|
||||
Arg::with_name("state")
|
||||
.long("state")
|
||||
.value_name("SSZ_STATE")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.help("BeaconState to generate committees from (SSZ)"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("attestations")
|
||||
.long("attestations")
|
||||
.value_name("JSON_ATTESTATIONS")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.help("List of Attestations to convert to indexed form (JSON)"),
|
||||
)
|
||||
)
|
||||
.get_matches();
|
||||
|
||||
let result = matches
|
||||
@ -679,6 +700,8 @@ fn run<T: EthSpec>(
|
||||
.map_err(|e| format!("Failed to run generate-bootnode-enr command: {}", e)),
|
||||
("insecure-validators", Some(matches)) => insecure_validators::run(matches)
|
||||
.map_err(|e| format!("Failed to run insecure-validators command: {}", e)),
|
||||
("indexed-attestations", Some(matches)) => indexed_attestations::run::<T>(matches)
|
||||
.map_err(|e| format!("Failed to run indexed-attestations command: {}", e)),
|
||||
(other, _) => Err(format!("Unknown subcommand {}. See --help.", other)),
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user