diff --git a/Cargo.toml b/Cargo.toml index cb070cc2d..d1a9f6bc0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,4 +29,5 @@ members = [ "beacon_node/beacon_chain/test_harness", "protos", "validator_client", + "account_manager", ] diff --git a/account_manager/Cargo.toml b/account_manager/Cargo.toml new file mode 100644 index 000000000..c26d4b70a --- /dev/null +++ b/account_manager/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "account_manager" +version = "0.0.1" +authors = ["Luke Anderson "] +edition = "2018" + +[dependencies] +bls = { path = "../eth2/utils/bls" } +clap = "2.32.0" +slog = "^2.2.3" +slog-term = "^2.4.0" +slog-async = "^2.3.0" +validator_client = { path = "../validator_client" } diff --git a/account_manager/README.md b/account_manager/README.md new file mode 100644 index 000000000..bf8891f40 --- /dev/null +++ b/account_manager/README.md @@ -0,0 +1,24 @@ +# Lighthouse Accounts Manager + +The accounts manager (AM) is a stand-alone binary which allows +users to generate and manage the cryptographic keys necessary to +interact with Ethereum Serenity. + +## Roles + +The AM is responsible for the following tasks: +- Generation of cryptographic key pairs + - Must acquire sufficient entropy to ensure keys are generated securely (TBD) +- Secure storage of private keys + - Keys must be encrypted while at rest on the disk (TBD) + - The format is compatible with the validator client +- Produces messages and transactions necessary to initiate +staking on Ethereum 1.x (TPD) + + +## Implementation + +The AM is not a service, and does not run continuously, nor does it +interact with any running services. +It is intended to be executed separately from other Lighthouse binaries +and produce files which can be consumed by them. \ No newline at end of file diff --git a/account_manager/src/main.rs b/account_manager/src/main.rs new file mode 100644 index 000000000..42c78aaea --- /dev/null +++ b/account_manager/src/main.rs @@ -0,0 +1,58 @@ +use bls::Keypair; +use clap::{App, Arg, SubCommand}; +use slog::{debug, info, o, Drain}; +use std::path::PathBuf; +use validator_client::Config as ValidatorClientConfig; + +fn main() { + // Logging + let decorator = slog_term::TermDecorator::new().build(); + let drain = slog_term::CompactFormat::new(decorator).build().fuse(); + let drain = slog_async::Async::new(drain).build().fuse(); + let log = slog::Logger::root(drain, o!()); + + // CLI + let matches = App::new("Lighthouse Accounts Manager") + .version("0.0.1") + .author("Sigma Prime ") + .about("Eth 2.0 Accounts Manager") + .arg( + Arg::with_name("datadir") + .long("datadir") + .value_name("DIR") + .help("Data directory for keys and databases.") + .takes_value(true), + ) + .subcommand( + SubCommand::with_name("generate") + .about("Generates a new validator private key") + .version("0.0.1") + .author("Sigma Prime "), + ) + .get_matches(); + + let config = ValidatorClientConfig::parse_args(&matches, &log) + .expect("Unable to build a configuration for the account manager."); + + // Log configuration + info!(log, ""; + "data_dir" => &config.data_dir.to_str()); + + match matches.subcommand() { + ("generate", Some(_gen_m)) => { + let keypair = Keypair::random(); + let key_path: PathBuf = config + .save_key(&keypair) + .expect("Unable to save newly generated private key."); + debug!( + log, + "Keypair generated {:?}, saved to: {:?}", + keypair.identifier(), + key_path.to_string_lossy() + ); + } + _ => panic!( + "The account manager must be run with a subcommand. See help for more information." + ), + } +} diff --git a/beacon_node/eth2-libp2p/src/behaviour.rs b/beacon_node/eth2-libp2p/src/behaviour.rs index 78d013002..458b32cf9 100644 --- a/beacon_node/eth2-libp2p/src/behaviour.rs +++ b/beacon_node/eth2-libp2p/src/behaviour.rs @@ -1,11 +1,18 @@ use crate::rpc::{RPCEvent, RPCMessage, Rpc}; +use crate::NetworkConfig; use futures::prelude::*; use libp2p::{ - core::swarm::{NetworkBehaviourAction, NetworkBehaviourEventProcess}, - gossipsub::{Gossipsub, GossipsubConfig, GossipsubEvent}, + core::{ + swarm::{NetworkBehaviourAction, NetworkBehaviourEventProcess}, + PublicKey, + }, + gossipsub::{Gossipsub, GossipsubEvent}, + identify::{protocol::IdentifyInfo, Identify, IdentifyEvent}, + ping::{Ping, PingEvent}, tokio_io::{AsyncRead, AsyncWrite}, NetworkBehaviour, PeerId, }; +use slog::{debug, o}; use types::Topic; /// Builds the network behaviour for the libp2p Swarm. @@ -13,12 +20,22 @@ use types::Topic; #[derive(NetworkBehaviour)] #[behaviour(out_event = "BehaviourEvent", poll_method = "poll")] pub struct Behaviour { + /// The routing pub-sub mechanism for eth2. gossipsub: Gossipsub, // TODO: Add Kademlia for peer discovery /// The events generated by this behaviour to be consumed in the swarm poll. serenity_rpc: Rpc, + /// Allows discovery of IP addresses for peers on the network. + identify: Identify, + /// Keep regular connection to peers and disconnect if absent. + // TODO: Keepalive, likely remove this later. + // TODO: Make the ping time customizeable. + ping: Ping, #[behaviour(ignore)] events: Vec, + /// Logger for behaviour actions. + #[behaviour(ignore)] + log: slog::Logger, } // Implement the NetworkBehaviourEventProcess trait so that we can derive NetworkBehaviour for Behaviour @@ -53,12 +70,54 @@ impl NetworkBehaviourEventProcess NetworkBehaviourEventProcess + for Behaviour +{ + fn inject_event(&mut self, event: IdentifyEvent) { + match event { + IdentifyEvent::Identified { + peer_id, mut info, .. + } => { + if info.listen_addrs.len() > 20 { + debug!( + self.log, + "More than 20 peers have been identified, truncating" + ); + info.listen_addrs.truncate(20); + } + self.events.push(BehaviourEvent::Identified(peer_id, info)); + } + IdentifyEvent::Error { .. } => {} + IdentifyEvent::SendBack { .. } => {} + } + } +} + +impl NetworkBehaviourEventProcess + for Behaviour +{ + fn inject_event(&mut self, _event: PingEvent) { + // not interested in ping responses at the moment. + } +} + impl Behaviour { - pub fn new(local_peer_id: PeerId, gs_config: GossipsubConfig, log: &slog::Logger) -> Self { + pub fn new(local_public_key: PublicKey, net_conf: &NetworkConfig, log: &slog::Logger) -> Self { + let local_peer_id = local_public_key.clone().into_peer_id(); + let identify_config = net_conf.identify_config.clone(); + let behaviour_log = log.new(o!()); + Behaviour { - gossipsub: Gossipsub::new(local_peer_id, gs_config), + gossipsub: Gossipsub::new(local_peer_id, net_conf.gs_config.clone()), serenity_rpc: Rpc::new(log), + identify: Identify::new( + identify_config.version, + identify_config.user_agent, + local_public_key, + ), + ping: Ping::new(), events: Vec::new(), + log: behaviour_log, } } @@ -91,6 +150,7 @@ impl Behaviour { pub enum BehaviourEvent { RPC(PeerId, RPCEvent), PeerDialed(PeerId), + Identified(PeerId, IdentifyInfo), // TODO: This is a stub at the moment Message(String), } diff --git a/beacon_node/eth2-libp2p/src/network_config.rs b/beacon_node/eth2-libp2p/src/config.rs similarity index 55% rename from beacon_node/eth2-libp2p/src/network_config.rs rename to beacon_node/eth2-libp2p/src/config.rs index 176892bb0..2b4972237 100644 --- a/beacon_node/eth2-libp2p/src/network_config.rs +++ b/beacon_node/eth2-libp2p/src/config.rs @@ -1,11 +1,9 @@ use crate::Multiaddr; use libp2p::gossipsub::{GossipsubConfig, GossipsubConfigBuilder}; -use libp2p::secio; -use std::fmt; -#[derive(Clone)] +#[derive(Clone, Debug)] /// Network configuration for lighthouse. -pub struct NetworkConfig { +pub struct Config { //TODO: stubbing networking initial params, change in the future /// IP address to listen on. pub listen_addresses: Vec, @@ -13,47 +11,56 @@ pub struct NetworkConfig { pub listen_port: u16, /// Gossipsub configuration parameters. pub gs_config: GossipsubConfig, + /// Configuration parameters for node identification protocol. + pub identify_config: IdentifyConfig, /// List of nodes to initially connect to. pub boot_nodes: Vec, - /// Peer key related to this nodes PeerId. - pub local_private_key: secio::SecioKeyPair, /// Client version pub client_version: String, /// List of topics to subscribe to as strings pub topics: Vec, } -impl Default for NetworkConfig { +impl Default for Config { /// Generate a default network configuration. fn default() -> Self { - // TODO: Currently using secp256k1 key pairs. Wire protocol specifies RSA. Waiting for this - // PR to be merged to generate RSA keys: https://github.com/briansmith/ring/pull/733 - - NetworkConfig { + Config { listen_addresses: vec!["/ip4/127.0.0.1/tcp/9000" .parse() .expect("is a correct multi-address")], listen_port: 9000, gs_config: GossipsubConfigBuilder::new().build(), + identify_config: IdentifyConfig::default(), boot_nodes: Vec::new(), - local_private_key: secio::SecioKeyPair::secp256k1_generated().unwrap(), client_version: version::version(), topics: vec![String::from("beacon_chain")], } } } -impl NetworkConfig { +impl Config { pub fn new(boot_nodes: Vec) -> Self { - let mut conf = NetworkConfig::default(); + let mut conf = Config::default(); conf.boot_nodes = boot_nodes; conf } } -impl fmt::Debug for NetworkConfig { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "NetworkConfig: listen_addresses: {:?}, listen_port: {:?}, gs_config: {:?}, boot_nodes: {:?}, local_private_key: , client_version: {:?}", self.listen_addresses, self.listen_port, self.gs_config, self.boot_nodes, self.local_private_key.to_public_key(), self.client_version) +/// The configuration parameters for the Identify protocol +#[derive(Debug, Clone)] +pub struct IdentifyConfig { + /// The protocol version to listen on. + pub version: String, + /// The client's name and version for identification. + pub user_agent: String, +} + +impl Default for IdentifyConfig { + fn default() -> Self { + Self { + version: "/eth/serenity/1.0".to_string(), + user_agent: version::version(), + } } } diff --git a/beacon_node/eth2-libp2p/src/lib.rs b/beacon_node/eth2-libp2p/src/lib.rs index f3e97355d..f7a961bb2 100644 --- a/beacon_node/eth2-libp2p/src/lib.rs +++ b/beacon_node/eth2-libp2p/src/lib.rs @@ -3,16 +3,16 @@ /// /// This crate builds and manages the libp2p services required by the beacon node. pub mod behaviour; +mod config; pub mod error; -mod network_config; pub mod rpc; mod service; +pub use config::Config as NetworkConfig; pub use libp2p::{ gossipsub::{GossipsubConfig, GossipsubConfigBuilder}, PeerId, }; -pub use network_config::NetworkConfig; pub use rpc::{HelloMessage, RPCEvent}; pub use service::Libp2pEvent; pub use service::Service; diff --git a/beacon_node/eth2-libp2p/src/rpc/protocol.rs b/beacon_node/eth2-libp2p/src/rpc/protocol.rs index c19aca8ff..f4fe26fac 100644 --- a/beacon_node/eth2-libp2p/src/rpc/protocol.rs +++ b/beacon_node/eth2-libp2p/src/rpc/protocol.rs @@ -1,4 +1,4 @@ -use super::methods::{HelloMessage, RPCMethod, RPCRequest, RPCResponse}; +use super::methods::*; use libp2p::core::{upgrade, InboundUpgrade, OutboundUpgrade, UpgradeInfo}; use ssz::{ssz_encode, Decodable, Encodable, SszStream}; use std::io; @@ -6,7 +6,7 @@ use std::iter; use tokio::io::{AsyncRead, AsyncWrite}; /// The maximum bytes that can be sent across the RPC. -const MAX_READ_SIZE: usize = 2048; +const MAX_READ_SIZE: usize = 4_194_304; // 4M /// Implementation of the `ConnectionUpgrade` for the rpc protocol. @@ -81,7 +81,31 @@ fn decode(packet: Vec) -> Result { let (hello_body, _index) = HelloMessage::ssz_decode(&packet, index)?; RPCRequest::Hello(hello_body) } - RPCMethod::Unknown | _ => return Err(DecodeError::UnknownRPCMethod), + RPCMethod::Goodbye => { + let (goodbye_code, _index) = u64::ssz_decode(&packet, index)?; + RPCRequest::Goodbye(goodbye_code) + } + RPCMethod::BeaconBlockRoots => { + let (block_roots_request, _index) = + BeaconBlockRootsRequest::ssz_decode(&packet, index)?; + RPCRequest::BeaconBlockRoots(block_roots_request) + } + RPCMethod::BeaconBlockHeaders => { + let (block_headers_request, _index) = + BeaconBlockHeadersRequest::ssz_decode(&packet, index)?; + RPCRequest::BeaconBlockHeaders(block_headers_request) + } + RPCMethod::BeaconBlockBodies => { + let (block_bodies_request, _index) = + BeaconBlockBodiesRequest::ssz_decode(&packet, index)?; + RPCRequest::BeaconBlockBodies(block_bodies_request) + } + RPCMethod::BeaconChainState => { + let (chain_state_request, _index) = + BeaconChainStateRequest::ssz_decode(&packet, index)?; + RPCRequest::BeaconChainState(chain_state_request) + } + RPCMethod::Unknown => return Err(DecodeError::UnknownRPCMethod), }; Ok(RPCEvent::Request { @@ -97,7 +121,24 @@ fn decode(packet: Vec) -> Result { let (body, _index) = HelloMessage::ssz_decode(&packet, index)?; RPCResponse::Hello(body) } - RPCMethod::Unknown | _ => return Err(DecodeError::UnknownRPCMethod), + RPCMethod::Goodbye => unreachable!("Should never receive a goodbye response"), + RPCMethod::BeaconBlockRoots => { + let (body, _index) = BeaconBlockRootsResponse::ssz_decode(&packet, index)?; + RPCResponse::BeaconBlockRoots(body) + } + RPCMethod::BeaconBlockHeaders => { + let (body, _index) = BeaconBlockHeadersResponse::ssz_decode(&packet, index)?; + RPCResponse::BeaconBlockHeaders(body) + } + RPCMethod::BeaconBlockBodies => { + let (body, _index) = BeaconBlockBodiesResponse::ssz_decode(&packet, index)?; + RPCResponse::BeaconBlockBodies(body) + } + RPCMethod::BeaconChainState => { + let (body, _index) = BeaconChainStateResponse::ssz_decode(&packet, index)?; + RPCResponse::BeaconChainState(body) + } + RPCMethod::Unknown => return Err(DecodeError::UnknownRPCMethod), }; Ok(RPCEvent::Response { id, @@ -137,7 +178,21 @@ impl Encodable for RPCEvent { RPCRequest::Hello(body) => { s.append(body); } - _ => {} + RPCRequest::Goodbye(body) => { + s.append(body); + } + RPCRequest::BeaconBlockRoots(body) => { + s.append(body); + } + RPCRequest::BeaconBlockHeaders(body) => { + s.append(body); + } + RPCRequest::BeaconBlockBodies(body) => { + s.append(body); + } + RPCRequest::BeaconChainState(body) => { + s.append(body); + } } } RPCEvent::Response { @@ -152,7 +207,18 @@ impl Encodable for RPCEvent { RPCResponse::Hello(response) => { s.append(response); } - _ => {} + RPCResponse::BeaconBlockRoots(response) => { + s.append(response); + } + RPCResponse::BeaconBlockHeaders(response) => { + s.append(response); + } + RPCResponse::BeaconBlockBodies(response) => { + s.append(response); + } + RPCResponse::BeaconChainState(response) => { + s.append(response); + } } } } diff --git a/beacon_node/eth2-libp2p/src/service.rs b/beacon_node/eth2-libp2p/src/service.rs index e378cd634..e68df2d38 100644 --- a/beacon_node/eth2-libp2p/src/service.rs +++ b/beacon_node/eth2-libp2p/src/service.rs @@ -11,8 +11,8 @@ use libp2p::core::{ transport::boxed::Boxed, upgrade::{InboundUpgradeExt, OutboundUpgradeExt}, }; -use libp2p::{core, secio, Transport}; -use libp2p::{PeerId, Swarm}; +use libp2p::identify::protocol::IdentifyInfo; +use libp2p::{core, secio, PeerId, Swarm, Transport}; use slog::{debug, info, trace, warn}; use std::io::{Error, ErrorKind}; use std::time::Duration; @@ -33,7 +33,12 @@ impl Service { pub fn new(config: NetworkConfig, log: slog::Logger) -> error::Result { debug!(log, "Libp2p Service starting"); - let local_private_key = config.local_private_key; + // TODO: Currently using secp256k1 key pairs. Wire protocol specifies RSA. Waiting for this + // PR to be merged to generate RSA keys: https://github.com/briansmith/ring/pull/733 + // TODO: Save and recover node key from disk + let local_private_key = secio::SecioKeyPair::secp256k1_generated().unwrap(); + + let local_public_key = local_private_key.to_public_key(); let local_peer_id = local_private_key.to_peer_id(); info!(log, "Local peer id: {:?}", local_peer_id); @@ -41,7 +46,7 @@ impl Service { // Set up the transport let transport = build_transport(local_private_key); // Set up gossipsub routing - let behaviour = Behaviour::new(local_peer_id.clone(), config.gs_config, &log); + let behaviour = Behaviour::new(local_public_key.clone(), &config, &log); // Set up Topology let topology = local_peer_id.clone(); Swarm::new(transport, behaviour, topology) @@ -99,17 +104,23 @@ impl Stream for Service { // TODO: Currently only gossipsub events passed here. // Build a type for more generic events match self.swarm.poll() { - Ok(Async::Ready(Some(BehaviourEvent::Message(m)))) => { + //Behaviour events + Ok(Async::Ready(Some(event))) => match event { // TODO: Stub here for debugging - debug!(self.log, "Message received: {}", m); - return Ok(Async::Ready(Some(Libp2pEvent::Message(m)))); - } - Ok(Async::Ready(Some(BehaviourEvent::RPC(peer_id, event)))) => { - return Ok(Async::Ready(Some(Libp2pEvent::RPC(peer_id, event)))); - } - Ok(Async::Ready(Some(BehaviourEvent::PeerDialed(peer_id)))) => { - return Ok(Async::Ready(Some(Libp2pEvent::PeerDialed(peer_id)))); - } + BehaviourEvent::Message(m) => { + debug!(self.log, "Message received: {}", m); + return Ok(Async::Ready(Some(Libp2pEvent::Message(m)))); + } + BehaviourEvent::RPC(peer_id, event) => { + return Ok(Async::Ready(Some(Libp2pEvent::RPC(peer_id, event)))); + } + BehaviourEvent::PeerDialed(peer_id) => { + return Ok(Async::Ready(Some(Libp2pEvent::PeerDialed(peer_id)))); + } + BehaviourEvent::Identified(peer_id, info) => { + return Ok(Async::Ready(Some(Libp2pEvent::Identified(peer_id, info)))); + } + }, Ok(Async::Ready(None)) => unreachable!("Swarm stream shouldn't end"), Ok(Async::NotReady) => break, _ => break, @@ -156,8 +167,12 @@ fn build_transport( /// Events that can be obtained from polling the Libp2p Service. pub enum Libp2pEvent { - // We have received an RPC event on the swarm + /// An RPC response request has been received on the swarm. RPC(PeerId, RPCEvent), + /// Initiated the connection to a new peer. PeerDialed(PeerId), + /// Received information about a peer on the network. + Identified(PeerId, IdentifyInfo), + // TODO: Pub-sub testing only. Message(String), } diff --git a/beacon_node/network/src/service.rs b/beacon_node/network/src/service.rs index 14f994e4a..a3eb6f0d9 100644 --- a/beacon_node/network/src/service.rs +++ b/beacon_node/network/src/service.rs @@ -15,8 +15,8 @@ use tokio::runtime::TaskExecutor; /// Service that handles communication between internal services and the eth2_libp2p network service. pub struct Service { - //eth2_libp2p_service: Arc>, - eth2_libp2p_exit: oneshot::Sender<()>, + //libp2p_service: Arc>, + libp2p_exit: oneshot::Sender<()>, network_send: crossbeam_channel::Sender, //message_handler: MessageHandler, //message_handler_send: Sender, @@ -40,20 +40,20 @@ impl Service { message_handler_log, )?; - // launch eth2_libp2p service - let eth2_libp2p_log = log.new(o!("Service" => "Libp2p")); - let eth2_libp2p_service = LibP2PService::new(config.clone(), eth2_libp2p_log)?; + // launch libp2p service + let libp2p_log = log.new(o!("Service" => "Libp2p")); + let libp2p_service = LibP2PService::new(config.clone(), libp2p_log)?; - // TODO: Spawn thread to handle eth2_libp2p messages and pass to message handler thread. - let eth2_libp2p_exit = spawn_service( - eth2_libp2p_service, + // TODO: Spawn thread to handle libp2p messages and pass to message handler thread. + let libp2p_exit = spawn_service( + libp2p_service, network_recv, message_handler_send, executor, log, )?; let network_service = Service { - eth2_libp2p_exit, + libp2p_exit, network_send: network_send.clone(), }; @@ -72,7 +72,7 @@ impl Service { } fn spawn_service( - eth2_libp2p_service: LibP2PService, + libp2p_service: LibP2PService, network_recv: crossbeam_channel::Receiver, message_handler_send: crossbeam_channel::Sender, executor: &TaskExecutor, @@ -83,7 +83,7 @@ fn spawn_service( // spawn on the current executor executor.spawn( network_service( - eth2_libp2p_service, + libp2p_service, network_recv, message_handler_send, log.clone(), @@ -100,7 +100,7 @@ fn spawn_service( } fn network_service( - mut eth2_libp2p_service: LibP2PService, + mut libp2p_service: LibP2PService, network_recv: crossbeam_channel::Receiver, message_handler_send: crossbeam_channel::Sender, log: slog::Logger, @@ -108,28 +108,34 @@ fn network_service( futures::future::poll_fn(move || -> Result<_, eth2_libp2p::error::Error> { // poll the swarm loop { - match eth2_libp2p_service.poll() { - Ok(Async::Ready(Some(Libp2pEvent::RPC(peer_id, rpc_event)))) => { - trace!( - eth2_libp2p_service.log, - "RPC Event: RPC message received: {:?}", - rpc_event - ); - message_handler_send - .send(HandlerMessage::RPC(peer_id, rpc_event)) - .map_err(|_| "failed to send rpc to handler")?; - } - Ok(Async::Ready(Some(Libp2pEvent::PeerDialed(peer_id)))) => { - debug!(eth2_libp2p_service.log, "Peer Dialed: {:?}", peer_id); - message_handler_send - .send(HandlerMessage::PeerDialed(peer_id)) - .map_err(|_| "failed to send rpc to handler")?; - } - Ok(Async::Ready(Some(Libp2pEvent::Message(m)))) => debug!( - eth2_libp2p_service.log, - "Network Service: Message received: {}", m - ), - _ => break, + match libp2p_service.poll() { + Ok(Async::Ready(Some(event))) => match event { + Libp2pEvent::RPC(peer_id, rpc_event) => { + trace!(log, "RPC Event: RPC message received: {:?}", rpc_event); + message_handler_send + .send(HandlerMessage::RPC(peer_id, rpc_event)) + .map_err(|_| "failed to send rpc to handler")?; + } + Libp2pEvent::PeerDialed(peer_id) => { + debug!(log, "Peer Dialed: {:?}", peer_id); + message_handler_send + .send(HandlerMessage::PeerDialed(peer_id)) + .map_err(|_| "failed to send rpc to handler")?; + } + Libp2pEvent::Identified(peer_id, info) => { + debug!( + log, + "We have identified peer: {:?} with {:?}", peer_id, info + ); + } + Libp2pEvent::Message(m) => debug!( + libp2p_service.log, + "Network Service: Message received: {}", m + ), + }, + Ok(Async::Ready(None)) => unreachable!("Stream never ends"), + Ok(Async::NotReady) => break, + Err(_) => break, } } // poll the network channel @@ -143,7 +149,7 @@ fn network_service( trace!(log, "Sending RPC Event: {:?}", rpc_event); //TODO: Make swarm private //TODO: Implement correct peer id topic message handling - eth2_libp2p_service.swarm.send_rpc(peer_id, rpc_event); + libp2p_service.swarm.send_rpc(peer_id, rpc_event); } OutgoingMessage::NotifierTest => { debug!(log, "Received message from notifier"); @@ -165,7 +171,7 @@ fn network_service( /// Types of messages that the network service can receive. #[derive(Debug, Clone)] pub enum NetworkMessage { - /// Send a message to eth2_libp2p service. + /// Send a message to libp2p service. //TODO: Define typing for messages across the wire Send(PeerId, OutgoingMessage), } diff --git a/eth2/state_processing/specs/example.yml b/eth2/state_processing/specs/example.yml index 95b749bc4..982f0b0dd 100644 --- a/eth2/state_processing/specs/example.yml +++ b/eth2/state_processing/specs/example.yml @@ -1,205 +1,395 @@ -title: Sanity tests -summary: Basic sanity checks from phase 0 spec pythonization. All tests are run with - `verify_signatures` as set to False. +title: Sanity tests -- small config -- 32 validators +summary: Basic sanity checks from phase 0 spec pythonization using a small state configuration and 32 validators. + All tests are run with `verify_signatures` as set to False. + Tests generated via https://github.com/ethereum/research/blob/master/spec_pythonizer/sanity_check.py test_suite: beacon_state -fork: tchaikovsky -version: v0.5.0 +fork: phase0-0.5.0 test_cases: - name: test_empty_block_transition - config: {SHARD_COUNT: 8, TARGET_COMMITTEE_SIZE: 4, MAX_BALANCE_CHURN_QUOTIENT: 32, - MAX_INDICES_PER_SLASHABLE_VOTE: 4096, MAX_EXIT_DEQUEUES_PER_EPOCH: 4, SHUFFLE_ROUND_COUNT: 90, - DEPOSIT_CONTRACT_TREE_DEPTH: 32, MIN_DEPOSIT_AMOUNT: 1000000000, MAX_DEPOSIT_AMOUNT: 32000000000, - FORK_CHOICE_BALANCE_INCREMENT: 1000000000, EJECTION_BALANCE: 16000000000, GENESIS_FORK_VERSION: 0, - GENESIS_SLOT: 4294967296, GENESIS_EPOCH: 536870912, GENESIS_START_SHARD: 0, BLS_WITHDRAWAL_PREFIX_BYTE: 0, - SECONDS_PER_SLOT: 6, MIN_ATTESTATION_INCLUSION_DELAY: 2, SLOTS_PER_EPOCH: 8, MIN_SEED_LOOKAHEAD: 1, - ACTIVATION_EXIT_DELAY: 4, EPOCHS_PER_ETH1_VOTING_PERIOD: 16, SLOTS_PER_HISTORICAL_ROOT: 64, - MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256, PERSISTENT_COMMITTEE_PERIOD: 2048, LATEST_RANDAO_MIXES_LENGTH: 64, - LATEST_ACTIVE_INDEX_ROOTS_LENGTH: 64, LATEST_SLASHED_EXIT_LENGTH: 64, BASE_REWARD_QUOTIENT: 32, - WHISTLEBLOWER_REWARD_QUOTIENT: 512, ATTESTATION_INCLUSION_REWARD_QUOTIENT: 8, - INACTIVITY_PENALTY_QUOTIENT: 16777216, MIN_PENALTY_QUOTIENT: 32, MAX_PROPOSER_SLASHINGS: 16, - MAX_ATTESTER_SLASHINGS: 1, MAX_ATTESTATIONS: 128, MAX_DEPOSITS: 16, MAX_VOLUNTARY_EXITS: 16, - MAX_TRANSFERS: 16, DOMAIN_BEACON_BLOCK: 0, DOMAIN_RANDAO: 1, DOMAIN_ATTESTATION: 2, - DOMAIN_DEPOSIT: 3, DOMAIN_VOLUNTARY_EXIT: 4, DOMAIN_TRANSFER: 5} + config: + SHARD_COUNT: 8 + TARGET_COMMITTEE_SIZE: 4 + MAX_BALANCE_CHURN_QUOTIENT: 32 + MAX_INDICES_PER_SLASHABLE_VOTE: 4096 + MAX_EXIT_DEQUEUES_PER_EPOCH: 4 + SHUFFLE_ROUND_COUNT: 90 + DEPOSIT_CONTRACT_TREE_DEPTH: 32 + MIN_DEPOSIT_AMOUNT: 1000000000 + MAX_DEPOSIT_AMOUNT: 32000000000 + FORK_CHOICE_BALANCE_INCREMENT: 1000000000 + EJECTION_BALANCE: 16000000000 + GENESIS_FORK_VERSION: 0 + GENESIS_SLOT: 4294967296 + GENESIS_EPOCH: 536870912 + GENESIS_START_SHARD: 0 + BLS_WITHDRAWAL_PREFIX_BYTE: '0x00' + SECONDS_PER_SLOT: 6 + MIN_ATTESTATION_INCLUSION_DELAY: 2 + SLOTS_PER_EPOCH: 8 + MIN_SEED_LOOKAHEAD: 1 + ACTIVATION_EXIT_DELAY: 4 + EPOCHS_PER_ETH1_VOTING_PERIOD: 16 + SLOTS_PER_HISTORICAL_ROOT: 64 + MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256 + PERSISTENT_COMMITTEE_PERIOD: 2048 + LATEST_RANDAO_MIXES_LENGTH: 64 + LATEST_ACTIVE_INDEX_ROOTS_LENGTH: 64 + LATEST_SLASHED_EXIT_LENGTH: 64 + BASE_REWARD_QUOTIENT: 32 + WHISTLEBLOWER_REWARD_QUOTIENT: 512 + ATTESTATION_INCLUSION_REWARD_QUOTIENT: 8 + INACTIVITY_PENALTY_QUOTIENT: 16777216 + MIN_PENALTY_QUOTIENT: 32 + MAX_PROPOSER_SLASHINGS: 16 + MAX_ATTESTER_SLASHINGS: 1 + MAX_ATTESTATIONS: 128 + MAX_DEPOSITS: 16 + MAX_VOLUNTARY_EXITS: 16 + MAX_TRANSFERS: 16 + DOMAIN_BEACON_BLOCK: 0 + DOMAIN_RANDAO: 1 + DOMAIN_ATTESTATION: 2 + DOMAIN_DEPOSIT: 3 + DOMAIN_VOLUNTARY_EXIT: 4 + DOMAIN_TRANSFER: 5 verify_signatures: false initial_state: slot: 4294967296 genesis_time: 0 - fork: {previous_version: 0, current_version: 0, epoch: 536870912} + fork: + previous_version: '0x00000000' + current_version: '0x00000000' + epoch: 536870912 validator_registry: - - {pubkey: '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - withdrawal_credentials: '0x2222222222222222222222222222222222222222222222222222222222222222', - activation_epoch: 536870912, exit_epoch: 18446744073709551615, withdrawable_epoch: 18446744073709551615, - initiated_exit: false, slashed: false} - - {pubkey: '0x010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - withdrawal_credentials: '0x2222222222222222222222222222222222222222222222222222222222222222', - activation_epoch: 536870912, exit_epoch: 18446744073709551615, withdrawable_epoch: 18446744073709551615, - initiated_exit: false, slashed: false} - - {pubkey: '0x020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - withdrawal_credentials: '0x2222222222222222222222222222222222222222222222222222222222222222', - activation_epoch: 536870912, exit_epoch: 18446744073709551615, withdrawable_epoch: 18446744073709551615, - initiated_exit: false, slashed: false} - - {pubkey: '0x030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - withdrawal_credentials: '0x2222222222222222222222222222222222222222222222222222222222222222', - activation_epoch: 536870912, exit_epoch: 18446744073709551615, withdrawable_epoch: 18446744073709551615, - initiated_exit: false, slashed: false} - - {pubkey: '0x040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - withdrawal_credentials: '0x2222222222222222222222222222222222222222222222222222222222222222', - activation_epoch: 536870912, exit_epoch: 18446744073709551615, withdrawable_epoch: 18446744073709551615, - initiated_exit: false, slashed: false} - - {pubkey: '0x050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - withdrawal_credentials: '0x2222222222222222222222222222222222222222222222222222222222222222', - activation_epoch: 536870912, exit_epoch: 18446744073709551615, withdrawable_epoch: 18446744073709551615, - initiated_exit: false, slashed: false} - - {pubkey: '0x060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - withdrawal_credentials: '0x2222222222222222222222222222222222222222222222222222222222222222', - activation_epoch: 536870912, exit_epoch: 18446744073709551615, withdrawable_epoch: 18446744073709551615, - initiated_exit: false, slashed: false} - - {pubkey: '0x070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - withdrawal_credentials: '0x2222222222222222222222222222222222222222222222222222222222222222', - activation_epoch: 536870912, exit_epoch: 18446744073709551615, withdrawable_epoch: 18446744073709551615, - initiated_exit: false, slashed: false} - - {pubkey: '0x080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - withdrawal_credentials: '0x2222222222222222222222222222222222222222222222222222222222222222', - activation_epoch: 536870912, exit_epoch: 18446744073709551615, withdrawable_epoch: 18446744073709551615, - initiated_exit: false, slashed: false} - - {pubkey: '0x090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - withdrawal_credentials: '0x2222222222222222222222222222222222222222222222222222222222222222', - activation_epoch: 536870912, exit_epoch: 18446744073709551615, withdrawable_epoch: 18446744073709551615, - initiated_exit: false, slashed: false} - - {pubkey: '0x0a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - withdrawal_credentials: '0x2222222222222222222222222222222222222222222222222222222222222222', - activation_epoch: 536870912, exit_epoch: 18446744073709551615, withdrawable_epoch: 18446744073709551615, - initiated_exit: false, slashed: false} - - {pubkey: '0x0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - withdrawal_credentials: '0x2222222222222222222222222222222222222222222222222222222222222222', - activation_epoch: 536870912, exit_epoch: 18446744073709551615, withdrawable_epoch: 18446744073709551615, - initiated_exit: false, slashed: false} - - {pubkey: '0x0c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - withdrawal_credentials: '0x2222222222222222222222222222222222222222222222222222222222222222', - activation_epoch: 536870912, exit_epoch: 18446744073709551615, withdrawable_epoch: 18446744073709551615, - initiated_exit: false, slashed: false} - - {pubkey: '0x0d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - withdrawal_credentials: '0x2222222222222222222222222222222222222222222222222222222222222222', - activation_epoch: 536870912, exit_epoch: 18446744073709551615, withdrawable_epoch: 18446744073709551615, - initiated_exit: false, slashed: false} - - {pubkey: '0x0e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - withdrawal_credentials: '0x2222222222222222222222222222222222222222222222222222222222222222', - activation_epoch: 536870912, exit_epoch: 18446744073709551615, withdrawable_epoch: 18446744073709551615, - initiated_exit: false, slashed: false} - - {pubkey: '0x0f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - withdrawal_credentials: '0x2222222222222222222222222222222222222222222222222222222222222222', - activation_epoch: 536870912, exit_epoch: 18446744073709551615, withdrawable_epoch: 18446744073709551615, - initiated_exit: false, slashed: false} - - {pubkey: '0x100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - withdrawal_credentials: '0x2222222222222222222222222222222222222222222222222222222222222222', - activation_epoch: 536870912, exit_epoch: 18446744073709551615, withdrawable_epoch: 18446744073709551615, - initiated_exit: false, slashed: false} - - {pubkey: '0x110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - withdrawal_credentials: '0x2222222222222222222222222222222222222222222222222222222222222222', - activation_epoch: 536870912, exit_epoch: 18446744073709551615, withdrawable_epoch: 18446744073709551615, - initiated_exit: false, slashed: false} - - {pubkey: '0x120000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - withdrawal_credentials: '0x2222222222222222222222222222222222222222222222222222222222222222', - activation_epoch: 536870912, exit_epoch: 18446744073709551615, withdrawable_epoch: 18446744073709551615, - initiated_exit: false, slashed: false} - - {pubkey: '0x130000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - withdrawal_credentials: '0x2222222222222222222222222222222222222222222222222222222222222222', - activation_epoch: 536870912, exit_epoch: 18446744073709551615, withdrawable_epoch: 18446744073709551615, - initiated_exit: false, slashed: false} - - {pubkey: '0x140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - withdrawal_credentials: '0x2222222222222222222222222222222222222222222222222222222222222222', - activation_epoch: 536870912, exit_epoch: 18446744073709551615, withdrawable_epoch: 18446744073709551615, - initiated_exit: false, slashed: false} - - {pubkey: '0x150000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - withdrawal_credentials: '0x2222222222222222222222222222222222222222222222222222222222222222', - activation_epoch: 536870912, exit_epoch: 18446744073709551615, withdrawable_epoch: 18446744073709551615, - initiated_exit: false, slashed: false} - - {pubkey: '0x160000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - withdrawal_credentials: '0x2222222222222222222222222222222222222222222222222222222222222222', - activation_epoch: 536870912, exit_epoch: 18446744073709551615, withdrawable_epoch: 18446744073709551615, - initiated_exit: false, slashed: false} - - {pubkey: '0x170000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - withdrawal_credentials: '0x2222222222222222222222222222222222222222222222222222222222222222', - activation_epoch: 536870912, exit_epoch: 18446744073709551615, withdrawable_epoch: 18446744073709551615, - initiated_exit: false, slashed: false} - - {pubkey: '0x180000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - withdrawal_credentials: '0x2222222222222222222222222222222222222222222222222222222222222222', - activation_epoch: 536870912, exit_epoch: 18446744073709551615, withdrawable_epoch: 18446744073709551615, - initiated_exit: false, slashed: false} - - {pubkey: '0x190000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - withdrawal_credentials: '0x2222222222222222222222222222222222222222222222222222222222222222', - activation_epoch: 536870912, exit_epoch: 18446744073709551615, withdrawable_epoch: 18446744073709551615, - initiated_exit: false, slashed: false} - - {pubkey: '0x1a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - withdrawal_credentials: '0x2222222222222222222222222222222222222222222222222222222222222222', - activation_epoch: 536870912, exit_epoch: 18446744073709551615, withdrawable_epoch: 18446744073709551615, - initiated_exit: false, slashed: false} - - {pubkey: '0x1b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - withdrawal_credentials: '0x2222222222222222222222222222222222222222222222222222222222222222', - activation_epoch: 536870912, exit_epoch: 18446744073709551615, withdrawable_epoch: 18446744073709551615, - initiated_exit: false, slashed: false} - - {pubkey: '0x1c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - withdrawal_credentials: '0x2222222222222222222222222222222222222222222222222222222222222222', - activation_epoch: 536870912, exit_epoch: 18446744073709551615, withdrawable_epoch: 18446744073709551615, - initiated_exit: false, slashed: false} - - {pubkey: '0x1d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - withdrawal_credentials: '0x2222222222222222222222222222222222222222222222222222222222222222', - activation_epoch: 536870912, exit_epoch: 18446744073709551615, withdrawable_epoch: 18446744073709551615, - initiated_exit: false, slashed: false} - - {pubkey: '0x1e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - withdrawal_credentials: '0x2222222222222222222222222222222222222222222222222222222222222222', - activation_epoch: 536870912, exit_epoch: 18446744073709551615, withdrawable_epoch: 18446744073709551615, - initiated_exit: false, slashed: false} - - {pubkey: '0x1f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - withdrawal_credentials: '0x2222222222222222222222222222222222222222222222222222222222222222', - activation_epoch: 536870912, exit_epoch: 18446744073709551615, withdrawable_epoch: 18446744073709551615, - initiated_exit: false, slashed: false} - validator_balances: [32000000000, 32000000000, 32000000000, 32000000000, 32000000000, - 32000000000, 32000000000, 32000000000, 32000000000, 32000000000, 32000000000, - 32000000000, 32000000000, 32000000000, 32000000000, 32000000000, 32000000000, - 32000000000, 32000000000, 32000000000, 32000000000, 32000000000, 32000000000, - 32000000000, 32000000000, 32000000000, 32000000000, 32000000000, 32000000000, - 32000000000, 32000000000, 32000000000] + - pubkey: '0x97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb' + withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000001' + activation_epoch: 536870912 + exit_epoch: 18446744073709551615 + withdrawable_epoch: 18446744073709551615 + initiated_exit: false + slashed: false + - pubkey: '0xa572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e' + withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000002' + activation_epoch: 536870912 + exit_epoch: 18446744073709551615 + withdrawable_epoch: 18446744073709551615 + initiated_exit: false + slashed: false + - pubkey: '0x89ece308f9d1f0131765212deca99697b112d61f9be9a5f1f3780a51335b3ff981747a0b2ca2179b96d2c0c9024e5224' + withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000003' + activation_epoch: 536870912 + exit_epoch: 18446744073709551615 + withdrawable_epoch: 18446744073709551615 + initiated_exit: false + slashed: false + - pubkey: '0xac9b60d5afcbd5663a8a44b7c5a02f19e9a77ab0a35bd65809bb5c67ec582c897feb04decc694b13e08587f3ff9b5b60' + withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000004' + activation_epoch: 536870912 + exit_epoch: 18446744073709551615 + withdrawable_epoch: 18446744073709551615 + initiated_exit: false + slashed: false + - pubkey: '0xb0e7791fb972fe014159aa33a98622da3cdc98ff707965e536d8636b5fcc5ac7a91a8c46e59a00dca575af0f18fb13dc' + withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000005' + activation_epoch: 536870912 + exit_epoch: 18446744073709551615 + withdrawable_epoch: 18446744073709551615 + initiated_exit: false + slashed: false + - pubkey: '0xa6e82f6da4520f85c5d27d8f329eccfa05944fd1096b20734c894966d12a9e2a9a9744529d7212d33883113a0cadb909' + withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000006' + activation_epoch: 536870912 + exit_epoch: 18446744073709551615 + withdrawable_epoch: 18446744073709551615 + initiated_exit: false + slashed: false + - pubkey: '0xb928f3beb93519eecf0145da903b40a4c97dca00b21f12ac0df3be9116ef2ef27b2ae6bcd4c5bc2d54ef5a70627efcb7' + withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000007' + activation_epoch: 536870912 + exit_epoch: 18446744073709551615 + withdrawable_epoch: 18446744073709551615 + initiated_exit: false + slashed: false + - pubkey: '0xa85ae765588126f5e860d019c0e26235f567a9c0c0b2d8ff30f3e8d436b1082596e5e7462d20f5be3764fd473e57f9cf' + withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000008' + activation_epoch: 536870912 + exit_epoch: 18446744073709551615 + withdrawable_epoch: 18446744073709551615 + initiated_exit: false + slashed: false + - pubkey: '0x99cdf3807146e68e041314ca93e1fee0991224ec2a74beb2866816fd0826ce7b6263ee31e953a86d1b72cc2215a57793' + withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000009' + activation_epoch: 536870912 + exit_epoch: 18446744073709551615 + withdrawable_epoch: 18446744073709551615 + initiated_exit: false + slashed: false + - pubkey: '0xaf81da25ecf1c84b577fefbedd61077a81dc43b00304015b2b596ab67f00e41c86bb00ebd0f90d4b125eb0539891aeed' + withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000000a' + activation_epoch: 536870912 + exit_epoch: 18446744073709551615 + withdrawable_epoch: 18446744073709551615 + initiated_exit: false + slashed: false + - pubkey: '0x80fd75ebcc0a21649e3177bcce15426da0e4f25d6828fbf4038d4d7ed3bd4421de3ef61d70f794687b12b2d571971a55' + withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000000b' + activation_epoch: 536870912 + exit_epoch: 18446744073709551615 + withdrawable_epoch: 18446744073709551615 + initiated_exit: false + slashed: false + - pubkey: '0x8345dd80ffef0eaec8920e39ebb7f5e9ae9c1d6179e9129b705923df7830c67f3690cbc48649d4079eadf5397339580c' + withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000000c' + activation_epoch: 536870912 + exit_epoch: 18446744073709551615 + withdrawable_epoch: 18446744073709551615 + initiated_exit: false + slashed: false + - pubkey: '0x851f8a0b82a6d86202a61cbc3b0f3db7d19650b914587bde4715ccd372e1e40cab95517779d840416e1679c84a6db24e' + withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000000d' + activation_epoch: 536870912 + exit_epoch: 18446744073709551615 + withdrawable_epoch: 18446744073709551615 + initiated_exit: false + slashed: false + - pubkey: '0x99bef05aaba1ea467fcbc9c420f5e3153c9d2b5f9bf2c7e2e7f6946f854043627b45b008607b9a9108bb96f3c1c089d3' + withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000000e' + activation_epoch: 536870912 + exit_epoch: 18446744073709551615 + withdrawable_epoch: 18446744073709551615 + initiated_exit: false + slashed: false + - pubkey: '0x8d9e19b3f4c7c233a6112e5397309f9812a4f61f754f11dd3dcb8b07d55a7b1dfea65f19a1488a14fef9a41495083582' + withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000000f' + activation_epoch: 536870912 + exit_epoch: 18446744073709551615 + withdrawable_epoch: 18446744073709551615 + initiated_exit: false + slashed: false + - pubkey: '0xa73eb991aa22cdb794da6fcde55a427f0a4df5a4a70de23a988b5e5fc8c4d844f66d990273267a54dd21579b7ba6a086' + withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000010' + activation_epoch: 536870912 + exit_epoch: 18446744073709551615 + withdrawable_epoch: 18446744073709551615 + initiated_exit: false + slashed: false + - pubkey: '0xb098f178f84fc753a76bb63709e9be91eec3ff5f7f3a5f4836f34fe8a1a6d6c5578d8fd820573cef3a01e2bfef3eaf3a' + withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000011' + activation_epoch: 536870912 + exit_epoch: 18446744073709551615 + withdrawable_epoch: 18446744073709551615 + initiated_exit: false + slashed: false + - pubkey: '0x9252a4ac3529f8b2b6e8189b95a60b8865f07f9a9b73f98d5df708511d3f68632c4c7d1e2b03e6b1d1e2c01839752ada' + withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000012' + activation_epoch: 536870912 + exit_epoch: 18446744073709551615 + withdrawable_epoch: 18446744073709551615 + initiated_exit: false + slashed: false + - pubkey: '0xb271205227c7aa27f45f20b3ba380dfea8b51efae91fd32e552774c99e2a1237aa59c0c43f52aad99bba3783ea2f36a4' + withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000013' + activation_epoch: 536870912 + exit_epoch: 18446744073709551615 + withdrawable_epoch: 18446744073709551615 + initiated_exit: false + slashed: false + - pubkey: '0xa272e9d1d50a4aea7d8f0583948090d0888be5777f2846800b8281139cd4aa9eee05f89b069857a3e77ccfaae1615f9c' + withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000014' + activation_epoch: 536870912 + exit_epoch: 18446744073709551615 + withdrawable_epoch: 18446744073709551615 + initiated_exit: false + slashed: false + - pubkey: '0x9780e853f8ce7eda772c6691d25e220ca1d2ab0db51a7824b700620f7ac94c06639e91c98bb6abd78128f0ec845df8ef' + withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000015' + activation_epoch: 536870912 + exit_epoch: 18446744073709551615 + withdrawable_epoch: 18446744073709551615 + initiated_exit: false + slashed: false + - pubkey: '0xab48aa2cc6f4a0bb63b5d67be54ac3aed10326dda304c5aeb9e942b40d6e7610478377680ab90e092ef1895e62786008' + withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000016' + activation_epoch: 536870912 + exit_epoch: 18446744073709551615 + withdrawable_epoch: 18446744073709551615 + initiated_exit: false + slashed: false + - pubkey: '0x8c8b694b04d98a749a0763c72fc020ef61b2bb3f63ebb182cb2e568f6a8b9ca3ae013ae78317599e7e7ba2a528ec754a' + withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000017' + activation_epoch: 536870912 + exit_epoch: 18446744073709551615 + withdrawable_epoch: 18446744073709551615 + initiated_exit: false + slashed: false + - pubkey: '0x9717182463fbe215168e6762abcbb55c5c65290f2b5a2af616f8a6f50d625b46164178a11622d21913efdfa4b800648d' + withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000018' + activation_epoch: 536870912 + exit_epoch: 18446744073709551615 + withdrawable_epoch: 18446744073709551615 + initiated_exit: false + slashed: false + - pubkey: '0xacb58c81ae0cae2e9d4d446b730922239923c345744eee58efaadb36e9a0925545b18a987acf0bad469035b291e37269' + withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000019' + activation_epoch: 536870912 + exit_epoch: 18446744073709551615 + withdrawable_epoch: 18446744073709551615 + initiated_exit: false + slashed: false + - pubkey: '0x81ccc19e3b938ec2405099e90022a4218baa5082a3ca0974b24be0bc8b07e5fffaed64bef0d02c4dbfb6a307829afc5c' + withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000001a' + activation_epoch: 536870912 + exit_epoch: 18446744073709551615 + withdrawable_epoch: 18446744073709551615 + initiated_exit: false + slashed: false + - pubkey: '0xab83dfefb120fab7665a607d749ef1765fbb3cc0ba5827a20a135402c09d987c701ddb5b60f0f5495026817e8ab6ea2e' + withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000001b' + activation_epoch: 536870912 + exit_epoch: 18446744073709551615 + withdrawable_epoch: 18446744073709551615 + initiated_exit: false + slashed: false + - pubkey: '0xb6ad11e5d15f77c1143b1697344911b9c590110fdd8dd09df2e58bfd757269169deefe8be3544d4e049fb3776fb0bcfb' + withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000001c' + activation_epoch: 536870912 + exit_epoch: 18446744073709551615 + withdrawable_epoch: 18446744073709551615 + initiated_exit: false + slashed: false + - pubkey: '0x8515e7f61ca0470e165a44d247a23f17f24bf6e37185467bedb7981c1003ea70bbec875703f793dd8d11e56afa7f74ba' + withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000001d' + activation_epoch: 536870912 + exit_epoch: 18446744073709551615 + withdrawable_epoch: 18446744073709551615 + initiated_exit: false + slashed: false + - pubkey: '0xad84464b3966ec5bede84aa487facfca7823af383715078da03b387cc2f5d5597cdd7d025aa07db00a38b953bdeb6e3f' + withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000001e' + activation_epoch: 536870912 + exit_epoch: 18446744073709551615 + withdrawable_epoch: 18446744073709551615 + initiated_exit: false + slashed: false + - pubkey: '0xb29043a7273d0a2dbc2b747dcf6a5eccbd7ccb44b2d72e985537b117929bc3fd3a99001481327788ad040b4077c47c0d' + withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000001f' + activation_epoch: 536870912 + exit_epoch: 18446744073709551615 + withdrawable_epoch: 18446744073709551615 + initiated_exit: false + slashed: false + - pubkey: '0xa72841987e4f219d54f2b6a9eac5fe6e78704644753c3579e776a3691bc123743f8c63770ed0f72a71e9e964dbf58f43' + withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000020' + activation_epoch: 536870912 + exit_epoch: 18446744073709551615 + withdrawable_epoch: 18446744073709551615 + initiated_exit: false + slashed: false + validator_balances: + - 32000000000 + - 32000000000 + - 32000000000 + - 32000000000 + - 32000000000 + - 32000000000 + - 32000000000 + - 32000000000 + - 32000000000 + - 32000000000 + - 32000000000 + - 32000000000 + - 32000000000 + - 32000000000 + - 32000000000 + - 32000000000 + - 32000000000 + - 32000000000 + - 32000000000 + - 32000000000 + - 32000000000 + - 32000000000 + - 32000000000 + - 32000000000 + - 32000000000 + - 32000000000 + - 32000000000 + - 32000000000 + - 32000000000 + - 32000000000 + - 32000000000 + - 32000000000 validator_registry_update_epoch: 536870912 - latest_randao_mixes: ['0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000'] + latest_randao_mixes: + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' previous_shuffling_start_shard: 0 current_shuffling_start_shard: 0 previous_shuffling_epoch: 536870912 current_shuffling_epoch: 536870912 previous_shuffling_seed: '0x0000000000000000000000000000000000000000000000000000000000000000' - current_shuffling_seed: '0x94ab448e948e6d501a2b48c1e9a0946f871100969f6fa70a990acf2348c9b185' + current_shuffling_seed: '0x7a81d831e99dc63f9f10d4abce84c26473d4c2f65ec4acf9000684059473b072' previous_epoch_attestations: [] current_epoch_attestations: [] previous_justified_epoch: 536870912 @@ -210,133 +400,303 @@ test_cases: finalized_epoch: 536870912 finalized_root: '0x0000000000000000000000000000000000000000000000000000000000000000' latest_crosslinks: - - {epoch: 536870912, crosslink_data_root: '0x0000000000000000000000000000000000000000000000000000000000000000'} - - {epoch: 536870912, crosslink_data_root: '0x0000000000000000000000000000000000000000000000000000000000000000'} - - {epoch: 536870912, crosslink_data_root: '0x0000000000000000000000000000000000000000000000000000000000000000'} - - {epoch: 536870912, crosslink_data_root: '0x0000000000000000000000000000000000000000000000000000000000000000'} - - {epoch: 536870912, crosslink_data_root: '0x0000000000000000000000000000000000000000000000000000000000000000'} - - {epoch: 536870912, crosslink_data_root: '0x0000000000000000000000000000000000000000000000000000000000000000'} - - {epoch: 536870912, crosslink_data_root: '0x0000000000000000000000000000000000000000000000000000000000000000'} - - {epoch: 536870912, crosslink_data_root: '0x0000000000000000000000000000000000000000000000000000000000000000'} - latest_block_roots: ['0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000'] - latest_state_roots: ['0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000'] - latest_active_index_roots: ['0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', - '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', - '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', - '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', - '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', - '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', - '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', - '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', - '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', - '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', - '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', - '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', - '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', - '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', - '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', - '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', - '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', - '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', - '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', - '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', - '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', - '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', - '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', - '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', - '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', - '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', - '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', - '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', - '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', - '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', - '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', - '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42', - '0xf6b8ca96e524598ba62d563347f5aea6ce2d81d644e2788687e5a92844df1b42'] - latest_slashed_balances: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - latest_block_header: {slot: 4294967296, previous_block_root: '0x0000000000000000000000000000000000000000000000000000000000000000', - state_root: '0x0000000000000000000000000000000000000000000000000000000000000000', - block_body_root: '0x5359b62990beb1d78e1cec479f5a4d80af84709886a8e16c535dff0556dc0e2d', - signature: '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'} + - epoch: 536870912 + crosslink_data_root: '0x0000000000000000000000000000000000000000000000000000000000000000' + - epoch: 536870912 + crosslink_data_root: '0x0000000000000000000000000000000000000000000000000000000000000000' + - epoch: 536870912 + crosslink_data_root: '0x0000000000000000000000000000000000000000000000000000000000000000' + - epoch: 536870912 + crosslink_data_root: '0x0000000000000000000000000000000000000000000000000000000000000000' + - epoch: 536870912 + crosslink_data_root: '0x0000000000000000000000000000000000000000000000000000000000000000' + - epoch: 536870912 + crosslink_data_root: '0x0000000000000000000000000000000000000000000000000000000000000000' + - epoch: 536870912 + crosslink_data_root: '0x0000000000000000000000000000000000000000000000000000000000000000' + - epoch: 536870912 + crosslink_data_root: '0x0000000000000000000000000000000000000000000000000000000000000000' + latest_block_roots: + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + latest_state_roots: + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + - '0x0000000000000000000000000000000000000000000000000000000000000000' + latest_active_index_roots: + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + - '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a' + latest_slashed_balances: + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + latest_block_header: + slot: 4294967296 + previous_block_root: '0x0000000000000000000000000000000000000000000000000000000000000000' + state_root: '0x0000000000000000000000000000000000000000000000000000000000000000' + block_body_root: '0x13f2001ff0ee4a528b3c43f63d70a997aefca990ed8eada2223ee6ec3807f7cc' + signature: '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' historical_roots: [] - latest_eth1_data: {deposit_root: '0xb05de6a9059df0c9a2ab5f76708d256941dfe9eb89e6fda549b30713087d2a5e', - block_hash: '0x0000000000000000000000000000000000000000000000000000000000000000'} + latest_eth1_data: + deposit_root: '0x826d25bfcb9161aabc799844c5176f7b3444dc5288856f65e0b8060560488912' + block_hash: '0x0000000000000000000000000000000000000000000000000000000000000000' eth1_data_votes: [] deposit_index: 32 blocks: - slot: 4294967297 - previous_block_root: '0x92ed652508d2b4c109a857107101716b18e257e7ce0d199d4b16232956e9e27e' + previous_block_root: '0x2befbd4b4fe8c91f3059082c8048e3376a9b7fb309e93044fac32b7cc8849773' state_root: '0x0000000000000000000000000000000000000000000000000000000000000000' body: randao_reveal: '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' - eth1_data: {deposit_root: '0x0000000000000000000000000000000000000000000000000000000000000000', - block_hash: '0x0000000000000000000000000000000000000000000000000000000000000000'} + eth1_data: + deposit_root: '0x0000000000000000000000000000000000000000000000000000000000000000' + block_hash: '0x0000000000000000000000000000000000000000000000000000000000000000' proposer_slashings: [] attester_slashings: [] attestations: [] @@ -344,4 +704,5 @@ test_cases: voluntary_exits: [] transfers: [] signature: '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' - expected_state: {slot: 4294967297} + expected_state: + slot: 4294967297 diff --git a/eth2/state_processing/tests/tests.rs b/eth2/state_processing/tests/tests.rs index 9cee7b34c..b6aa3e76f 100644 --- a/eth2/state_processing/tests/tests.rs +++ b/eth2/state_processing/tests/tests.rs @@ -15,12 +15,10 @@ pub struct TestDoc { pub title: String, pub summary: String, pub fork: String, - pub version: String, pub test_cases: Vec, } #[test] -#[ignore] fn yaml() { use serde_yaml; use std::{fs::File, io::prelude::*, path::PathBuf}; diff --git a/eth2/types/Cargo.toml b/eth2/types/Cargo.toml index 1b5f79d23..e4ccfd63e 100644 --- a/eth2/types/Cargo.toml +++ b/eth2/types/Cargo.toml @@ -10,6 +10,7 @@ boolean-bitfield = { path = "../utils/boolean-bitfield" } dirs = "1.0" ethereum-types = "0.5" hashing = { path = "../utils/hashing" } +hex = "0.3" honey-badger-split = { path = "../utils/honey-badger-split" } int_to_bytes = { path = "../utils/int_to_bytes" } log = "0.4" diff --git a/eth2/types/src/chain_spec.rs b/eth2/types/src/chain_spec.rs index 5fa28b6ac..0042304f8 100644 --- a/eth2/types/src/chain_spec.rs +++ b/eth2/types/src/chain_spec.rs @@ -2,6 +2,7 @@ use crate::*; use bls::Signature; use int_to_bytes::int_to_bytes4; use serde_derive::Deserialize; +use test_utils::u8_from_hex_str; const GWEI: u64 = 1_000_000_000; @@ -57,6 +58,7 @@ pub struct ChainSpec { pub far_future_epoch: Epoch, pub zero_hash: Hash256, pub empty_signature: Signature, + #[serde(deserialize_with = "u8_from_hex_str")] pub bls_withdrawal_prefix_byte: u8, /* diff --git a/eth2/types/src/fork.rs b/eth2/types/src/fork.rs index b780b95ef..b9d16c333 100644 --- a/eth2/types/src/fork.rs +++ b/eth2/types/src/fork.rs @@ -1,4 +1,7 @@ -use crate::{test_utils::TestRandom, ChainSpec, Epoch}; +use crate::{ + test_utils::{fork_from_hex_str, TestRandom}, + ChainSpec, Epoch, +}; use int_to_bytes::int_to_bytes4; use rand::RngCore; use serde_derive::{Deserialize, Serialize}; @@ -12,7 +15,9 @@ use test_random_derive::TestRandom; Debug, Clone, PartialEq, Default, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom, )] pub struct Fork { + #[serde(deserialize_with = "fork_from_hex_str")] pub previous_version: [u8; 4], + #[serde(deserialize_with = "fork_from_hex_str")] pub current_version: [u8; 4], pub epoch: Epoch, } diff --git a/eth2/types/src/test_utils/mod.rs b/eth2/types/src/test_utils/mod.rs index bc8da0548..018b70d15 100644 --- a/eth2/types/src/test_utils/mod.rs +++ b/eth2/types/src/test_utils/mod.rs @@ -2,6 +2,7 @@ mod macros; mod generate_deterministic_keypairs; mod keypairs_file; +mod serde_utils; mod test_random; mod testing_attestation_builder; mod testing_attestation_data_builder; @@ -17,6 +18,7 @@ mod testing_voluntary_exit_builder; pub use generate_deterministic_keypairs::generate_deterministic_keypairs; pub use keypairs_file::KeypairsFile; pub use rand::{prng::XorShiftRng, SeedableRng}; +pub use serde_utils::{fork_from_hex_str, u8_from_hex_str}; pub use test_random::TestRandom; pub use testing_attestation_builder::TestingAttestationBuilder; pub use testing_attestation_data_builder::TestingAttestationDataBuilder; diff --git a/eth2/types/src/test_utils/serde_utils.rs b/eth2/types/src/test_utils/serde_utils.rs new file mode 100644 index 000000000..e0e88fbec --- /dev/null +++ b/eth2/types/src/test_utils/serde_utils.rs @@ -0,0 +1,28 @@ +use serde::de::Error; +use serde::{Deserialize, Deserializer}; + +pub fn u8_from_hex_str<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + let s: String = Deserialize::deserialize(deserializer)?; + + u8::from_str_radix(&s.as_str()[2..], 16).map_err(D::Error::custom) +} + +pub fn fork_from_hex_str<'de, D>(deserializer: D) -> Result<[u8; 4], D::Error> +where + D: Deserializer<'de>, +{ + let s: String = Deserialize::deserialize(deserializer)?; + let mut array = [0 as u8; 4]; + let decoded: Vec = hex::decode(&s.as_str()[2..]).map_err(D::Error::custom)?; + + for (i, item) in array.iter_mut().enumerate() { + if i > decoded.len() { + break; + } + *item = decoded[i]; + } + Ok(array) +} diff --git a/eth2/utils/bls/src/keypair.rs b/eth2/utils/bls/src/keypair.rs index d60a2fc25..6feb2a585 100644 --- a/eth2/utils/bls/src/keypair.rs +++ b/eth2/utils/bls/src/keypair.rs @@ -14,4 +14,8 @@ impl Keypair { let pk = PublicKey::from_secret_key(&sk); Keypair { sk, pk } } + + pub fn identifier(&self) -> String { + self.pk.concatenated_hex_id() + } } diff --git a/eth2/utils/bls/src/serde_vistors.rs b/eth2/utils/bls/src/serde_vistors.rs index 55eadb883..58f4a4965 100644 --- a/eth2/utils/bls/src/serde_vistors.rs +++ b/eth2/utils/bls/src/serde_vistors.rs @@ -8,13 +8,14 @@ impl<'de> Visitor<'de> for HexVisitor { type Value = Vec; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("a hex string (without 0x prefix)") + formatter.write_str("a hex string (irrelevant of prefix)") } fn visit_str(self, value: &str) -> Result where E: de::Error, { - Ok(hex::decode(value).map_err(|e| de::Error::custom(format!("invalid hex ({:?})", e)))?) + Ok(hex::decode(value.trim_start_matches("0x")) + .map_err(|e| de::Error::custom(format!("invalid hex ({:?})", e)))?) } } diff --git a/eth2/utils/bls/src/signature.rs b/eth2/utils/bls/src/signature.rs index 47598bc66..8a080e56d 100644 --- a/eth2/utils/bls/src/signature.rs +++ b/eth2/utils/bls/src/signature.rs @@ -13,27 +13,35 @@ use ssz::{ /// This struct is a wrapper upon a base type and provides helper functions (e.g., SSZ /// serialization). #[derive(Debug, PartialEq, Clone, Eq)] -pub struct Signature(RawSignature); +pub struct Signature { + signature: RawSignature, + is_empty: bool, +} impl Signature { /// Instantiate a new Signature from a message and a SecretKey. pub fn new(msg: &[u8], domain: u64, sk: &SecretKey) -> Self { - Signature(RawSignature::new(msg, domain, sk.as_raw())) + Signature { + signature: RawSignature::new(msg, domain, sk.as_raw()), + is_empty: false, + } } /// Instantiate a new Signature from a message and a SecretKey, where the message has already /// been hashed. pub fn new_hashed(x_real_hashed: &[u8], x_imaginary_hashed: &[u8], sk: &SecretKey) -> Self { - Signature(RawSignature::new_hashed( - x_real_hashed, - x_imaginary_hashed, - sk.as_raw(), - )) + Signature { + signature: RawSignature::new_hashed(x_real_hashed, x_imaginary_hashed, sk.as_raw()), + is_empty: false, + } } /// Verify the Signature against a PublicKey. pub fn verify(&self, msg: &[u8], domain: u64, pk: &PublicKey) -> bool { - self.0.verify(msg, domain, pk.as_raw()) + if self.is_empty { + return false; + } + self.signature.verify(msg, domain, pk.as_raw()) } /// Verify the Signature against a PublicKey, where the message has already been hashed. @@ -43,44 +51,72 @@ impl Signature { x_imaginary_hashed: &[u8], pk: &PublicKey, ) -> bool { - self.0 + self.signature .verify_hashed(x_real_hashed, x_imaginary_hashed, pk.as_raw()) } /// Returns the underlying signature. pub fn as_raw(&self) -> &RawSignature { - &self.0 + &self.signature } /// Returns a new empty signature. pub fn empty_signature() -> Self { - // Empty Signature is currently being represented as BLS::Signature.point_at_infinity() - // However it should be represented as vec![0; 96] but this - // would require all signatures to be represented in byte form as opposed to Signature + // Set RawSignature = infinity let mut empty: Vec = vec![0; 96]; - // Sets C_flag and B_flag to 1 and all else to 0 empty[0] += u8::pow(2, 6) + u8::pow(2, 7); - Signature(RawSignature::from_bytes(&empty).unwrap()) + Signature { + signature: RawSignature::from_bytes(&empty).unwrap(), + is_empty: true, + } + } + + // Converts a BLS Signature to bytes + pub fn as_bytes(&self) -> Vec { + if self.is_empty { + return vec![0; 96]; + } + self.signature.as_bytes() + } + + // Convert bytes to BLS Signature + pub fn from_bytes(bytes: &[u8]) -> Result { + for byte in bytes { + if *byte != 0 { + let raw_signature = + RawSignature::from_bytes(&bytes).map_err(|_| DecodeError::Invalid)?; + return Ok(Signature { + signature: raw_signature, + is_empty: false, + }); + } + } + Ok(Signature::empty_signature()) + } + + // Check for empty Signature + pub fn is_empty(&self) -> bool { + self.is_empty } } impl Encodable for Signature { fn ssz_append(&self, s: &mut SszStream) { - s.append_vec(&self.0.as_bytes()); + s.append_vec(&self.as_bytes()); } } impl Decodable for Signature { fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> { let (sig_bytes, i) = decode_ssz_list(bytes, i)?; - let raw_sig = RawSignature::from_bytes(&sig_bytes).map_err(|_| DecodeError::TooShort)?; - Ok((Signature(raw_sig), i)) + let signature = Signature::from_bytes(&sig_bytes)?; + Ok((signature, i)) } } impl TreeHash for Signature { fn hash_tree_root(&self) -> Vec { - hash(&self.0.as_bytes()) + hash(&self.as_bytes()) } } diff --git a/validator_client/Cargo.toml b/validator_client/Cargo.toml index ea97ef5d4..eace153fa 100644 --- a/validator_client/Cargo.toml +++ b/validator_client/Cargo.toml @@ -1,9 +1,18 @@ [package] name = "validator_client" version = "0.1.0" -authors = ["Paul Hauner ", "Age Manning "] +authors = ["Paul Hauner ", "Age Manning ", "Luke Anderson "] edition = "2018" +[[bin]] +name = "validator_client" +path = "src/main.rs" + +[lib] +name = "validator_client" +path = "src/lib.rs" + + [dependencies] block_proposer = { path = "../eth2/block_proposer" } attester = { path = "../eth2/attester" } @@ -22,3 +31,4 @@ slog-async = "^2.3.0" tokio = "0.1.18" tokio-timer = "0.2.10" error-chain = "0.12.0" +bincode = "^1.1.2" diff --git a/validator_client/README.md b/validator_client/README.md index aa84fe013..03979fbb8 100644 --- a/validator_client/README.md +++ b/validator_client/README.md @@ -57,10 +57,30 @@ complete and return a block from the BN. ### Configuration -Presently the validator specifics (pubkey, etc.) are randomly generated and the -chain specification (slot length, BLS domain, etc.) are fixed to foundation -parameters. This is temporary and will be upgrade so these parameters can be -read from file (or initialized on first-boot). +Validator configurations are stored in a separate data directory from the main Beacon Node +binary. The validator data directory defaults to: +`$HOME/.lighthouse-validator`, however an alternative can be specified on the command line +with `--datadir`. + +The configuration directory structure looks like: +``` +~/.lighthouse-validator + ├── 3cf4210d58ec + │   └── private.key + ├── 9b5d8b5be4e7 + │   └── private.key + └── cf6e07188f48 + └── private.key +``` + +Where the hex value of the directory is a portion of the validator public key. + +Validator keys must be generated using the separate `accounts_manager` binary, which will +place the keys into this directory structure in a format compatible with the validator client. + +The chain specification (slot length, BLS domain, etc.) defaults to foundation +parameters, however is temporary and an upgrade will allow these parameters to be +read from a file (or initialized on first-boot). ## BN Communication diff --git a/validator_client/src/config.rs b/validator_client/src/config.rs index 0bf320b4f..78900374a 100644 --- a/validator_client/src/config.rs +++ b/validator_client/src/config.rs @@ -1,69 +1,158 @@ use clap::ArgMatches; -use slog::{error, info}; +use bincode; +use bls::Keypair; +use slog::{debug, error, info}; use std::fs; +use std::fs::File; +use std::io::{Error, ErrorKind}; use std::path::PathBuf; use types::ChainSpec; /// Stores the core configuration for this validator instance. #[derive(Clone)] pub struct Config { + /// The data directory, which stores all validator databases pub data_dir: PathBuf, + /// The server at which the Beacon Node can be contacted pub server: String, + /// The chain specification that we are connecting to pub spec: ChainSpec, } -const DEFAULT_LIGHTHOUSE_DIR: &str = ".lighthouse-validators"; +const DEFAULT_PRIVATE_KEY_FILENAME: &str = "private.key"; -impl Config { +impl Default for Config { /// Build a new configuration from defaults. - pub fn default() -> Self { + fn default() -> Self { let data_dir = { - let home = dirs::home_dir().expect("Unable to determine home dir."); - home.join(DEFAULT_LIGHTHOUSE_DIR) + let home = dirs::home_dir().expect("Unable to determine home directory."); + home.join(".lighthouse-validator") }; - fs::create_dir_all(&data_dir) - .unwrap_or_else(|_| panic!("Unable to create {:?}", &data_dir)); + let server = "localhost:5051".to_string(); + let spec = ChainSpec::foundation(); + Self { data_dir, server, spec, } } +} - pub fn parse_args(matches: ArgMatches, log: &slog::Logger) -> Result { +impl Config { + /// Build a new configuration from defaults, which are overrided by arguments provided. + pub fn parse_args(args: &ArgMatches, log: &slog::Logger) -> Result { let mut config = Config::default(); - // Custom datadir - if let Some(dir) = matches.value_of("datadir") { - config.data_dir = PathBuf::from(dir.to_string()); - } - // Custom server port - if let Some(server_str) = matches.value_of("server") { - if let Ok(addr) = server_str.parse::() { - config.server = addr.to_string(); - } else { - error!(log, "Invalid address"; "server" => server_str); - return Err("Invalid address"); - } - } + // Use the specified datadir, or default in the home directory + if let Some(datadir) = args.value_of("datadir") { + config.data_dir = PathBuf::from(datadir); + info!(log, "Using custom data dir: {:?}", &config.data_dir); + }; + + fs::create_dir_all(&config.data_dir) + .unwrap_or_else(|_| panic!("Unable to create {:?}", &config.data_dir)); + + if let Some(srv) = args.value_of("server") { + //TODO: Validate the server value, to ensure it makes sense. + config.server = srv.to_string(); + info!(log, "Using custom server: {:?}", &config.server); + }; // TODO: Permit loading a custom spec from file. - // Custom spec - if let Some(spec_str) = matches.value_of("spec") { - match spec_str { - "foundation" => config.spec = ChainSpec::foundation(), - "few_validators" => config.spec = ChainSpec::few_validators(), + if let Some(spec_str) = args.value_of("spec") { + info!(log, "Using custom spec: {:?}", spec_str); + config.spec = match spec_str { + "foundation" => ChainSpec::foundation(), + "few_validators" => ChainSpec::few_validators(), // Should be impossible due to clap's `possible_values(..)` function. _ => unreachable!(), }; - } - + }; // Log configuration info!(log, ""; "data_dir" => &config.data_dir.to_str(), "server" => &config.server); + Ok(config) } + + /// Try to load keys from validator_dir, returning None if none are found or an error. + pub fn fetch_keys(&self, log: &slog::Logger) -> Option> { + let key_pairs: Vec = fs::read_dir(&self.data_dir) + .unwrap() + .filter_map(|validator_dir| { + let validator_dir = validator_dir.ok()?; + + if !(validator_dir.file_type().ok()?.is_dir()) { + // Skip non-directories (i.e. no files/symlinks) + return None; + } + + let key_filename = validator_dir.path().join(DEFAULT_PRIVATE_KEY_FILENAME); + + if !(key_filename.is_file()) { + info!( + log, + "Private key is not a file: {:?}", + key_filename.to_str() + ); + return None; + } + + debug!( + log, + "Deserializing private key from file: {:?}", + key_filename.to_str() + ); + + let mut key_file = File::open(key_filename.clone()).ok()?; + + let key: Keypair = if let Ok(key_ok) = bincode::deserialize_from(&mut key_file) { + key_ok + } else { + error!( + log, + "Unable to deserialize the private key file: {:?}", key_filename + ); + return None; + }; + + let ki = key.identifier(); + if ki != validator_dir.file_name().into_string().ok()? { + error!( + log, + "The validator key ({:?}) did not match the directory filename {:?}.", + ki, + &validator_dir.path().to_string_lossy() + ); + return None; + } + Some(key) + }) + .collect(); + + // Check if it's an empty vector, and return none. + if key_pairs.is_empty() { + None + } else { + Some(key_pairs) + } + } + + /// Saves a keypair to a file inside the appropriate validator directory. Returns the saved path filename. + pub fn save_key(&self, key: &Keypair) -> Result { + let validator_config_path = self.data_dir.join(key.identifier()); + let key_path = validator_config_path.join(DEFAULT_PRIVATE_KEY_FILENAME); + + fs::create_dir_all(&validator_config_path)?; + + let mut key_file = File::create(&key_path)?; + + bincode::serialize_into(&mut key_file, &key) + .map_err(|e| Error::new(ErrorKind::InvalidData, e))?; + Ok(key_path) + } } diff --git a/validator_client/src/lib.rs b/validator_client/src/lib.rs new file mode 100644 index 000000000..470a070e8 --- /dev/null +++ b/validator_client/src/lib.rs @@ -0,0 +1,3 @@ +pub mod config; + +pub use crate::config::Config; diff --git a/validator_client/src/main.rs b/validator_client/src/main.rs index 127df8494..1c59513a7 100644 --- a/validator_client/src/main.rs +++ b/validator_client/src/main.rs @@ -5,7 +5,7 @@ mod duties; pub mod error; mod service; -use crate::config::Config as ValidatorConfig; +use crate::config::Config as ValidatorClientConfig; use clap::{App, Arg}; use service::Service as ValidatorService; use slog::{error, info, o, Drain}; @@ -48,7 +48,8 @@ fn main() { ) .get_matches(); - let config = ValidatorConfig::parse_args(matches, &log).unwrap(); + let config = ValidatorClientConfig::parse_args(&matches, &log) + .expect("Unable to build a configuration for the validator client."); // start the validator service. match ValidatorService::start(config, log.clone()) {