From 40cf65056319213ded91fdf64c57fb0f68abec68 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Mon, 14 Jan 2019 12:55:55 +1100 Subject: [PATCH 01/28] Add validator_node, restructure binaries, gRPC. This is a massive commit which restructures the workspace, adds a very basic, untested, validator client and some very basic, non-functioning gRPC endpoints to the beacon-node. --- Cargo.toml | 39 +- .../attestation_validation/Cargo.toml | 2 +- beacon_chain/naive_fork_choice/Cargo.toml | 2 +- beacon_chain/types/src/lib.rs | 2 + beacon_node/Cargo.toml | 18 + {lighthouse => beacon_node}/db/Cargo.toml | 0 {lighthouse => beacon_node}/db/src/disk_db.rs | 0 {lighthouse => beacon_node}/db/src/lib.rs | 0 .../db/src/memory_db.rs | 0 .../db/src/stores/beacon_block_store.rs | 0 .../db/src/stores/beacon_state_store.rs | 0 .../db/src/stores/macros.rs | 0 .../db/src/stores/mod.rs | 0 .../db/src/stores/pow_chain_store.rs | 0 .../db/src/stores/validator_store.rs | 0 {lighthouse => beacon_node}/db/src/traits.rs | 0 .../src/beacon_chain}/block_processing.rs | 0 .../src/beacon_chain}/block_production.rs | 0 .../src/beacon_chain/mod.rs | 0 .../src}/beacon_chain/tests/chain_test.rs | 0 .../src/beacon_chain}/transition.rs | 0 {lighthouse => beacon_node/src}/config/mod.rs | 2 - {lighthouse => beacon_node/src}/main.rs | 29 +- beacon_node/src/rpc/mod.rs | 79 ++ lighthouse/beacon_chain/Cargo.toml | 17 - protos/Cargo.toml | 13 + protos/build.rs | 8 + protos/src/lib.rs | 2 + protos/src/services.proto | 46 + protos/src/services.rs | 1049 +++++++++++++++++ protos/src/services_grpc.rs | 99 ++ validator_client/Cargo.toml | 18 + validator_client/src/block_producer/mod.rs | 127 ++ validator_client/src/block_producer/traits.rs | 73 ++ validator_client/src/main.rs | 102 ++ 35 files changed, 1654 insertions(+), 73 deletions(-) create mode 100644 beacon_node/Cargo.toml rename {lighthouse => beacon_node}/db/Cargo.toml (100%) rename {lighthouse => beacon_node}/db/src/disk_db.rs (100%) rename {lighthouse => beacon_node}/db/src/lib.rs (100%) rename {lighthouse => beacon_node}/db/src/memory_db.rs (100%) rename {lighthouse => beacon_node}/db/src/stores/beacon_block_store.rs (100%) rename {lighthouse => beacon_node}/db/src/stores/beacon_state_store.rs (100%) rename {lighthouse => beacon_node}/db/src/stores/macros.rs (100%) rename {lighthouse => beacon_node}/db/src/stores/mod.rs (100%) rename {lighthouse => beacon_node}/db/src/stores/pow_chain_store.rs (100%) rename {lighthouse => beacon_node}/db/src/stores/validator_store.rs (100%) rename {lighthouse => beacon_node}/db/src/traits.rs (100%) rename {lighthouse/beacon_chain/src => beacon_node/src/beacon_chain}/block_processing.rs (100%) rename {lighthouse/beacon_chain/src => beacon_node/src/beacon_chain}/block_production.rs (100%) rename lighthouse/beacon_chain/src/lib.rs => beacon_node/src/beacon_chain/mod.rs (100%) rename {lighthouse => beacon_node/src}/beacon_chain/tests/chain_test.rs (100%) rename {lighthouse/beacon_chain/src => beacon_node/src/beacon_chain}/transition.rs (100%) rename {lighthouse => beacon_node/src}/config/mod.rs (97%) rename {lighthouse => beacon_node/src}/main.rs (82%) create mode 100644 beacon_node/src/rpc/mod.rs delete mode 100644 lighthouse/beacon_chain/Cargo.toml create mode 100644 protos/Cargo.toml create mode 100644 protos/build.rs create mode 100644 protos/src/lib.rs create mode 100644 protos/src/services.proto create mode 100644 protos/src/services.rs create mode 100644 protos/src/services_grpc.rs create mode 100644 validator_client/Cargo.toml create mode 100644 validator_client/src/block_producer/mod.rs create mode 100644 validator_client/src/block_producer/traits.rs create mode 100644 validator_client/src/main.rs diff --git a/Cargo.toml b/Cargo.toml index a12317daa..1ca11dcbb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,36 +1,3 @@ -[package] -name = "lighthouse" -version = "0.0.1" -authors = ["Paul Hauner "] -edition = "2018" - -[dependencies] -blake2-rfc = "0.2.18" -bls-aggregates = { git = "https://github.com/sigp/signature-schemes" } -bytes = "" -crypto-mac = "^0.6.2" -clap = "2.32.0" -db = { path = "lighthouse/db" } -dirs = "1.0.3" -futures = "0.1.23" -rand = "0.3" -rlp = { git = "https://github.com/paritytech/parity-common" } -slog = "^2.2.3" -slog-term = "^2.4.0" -slog-async = "^2.3.0" -tokio = "0.1" - -[dependencies.pairing] -git = "https://github.com/mmaker/pairing" -branch = "feature/hashing" - -[patch.crates-io] -ring = { git = "https://github.com/paritytech/ring" } - -[[bin]] -path = "lighthouse/main.rs" -name = "lighthouse" - [workspace] members = [ "beacon_chain/attestation_validation", @@ -47,6 +14,8 @@ members = [ "beacon_chain/utils/vec_shuffle", "beacon_chain/validator_induction", "beacon_chain/validator_shuffling", - "lighthouse/beacon_chain", - "lighthouse/db", + "beacon_node", + "beacon_node/db", + "protos", + "validator_client", ] diff --git a/beacon_chain/attestation_validation/Cargo.toml b/beacon_chain/attestation_validation/Cargo.toml index bc357a26a..b944f90f9 100644 --- a/beacon_chain/attestation_validation/Cargo.toml +++ b/beacon_chain/attestation_validation/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" [dependencies] bls = { path = "../utils/bls" } -db = { path = "../../lighthouse/db" } +db = { path = "../../beacon_node/db" } hashing = { path = "../utils/hashing" } ssz = { path = "../utils/ssz" } types = { path = "../types" } diff --git a/beacon_chain/naive_fork_choice/Cargo.toml b/beacon_chain/naive_fork_choice/Cargo.toml index 9508ed02e..5b3a1b8d2 100644 --- a/beacon_chain/naive_fork_choice/Cargo.toml +++ b/beacon_chain/naive_fork_choice/Cargo.toml @@ -5,6 +5,6 @@ authors = ["Paul Hauner "] edition = "2018" [dependencies] -db = { path = "../../lighthouse/db" } +db = { path = "../../beacon_node/db" } ssz = { path = "../utils/ssz" } types = { path = "../types" } diff --git a/beacon_chain/types/src/lib.rs b/beacon_chain/types/src/lib.rs index 42bea9e0a..cbb2df152 100644 --- a/beacon_chain/types/src/lib.rs +++ b/beacon_chain/types/src/lib.rs @@ -63,3 +63,5 @@ pub type AttesterMap = HashMap<(u64, u64), Vec>; /// Maps a slot to a block proposer. pub type ProposerMap = HashMap; + +pub use bls::{AggregatePublicKey, AggregateSignature, PublicKey, Signature}; diff --git a/beacon_node/Cargo.toml b/beacon_node/Cargo.toml new file mode 100644 index 000000000..002a266b8 --- /dev/null +++ b/beacon_node/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "beacon_node" +version = "0.1.0" +authors = ["Paul Hauner "] +edition = "2018" + +[dependencies] +grpcio = { version = "0.4", default-features = false, features = ["protobuf-codec"] } +protobuf = "2.0.2" +protos = { path = "../protos" } +clap = "2.32.0" +db = { path = "db" } +dirs = "1.0.3" +futures = "0.1.23" +slog = "^2.2.3" +slog-term = "^2.4.0" +slog-async = "^2.3.0" +tokio = "0.1" diff --git a/lighthouse/db/Cargo.toml b/beacon_node/db/Cargo.toml similarity index 100% rename from lighthouse/db/Cargo.toml rename to beacon_node/db/Cargo.toml diff --git a/lighthouse/db/src/disk_db.rs b/beacon_node/db/src/disk_db.rs similarity index 100% rename from lighthouse/db/src/disk_db.rs rename to beacon_node/db/src/disk_db.rs diff --git a/lighthouse/db/src/lib.rs b/beacon_node/db/src/lib.rs similarity index 100% rename from lighthouse/db/src/lib.rs rename to beacon_node/db/src/lib.rs diff --git a/lighthouse/db/src/memory_db.rs b/beacon_node/db/src/memory_db.rs similarity index 100% rename from lighthouse/db/src/memory_db.rs rename to beacon_node/db/src/memory_db.rs diff --git a/lighthouse/db/src/stores/beacon_block_store.rs b/beacon_node/db/src/stores/beacon_block_store.rs similarity index 100% rename from lighthouse/db/src/stores/beacon_block_store.rs rename to beacon_node/db/src/stores/beacon_block_store.rs diff --git a/lighthouse/db/src/stores/beacon_state_store.rs b/beacon_node/db/src/stores/beacon_state_store.rs similarity index 100% rename from lighthouse/db/src/stores/beacon_state_store.rs rename to beacon_node/db/src/stores/beacon_state_store.rs diff --git a/lighthouse/db/src/stores/macros.rs b/beacon_node/db/src/stores/macros.rs similarity index 100% rename from lighthouse/db/src/stores/macros.rs rename to beacon_node/db/src/stores/macros.rs diff --git a/lighthouse/db/src/stores/mod.rs b/beacon_node/db/src/stores/mod.rs similarity index 100% rename from lighthouse/db/src/stores/mod.rs rename to beacon_node/db/src/stores/mod.rs diff --git a/lighthouse/db/src/stores/pow_chain_store.rs b/beacon_node/db/src/stores/pow_chain_store.rs similarity index 100% rename from lighthouse/db/src/stores/pow_chain_store.rs rename to beacon_node/db/src/stores/pow_chain_store.rs diff --git a/lighthouse/db/src/stores/validator_store.rs b/beacon_node/db/src/stores/validator_store.rs similarity index 100% rename from lighthouse/db/src/stores/validator_store.rs rename to beacon_node/db/src/stores/validator_store.rs diff --git a/lighthouse/db/src/traits.rs b/beacon_node/db/src/traits.rs similarity index 100% rename from lighthouse/db/src/traits.rs rename to beacon_node/db/src/traits.rs diff --git a/lighthouse/beacon_chain/src/block_processing.rs b/beacon_node/src/beacon_chain/block_processing.rs similarity index 100% rename from lighthouse/beacon_chain/src/block_processing.rs rename to beacon_node/src/beacon_chain/block_processing.rs diff --git a/lighthouse/beacon_chain/src/block_production.rs b/beacon_node/src/beacon_chain/block_production.rs similarity index 100% rename from lighthouse/beacon_chain/src/block_production.rs rename to beacon_node/src/beacon_chain/block_production.rs diff --git a/lighthouse/beacon_chain/src/lib.rs b/beacon_node/src/beacon_chain/mod.rs similarity index 100% rename from lighthouse/beacon_chain/src/lib.rs rename to beacon_node/src/beacon_chain/mod.rs diff --git a/lighthouse/beacon_chain/tests/chain_test.rs b/beacon_node/src/beacon_chain/tests/chain_test.rs similarity index 100% rename from lighthouse/beacon_chain/tests/chain_test.rs rename to beacon_node/src/beacon_chain/tests/chain_test.rs diff --git a/lighthouse/beacon_chain/src/transition.rs b/beacon_node/src/beacon_chain/transition.rs similarity index 100% rename from lighthouse/beacon_chain/src/transition.rs rename to beacon_node/src/beacon_chain/transition.rs diff --git a/lighthouse/config/mod.rs b/beacon_node/src/config/mod.rs similarity index 97% rename from lighthouse/config/mod.rs rename to beacon_node/src/config/mod.rs index e22b62fb9..5c94e300c 100644 --- a/lighthouse/config/mod.rs +++ b/beacon_node/src/config/mod.rs @@ -1,5 +1,3 @@ -extern crate dirs; - use std::fs; use std::path::PathBuf; diff --git a/lighthouse/main.rs b/beacon_node/src/main.rs similarity index 82% rename from lighthouse/main.rs rename to beacon_node/src/main.rs index b2c199db9..86329c4a2 100644 --- a/lighthouse/main.rs +++ b/beacon_node/src/main.rs @@ -1,20 +1,14 @@ -#[macro_use] extern crate slog; -extern crate slog_async; -extern crate slog_term; -// extern crate ssz; -extern crate clap; -extern crate futures; - -extern crate db; mod config; +mod rpc; use std::path::PathBuf; -use clap::{App, Arg}; use crate::config::LighthouseConfig; -use slog::Drain; +use crate::rpc::start_server; +use clap::{App, Arg}; +use slog::{error, info, o, Drain}; fn main() { let decorator = slog_term::TermDecorator::new().build(); @@ -32,13 +26,15 @@ fn main() { .value_name("DIR") .help("Data directory for keys and databases.") .takes_value(true), - ).arg( + ) + .arg( Arg::with_name("port") .long("port") .value_name("PORT") .help("Network listen port for p2p connections.") .takes_value(true), - ).get_matches(); + ) + .get_matches(); let mut config = LighthouseConfig::default(); @@ -62,10 +58,9 @@ fn main() { "data_dir" => &config.data_dir.to_str(), "port" => &config.p2p_listen_port); - error!( - log, - "Lighthouse under development and does not provide a user demo." - ); + let _server = start_server(log.clone()); - info!(log, "Exiting."); + loop {} + + // info!(log, "Exiting."); } diff --git a/beacon_node/src/rpc/mod.rs b/beacon_node/src/rpc/mod.rs new file mode 100644 index 000000000..38fc049c7 --- /dev/null +++ b/beacon_node/src/rpc/mod.rs @@ -0,0 +1,79 @@ +use std::sync::Arc; + +use futures::Future; +use grpcio::{Environment, RpcContext, Server, ServerBuilder, UnarySink}; + +use protos::services::{ + BeaconBlock as BeaconBlockProto, ProduceBeaconBlockRequest, ProduceBeaconBlockResponse, + PublishBeaconBlockRequest, PublishBeaconBlockResponse, +}; +use protos::services_grpc::{create_beacon_block_service, BeaconBlockService}; + +use slog::{info, Logger}; + +#[derive(Clone)] +struct BeaconBlockServiceInstance { + log: Logger, +} + +impl BeaconBlockService for BeaconBlockServiceInstance { + /// Produce a `BeaconBlock` for signing by a validator. + fn produce_beacon_block( + &mut self, + ctx: RpcContext, + req: ProduceBeaconBlockRequest, + sink: UnarySink, + ) { + println!("producing at slot {}", req.get_slot()); + + // TODO: build a legit block. + let mut block = BeaconBlockProto::new(); + block.set_slot(req.get_slot()); + block.set_block_root("cats".as_bytes().to_vec()); + + let mut resp = ProduceBeaconBlockResponse::new(); + resp.set_block(block); + + let f = sink + .success(resp) + .map_err(move |e| println!("failed to reply {:?}: {:?}", req, e)); + ctx.spawn(f) + } + + /// Accept some fully-formed `BeaconBlock`, process and publish it. + fn publish_beacon_block( + &mut self, + ctx: RpcContext, + req: PublishBeaconBlockRequest, + sink: UnarySink, + ) { + println!("publishing {:?}", req.get_block()); + + // TODO: actually process the block. + let mut resp = PublishBeaconBlockResponse::new(); + resp.set_success(true); + + let f = sink + .success(resp) + .map_err(move |e| println!("failed to reply {:?}: {:?}", req, e)); + ctx.spawn(f) + } +} + +pub fn start_server(log: Logger) -> Server { + let log_clone = log.clone(); + + let env = Arc::new(Environment::new(1)); + let instance = BeaconBlockServiceInstance { log }; + let service = create_beacon_block_service(instance); + let mut server = ServerBuilder::new(env) + .register_service(service) + .bind("127.0.0.1", 50_051) + .build() + .unwrap(); + server.start(); + for &(ref host, port) in server.bind_addrs() { + info!(log_clone, "gRPC listening on {}:{}", host, port); + } + server +} diff --git a/lighthouse/beacon_chain/Cargo.toml b/lighthouse/beacon_chain/Cargo.toml deleted file mode 100644 index 5e2794977..000000000 --- a/lighthouse/beacon_chain/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "chain" -version = "0.1.0" -authors = ["Paul Hauner "] -edition = "2018" - -[dependencies] -bls = { path = "../../beacon_chain/utils/bls" } -db = { path = "../db" } -genesis = { path = "../../beacon_chain/genesis" } -naive_fork_choice = { path = "../../beacon_chain/naive_fork_choice" } -slot_clock = { path = "../../beacon_chain/utils/slot_clock" } -spec = { path = "../../beacon_chain/spec" } -ssz = { path = "../../beacon_chain/utils/ssz" } -types = { path = "../../beacon_chain/types" } -validator_induction = { path = "../../beacon_chain/validator_induction" } -validator_shuffling = { path = "../../beacon_chain/validator_shuffling" } diff --git a/protos/Cargo.toml b/protos/Cargo.toml new file mode 100644 index 000000000..8a2bf6245 --- /dev/null +++ b/protos/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "protos" +version = "0.1.0" +authors = ["Paul Hauner "] +edition = "2018" + +[dependencies] +futures = "0.1.16" +grpcio = { version = "0.4", default-features = false, features = ["protobuf-codec"] } +protobuf = "2.0.2" + +[build-dependencies] +protoc-grpcio = "0.3.1" diff --git a/protos/build.rs b/protos/build.rs new file mode 100644 index 000000000..d8becfa51 --- /dev/null +++ b/protos/build.rs @@ -0,0 +1,8 @@ +extern crate protoc_grpcio; + +fn main() { + let proto_root = "src/"; + println!("cargo:rerun-if-changed={}", proto_root); + protoc_grpcio::compile_grpc_protos(&["services.proto"], &[proto_root], &proto_root) + .expect("Failed to compile gRPC definitions!"); +} diff --git a/protos/src/lib.rs b/protos/src/lib.rs new file mode 100644 index 000000000..a9684909d --- /dev/null +++ b/protos/src/lib.rs @@ -0,0 +1,2 @@ +pub mod services; +pub mod services_grpc; diff --git a/protos/src/services.proto b/protos/src/services.proto new file mode 100644 index 000000000..dd6c51325 --- /dev/null +++ b/protos/src/services.proto @@ -0,0 +1,46 @@ +// TODO: This setup requires that the BN (beacon node) holds the block in state +// during the interval between the `GenerateProposalRequest` and the +// `SubmitProposalRequest`. +// +// This is sub-optimal as if a validator client switches BN during this process +// the block will be lost. +// +// This "stateful" method is being used presently because it's easier and +// requires less maintainence as the `BeaconBlock` definition changes. + +syntax = "proto3"; + +package ethereum.beacon.rpc.v1; + +service BeaconBlockService { + rpc ProduceBeaconBlock(ProduceBeaconBlockRequest) returns (ProduceBeaconBlockResponse); + rpc PublishBeaconBlock(PublishBeaconBlockRequest) returns (PublishBeaconBlockResponse); +} + +message BeaconBlock { + uint64 slot = 1; + bytes block_root = 2; + bytes randao_reveal = 3; + bytes signature = 4; +} + +// Validator requests an unsigned proposal. +message ProduceBeaconBlockRequest { + uint64 slot = 1; +} + +// Beacon node returns an unsigned proposal. +message ProduceBeaconBlockResponse { + BeaconBlock block = 1; +} + +// Validator submits a signed proposal. +message PublishBeaconBlockRequest { + BeaconBlock block = 1; +} + +// Beacon node indicates a sucessfully submitted proposal. +message PublishBeaconBlockResponse { + bool success = 1; + bytes msg = 2; +} diff --git a/protos/src/services.rs b/protos/src/services.rs new file mode 100644 index 000000000..226e0ae9a --- /dev/null +++ b/protos/src/services.rs @@ -0,0 +1,1049 @@ +// This file is generated by rust-protobuf 2.0.5. Do not edit +// @generated + +// https://github.com/Manishearth/rust-clippy/issues/702 +#![allow(unknown_lints)] +#![allow(clippy)] + +#![cfg_attr(rustfmt, rustfmt_skip)] + +#![allow(box_pointers)] +#![allow(dead_code)] +#![allow(missing_docs)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +#![allow(non_upper_case_globals)] +#![allow(trivial_casts)] +#![allow(unsafe_code)] +#![allow(unused_imports)] +#![allow(unused_results)] + +use protobuf::Message as Message_imported_for_functions; +use protobuf::ProtobufEnum as ProtobufEnum_imported_for_functions; + +#[derive(PartialEq,Clone,Default)] +pub struct BeaconBlock { + // message fields + pub slot: u64, + pub block_root: ::std::vec::Vec, + pub randao_reveal: ::std::vec::Vec, + pub signature: ::std::vec::Vec, + // special fields + unknown_fields: ::protobuf::UnknownFields, + cached_size: ::protobuf::CachedSize, +} + +impl BeaconBlock { + pub fn new() -> BeaconBlock { + ::std::default::Default::default() + } + + // uint64 slot = 1; + + pub fn clear_slot(&mut self) { + self.slot = 0; + } + + // Param is passed by value, moved + pub fn set_slot(&mut self, v: u64) { + self.slot = v; + } + + pub fn get_slot(&self) -> u64 { + self.slot + } + + // bytes block_root = 2; + + pub fn clear_block_root(&mut self) { + self.block_root.clear(); + } + + // Param is passed by value, moved + pub fn set_block_root(&mut self, v: ::std::vec::Vec) { + self.block_root = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_block_root(&mut self) -> &mut ::std::vec::Vec { + &mut self.block_root + } + + // Take field + pub fn take_block_root(&mut self) -> ::std::vec::Vec { + ::std::mem::replace(&mut self.block_root, ::std::vec::Vec::new()) + } + + pub fn get_block_root(&self) -> &[u8] { + &self.block_root + } + + // bytes randao_reveal = 3; + + pub fn clear_randao_reveal(&mut self) { + self.randao_reveal.clear(); + } + + // Param is passed by value, moved + pub fn set_randao_reveal(&mut self, v: ::std::vec::Vec) { + self.randao_reveal = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_randao_reveal(&mut self) -> &mut ::std::vec::Vec { + &mut self.randao_reveal + } + + // Take field + pub fn take_randao_reveal(&mut self) -> ::std::vec::Vec { + ::std::mem::replace(&mut self.randao_reveal, ::std::vec::Vec::new()) + } + + pub fn get_randao_reveal(&self) -> &[u8] { + &self.randao_reveal + } + + // bytes signature = 4; + + pub fn clear_signature(&mut self) { + self.signature.clear(); + } + + // Param is passed by value, moved + pub fn set_signature(&mut self, v: ::std::vec::Vec) { + self.signature = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_signature(&mut self) -> &mut ::std::vec::Vec { + &mut self.signature + } + + // Take field + pub fn take_signature(&mut self) -> ::std::vec::Vec { + ::std::mem::replace(&mut self.signature, ::std::vec::Vec::new()) + } + + pub fn get_signature(&self) -> &[u8] { + &self.signature + } +} + +impl ::protobuf::Message for BeaconBlock { + fn is_initialized(&self) -> bool { + true + } + + fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream) -> ::protobuf::ProtobufResult<()> { + while !is.eof()? { + let (field_number, wire_type) = is.read_tag_unpack()?; + match field_number { + 1 => { + if wire_type != ::protobuf::wire_format::WireTypeVarint { + return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); + } + let tmp = is.read_uint64()?; + self.slot = tmp; + }, + 2 => { + ::protobuf::rt::read_singular_proto3_bytes_into(wire_type, is, &mut self.block_root)?; + }, + 3 => { + ::protobuf::rt::read_singular_proto3_bytes_into(wire_type, is, &mut self.randao_reveal)?; + }, + 4 => { + ::protobuf::rt::read_singular_proto3_bytes_into(wire_type, is, &mut self.signature)?; + }, + _ => { + ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; + }, + }; + } + ::std::result::Result::Ok(()) + } + + // Compute sizes of nested messages + #[allow(unused_variables)] + fn compute_size(&self) -> u32 { + let mut my_size = 0; + if self.slot != 0 { + my_size += ::protobuf::rt::value_size(1, self.slot, ::protobuf::wire_format::WireTypeVarint); + } + if !self.block_root.is_empty() { + my_size += ::protobuf::rt::bytes_size(2, &self.block_root); + } + if !self.randao_reveal.is_empty() { + my_size += ::protobuf::rt::bytes_size(3, &self.randao_reveal); + } + if !self.signature.is_empty() { + my_size += ::protobuf::rt::bytes_size(4, &self.signature); + } + my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); + self.cached_size.set(my_size); + my_size + } + + fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream) -> ::protobuf::ProtobufResult<()> { + if self.slot != 0 { + os.write_uint64(1, self.slot)?; + } + if !self.block_root.is_empty() { + os.write_bytes(2, &self.block_root)?; + } + if !self.randao_reveal.is_empty() { + os.write_bytes(3, &self.randao_reveal)?; + } + if !self.signature.is_empty() { + os.write_bytes(4, &self.signature)?; + } + os.write_unknown_fields(self.get_unknown_fields())?; + ::std::result::Result::Ok(()) + } + + fn get_cached_size(&self) -> u32 { + self.cached_size.get() + } + + fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { + &self.unknown_fields + } + + fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { + &mut self.unknown_fields + } + + fn as_any(&self) -> &::std::any::Any { + self as &::std::any::Any + } + fn as_any_mut(&mut self) -> &mut ::std::any::Any { + self as &mut ::std::any::Any + } + fn into_any(self: Box) -> ::std::boxed::Box<::std::any::Any> { + self + } + + fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { + Self::descriptor_static() + } + + fn new() -> BeaconBlock { + BeaconBlock::new() + } + + fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { + static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::lazy::Lazy { + lock: ::protobuf::lazy::ONCE_INIT, + ptr: 0 as *const ::protobuf::reflect::MessageDescriptor, + }; + unsafe { + descriptor.get(|| { + let mut fields = ::std::vec::Vec::new(); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeUint64>( + "slot", + |m: &BeaconBlock| { &m.slot }, + |m: &mut BeaconBlock| { &mut m.slot }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>( + "block_root", + |m: &BeaconBlock| { &m.block_root }, + |m: &mut BeaconBlock| { &mut m.block_root }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>( + "randao_reveal", + |m: &BeaconBlock| { &m.randao_reveal }, + |m: &mut BeaconBlock| { &mut m.randao_reveal }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>( + "signature", + |m: &BeaconBlock| { &m.signature }, + |m: &mut BeaconBlock| { &mut m.signature }, + )); + ::protobuf::reflect::MessageDescriptor::new::( + "BeaconBlock", + fields, + file_descriptor_proto() + ) + }) + } + } + + fn default_instance() -> &'static BeaconBlock { + static mut instance: ::protobuf::lazy::Lazy = ::protobuf::lazy::Lazy { + lock: ::protobuf::lazy::ONCE_INIT, + ptr: 0 as *const BeaconBlock, + }; + unsafe { + instance.get(BeaconBlock::new) + } + } +} + +impl ::protobuf::Clear for BeaconBlock { + fn clear(&mut self) { + self.clear_slot(); + self.clear_block_root(); + self.clear_randao_reveal(); + self.clear_signature(); + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for BeaconBlock { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for BeaconBlock { + fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef { + ::protobuf::reflect::ProtobufValueRef::Message(self) + } +} + +#[derive(PartialEq,Clone,Default)] +pub struct ProduceBeaconBlockRequest { + // message fields + pub slot: u64, + // special fields + unknown_fields: ::protobuf::UnknownFields, + cached_size: ::protobuf::CachedSize, +} + +impl ProduceBeaconBlockRequest { + pub fn new() -> ProduceBeaconBlockRequest { + ::std::default::Default::default() + } + + // uint64 slot = 1; + + pub fn clear_slot(&mut self) { + self.slot = 0; + } + + // Param is passed by value, moved + pub fn set_slot(&mut self, v: u64) { + self.slot = v; + } + + pub fn get_slot(&self) -> u64 { + self.slot + } +} + +impl ::protobuf::Message for ProduceBeaconBlockRequest { + fn is_initialized(&self) -> bool { + true + } + + fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream) -> ::protobuf::ProtobufResult<()> { + while !is.eof()? { + let (field_number, wire_type) = is.read_tag_unpack()?; + match field_number { + 1 => { + if wire_type != ::protobuf::wire_format::WireTypeVarint { + return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); + } + let tmp = is.read_uint64()?; + self.slot = tmp; + }, + _ => { + ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; + }, + }; + } + ::std::result::Result::Ok(()) + } + + // Compute sizes of nested messages + #[allow(unused_variables)] + fn compute_size(&self) -> u32 { + let mut my_size = 0; + if self.slot != 0 { + my_size += ::protobuf::rt::value_size(1, self.slot, ::protobuf::wire_format::WireTypeVarint); + } + my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); + self.cached_size.set(my_size); + my_size + } + + fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream) -> ::protobuf::ProtobufResult<()> { + if self.slot != 0 { + os.write_uint64(1, self.slot)?; + } + os.write_unknown_fields(self.get_unknown_fields())?; + ::std::result::Result::Ok(()) + } + + fn get_cached_size(&self) -> u32 { + self.cached_size.get() + } + + fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { + &self.unknown_fields + } + + fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { + &mut self.unknown_fields + } + + fn as_any(&self) -> &::std::any::Any { + self as &::std::any::Any + } + fn as_any_mut(&mut self) -> &mut ::std::any::Any { + self as &mut ::std::any::Any + } + fn into_any(self: Box) -> ::std::boxed::Box<::std::any::Any> { + self + } + + fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { + Self::descriptor_static() + } + + fn new() -> ProduceBeaconBlockRequest { + ProduceBeaconBlockRequest::new() + } + + fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { + static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::lazy::Lazy { + lock: ::protobuf::lazy::ONCE_INIT, + ptr: 0 as *const ::protobuf::reflect::MessageDescriptor, + }; + unsafe { + descriptor.get(|| { + let mut fields = ::std::vec::Vec::new(); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeUint64>( + "slot", + |m: &ProduceBeaconBlockRequest| { &m.slot }, + |m: &mut ProduceBeaconBlockRequest| { &mut m.slot }, + )); + ::protobuf::reflect::MessageDescriptor::new::( + "ProduceBeaconBlockRequest", + fields, + file_descriptor_proto() + ) + }) + } + } + + fn default_instance() -> &'static ProduceBeaconBlockRequest { + static mut instance: ::protobuf::lazy::Lazy = ::protobuf::lazy::Lazy { + lock: ::protobuf::lazy::ONCE_INIT, + ptr: 0 as *const ProduceBeaconBlockRequest, + }; + unsafe { + instance.get(ProduceBeaconBlockRequest::new) + } + } +} + +impl ::protobuf::Clear for ProduceBeaconBlockRequest { + fn clear(&mut self) { + self.clear_slot(); + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for ProduceBeaconBlockRequest { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for ProduceBeaconBlockRequest { + fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef { + ::protobuf::reflect::ProtobufValueRef::Message(self) + } +} + +#[derive(PartialEq,Clone,Default)] +pub struct ProduceBeaconBlockResponse { + // message fields + pub block: ::protobuf::SingularPtrField, + // special fields + unknown_fields: ::protobuf::UnknownFields, + cached_size: ::protobuf::CachedSize, +} + +impl ProduceBeaconBlockResponse { + pub fn new() -> ProduceBeaconBlockResponse { + ::std::default::Default::default() + } + + // .ethereum.beacon.rpc.v1.BeaconBlock block = 1; + + pub fn clear_block(&mut self) { + self.block.clear(); + } + + pub fn has_block(&self) -> bool { + self.block.is_some() + } + + // Param is passed by value, moved + pub fn set_block(&mut self, v: BeaconBlock) { + self.block = ::protobuf::SingularPtrField::some(v); + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_block(&mut self) -> &mut BeaconBlock { + if self.block.is_none() { + self.block.set_default(); + } + self.block.as_mut().unwrap() + } + + // Take field + pub fn take_block(&mut self) -> BeaconBlock { + self.block.take().unwrap_or_else(|| BeaconBlock::new()) + } + + pub fn get_block(&self) -> &BeaconBlock { + self.block.as_ref().unwrap_or_else(|| BeaconBlock::default_instance()) + } +} + +impl ::protobuf::Message for ProduceBeaconBlockResponse { + fn is_initialized(&self) -> bool { + for v in &self.block { + if !v.is_initialized() { + return false; + } + }; + true + } + + fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream) -> ::protobuf::ProtobufResult<()> { + while !is.eof()? { + let (field_number, wire_type) = is.read_tag_unpack()?; + match field_number { + 1 => { + ::protobuf::rt::read_singular_message_into(wire_type, is, &mut self.block)?; + }, + _ => { + ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; + }, + }; + } + ::std::result::Result::Ok(()) + } + + // Compute sizes of nested messages + #[allow(unused_variables)] + fn compute_size(&self) -> u32 { + let mut my_size = 0; + if let Some(ref v) = self.block.as_ref() { + let len = v.compute_size(); + my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; + } + my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); + self.cached_size.set(my_size); + my_size + } + + fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream) -> ::protobuf::ProtobufResult<()> { + if let Some(ref v) = self.block.as_ref() { + os.write_tag(1, ::protobuf::wire_format::WireTypeLengthDelimited)?; + os.write_raw_varint32(v.get_cached_size())?; + v.write_to_with_cached_sizes(os)?; + } + os.write_unknown_fields(self.get_unknown_fields())?; + ::std::result::Result::Ok(()) + } + + fn get_cached_size(&self) -> u32 { + self.cached_size.get() + } + + fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { + &self.unknown_fields + } + + fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { + &mut self.unknown_fields + } + + fn as_any(&self) -> &::std::any::Any { + self as &::std::any::Any + } + fn as_any_mut(&mut self) -> &mut ::std::any::Any { + self as &mut ::std::any::Any + } + fn into_any(self: Box) -> ::std::boxed::Box<::std::any::Any> { + self + } + + fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { + Self::descriptor_static() + } + + fn new() -> ProduceBeaconBlockResponse { + ProduceBeaconBlockResponse::new() + } + + fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { + static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::lazy::Lazy { + lock: ::protobuf::lazy::ONCE_INIT, + ptr: 0 as *const ::protobuf::reflect::MessageDescriptor, + }; + unsafe { + descriptor.get(|| { + let mut fields = ::std::vec::Vec::new(); + fields.push(::protobuf::reflect::accessor::make_singular_ptr_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( + "block", + |m: &ProduceBeaconBlockResponse| { &m.block }, + |m: &mut ProduceBeaconBlockResponse| { &mut m.block }, + )); + ::protobuf::reflect::MessageDescriptor::new::( + "ProduceBeaconBlockResponse", + fields, + file_descriptor_proto() + ) + }) + } + } + + fn default_instance() -> &'static ProduceBeaconBlockResponse { + static mut instance: ::protobuf::lazy::Lazy = ::protobuf::lazy::Lazy { + lock: ::protobuf::lazy::ONCE_INIT, + ptr: 0 as *const ProduceBeaconBlockResponse, + }; + unsafe { + instance.get(ProduceBeaconBlockResponse::new) + } + } +} + +impl ::protobuf::Clear for ProduceBeaconBlockResponse { + fn clear(&mut self) { + self.clear_block(); + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for ProduceBeaconBlockResponse { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for ProduceBeaconBlockResponse { + fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef { + ::protobuf::reflect::ProtobufValueRef::Message(self) + } +} + +#[derive(PartialEq,Clone,Default)] +pub struct PublishBeaconBlockRequest { + // message fields + pub block: ::protobuf::SingularPtrField, + // special fields + unknown_fields: ::protobuf::UnknownFields, + cached_size: ::protobuf::CachedSize, +} + +impl PublishBeaconBlockRequest { + pub fn new() -> PublishBeaconBlockRequest { + ::std::default::Default::default() + } + + // .ethereum.beacon.rpc.v1.BeaconBlock block = 1; + + pub fn clear_block(&mut self) { + self.block.clear(); + } + + pub fn has_block(&self) -> bool { + self.block.is_some() + } + + // Param is passed by value, moved + pub fn set_block(&mut self, v: BeaconBlock) { + self.block = ::protobuf::SingularPtrField::some(v); + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_block(&mut self) -> &mut BeaconBlock { + if self.block.is_none() { + self.block.set_default(); + } + self.block.as_mut().unwrap() + } + + // Take field + pub fn take_block(&mut self) -> BeaconBlock { + self.block.take().unwrap_or_else(|| BeaconBlock::new()) + } + + pub fn get_block(&self) -> &BeaconBlock { + self.block.as_ref().unwrap_or_else(|| BeaconBlock::default_instance()) + } +} + +impl ::protobuf::Message for PublishBeaconBlockRequest { + fn is_initialized(&self) -> bool { + for v in &self.block { + if !v.is_initialized() { + return false; + } + }; + true + } + + fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream) -> ::protobuf::ProtobufResult<()> { + while !is.eof()? { + let (field_number, wire_type) = is.read_tag_unpack()?; + match field_number { + 1 => { + ::protobuf::rt::read_singular_message_into(wire_type, is, &mut self.block)?; + }, + _ => { + ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; + }, + }; + } + ::std::result::Result::Ok(()) + } + + // Compute sizes of nested messages + #[allow(unused_variables)] + fn compute_size(&self) -> u32 { + let mut my_size = 0; + if let Some(ref v) = self.block.as_ref() { + let len = v.compute_size(); + my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; + } + my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); + self.cached_size.set(my_size); + my_size + } + + fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream) -> ::protobuf::ProtobufResult<()> { + if let Some(ref v) = self.block.as_ref() { + os.write_tag(1, ::protobuf::wire_format::WireTypeLengthDelimited)?; + os.write_raw_varint32(v.get_cached_size())?; + v.write_to_with_cached_sizes(os)?; + } + os.write_unknown_fields(self.get_unknown_fields())?; + ::std::result::Result::Ok(()) + } + + fn get_cached_size(&self) -> u32 { + self.cached_size.get() + } + + fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { + &self.unknown_fields + } + + fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { + &mut self.unknown_fields + } + + fn as_any(&self) -> &::std::any::Any { + self as &::std::any::Any + } + fn as_any_mut(&mut self) -> &mut ::std::any::Any { + self as &mut ::std::any::Any + } + fn into_any(self: Box) -> ::std::boxed::Box<::std::any::Any> { + self + } + + fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { + Self::descriptor_static() + } + + fn new() -> PublishBeaconBlockRequest { + PublishBeaconBlockRequest::new() + } + + fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { + static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::lazy::Lazy { + lock: ::protobuf::lazy::ONCE_INIT, + ptr: 0 as *const ::protobuf::reflect::MessageDescriptor, + }; + unsafe { + descriptor.get(|| { + let mut fields = ::std::vec::Vec::new(); + fields.push(::protobuf::reflect::accessor::make_singular_ptr_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( + "block", + |m: &PublishBeaconBlockRequest| { &m.block }, + |m: &mut PublishBeaconBlockRequest| { &mut m.block }, + )); + ::protobuf::reflect::MessageDescriptor::new::( + "PublishBeaconBlockRequest", + fields, + file_descriptor_proto() + ) + }) + } + } + + fn default_instance() -> &'static PublishBeaconBlockRequest { + static mut instance: ::protobuf::lazy::Lazy = ::protobuf::lazy::Lazy { + lock: ::protobuf::lazy::ONCE_INIT, + ptr: 0 as *const PublishBeaconBlockRequest, + }; + unsafe { + instance.get(PublishBeaconBlockRequest::new) + } + } +} + +impl ::protobuf::Clear for PublishBeaconBlockRequest { + fn clear(&mut self) { + self.clear_block(); + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for PublishBeaconBlockRequest { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for PublishBeaconBlockRequest { + fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef { + ::protobuf::reflect::ProtobufValueRef::Message(self) + } +} + +#[derive(PartialEq,Clone,Default)] +pub struct PublishBeaconBlockResponse { + // message fields + pub success: bool, + pub msg: ::std::vec::Vec, + // special fields + unknown_fields: ::protobuf::UnknownFields, + cached_size: ::protobuf::CachedSize, +} + +impl PublishBeaconBlockResponse { + pub fn new() -> PublishBeaconBlockResponse { + ::std::default::Default::default() + } + + // bool success = 1; + + pub fn clear_success(&mut self) { + self.success = false; + } + + // Param is passed by value, moved + pub fn set_success(&mut self, v: bool) { + self.success = v; + } + + pub fn get_success(&self) -> bool { + self.success + } + + // bytes msg = 2; + + pub fn clear_msg(&mut self) { + self.msg.clear(); + } + + // Param is passed by value, moved + pub fn set_msg(&mut self, v: ::std::vec::Vec) { + self.msg = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_msg(&mut self) -> &mut ::std::vec::Vec { + &mut self.msg + } + + // Take field + pub fn take_msg(&mut self) -> ::std::vec::Vec { + ::std::mem::replace(&mut self.msg, ::std::vec::Vec::new()) + } + + pub fn get_msg(&self) -> &[u8] { + &self.msg + } +} + +impl ::protobuf::Message for PublishBeaconBlockResponse { + fn is_initialized(&self) -> bool { + true + } + + fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream) -> ::protobuf::ProtobufResult<()> { + while !is.eof()? { + let (field_number, wire_type) = is.read_tag_unpack()?; + match field_number { + 1 => { + if wire_type != ::protobuf::wire_format::WireTypeVarint { + return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); + } + let tmp = is.read_bool()?; + self.success = tmp; + }, + 2 => { + ::protobuf::rt::read_singular_proto3_bytes_into(wire_type, is, &mut self.msg)?; + }, + _ => { + ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; + }, + }; + } + ::std::result::Result::Ok(()) + } + + // Compute sizes of nested messages + #[allow(unused_variables)] + fn compute_size(&self) -> u32 { + let mut my_size = 0; + if self.success != false { + my_size += 2; + } + if !self.msg.is_empty() { + my_size += ::protobuf::rt::bytes_size(2, &self.msg); + } + my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); + self.cached_size.set(my_size); + my_size + } + + fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream) -> ::protobuf::ProtobufResult<()> { + if self.success != false { + os.write_bool(1, self.success)?; + } + if !self.msg.is_empty() { + os.write_bytes(2, &self.msg)?; + } + os.write_unknown_fields(self.get_unknown_fields())?; + ::std::result::Result::Ok(()) + } + + fn get_cached_size(&self) -> u32 { + self.cached_size.get() + } + + fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { + &self.unknown_fields + } + + fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { + &mut self.unknown_fields + } + + fn as_any(&self) -> &::std::any::Any { + self as &::std::any::Any + } + fn as_any_mut(&mut self) -> &mut ::std::any::Any { + self as &mut ::std::any::Any + } + fn into_any(self: Box) -> ::std::boxed::Box<::std::any::Any> { + self + } + + fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { + Self::descriptor_static() + } + + fn new() -> PublishBeaconBlockResponse { + PublishBeaconBlockResponse::new() + } + + fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { + static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::lazy::Lazy { + lock: ::protobuf::lazy::ONCE_INIT, + ptr: 0 as *const ::protobuf::reflect::MessageDescriptor, + }; + unsafe { + descriptor.get(|| { + let mut fields = ::std::vec::Vec::new(); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBool>( + "success", + |m: &PublishBeaconBlockResponse| { &m.success }, + |m: &mut PublishBeaconBlockResponse| { &mut m.success }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>( + "msg", + |m: &PublishBeaconBlockResponse| { &m.msg }, + |m: &mut PublishBeaconBlockResponse| { &mut m.msg }, + )); + ::protobuf::reflect::MessageDescriptor::new::( + "PublishBeaconBlockResponse", + fields, + file_descriptor_proto() + ) + }) + } + } + + fn default_instance() -> &'static PublishBeaconBlockResponse { + static mut instance: ::protobuf::lazy::Lazy = ::protobuf::lazy::Lazy { + lock: ::protobuf::lazy::ONCE_INIT, + ptr: 0 as *const PublishBeaconBlockResponse, + }; + unsafe { + instance.get(PublishBeaconBlockResponse::new) + } + } +} + +impl ::protobuf::Clear for PublishBeaconBlockResponse { + fn clear(&mut self) { + self.clear_success(); + self.clear_msg(); + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for PublishBeaconBlockResponse { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for PublishBeaconBlockResponse { + fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef { + ::protobuf::reflect::ProtobufValueRef::Message(self) + } +} + +static file_descriptor_proto_data: &'static [u8] = b"\ + \n\x0eservices.proto\x12\x16ethereum.beacon.rpc.v1\"\x83\x01\n\x0bBeacon\ + Block\x12\x12\n\x04slot\x18\x01\x20\x01(\x04R\x04slot\x12\x1d\n\nblock_r\ + oot\x18\x02\x20\x01(\x0cR\tblockRoot\x12#\n\rrandao_reveal\x18\x03\x20\ + \x01(\x0cR\x0crandaoReveal\x12\x1c\n\tsignature\x18\x04\x20\x01(\x0cR\ts\ + ignature\"/\n\x19ProduceBeaconBlockRequest\x12\x12\n\x04slot\x18\x01\x20\ + \x01(\x04R\x04slot\"W\n\x1aProduceBeaconBlockResponse\x129\n\x05block\ + \x18\x01\x20\x01(\x0b2#.ethereum.beacon.rpc.v1.BeaconBlockR\x05block\"V\ + \n\x19PublishBeaconBlockRequest\x129\n\x05block\x18\x01\x20\x01(\x0b2#.e\ + thereum.beacon.rpc.v1.BeaconBlockR\x05block\"H\n\x1aPublishBeaconBlockRe\ + sponse\x12\x18\n\x07success\x18\x01\x20\x01(\x08R\x07success\x12\x10\n\ + \x03msg\x18\x02\x20\x01(\x0cR\x03msg2\x8e\x02\n\x12BeaconBlockService\ + \x12{\n\x12ProduceBeaconBlock\x121.ethereum.beacon.rpc.v1.ProduceBeaconB\ + lockRequest\x1a2.ethereum.beacon.rpc.v1.ProduceBeaconBlockResponse\x12{\ + \n\x12PublishBeaconBlock\x121.ethereum.beacon.rpc.v1.PublishBeaconBlockR\ + equest\x1a2.ethereum.beacon.rpc.v1.PublishBeaconBlockResponseb\x06proto3\ +"; + +static mut file_descriptor_proto_lazy: ::protobuf::lazy::Lazy<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::lazy::Lazy { + lock: ::protobuf::lazy::ONCE_INIT, + ptr: 0 as *const ::protobuf::descriptor::FileDescriptorProto, +}; + +fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto { + ::protobuf::parse_from_bytes(file_descriptor_proto_data).unwrap() +} + +pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto { + unsafe { + file_descriptor_proto_lazy.get(|| { + parse_descriptor_proto() + }) + } +} diff --git a/protos/src/services_grpc.rs b/protos/src/services_grpc.rs new file mode 100644 index 000000000..701c59d0d --- /dev/null +++ b/protos/src/services_grpc.rs @@ -0,0 +1,99 @@ +// This file is generated. Do not edit +// @generated + +// https://github.com/Manishearth/rust-clippy/issues/702 +#![allow(unknown_lints)] +#![allow(clippy)] + +#![cfg_attr(rustfmt, rustfmt_skip)] + +#![allow(box_pointers)] +#![allow(dead_code)] +#![allow(missing_docs)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +#![allow(non_upper_case_globals)] +#![allow(trivial_casts)] +#![allow(unsafe_code)] +#![allow(unused_imports)] +#![allow(unused_results)] + +const METHOD_BEACON_BLOCK_SERVICE_PRODUCE_BEACON_BLOCK: ::grpcio::Method = ::grpcio::Method { + ty: ::grpcio::MethodType::Unary, + name: "/ethereum.beacon.rpc.v1.BeaconBlockService/ProduceBeaconBlock", + req_mar: ::grpcio::Marshaller { ser: ::grpcio::pb_ser, de: ::grpcio::pb_de }, + resp_mar: ::grpcio::Marshaller { ser: ::grpcio::pb_ser, de: ::grpcio::pb_de }, +}; + +const METHOD_BEACON_BLOCK_SERVICE_PUBLISH_BEACON_BLOCK: ::grpcio::Method = ::grpcio::Method { + ty: ::grpcio::MethodType::Unary, + name: "/ethereum.beacon.rpc.v1.BeaconBlockService/PublishBeaconBlock", + req_mar: ::grpcio::Marshaller { ser: ::grpcio::pb_ser, de: ::grpcio::pb_de }, + resp_mar: ::grpcio::Marshaller { ser: ::grpcio::pb_ser, de: ::grpcio::pb_de }, +}; + +#[derive(Clone)] +pub struct BeaconBlockServiceClient { + client: ::grpcio::Client, +} + +impl BeaconBlockServiceClient { + pub fn new(channel: ::grpcio::Channel) -> Self { + BeaconBlockServiceClient { + client: ::grpcio::Client::new(channel), + } + } + + pub fn produce_beacon_block_opt(&self, req: &super::services::ProduceBeaconBlockRequest, opt: ::grpcio::CallOption) -> ::grpcio::Result { + self.client.unary_call(&METHOD_BEACON_BLOCK_SERVICE_PRODUCE_BEACON_BLOCK, req, opt) + } + + pub fn produce_beacon_block(&self, req: &super::services::ProduceBeaconBlockRequest) -> ::grpcio::Result { + self.produce_beacon_block_opt(req, ::grpcio::CallOption::default()) + } + + pub fn produce_beacon_block_async_opt(&self, req: &super::services::ProduceBeaconBlockRequest, opt: ::grpcio::CallOption) -> ::grpcio::Result<::grpcio::ClientUnaryReceiver> { + self.client.unary_call_async(&METHOD_BEACON_BLOCK_SERVICE_PRODUCE_BEACON_BLOCK, req, opt) + } + + pub fn produce_beacon_block_async(&self, req: &super::services::ProduceBeaconBlockRequest) -> ::grpcio::Result<::grpcio::ClientUnaryReceiver> { + self.produce_beacon_block_async_opt(req, ::grpcio::CallOption::default()) + } + + pub fn publish_beacon_block_opt(&self, req: &super::services::PublishBeaconBlockRequest, opt: ::grpcio::CallOption) -> ::grpcio::Result { + self.client.unary_call(&METHOD_BEACON_BLOCK_SERVICE_PUBLISH_BEACON_BLOCK, req, opt) + } + + pub fn publish_beacon_block(&self, req: &super::services::PublishBeaconBlockRequest) -> ::grpcio::Result { + self.publish_beacon_block_opt(req, ::grpcio::CallOption::default()) + } + + pub fn publish_beacon_block_async_opt(&self, req: &super::services::PublishBeaconBlockRequest, opt: ::grpcio::CallOption) -> ::grpcio::Result<::grpcio::ClientUnaryReceiver> { + self.client.unary_call_async(&METHOD_BEACON_BLOCK_SERVICE_PUBLISH_BEACON_BLOCK, req, opt) + } + + pub fn publish_beacon_block_async(&self, req: &super::services::PublishBeaconBlockRequest) -> ::grpcio::Result<::grpcio::ClientUnaryReceiver> { + self.publish_beacon_block_async_opt(req, ::grpcio::CallOption::default()) + } + pub fn spawn(&self, f: F) where F: ::futures::Future + Send + 'static { + self.client.spawn(f) + } +} + +pub trait BeaconBlockService { + fn produce_beacon_block(&mut self, ctx: ::grpcio::RpcContext, req: super::services::ProduceBeaconBlockRequest, sink: ::grpcio::UnarySink); + fn publish_beacon_block(&mut self, ctx: ::grpcio::RpcContext, req: super::services::PublishBeaconBlockRequest, sink: ::grpcio::UnarySink); +} + +pub fn create_beacon_block_service(s: S) -> ::grpcio::Service { + let mut builder = ::grpcio::ServiceBuilder::new(); + let mut instance = s.clone(); + builder = builder.add_unary_handler(&METHOD_BEACON_BLOCK_SERVICE_PRODUCE_BEACON_BLOCK, move |ctx, req, resp| { + instance.produce_beacon_block(ctx, req, resp) + }); + let mut instance = s.clone(); + builder = builder.add_unary_handler(&METHOD_BEACON_BLOCK_SERVICE_PUBLISH_BEACON_BLOCK, move |ctx, req, resp| { + instance.publish_beacon_block(ctx, req, resp) + }); + builder.build() +} diff --git a/validator_client/Cargo.toml b/validator_client/Cargo.toml new file mode 100644 index 000000000..ce74639d0 --- /dev/null +++ b/validator_client/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "validator_client" +version = "0.1.0" +authors = ["Paul Hauner "] +edition = "2018" + +[dependencies] +grpcio = { version = "0.4", default-features = false, features = ["protobuf-codec"] } +protobuf = "2.0.2" +protos = { path = "../protos" } +slot_clock = { path = "../beacon_chain/utils/slot_clock" } +spec = { path = "../beacon_chain/spec" } +tokio = "0.1.14" +types = { path = "../beacon_chain/types" } +slog = "^2.2.3" +slog-term = "^2.4.0" +slog-async = "^2.3.0" +ssz = { path = "../beacon_chain/utils/ssz" } diff --git a/validator_client/src/block_producer/mod.rs b/validator_client/src/block_producer/mod.rs new file mode 100644 index 000000000..4d755979b --- /dev/null +++ b/validator_client/src/block_producer/mod.rs @@ -0,0 +1,127 @@ +mod traits; + +use self::traits::{BeaconNode, BeaconNodeError}; +use crate::EpochDuties; +use slot_clock::SlotClock; +use spec::ChainSpec; +use std::collections::HashMap; +use std::sync::{Arc, RwLock}; +use types::BeaconBlock; + +#[derive(Debug, PartialEq)] +pub enum PollOutcome { + BlockProduced, + SlashableBlockNotProduced, + BlockProductionNotRequired, + ProducerDutiesUnknown, + SlotAlreadyProcessed, + BeaconNodeUnableToProduceBlock, +} + +#[derive(Debug, PartialEq)] +pub enum PollError { + SlotClockError, + SlotUnknowable, + EpochMapPoisoned, + SlotClockPoisoned, + BeaconNodeError(BeaconNodeError), +} + +pub struct BlockProducer { + pub last_processed_slot: u64, + _spec: Arc, + epoch_map: Arc>>, + slot_clock: Arc>, + beacon_node: U, +} + +impl BlockProducer { + pub fn new( + spec: Arc, + epoch_map: Arc>>, + slot_clock: Arc>, + beacon_node: U, + ) -> Self { + Self { + last_processed_slot: 0, + _spec: spec, + epoch_map, + slot_clock, + beacon_node, + } + } +} + +impl BlockProducer { + /// "Poll" to see if the validator is required to take any action. + /// + /// The slot clock will be read and any new actions undertaken. + pub fn poll(&mut self) -> Result { + let slot = self + .slot_clock + .read() + .map_err(|_| PollError::SlotClockPoisoned)? + .present_slot() + .map_err(|_| PollError::SlotClockError)? + .ok_or(PollError::SlotUnknowable)?; + + // If this is a new slot. + if slot > self.last_processed_slot { + let is_block_production_slot = { + let epoch_map = self + .epoch_map + .read() + .map_err(|_| PollError::EpochMapPoisoned)?; + match epoch_map.get(&slot) { + None => return Ok(PollOutcome::ProducerDutiesUnknown), + Some(duties) => duties.is_block_production_slot(slot) + } + }; + + if is_block_production_slot { + self.last_processed_slot = slot; + + self.produce_block(slot) + } else { + Ok(PollOutcome::BlockProductionNotRequired) + } + } else { + Ok(PollOutcome::SlotAlreadyProcessed) + } + } + + fn produce_block(&mut self, slot: u64) -> Result { + if let Some(block) = self.beacon_node.produce_beacon_block(slot)? { + if self.safe_to_produce(&block) { + let block = self.sign_block(block); + self.beacon_node.publish_beacon_block(block)?; + Ok(PollOutcome::BlockProduced) + } else { + Ok(PollOutcome::SlashableBlockNotProduced) + } + } else { + Ok(PollOutcome::BeaconNodeUnableToProduceBlock) + } + } + + fn sign_block(&mut self, block: BeaconBlock) -> BeaconBlock { + // TODO: sign the block + self.store_produce(&block); + block + } + + fn safe_to_produce(&self, _block: &BeaconBlock) -> bool { + // TODO: ensure the producer doesn't produce slashable blocks. + true + } + + fn store_produce(&mut self, _block: &BeaconBlock) { + // TODO: record this block production to prevent future slashings. + } +} + +impl From for PollError { + fn from(e: BeaconNodeError) -> PollError { + PollError::BeaconNodeError(e) + } +} diff --git a/validator_client/src/block_producer/traits.rs b/validator_client/src/block_producer/traits.rs new file mode 100644 index 000000000..42ceb8c4a --- /dev/null +++ b/validator_client/src/block_producer/traits.rs @@ -0,0 +1,73 @@ +use protos::services::{ + BeaconBlock as GrpcBeaconBlock, ProduceBeaconBlockRequest, PublishBeaconBlockRequest, +}; +use protos::services_grpc::BeaconBlockServiceClient; +use ssz::{ssz_encode, Decodable}; +use types::{BeaconBlock, BeaconBlockBody, Hash256, Signature}; + +#[derive(Debug, PartialEq)] +pub enum BeaconNodeError { + RemoteFailure(String), + DecodeFailure, +} + +pub trait BeaconNode { + fn produce_beacon_block(&self, slot: u64) -> Result, BeaconNodeError>; + fn publish_beacon_block(&self, block: BeaconBlock) -> Result; +} + +impl BeaconNode for BeaconBlockServiceClient { + fn produce_beacon_block(&self, slot: u64) -> Result, BeaconNodeError> { + let mut req = ProduceBeaconBlockRequest::new(); + req.set_slot(slot); + + let reply = self + .produce_beacon_block(&req) + .map_err(|err| BeaconNodeError::RemoteFailure(format!("{:?}", err)))?; + + if reply.has_block() { + let block = reply.get_block(); + + let (signature, _) = Signature::ssz_decode(block.get_signature(), 0) + .map_err(|_| BeaconNodeError::DecodeFailure)?; + + // TODO: this conversion is incomplete; fix it. + Ok(Some(BeaconBlock { + slot: block.get_slot(), + parent_root: Hash256::zero(), + state_root: Hash256::zero(), + randao_reveal: Hash256::from(block.get_randao_reveal()), + candidate_pow_receipt_root: Hash256::zero(), + signature, + body: BeaconBlockBody { + proposer_slashings: vec![], + casper_slashings: vec![], + attestations: vec![], + deposits: vec![], + exits: vec![], + }, + })) + } else { + Ok(None) + } + } + + fn publish_beacon_block(&self, block: BeaconBlock) -> Result { + let mut req = PublishBeaconBlockRequest::new(); + + // TODO: this conversion is incomplete; fix it. + let mut grpc_block = GrpcBeaconBlock::new(); + grpc_block.set_slot(block.slot); + grpc_block.set_block_root(vec![0]); + grpc_block.set_randao_reveal(block.randao_reveal.to_vec()); + grpc_block.set_signature(ssz_encode(&block.signature)); + + req.set_block(grpc_block); + + let reply = self + .publish_beacon_block(&req) + .map_err(|err| BeaconNodeError::RemoteFailure(format!("{:?}", err)))?; + + Ok(reply.get_success()) + } +} diff --git a/validator_client/src/main.rs b/validator_client/src/main.rs new file mode 100644 index 000000000..092f51285 --- /dev/null +++ b/validator_client/src/main.rs @@ -0,0 +1,102 @@ +mod block_producer; + +use spec::ChainSpec; +use tokio::prelude::*; +use tokio::timer::Interval; + +use crate::block_producer::{BlockProducer, PollOutcome as BlockProducerPollOutcome}; + +use std::time::{Duration, Instant}; + +use std::sync::{Arc, RwLock}; + +use std::collections::HashMap; + +use slot_clock::SystemTimeSlotClock; + +use grpcio::{ChannelBuilder, EnvBuilder}; +use protos::services_grpc::BeaconBlockServiceClient; + +use slog::{error, info, o, warn, Drain}; + +fn main() { + // gRPC + let env = Arc::new(EnvBuilder::new().build()); + let ch = ChannelBuilder::new(env).connect("localhost:50051"); + let client = BeaconBlockServiceClient::new(ch); + + // 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!()); + + // Ethereum + let spec = Arc::new(ChainSpec::foundation()); + + let duration = spec + .slot_duration + .checked_mul(1_000) + .expect("Slot duration overflow when converting from seconds to millis."); + + let epoch_map = Arc::new(RwLock::new(HashMap::new())); + let slot_clock = { + info!(log, "Genesis time"; "unix_epoch_seconds" => spec.genesis_time); + let clock = SystemTimeSlotClock::new(spec.genesis_time, spec.slot_duration) + .expect("Unable to instantiate SystemTimeSlotClock."); + Arc::new(RwLock::new(clock)) + }; + + let mut block_producer = + BlockProducer::new(spec.clone(), epoch_map.clone(), slot_clock.clone(), client); + + info!(log, "Slot duration"; "milliseconds" => duration); + + let task = Interval::new(Instant::now(), Duration::from_millis(duration)) + // .take(10) + .for_each(move |_instant| { + match block_producer.poll() { + Err(error) => { + error!(log, "Block producer poll error"; "error" => format!("{:?}", error)) + } + Ok(BlockProducerPollOutcome::BlockProduced) => info!(log, "Produced block"), + Ok(BlockProducerPollOutcome::SlashableBlockNotProduced) => { + warn!(log, "Slashable block was not signed") + } + Ok(BlockProducerPollOutcome::BlockProductionNotRequired) => { + info!(log, "Block production not required") + } + Ok(BlockProducerPollOutcome::ProducerDutiesUnknown) => { + error!(log, "Block production duties unknown") + } + Ok(BlockProducerPollOutcome::SlotAlreadyProcessed) => { + warn!(log, "Attempted to re-process slot") + } + Ok(BlockProducerPollOutcome::BeaconNodeUnableToProduceBlock) => { + error!(log, "Beacon node unable to produce block") + } + }; + Ok(()) + }) + .map_err(|e| panic!("Block producer interval errored; err={:?}", e)); + + tokio::run(task); +} + +pub struct EpochDuties { + block_production_slot: Option, + shard: Option, +} + +impl EpochDuties { + pub fn is_block_production_slot(&self, slot: u64) -> bool { + match self.block_production_slot { + Some(s) if s == slot => true, + _ => false, + } + } + + pub fn has_shard(&self) -> bool { + self.shard.is_some() + } +} From b87ff828efcb5ac0d2d14026f38b332ebd16c6a2 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Tue, 15 Jan 2019 15:52:25 +1100 Subject: [PATCH 02/28] Impl more validator logic --- validator_client/src/block_producer/grpc.rs | 63 ++++++++++++++ validator_client/src/block_producer/mod.rs | 85 +++++++++++++++++-- .../src/block_producer/test_node.rs | 42 +++++++++ validator_client/src/block_producer/traits.rs | 65 +------------- validator_client/src/main.rs | 3 +- 5 files changed, 187 insertions(+), 71 deletions(-) create mode 100644 validator_client/src/block_producer/grpc.rs create mode 100644 validator_client/src/block_producer/test_node.rs diff --git a/validator_client/src/block_producer/grpc.rs b/validator_client/src/block_producer/grpc.rs new file mode 100644 index 000000000..4032d49f3 --- /dev/null +++ b/validator_client/src/block_producer/grpc.rs @@ -0,0 +1,63 @@ +use super::traits::{BeaconNode, BeaconNodeError}; +use protos::services::{ + BeaconBlock as GrpcBeaconBlock, ProduceBeaconBlockRequest, PublishBeaconBlockRequest, +}; +use protos::services_grpc::BeaconBlockServiceClient; +use ssz::{ssz_encode, Decodable}; +use types::{BeaconBlock, BeaconBlockBody, Hash256, Signature}; + +impl BeaconNode for BeaconBlockServiceClient { + fn produce_beacon_block(&self, slot: u64) -> Result, BeaconNodeError> { + let mut req = ProduceBeaconBlockRequest::new(); + req.set_slot(slot); + + let reply = self + .produce_beacon_block(&req) + .map_err(|err| BeaconNodeError::RemoteFailure(format!("{:?}", err)))?; + + if reply.has_block() { + let block = reply.get_block(); + + let (signature, _) = Signature::ssz_decode(block.get_signature(), 0) + .map_err(|_| BeaconNodeError::DecodeFailure)?; + + // TODO: this conversion is incomplete; fix it. + Ok(Some(BeaconBlock { + slot: block.get_slot(), + parent_root: Hash256::zero(), + state_root: Hash256::zero(), + randao_reveal: Hash256::from(block.get_randao_reveal()), + candidate_pow_receipt_root: Hash256::zero(), + signature, + body: BeaconBlockBody { + proposer_slashings: vec![], + casper_slashings: vec![], + attestations: vec![], + deposits: vec![], + exits: vec![], + }, + })) + } else { + Ok(None) + } + } + + fn publish_beacon_block(&self, block: BeaconBlock) -> Result { + let mut req = PublishBeaconBlockRequest::new(); + + // TODO: this conversion is incomplete; fix it. + let mut grpc_block = GrpcBeaconBlock::new(); + grpc_block.set_slot(block.slot); + grpc_block.set_block_root(vec![0]); + grpc_block.set_randao_reveal(block.randao_reveal.to_vec()); + grpc_block.set_signature(ssz_encode(&block.signature)); + + req.set_block(grpc_block); + + let reply = self + .publish_beacon_block(&req) + .map_err(|err| BeaconNodeError::RemoteFailure(format!("{:?}", err)))?; + + Ok(reply.get_success()) + } +} diff --git a/validator_client/src/block_producer/mod.rs b/validator_client/src/block_producer/mod.rs index 4d755979b..80896d873 100644 --- a/validator_client/src/block_producer/mod.rs +++ b/validator_client/src/block_producer/mod.rs @@ -1,3 +1,5 @@ +mod grpc; +mod test_node; mod traits; use self::traits::{BeaconNode, BeaconNodeError}; @@ -8,6 +10,8 @@ use std::collections::HashMap; use std::sync::{Arc, RwLock}; use types::BeaconBlock; +type EpochMap = HashMap; + #[derive(Debug, PartialEq)] pub enum PollOutcome { BlockProduced, @@ -24,27 +28,28 @@ pub enum PollError { SlotUnknowable, EpochMapPoisoned, SlotClockPoisoned, + EpochLengthIsZero, BeaconNodeError(BeaconNodeError), } pub struct BlockProducer { pub last_processed_slot: u64, - _spec: Arc, + spec: Arc, epoch_map: Arc>>, slot_clock: Arc>, - beacon_node: U, + beacon_node: Arc, } impl BlockProducer { pub fn new( spec: Arc, - epoch_map: Arc>>, + epoch_map: Arc>, slot_clock: Arc>, - beacon_node: U, + beacon_node: Arc, ) -> Self { Self { last_processed_slot: 0, - _spec: spec, + spec, epoch_map, slot_clock, beacon_node, @@ -65,6 +70,9 @@ impl BlockProducer { .map_err(|_| PollError::SlotClockError)? .ok_or(PollError::SlotUnknowable)?; + let epoch = slot.checked_div(self.spec.epoch_length) + .ok_or(PollError::EpochLengthIsZero)?; + // If this is a new slot. if slot > self.last_processed_slot { let is_block_production_slot = { @@ -72,9 +80,9 @@ impl BlockProducer { .epoch_map .read() .map_err(|_| PollError::EpochMapPoisoned)?; - match epoch_map.get(&slot) { + match epoch_map.get(&epoch) { None => return Ok(PollOutcome::ProducerDutiesUnknown), - Some(duties) => duties.is_block_production_slot(slot) + Some(duties) => duties.is_block_production_slot(slot), } }; @@ -125,3 +133,66 @@ impl From for PollError { PollError::BeaconNodeError(e) } } + +#[cfg(test)] +mod tests { + use super::test_node::TestBeaconNode; + use super::*; + use slot_clock::TestingSlotClock; + use types::test_utils::{SeedableRng, TestRandom, XorShiftRng}; + + // TODO: implement more thorough testing. + // + // These tests should serve as a good example for future tests. + + #[test] + pub fn polling() { + let mut rng = XorShiftRng::from_seed([42; 16]); + + let spec = Arc::new(ChainSpec::foundation()); + let epoch_map = Arc::new(RwLock::new(EpochMap::new())); + let slot_clock = Arc::new(RwLock::new(TestingSlotClock::new(0))); + let beacon_node = Arc::new(TestBeaconNode::default()); + + let mut block_producer = BlockProducer::new( + spec.clone(), + epoch_map.clone(), + slot_clock.clone(), + beacon_node.clone(), + ); + + // Configure responses from the BeaconNode. + beacon_node.set_next_produce_result(Ok(Some(BeaconBlock::random_for_test(&mut rng)))); + beacon_node.set_next_publish_result(Ok(true)); + + + // Setup some valid duties for the validator + let produce_slot = 100; + let duties = EpochDuties { + block_production_slot: Some(produce_slot), + ..std::default::Default::default() + }; + let produce_epoch = produce_slot / spec.epoch_length; + epoch_map.write().unwrap().insert(produce_epoch, duties); + + // One slot before production slot... + slot_clock.write().unwrap().set_slot(produce_slot - 1); + assert_eq!(block_producer.poll(), Ok(PollOutcome::BlockProductionNotRequired)); + + // On the produce slot... + slot_clock.write().unwrap().set_slot(produce_slot); + assert_eq!(block_producer.poll(), Ok(PollOutcome::BlockProduced)); + + // Trying the same produce slot again... + slot_clock.write().unwrap().set_slot(produce_slot); + assert_eq!(block_producer.poll(), Ok(PollOutcome::SlotAlreadyProcessed)); + + // One slot after the produce slot... + slot_clock.write().unwrap().set_slot(produce_slot + 1); + assert_eq!(block_producer.poll(), Ok(PollOutcome::BlockProductionNotRequired)); + + // In an epoch without known duties... + slot_clock.write().unwrap().set_slot((produce_epoch + 1) * spec.epoch_length); + assert_eq!(block_producer.poll(), Ok(PollOutcome::ProducerDutiesUnknown)); + } +} diff --git a/validator_client/src/block_producer/test_node.rs b/validator_client/src/block_producer/test_node.rs new file mode 100644 index 000000000..fdb179b5c --- /dev/null +++ b/validator_client/src/block_producer/test_node.rs @@ -0,0 +1,42 @@ +use super::traits::{BeaconNode, BeaconNodeError}; +use types::BeaconBlock; +use std::sync::RwLock; + +type ProduceResult = Result, BeaconNodeError>; +type PublishResult = Result; + +#[derive(Default)] +pub struct TestBeaconNode { + pub produce_input: RwLock>, + pub produce_result: RwLock>, + pub publish_input: RwLock>, + pub publish_result: RwLock>, +} + +impl TestBeaconNode { + pub fn set_next_produce_result(&self, result: ProduceResult) { + *self.produce_result.write().unwrap() = Some(result); + } + + pub fn set_next_publish_result(&self, result: PublishResult) { + *self.publish_result.write().unwrap() = Some(result); + } +} + +impl BeaconNode for TestBeaconNode { + fn produce_beacon_block(&self, slot: u64) -> ProduceResult { + *self.produce_input.write().unwrap() = Some(slot); + match *self.produce_result.read().unwrap() { + Some(ref r) => r.clone(), + None => panic!("TestBeaconNode: produce_result == None") + } + } + + fn publish_beacon_block(&self, block: BeaconBlock) -> PublishResult { + *self.publish_input.write().unwrap() = Some(block); + match *self.publish_result.read().unwrap() { + Some(ref r) => r.clone(), + None => panic!("TestBeaconNode: publish_result == None") + } + } +} diff --git a/validator_client/src/block_producer/traits.rs b/validator_client/src/block_producer/traits.rs index 42ceb8c4a..4c92b92dd 100644 --- a/validator_client/src/block_producer/traits.rs +++ b/validator_client/src/block_producer/traits.rs @@ -1,11 +1,6 @@ -use protos::services::{ - BeaconBlock as GrpcBeaconBlock, ProduceBeaconBlockRequest, PublishBeaconBlockRequest, -}; -use protos::services_grpc::BeaconBlockServiceClient; -use ssz::{ssz_encode, Decodable}; -use types::{BeaconBlock, BeaconBlockBody, Hash256, Signature}; +use types::BeaconBlock; -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum BeaconNodeError { RemoteFailure(String), DecodeFailure, @@ -15,59 +10,3 @@ pub trait BeaconNode { fn produce_beacon_block(&self, slot: u64) -> Result, BeaconNodeError>; fn publish_beacon_block(&self, block: BeaconBlock) -> Result; } - -impl BeaconNode for BeaconBlockServiceClient { - fn produce_beacon_block(&self, slot: u64) -> Result, BeaconNodeError> { - let mut req = ProduceBeaconBlockRequest::new(); - req.set_slot(slot); - - let reply = self - .produce_beacon_block(&req) - .map_err(|err| BeaconNodeError::RemoteFailure(format!("{:?}", err)))?; - - if reply.has_block() { - let block = reply.get_block(); - - let (signature, _) = Signature::ssz_decode(block.get_signature(), 0) - .map_err(|_| BeaconNodeError::DecodeFailure)?; - - // TODO: this conversion is incomplete; fix it. - Ok(Some(BeaconBlock { - slot: block.get_slot(), - parent_root: Hash256::zero(), - state_root: Hash256::zero(), - randao_reveal: Hash256::from(block.get_randao_reveal()), - candidate_pow_receipt_root: Hash256::zero(), - signature, - body: BeaconBlockBody { - proposer_slashings: vec![], - casper_slashings: vec![], - attestations: vec![], - deposits: vec![], - exits: vec![], - }, - })) - } else { - Ok(None) - } - } - - fn publish_beacon_block(&self, block: BeaconBlock) -> Result { - let mut req = PublishBeaconBlockRequest::new(); - - // TODO: this conversion is incomplete; fix it. - let mut grpc_block = GrpcBeaconBlock::new(); - grpc_block.set_slot(block.slot); - grpc_block.set_block_root(vec![0]); - grpc_block.set_randao_reveal(block.randao_reveal.to_vec()); - grpc_block.set_signature(ssz_encode(&block.signature)); - - req.set_block(grpc_block); - - let reply = self - .publish_beacon_block(&req) - .map_err(|err| BeaconNodeError::RemoteFailure(format!("{:?}", err)))?; - - Ok(reply.get_success()) - } -} diff --git a/validator_client/src/main.rs b/validator_client/src/main.rs index 092f51285..51f4de6c2 100644 --- a/validator_client/src/main.rs +++ b/validator_client/src/main.rs @@ -23,7 +23,7 @@ fn main() { // gRPC let env = Arc::new(EnvBuilder::new().build()); let ch = ChannelBuilder::new(env).connect("localhost:50051"); - let client = BeaconBlockServiceClient::new(ch); + let client = Arc::new(BeaconBlockServiceClient::new(ch)); // Logging let decorator = slog_term::TermDecorator::new().build(); @@ -83,6 +83,7 @@ fn main() { tokio::run(task); } +#[derive(Debug, PartialEq, Clone, Copy, Default)] pub struct EpochDuties { block_production_slot: Option, shard: Option, From 3106d28bfa9ec50a769884f5d9529893ed98d1dc Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Tue, 15 Jan 2019 17:42:45 +1100 Subject: [PATCH 03/28] Add Send + Sync to slot_clock --- beacon_chain/utils/slot_clock/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beacon_chain/utils/slot_clock/src/lib.rs b/beacon_chain/utils/slot_clock/src/lib.rs index 7bdb775af..4863f7669 100644 --- a/beacon_chain/utils/slot_clock/src/lib.rs +++ b/beacon_chain/utils/slot_clock/src/lib.rs @@ -4,7 +4,7 @@ mod testing_slot_clock; pub use crate::system_time_slot_clock::{Error as SystemTimeSlotClockError, SystemTimeSlotClock}; pub use crate::testing_slot_clock::{Error as TestingSlotClockError, TestingSlotClock}; -pub trait SlotClock { +pub trait SlotClock: Send + Sync { type Error; fn present_slot(&self) -> Result, Self::Error>; From 3891a6017a0e9f4410e33d8e0036229bbacc2392 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Tue, 15 Jan 2019 17:42:55 +1100 Subject: [PATCH 04/28] Impl more validator client --- validator_client/Cargo.toml | 1 - validator_client/src/block_producer/mod.rs | 84 +++++++++++-------- .../src/block_producer/service.rs | 40 +++++++++ validator_client/src/block_producer/traits.rs | 2 +- validator_client/src/main.rs | 60 ++++--------- 5 files changed, 105 insertions(+), 82 deletions(-) create mode 100644 validator_client/src/block_producer/service.rs diff --git a/validator_client/Cargo.toml b/validator_client/Cargo.toml index ce74639d0..77f57d601 100644 --- a/validator_client/Cargo.toml +++ b/validator_client/Cargo.toml @@ -10,7 +10,6 @@ protobuf = "2.0.2" protos = { path = "../protos" } slot_clock = { path = "../beacon_chain/utils/slot_clock" } spec = { path = "../beacon_chain/spec" } -tokio = "0.1.14" types = { path = "../beacon_chain/types" } slog = "^2.2.3" slog-term = "^2.4.0" diff --git a/validator_client/src/block_producer/mod.rs b/validator_client/src/block_producer/mod.rs index 80896d873..5987f3a24 100644 --- a/validator_client/src/block_producer/mod.rs +++ b/validator_client/src/block_producer/mod.rs @@ -1,4 +1,5 @@ mod grpc; +mod service; mod test_node; mod traits; @@ -10,20 +11,22 @@ use std::collections::HashMap; use std::sync::{Arc, RwLock}; use types::BeaconBlock; +pub use self::service::BlockProducerService; + type EpochMap = HashMap; #[derive(Debug, PartialEq)] pub enum PollOutcome { - BlockProduced, - SlashableBlockNotProduced, - BlockProductionNotRequired, - ProducerDutiesUnknown, - SlotAlreadyProcessed, - BeaconNodeUnableToProduceBlock, + BlockProduced(u64), + SlashableBlockNotProduced(u64), + BlockProductionNotRequired(u64), + ProducerDutiesUnknown(u64), + SlotAlreadyProcessed(u64), + BeaconNodeUnableToProduceBlock(u64), } #[derive(Debug, PartialEq)] -pub enum PollError { +pub enum Error { SlotClockError, SlotUnknowable, EpochMapPoisoned, @@ -61,27 +64,25 @@ impl BlockProducer { /// "Poll" to see if the validator is required to take any action. /// /// The slot clock will be read and any new actions undertaken. - pub fn poll(&mut self) -> Result { + pub fn poll(&mut self) -> Result { let slot = self .slot_clock .read() - .map_err(|_| PollError::SlotClockPoisoned)? + .map_err(|_| Error::SlotClockPoisoned)? .present_slot() - .map_err(|_| PollError::SlotClockError)? - .ok_or(PollError::SlotUnknowable)?; + .map_err(|_| Error::SlotClockError)? + .ok_or(Error::SlotUnknowable)?; - let epoch = slot.checked_div(self.spec.epoch_length) - .ok_or(PollError::EpochLengthIsZero)?; + let epoch = slot + .checked_div(self.spec.epoch_length) + .ok_or(Error::EpochLengthIsZero)?; // If this is a new slot. if slot > self.last_processed_slot { let is_block_production_slot = { - let epoch_map = self - .epoch_map - .read() - .map_err(|_| PollError::EpochMapPoisoned)?; + let epoch_map = self.epoch_map.read().map_err(|_| Error::EpochMapPoisoned)?; match epoch_map.get(&epoch) { - None => return Ok(PollOutcome::ProducerDutiesUnknown), + None => return Ok(PollOutcome::ProducerDutiesUnknown(slot)), Some(duties) => duties.is_block_production_slot(slot), } }; @@ -91,24 +92,24 @@ impl BlockProducer { self.produce_block(slot) } else { - Ok(PollOutcome::BlockProductionNotRequired) + Ok(PollOutcome::BlockProductionNotRequired(slot)) } } else { - Ok(PollOutcome::SlotAlreadyProcessed) + Ok(PollOutcome::SlotAlreadyProcessed(slot)) } } - fn produce_block(&mut self, slot: u64) -> Result { + fn produce_block(&mut self, slot: u64) -> Result { if let Some(block) = self.beacon_node.produce_beacon_block(slot)? { if self.safe_to_produce(&block) { let block = self.sign_block(block); self.beacon_node.publish_beacon_block(block)?; - Ok(PollOutcome::BlockProduced) + Ok(PollOutcome::BlockProduced(slot)) } else { - Ok(PollOutcome::SlashableBlockNotProduced) + Ok(PollOutcome::SlashableBlockNotProduced(slot)) } } else { - Ok(PollOutcome::BeaconNodeUnableToProduceBlock) + Ok(PollOutcome::BeaconNodeUnableToProduceBlock(slot)) } } @@ -128,9 +129,9 @@ impl BlockProducer { } } -impl From for PollError { - fn from(e: BeaconNodeError) -> PollError { - PollError::BeaconNodeError(e) +impl From for Error { + fn from(e: BeaconNodeError) -> Error { + Error::BeaconNodeError(e) } } @@ -165,7 +166,6 @@ mod tests { beacon_node.set_next_produce_result(Ok(Some(BeaconBlock::random_for_test(&mut rng)))); beacon_node.set_next_publish_result(Ok(true)); - // Setup some valid duties for the validator let produce_slot = 100; let duties = EpochDuties { @@ -177,22 +177,38 @@ mod tests { // One slot before production slot... slot_clock.write().unwrap().set_slot(produce_slot - 1); - assert_eq!(block_producer.poll(), Ok(PollOutcome::BlockProductionNotRequired)); + assert_eq!( + block_producer.poll(), + Ok(PollOutcome::BlockProductionNotRequired(produce_slot - 1)) + ); // On the produce slot... slot_clock.write().unwrap().set_slot(produce_slot); - assert_eq!(block_producer.poll(), Ok(PollOutcome::BlockProduced)); + assert_eq!( + block_producer.poll(), + Ok(PollOutcome::BlockProduced(produce_slot)) + ); // Trying the same produce slot again... slot_clock.write().unwrap().set_slot(produce_slot); - assert_eq!(block_producer.poll(), Ok(PollOutcome::SlotAlreadyProcessed)); + assert_eq!( + block_producer.poll(), + Ok(PollOutcome::SlotAlreadyProcessed(produce_slot)) + ); // One slot after the produce slot... slot_clock.write().unwrap().set_slot(produce_slot + 1); - assert_eq!(block_producer.poll(), Ok(PollOutcome::BlockProductionNotRequired)); + assert_eq!( + block_producer.poll(), + Ok(PollOutcome::BlockProductionNotRequired(produce_slot + 1)) + ); // In an epoch without known duties... - slot_clock.write().unwrap().set_slot((produce_epoch + 1) * spec.epoch_length); - assert_eq!(block_producer.poll(), Ok(PollOutcome::ProducerDutiesUnknown)); + let slot = (produce_epoch + 1) * spec.epoch_length; + slot_clock.write().unwrap().set_slot(slot); + assert_eq!( + block_producer.poll(), + Ok(PollOutcome::ProducerDutiesUnknown(slot)) + ); } } diff --git a/validator_client/src/block_producer/service.rs b/validator_client/src/block_producer/service.rs new file mode 100644 index 000000000..aef1e3c28 --- /dev/null +++ b/validator_client/src/block_producer/service.rs @@ -0,0 +1,40 @@ +use super::traits::BeaconNode; +use super::{BlockProducer, PollOutcome as BlockProducerPollOutcome, SlotClock}; +use slog::{error, info, warn, Logger}; +use std::time::Duration; + +pub struct BlockProducerService { + pub block_producer: BlockProducer, + pub poll_interval_millis: u64, + pub log: Logger, +} + +impl BlockProducerService { + pub fn run(&mut self) { + loop { + match self.block_producer.poll() { + Err(error) => { + error!(self.log, "Block producer poll error"; "error" => format!("{:?}", error)) + } + Ok(BlockProducerPollOutcome::BlockProduced(slot)) => info!(self.log, "Produced block"; "slot" => slot), + Ok(BlockProducerPollOutcome::SlashableBlockNotProduced(slot)) => { + warn!(self.log, "Slashable block was not signed"; "slot" => slot) + } + Ok(BlockProducerPollOutcome::BlockProductionNotRequired(slot)) => { + info!(self.log, "Block production not required"; "slot" => slot) + } + Ok(BlockProducerPollOutcome::ProducerDutiesUnknown(slot)) => { + error!(self.log, "Block production duties unknown"; "slot" => slot) + } + Ok(BlockProducerPollOutcome::SlotAlreadyProcessed(slot)) => { + warn!(self.log, "Attempted to re-process slot"; "slot" => slot) + } + Ok(BlockProducerPollOutcome::BeaconNodeUnableToProduceBlock(slot)) => { + error!(self.log, "Beacon node unable to produce block"; "slot" => slot) + } + }; + + std::thread::sleep(Duration::from_millis(self.poll_interval_millis)); + } + } +} diff --git a/validator_client/src/block_producer/traits.rs b/validator_client/src/block_producer/traits.rs index 4c92b92dd..aaae031ec 100644 --- a/validator_client/src/block_producer/traits.rs +++ b/validator_client/src/block_producer/traits.rs @@ -6,7 +6,7 @@ pub enum BeaconNodeError { DecodeFailure, } -pub trait BeaconNode { +pub trait BeaconNode: Send + Sync { fn produce_beacon_block(&self, slot: u64) -> Result, BeaconNodeError>; fn publish_beacon_block(&self, block: BeaconBlock) -> Result; } diff --git a/validator_client/src/main.rs b/validator_client/src/main.rs index 51f4de6c2..53c289d14 100644 --- a/validator_client/src/main.rs +++ b/validator_client/src/main.rs @@ -1,23 +1,13 @@ -mod block_producer; - -use spec::ChainSpec; -use tokio::prelude::*; -use tokio::timer::Interval; - -use crate::block_producer::{BlockProducer, PollOutcome as BlockProducerPollOutcome}; - -use std::time::{Duration, Instant}; - -use std::sync::{Arc, RwLock}; - -use std::collections::HashMap; - -use slot_clock::SystemTimeSlotClock; - +use crate::block_producer::{BlockProducer, BlockProducerService}; use grpcio::{ChannelBuilder, EnvBuilder}; use protos::services_grpc::BeaconBlockServiceClient; +use slog::{info, o, Drain}; +use slot_clock::SystemTimeSlotClock; +use spec::ChainSpec; +use std::collections::HashMap; +use std::sync::{Arc, RwLock}; -use slog::{error, info, o, warn, Drain}; +mod block_producer; fn main() { // gRPC @@ -47,40 +37,18 @@ fn main() { Arc::new(RwLock::new(clock)) }; - let mut block_producer = + let block_producer = BlockProducer::new(spec.clone(), epoch_map.clone(), slot_clock.clone(), client); info!(log, "Slot duration"; "milliseconds" => duration); - let task = Interval::new(Instant::now(), Duration::from_millis(duration)) - // .take(10) - .for_each(move |_instant| { - match block_producer.poll() { - Err(error) => { - error!(log, "Block producer poll error"; "error" => format!("{:?}", error)) - } - Ok(BlockProducerPollOutcome::BlockProduced) => info!(log, "Produced block"), - Ok(BlockProducerPollOutcome::SlashableBlockNotProduced) => { - warn!(log, "Slashable block was not signed") - } - Ok(BlockProducerPollOutcome::BlockProductionNotRequired) => { - info!(log, "Block production not required") - } - Ok(BlockProducerPollOutcome::ProducerDutiesUnknown) => { - error!(log, "Block production duties unknown") - } - Ok(BlockProducerPollOutcome::SlotAlreadyProcessed) => { - warn!(log, "Attempted to re-process slot") - } - Ok(BlockProducerPollOutcome::BeaconNodeUnableToProduceBlock) => { - error!(log, "Beacon node unable to produce block") - } - }; - Ok(()) - }) - .map_err(|e| panic!("Block producer interval errored; err={:?}", e)); + let mut block_producer_service = BlockProducerService { + block_producer, + poll_interval_millis: spec.epoch_length * 1000 / 100, // 1% epoch time precision. + log: log.clone(), + }; - tokio::run(task); + block_producer_service.run(); } #[derive(Debug, PartialEq, Clone, Copy, Default)] From c9aaf4f1ca4446942215c5686bb5be5a2de5e4bb Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Wed, 16 Jan 2019 20:34:24 +1100 Subject: [PATCH 05/28] Add Eq traits for BLS newtypes --- beacon_chain/utils/bls/src/aggregate_signature.rs | 2 +- beacon_chain/utils/bls/src/keypair.rs | 2 +- beacon_chain/utils/bls/src/public_key.rs | 11 +++++++++-- beacon_chain/utils/bls/src/secret_key.rs | 2 +- beacon_chain/utils/bls/src/signature.rs | 2 +- 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/beacon_chain/utils/bls/src/aggregate_signature.rs b/beacon_chain/utils/bls/src/aggregate_signature.rs index 90bf44702..6012f78c1 100644 --- a/beacon_chain/utils/bls/src/aggregate_signature.rs +++ b/beacon_chain/utils/bls/src/aggregate_signature.rs @@ -6,7 +6,7 @@ use bls_aggregates::AggregateSignature as RawAggregateSignature; /// /// This struct is a wrapper upon a base type and provides helper functions (e.g., SSZ /// serialization). -#[derive(Debug, PartialEq, Clone, Default)] +#[derive(Debug, PartialEq, Clone, Default, Eq)] pub struct AggregateSignature(RawAggregateSignature); impl AggregateSignature { diff --git a/beacon_chain/utils/bls/src/keypair.rs b/beacon_chain/utils/bls/src/keypair.rs index 51a61f8f7..1cce9c10e 100644 --- a/beacon_chain/utils/bls/src/keypair.rs +++ b/beacon_chain/utils/bls/src/keypair.rs @@ -1,6 +1,6 @@ use super::{PublicKey, SecretKey}; -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct Keypair { pub sk: SecretKey, pub pk: PublicKey, diff --git a/beacon_chain/utils/bls/src/public_key.rs b/beacon_chain/utils/bls/src/public_key.rs index 49dbc9e4b..62543589f 100644 --- a/beacon_chain/utils/bls/src/public_key.rs +++ b/beacon_chain/utils/bls/src/public_key.rs @@ -1,12 +1,13 @@ use super::SecretKey; use bls_aggregates::PublicKey as RawPublicKey; -use ssz::{decode_ssz_list, Decodable, DecodeError, Encodable, SszStream}; +use ssz::{decode_ssz_list, ssz_encode, Decodable, DecodeError, Encodable, SszStream}; +use std::hash::{Hash, Hasher}; /// A single BLS signature. /// /// This struct is a wrapper upon a base type and provides helper functions (e.g., SSZ /// serialization). -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug, PartialEq, Clone, Eq)] pub struct PublicKey(RawPublicKey); impl PublicKey { @@ -34,6 +35,12 @@ impl Decodable for PublicKey { } } +impl Hash for PublicKey { + fn hash(&self, state: &mut H) { + ssz_encode(self).hash(state) + } +} + #[cfg(test)] mod tests { use super::super::ssz::ssz_encode; diff --git a/beacon_chain/utils/bls/src/secret_key.rs b/beacon_chain/utils/bls/src/secret_key.rs index 7c4383695..e86e8dec0 100644 --- a/beacon_chain/utils/bls/src/secret_key.rs +++ b/beacon_chain/utils/bls/src/secret_key.rs @@ -5,7 +5,7 @@ use ssz::{decode_ssz_list, Decodable, DecodeError, Encodable, SszStream}; /// /// This struct is a wrapper upon a base type and provides helper functions (e.g., SSZ /// serialization). -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug, PartialEq, Clone, Eq)] pub struct SecretKey(RawSecretKey); impl SecretKey { diff --git a/beacon_chain/utils/bls/src/signature.rs b/beacon_chain/utils/bls/src/signature.rs index 242908e21..f70c5029e 100644 --- a/beacon_chain/utils/bls/src/signature.rs +++ b/beacon_chain/utils/bls/src/signature.rs @@ -6,7 +6,7 @@ use bls_aggregates::Signature as RawSignature; /// /// This struct is a wrapper upon a base type and provides helper functions (e.g., SSZ /// serialization). -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug, PartialEq, Clone, Eq)] pub struct Signature(RawSignature); impl Signature { From 27bfec6692d0b29d2e01e1ec42a3ce27b8ee1234 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Wed, 16 Jan 2019 20:38:53 +1100 Subject: [PATCH 06/28] Add duties service to validator --- protos/src/services.rs | 2 +- validator_client/Cargo.toml | 3 + validator_client/src/block_producer/mod.rs | 2 +- validator_client/src/config.rs | 25 ++++ validator_client/src/duties/mod.rs | 149 +++++++++++++++++++++ validator_client/src/duties/service.rs | 33 +++++ validator_client/src/duties/test_node.rs | 28 ++++ validator_client/src/duties/traits.rs | 16 +++ validator_client/src/main.rs | 92 ++++++++----- 9 files changed, 316 insertions(+), 34 deletions(-) create mode 100644 validator_client/src/config.rs create mode 100644 validator_client/src/duties/mod.rs create mode 100644 validator_client/src/duties/service.rs create mode 100644 validator_client/src/duties/test_node.rs create mode 100644 validator_client/src/duties/traits.rs diff --git a/protos/src/services.rs b/protos/src/services.rs index 226e0ae9a..0a79a96a9 100644 --- a/protos/src/services.rs +++ b/protos/src/services.rs @@ -1,4 +1,4 @@ -// This file is generated by rust-protobuf 2.0.5. Do not edit +// This file is generated by rust-protobuf 2.0.6. Do not edit // @generated // https://github.com/Manishearth/rust-clippy/issues/702 diff --git a/validator_client/Cargo.toml b/validator_client/Cargo.toml index 77f57d601..05a9a640f 100644 --- a/validator_client/Cargo.toml +++ b/validator_client/Cargo.toml @@ -5,6 +5,9 @@ authors = ["Paul Hauner "] edition = "2018" [dependencies] +bls = { path = "../beacon_chain/utils/bls" } +clap = "2.32.0" +dirs = "1.0.3" grpcio = { version = "0.4", default-features = false, features = ["protobuf-codec"] } protobuf = "2.0.2" protos = { path = "../protos" } diff --git a/validator_client/src/block_producer/mod.rs b/validator_client/src/block_producer/mod.rs index 5987f3a24..af12010da 100644 --- a/validator_client/src/block_producer/mod.rs +++ b/validator_client/src/block_producer/mod.rs @@ -4,7 +4,7 @@ mod test_node; mod traits; use self::traits::{BeaconNode, BeaconNodeError}; -use crate::EpochDuties; +use crate::duties::EpochDuties; use slot_clock::SlotClock; use spec::ChainSpec; use std::collections::HashMap; diff --git a/validator_client/src/config.rs b/validator_client/src/config.rs new file mode 100644 index 000000000..4b646074d --- /dev/null +++ b/validator_client/src/config.rs @@ -0,0 +1,25 @@ +use std::fs; +use std::path::PathBuf; + +/// Stores the core configuration for this validator instance. +#[derive(Clone)] +pub struct ClientConfig { + pub data_dir: PathBuf, + pub server: String, +} + +const DEFAULT_LIGHTHOUSE_DIR: &str = ".lighthouse-validators"; + +impl ClientConfig { + /// Build a new lighthouse configuration from defaults. + pub fn default() -> Self { + let data_dir = { + let home = dirs::home_dir().expect("Unable to determine home dir."); + home.join(DEFAULT_LIGHTHOUSE_DIR) + }; + fs::create_dir_all(&data_dir) + .unwrap_or_else(|_| panic!("Unable to create {:?}", &data_dir)); + let server = "localhost:50051".to_string(); + Self { data_dir, server } + } +} diff --git a/validator_client/src/duties/mod.rs b/validator_client/src/duties/mod.rs new file mode 100644 index 000000000..f3c25f221 --- /dev/null +++ b/validator_client/src/duties/mod.rs @@ -0,0 +1,149 @@ +use self::traits::{BeaconNode, BeaconNodeError}; +use bls::PublicKey; +use slot_clock::SlotClock; +use spec::ChainSpec; +use std::collections::HashMap; +use std::sync::{Arc, RwLock}; + +mod service; +mod test_node; +mod traits; + +#[derive(Debug, PartialEq, Clone, Copy, Default)] +pub struct EpochDuties { + pub block_production_slot: Option, + pub shard: Option, +} + +impl EpochDuties { + pub fn is_block_production_slot(&self, slot: u64) -> bool { + match self.block_production_slot { + Some(s) if s == slot => true, + _ => false, + } + } +} + +type EpochDutiesMap = HashMap<(PublicKey, u64), EpochDuties>; + +#[derive(Debug, PartialEq, Clone, Copy)] +pub enum PollOutcome { + NoChange, + NewDuties, + DutiesChanged, + UnknownValidatorOrEpoch, +} + +#[derive(Debug, PartialEq)] +pub enum Error { + SlotClockError, + SlotUnknowable, + EpochMapPoisoned, + SlotClockPoisoned, + EpochLengthIsZero, + BeaconNodeError(BeaconNodeError), +} + +pub struct DutiesManager { + pub duties_map: Arc>, + pub pubkey: PublicKey, + pub spec: Arc, + pub slot_clock: Arc>, + pub beacon_node: Arc, +} + +impl DutiesManager { + pub fn poll(&self) -> Result { + let slot = self + .slot_clock + .read() + .map_err(|_| Error::SlotClockPoisoned)? + .present_slot() + .map_err(|_| Error::SlotClockError)? + .ok_or(Error::SlotUnknowable)?; + + let epoch = slot + .checked_div(self.spec.epoch_length) + .ok_or(Error::EpochLengthIsZero)?; + + if let Some(duties) = self.beacon_node.request_shuffling(epoch, &self.pubkey)? { + let mut map = self + .duties_map + .write() + .map_err(|_| Error::EpochMapPoisoned)?; + + // If these duties were known, check to see if they're updates or identical. + let result = if let Some(known_duties) = map.get(&(self.pubkey.clone(), epoch)) { + if *known_duties == duties { + Ok(PollOutcome::NoChange) + } else { + Ok(PollOutcome::DutiesChanged) + } + } else { + Ok(PollOutcome::NewDuties) + }; + map.insert((self.pubkey.clone(), epoch), duties); + result + } else { + Ok(PollOutcome::UnknownValidatorOrEpoch) + } + } + +} + +impl From for Error { + fn from(e: BeaconNodeError) -> Error { + Error::BeaconNodeError(e) + } +} + +#[cfg(test)] +mod tests { + use super::test_node::TestBeaconNode; + use super::*; + use slot_clock::TestingSlotClock; + use bls::Keypair; + + // TODO: implement more thorough testing. + // + // These tests should serve as a good example for future tests. + + #[test] + pub fn polling() { + let spec = Arc::new(ChainSpec::foundation()); + let duties_map = Arc::new(RwLock::new(EpochDutiesMap::new())); + let keypair = Keypair::random(); + let slot_clock = Arc::new(RwLock::new(TestingSlotClock::new(0))); + let beacon_node = Arc::new(TestBeaconNode::default()); + + let manager = DutiesManager { + spec: spec.clone(), + pubkey: keypair.pk.clone(), + duties_map: duties_map.clone(), + slot_clock: slot_clock.clone(), + beacon_node: beacon_node.clone(), + }; + + // Configure response from the BeaconNode. + beacon_node.set_next_shuffling_result(Ok(Some(EpochDuties{ + block_production_slot: Some(10), + shard: Some(12), + }))); + + // Get the duties for the first time... + assert_eq!(manager.poll(), Ok(PollOutcome::NewDuties)); + // Get the same duties again... + assert_eq!(manager.poll(), Ok(PollOutcome::NoChange)); + + // Return new duties. + beacon_node.set_next_shuffling_result(Ok(Some(EpochDuties{ + block_production_slot: Some(11), + shard: Some(12), + }))); + assert_eq!(manager.poll(), Ok(PollOutcome::DutiesChanged)); + + // Return no duties. + beacon_node.set_next_shuffling_result(Ok(None)); + assert_eq!(manager.poll(), Ok(PollOutcome::UnknownValidatorOrEpoch)); + } +} diff --git a/validator_client/src/duties/service.rs b/validator_client/src/duties/service.rs new file mode 100644 index 000000000..10de53634 --- /dev/null +++ b/validator_client/src/duties/service.rs @@ -0,0 +1,33 @@ +use super::traits::{BeaconNode, BeaconNodeError}; +use super::{DutiesManager, PollOutcome}; +use slog::{debug, error, info, warn, Logger}; +use slot_clock::SlotClock; +use std::time::Duration; + +pub struct DutiesService { + pub manager: DutiesManager, + pub poll_interval_millis: u64, + pub log: Logger, +} + +impl DutiesService { + pub fn run(&mut self) { + loop { + match self.manager.poll() { + Err(error) => { + error!(self.log, "Epoch duties poll error"; "error" => format!("{:?}", error)) + } + Ok(PollOutcome::NoChange) => debug!(self.log, "No change in duties"), + Ok(PollOutcome::DutiesChanged) => { + info!(self.log, "Duties changed (potential re-org)") + } + Ok(PollOutcome::NewDuties) => info!(self.log, "New duties obtained"), + Ok(PollOutcome::UnknownValidatorOrEpoch) => { + error!(self.log, "Epoch or validator unknown") + } + }; + + std::thread::sleep(Duration::from_millis(self.poll_interval_millis)); + } + } +} diff --git a/validator_client/src/duties/test_node.rs b/validator_client/src/duties/test_node.rs new file mode 100644 index 000000000..4ec002224 --- /dev/null +++ b/validator_client/src/duties/test_node.rs @@ -0,0 +1,28 @@ +use super::traits::{BeaconNode, BeaconNodeError}; +use super::EpochDuties; +use bls::PublicKey; +use std::sync::RwLock; + +type ShufflingResult = Result, BeaconNodeError>; + +#[derive(Default)] +pub struct TestBeaconNode { + pub request_shuffling_input: RwLock>, + pub request_shuffling_result: RwLock>, +} + +impl TestBeaconNode { + pub fn set_next_shuffling_result(&self, result: ShufflingResult) { + *self.request_shuffling_result.write().unwrap() = Some(result); + } +} + +impl BeaconNode for TestBeaconNode { + fn request_shuffling(&self, epoch: u64, public_key: &PublicKey) -> ShufflingResult { + *self.request_shuffling_input.write().unwrap() = Some((epoch, public_key.clone())); + match *self.request_shuffling_result.read().unwrap() { + Some(ref r) => r.clone(), + None => panic!("TestBeaconNode: produce_result == None"), + } + } +} diff --git a/validator_client/src/duties/traits.rs b/validator_client/src/duties/traits.rs new file mode 100644 index 000000000..eb0f1583e --- /dev/null +++ b/validator_client/src/duties/traits.rs @@ -0,0 +1,16 @@ +use super::EpochDuties; +use bls::PublicKey; + +#[derive(Debug, PartialEq, Clone)] +pub enum BeaconNodeError { + RemoteFailure(String), + DecodeFailure, +} + +pub trait BeaconNode: Send + Sync { + fn request_shuffling( + &self, + epoch: u64, + public_key: &PublicKey, + ) -> Result, BeaconNodeError>; +} diff --git a/validator_client/src/main.rs b/validator_client/src/main.rs index 53c289d14..a507b8b4b 100644 --- a/validator_client/src/main.rs +++ b/validator_client/src/main.rs @@ -1,34 +1,80 @@ use crate::block_producer::{BlockProducer, BlockProducerService}; +use crate::config::ClientConfig; +use clap::{App, Arg}; use grpcio::{ChannelBuilder, EnvBuilder}; use protos::services_grpc::BeaconBlockServiceClient; -use slog::{info, o, Drain}; +use slog::{error, info, o, Drain}; use slot_clock::SystemTimeSlotClock; use spec::ChainSpec; use std::collections::HashMap; +use std::path::PathBuf; use std::sync::{Arc, RwLock}; mod block_producer; +mod config; +mod duties; fn main() { - // gRPC - let env = Arc::new(EnvBuilder::new().build()); - let ch = ChannelBuilder::new(env).connect("localhost:50051"); - let client = Arc::new(BeaconBlockServiceClient::new(ch)); - // 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 Validator Client") + .version("0.0.1") + .author("Sigma Prime ") + .about("Eth 2.0 Validator Client") + .arg( + Arg::with_name("datadir") + .long("datadir") + .value_name("DIR") + .help("Data directory for keys and databases.") + .takes_value(true), + ) + .arg( + Arg::with_name("server") + .long("server") + .value_name("server") + .help("Address to connect to BeaconNode.") + .takes_value(true), + ) + .get_matches(); + + let mut config = ClientConfig::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; + } + } + + // Log configuration + info!(log, ""; + "data_dir" => &config.data_dir.to_str(), + "server" => &config.server); + + // gRPC + let env = Arc::new(EnvBuilder::new().build()); + let ch = ChannelBuilder::new(env).connect(&config.server); + let client = Arc::new(BeaconBlockServiceClient::new(ch)); + // Ethereum + // + // TODO: Permit loading a custom spec from file. let spec = Arc::new(ChainSpec::foundation()); - let duration = spec - .slot_duration - .checked_mul(1_000) - .expect("Slot duration overflow when converting from seconds to millis."); - + // Global map of epoch -> validator duties. let epoch_map = Arc::new(RwLock::new(HashMap::new())); let slot_clock = { info!(log, "Genesis time"; "unix_epoch_seconds" => spec.genesis_time); @@ -40,32 +86,14 @@ fn main() { let block_producer = BlockProducer::new(spec.clone(), epoch_map.clone(), slot_clock.clone(), client); - info!(log, "Slot duration"; "milliseconds" => duration); + let poll_interval_millis = spec.slot_duration * 1000 / 10; // 10% epoch time precision. + info!(log, "Starting block producer service"; "polls_per_epoch" => spec.slot_duration * 1000 / poll_interval_millis); let mut block_producer_service = BlockProducerService { block_producer, - poll_interval_millis: spec.epoch_length * 1000 / 100, // 1% epoch time precision. + poll_interval_millis, log: log.clone(), }; block_producer_service.run(); } - -#[derive(Debug, PartialEq, Clone, Copy, Default)] -pub struct EpochDuties { - block_production_slot: Option, - shard: Option, -} - -impl EpochDuties { - pub fn is_block_production_slot(&self, slot: u64) -> bool { - match self.block_production_slot { - Some(s) if s == slot => true, - _ => false, - } - } - - pub fn has_shard(&self) -> bool { - self.shard.is_some() - } -} From ebba4977a8a647761b6462533dc752ed2099e104 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Wed, 16 Jan 2019 21:44:44 +1100 Subject: [PATCH 07/28] Introduce threading to validator client --- validator_client/src/block_producer/mod.rs | 10 ++-- validator_client/src/duties/grpc.rs | 63 ++++++++++++++++++++++ validator_client/src/duties/mod.rs | 19 ++++--- validator_client/src/duties/service.rs | 8 +-- validator_client/src/main.rs | 48 ++++++++++++----- 5 files changed, 116 insertions(+), 32 deletions(-) create mode 100644 validator_client/src/duties/grpc.rs diff --git a/validator_client/src/block_producer/mod.rs b/validator_client/src/block_producer/mod.rs index af12010da..2efcbd6ef 100644 --- a/validator_client/src/block_producer/mod.rs +++ b/validator_client/src/block_producer/mod.rs @@ -4,17 +4,15 @@ mod test_node; mod traits; use self::traits::{BeaconNode, BeaconNodeError}; +use super::EpochDutiesMap; use crate::duties::EpochDuties; use slot_clock::SlotClock; use spec::ChainSpec; -use std::collections::HashMap; use std::sync::{Arc, RwLock}; use types::BeaconBlock; pub use self::service::BlockProducerService; -type EpochMap = HashMap; - #[derive(Debug, PartialEq)] pub enum PollOutcome { BlockProduced(u64), @@ -38,7 +36,7 @@ pub enum Error { pub struct BlockProducer { pub last_processed_slot: u64, spec: Arc, - epoch_map: Arc>>, + epoch_map: Arc>, slot_clock: Arc>, beacon_node: Arc, } @@ -46,7 +44,7 @@ pub struct BlockProducer { impl BlockProducer { pub fn new( spec: Arc, - epoch_map: Arc>, + epoch_map: Arc>, slot_clock: Arc>, beacon_node: Arc, ) -> Self { @@ -151,7 +149,7 @@ mod tests { let mut rng = XorShiftRng::from_seed([42; 16]); let spec = Arc::new(ChainSpec::foundation()); - let epoch_map = Arc::new(RwLock::new(EpochMap::new())); + let epoch_map = Arc::new(RwLock::new(EpochDutiesMap::new())); let slot_clock = Arc::new(RwLock::new(TestingSlotClock::new(0))); let beacon_node = Arc::new(TestBeaconNode::default()); diff --git a/validator_client/src/duties/grpc.rs b/validator_client/src/duties/grpc.rs new file mode 100644 index 000000000..4032d49f3 --- /dev/null +++ b/validator_client/src/duties/grpc.rs @@ -0,0 +1,63 @@ +use super::traits::{BeaconNode, BeaconNodeError}; +use protos::services::{ + BeaconBlock as GrpcBeaconBlock, ProduceBeaconBlockRequest, PublishBeaconBlockRequest, +}; +use protos::services_grpc::BeaconBlockServiceClient; +use ssz::{ssz_encode, Decodable}; +use types::{BeaconBlock, BeaconBlockBody, Hash256, Signature}; + +impl BeaconNode for BeaconBlockServiceClient { + fn produce_beacon_block(&self, slot: u64) -> Result, BeaconNodeError> { + let mut req = ProduceBeaconBlockRequest::new(); + req.set_slot(slot); + + let reply = self + .produce_beacon_block(&req) + .map_err(|err| BeaconNodeError::RemoteFailure(format!("{:?}", err)))?; + + if reply.has_block() { + let block = reply.get_block(); + + let (signature, _) = Signature::ssz_decode(block.get_signature(), 0) + .map_err(|_| BeaconNodeError::DecodeFailure)?; + + // TODO: this conversion is incomplete; fix it. + Ok(Some(BeaconBlock { + slot: block.get_slot(), + parent_root: Hash256::zero(), + state_root: Hash256::zero(), + randao_reveal: Hash256::from(block.get_randao_reveal()), + candidate_pow_receipt_root: Hash256::zero(), + signature, + body: BeaconBlockBody { + proposer_slashings: vec![], + casper_slashings: vec![], + attestations: vec![], + deposits: vec![], + exits: vec![], + }, + })) + } else { + Ok(None) + } + } + + fn publish_beacon_block(&self, block: BeaconBlock) -> Result { + let mut req = PublishBeaconBlockRequest::new(); + + // TODO: this conversion is incomplete; fix it. + let mut grpc_block = GrpcBeaconBlock::new(); + grpc_block.set_slot(block.slot); + grpc_block.set_block_root(vec![0]); + grpc_block.set_randao_reveal(block.randao_reveal.to_vec()); + grpc_block.set_signature(ssz_encode(&block.signature)); + + req.set_block(grpc_block); + + let reply = self + .publish_beacon_block(&req) + .map_err(|err| BeaconNodeError::RemoteFailure(format!("{:?}", err)))?; + + Ok(reply.get_success()) + } +} diff --git a/validator_client/src/duties/mod.rs b/validator_client/src/duties/mod.rs index f3c25f221..d401d350e 100644 --- a/validator_client/src/duties/mod.rs +++ b/validator_client/src/duties/mod.rs @@ -9,10 +9,12 @@ mod service; mod test_node; mod traits; +pub use self::service::DutiesManagerService; + #[derive(Debug, PartialEq, Clone, Copy, Default)] pub struct EpochDuties { pub block_production_slot: Option, - pub shard: Option, + // Future shard info } impl EpochDuties { @@ -24,7 +26,7 @@ impl EpochDuties { } } -type EpochDutiesMap = HashMap<(PublicKey, u64), EpochDuties>; +pub type EpochDutiesMap = HashMap; #[derive(Debug, PartialEq, Clone, Copy)] pub enum PollOutcome { @@ -73,7 +75,7 @@ impl DutiesManager { .map_err(|_| Error::EpochMapPoisoned)?; // If these duties were known, check to see if they're updates or identical. - let result = if let Some(known_duties) = map.get(&(self.pubkey.clone(), epoch)) { + let result = if let Some(known_duties) = map.get(&epoch) { if *known_duties == duties { Ok(PollOutcome::NoChange) } else { @@ -82,13 +84,12 @@ impl DutiesManager { } else { Ok(PollOutcome::NewDuties) }; - map.insert((self.pubkey.clone(), epoch), duties); + map.insert(epoch, duties); result } else { Ok(PollOutcome::UnknownValidatorOrEpoch) } } - } impl From for Error { @@ -101,8 +102,8 @@ impl From for Error { mod tests { use super::test_node::TestBeaconNode; use super::*; - use slot_clock::TestingSlotClock; use bls::Keypair; + use slot_clock::TestingSlotClock; // TODO: implement more thorough testing. // @@ -125,9 +126,8 @@ mod tests { }; // Configure response from the BeaconNode. - beacon_node.set_next_shuffling_result(Ok(Some(EpochDuties{ + beacon_node.set_next_shuffling_result(Ok(Some(EpochDuties { block_production_slot: Some(10), - shard: Some(12), }))); // Get the duties for the first time... @@ -136,9 +136,8 @@ mod tests { assert_eq!(manager.poll(), Ok(PollOutcome::NoChange)); // Return new duties. - beacon_node.set_next_shuffling_result(Ok(Some(EpochDuties{ + beacon_node.set_next_shuffling_result(Ok(Some(EpochDuties { block_production_slot: Some(11), - shard: Some(12), }))); assert_eq!(manager.poll(), Ok(PollOutcome::DutiesChanged)); diff --git a/validator_client/src/duties/service.rs b/validator_client/src/duties/service.rs index 10de53634..bedfd69ca 100644 --- a/validator_client/src/duties/service.rs +++ b/validator_client/src/duties/service.rs @@ -1,16 +1,16 @@ -use super::traits::{BeaconNode, BeaconNodeError}; +use super::traits::BeaconNode; use super::{DutiesManager, PollOutcome}; -use slog::{debug, error, info, warn, Logger}; +use slog::{debug, error, info, Logger}; use slot_clock::SlotClock; use std::time::Duration; -pub struct DutiesService { +pub struct DutiesManagerService { pub manager: DutiesManager, pub poll_interval_millis: u64, pub log: Logger, } -impl DutiesService { +impl DutiesManagerService { pub fn run(&mut self) { loop { match self.manager.poll() { diff --git a/validator_client/src/main.rs b/validator_client/src/main.rs index a507b8b4b..179146897 100644 --- a/validator_client/src/main.rs +++ b/validator_client/src/main.rs @@ -1,14 +1,16 @@ +use self::duties::{DutiesManager, DutiesManagerService, EpochDutiesMap}; use crate::block_producer::{BlockProducer, BlockProducerService}; use crate::config::ClientConfig; +use bls::Keypair; use clap::{App, Arg}; use grpcio::{ChannelBuilder, EnvBuilder}; use protos::services_grpc::BeaconBlockServiceClient; use slog::{error, info, o, Drain}; use slot_clock::SystemTimeSlotClock; use spec::ChainSpec; -use std::collections::HashMap; use std::path::PathBuf; use std::sync::{Arc, RwLock}; +use std::thread; mod block_producer; mod config; @@ -74,8 +76,7 @@ fn main() { // TODO: Permit loading a custom spec from file. let spec = Arc::new(ChainSpec::foundation()); - // Global map of epoch -> validator duties. - let epoch_map = Arc::new(RwLock::new(HashMap::new())); + // Clock for determining the present slot. let slot_clock = { info!(log, "Genesis time"; "unix_epoch_seconds" => spec.genesis_time); let clock = SystemTimeSlotClock::new(spec.genesis_time, spec.slot_duration) @@ -83,17 +84,40 @@ fn main() { Arc::new(RwLock::new(clock)) }; - let block_producer = - BlockProducer::new(spec.clone(), epoch_map.clone(), slot_clock.clone(), client); - let poll_interval_millis = spec.slot_duration * 1000 / 10; // 10% epoch time precision. info!(log, "Starting block producer service"; "polls_per_epoch" => spec.slot_duration * 1000 / poll_interval_millis); - let mut block_producer_service = BlockProducerService { - block_producer, - poll_interval_millis, - log: log.clone(), - }; + /* + * Start threads. + */ + let keypairs = vec![Keypair::random()]; + let mut threads = vec![]; - block_producer_service.run(); + for keypair in keypairs { + let duties_map = Arc::new(RwLock::new(EpochDutiesMap::new())); + + let producer_thread = { + let spec = spec.clone(); + let duties_map = duties_map.clone(); + let slot_clock = slot_clock.clone(); + let log = log.clone(); + let client = client.clone(); + thread::spawn(move || { + let block_producer = BlockProducer::new(spec, duties_map, slot_clock, client); + let mut block_producer_service = BlockProducerService { + block_producer, + poll_interval_millis, + log, + }; + + block_producer_service.run(); + }) + }; + threads.push(((), producer_thread)); + } + + for tuple in threads { + let (manager, producer) = tuple; + let _ = producer.join(); + } } From fc5bcb88fba13e76403af4f9ac30eb5b66f77c30 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Mon, 21 Jan 2019 18:28:12 +1100 Subject: [PATCH 08/28] Update install deps in README --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index e28855504..2d80f565c 100644 --- a/README.md +++ b/README.md @@ -140,6 +140,10 @@ A few basic steps are needed to get set up: 3. Use the command `rustup show` to get information about the Rust installation. You should see that the active toolchain is the stable version. 4. Run `rustc --version` to check the installation and version of rust. - Updates can be performed using` rustup update` . + 5. Install build dependancies (Arch packages are listed here, your distribution will + likely be similar): + - `clang`: required by RocksDB. + - `protobuf`: required for protobuf serialization (gRPC). 5. Navigate to the working directory. 6. Run the test by using command `cargo test --all` . By running, it will pass all the required test cases. If you are doing it for the first time, then you can grab a coffee meantime. Usually, it takes time to build, compile and pass all test cases. If there is no error then, it means everything is working properly and it's time to get hand's dirty. In case, if there is an error, then please raise the [issue](https://github.com/sigp/lighthouse/issues). We will help you. 7. As an alternative to, or instead of the above step, you may also run benchmarks by using the command `cargo bench --all` From 5a45093156e3b2f78c55dd51017db7a0a4ddc626 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Mon, 21 Jan 2019 18:28:33 +1100 Subject: [PATCH 09/28] Manually impl PartialEq for bls::PublicKey To fix: https://rust-lang.github.io/rust-clippy/master/#derive_hash_xor_eq --- beacon_chain/utils/bls/src/public_key.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/beacon_chain/utils/bls/src/public_key.rs b/beacon_chain/utils/bls/src/public_key.rs index 62543589f..be260bf79 100644 --- a/beacon_chain/utils/bls/src/public_key.rs +++ b/beacon_chain/utils/bls/src/public_key.rs @@ -7,7 +7,7 @@ use std::hash::{Hash, Hasher}; /// /// This struct is a wrapper upon a base type and provides helper functions (e.g., SSZ /// serialization). -#[derive(Debug, PartialEq, Clone, Eq)] +#[derive(Debug, Clone, Eq)] pub struct PublicKey(RawPublicKey); impl PublicKey { @@ -35,6 +35,12 @@ impl Decodable for PublicKey { } } +impl PartialEq for PublicKey { + fn eq(&self, other: &PublicKey) -> bool { + ssz_encode(self) == ssz_encode(other) + } +} + impl Hash for PublicKey { fn hash(&self, state: &mut H) { ssz_encode(self).hash(state) From d63d3c908b237ec8fee6c720f48bace99b0d194a Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Mon, 21 Jan 2019 18:29:28 +1100 Subject: [PATCH 10/28] Add validator duties proto service --- protos/src/services.proto | 17 + protos/src/services.rs | 618 +++++++++++++++++++++++++++++++++++- protos/src/services_grpc.rs | 28 ++ 3 files changed, 658 insertions(+), 5 deletions(-) diff --git a/protos/src/services.proto b/protos/src/services.proto index dd6c51325..6d1d8f911 100644 --- a/protos/src/services.proto +++ b/protos/src/services.proto @@ -15,6 +15,7 @@ package ethereum.beacon.rpc.v1; service BeaconBlockService { rpc ProduceBeaconBlock(ProduceBeaconBlockRequest) returns (ProduceBeaconBlockResponse); rpc PublishBeaconBlock(PublishBeaconBlockRequest) returns (PublishBeaconBlockResponse); + rpc ValidatorAssignment(ValidatorAssignmentRequest) returns (ValidatorAssignmentResponse); } message BeaconBlock { @@ -44,3 +45,19 @@ message PublishBeaconBlockResponse { bool success = 1; bytes msg = 2; } + +message ValidatorAssignment { + oneof block_production_slot_oneof { + bool block_production_slot_none = 1; + uint64 block_production_slot = 2; + } +} + +message ValidatorAssignmentRequest { + uint64 epoch = 1; + bytes public_key = 2; +} + +message ValidatorAssignmentResponse { + ValidatorAssignment validator_assignment = 1; +} diff --git a/protos/src/services.rs b/protos/src/services.rs index 0a79a96a9..4273d9663 100644 --- a/protos/src/services.rs +++ b/protos/src/services.rs @@ -1013,6 +1013,604 @@ impl ::protobuf::reflect::ProtobufValue for PublishBeaconBlockResponse { } } +#[derive(PartialEq,Clone,Default)] +pub struct ValidatorAssignment { + // message oneof groups + pub block_production_slot_oneof: ::std::option::Option, + // special fields + unknown_fields: ::protobuf::UnknownFields, + cached_size: ::protobuf::CachedSize, +} + +#[derive(Clone,PartialEq)] +pub enum ValidatorAssignment_oneof_block_production_slot_oneof { + block_production_slot_none(bool), + block_production_slot(u64), +} + +impl ValidatorAssignment { + pub fn new() -> ValidatorAssignment { + ::std::default::Default::default() + } + + // bool block_production_slot_none = 1; + + pub fn clear_block_production_slot_none(&mut self) { + self.block_production_slot_oneof = ::std::option::Option::None; + } + + pub fn has_block_production_slot_none(&self) -> bool { + match self.block_production_slot_oneof { + ::std::option::Option::Some(ValidatorAssignment_oneof_block_production_slot_oneof::block_production_slot_none(..)) => true, + _ => false, + } + } + + // Param is passed by value, moved + pub fn set_block_production_slot_none(&mut self, v: bool) { + self.block_production_slot_oneof = ::std::option::Option::Some(ValidatorAssignment_oneof_block_production_slot_oneof::block_production_slot_none(v)) + } + + pub fn get_block_production_slot_none(&self) -> bool { + match self.block_production_slot_oneof { + ::std::option::Option::Some(ValidatorAssignment_oneof_block_production_slot_oneof::block_production_slot_none(v)) => v, + _ => false, + } + } + + // uint64 block_production_slot = 2; + + pub fn clear_block_production_slot(&mut self) { + self.block_production_slot_oneof = ::std::option::Option::None; + } + + pub fn has_block_production_slot(&self) -> bool { + match self.block_production_slot_oneof { + ::std::option::Option::Some(ValidatorAssignment_oneof_block_production_slot_oneof::block_production_slot(..)) => true, + _ => false, + } + } + + // Param is passed by value, moved + pub fn set_block_production_slot(&mut self, v: u64) { + self.block_production_slot_oneof = ::std::option::Option::Some(ValidatorAssignment_oneof_block_production_slot_oneof::block_production_slot(v)) + } + + pub fn get_block_production_slot(&self) -> u64 { + match self.block_production_slot_oneof { + ::std::option::Option::Some(ValidatorAssignment_oneof_block_production_slot_oneof::block_production_slot(v)) => v, + _ => 0, + } + } +} + +impl ::protobuf::Message for ValidatorAssignment { + fn is_initialized(&self) -> bool { + true + } + + fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream) -> ::protobuf::ProtobufResult<()> { + while !is.eof()? { + let (field_number, wire_type) = is.read_tag_unpack()?; + match field_number { + 1 => { + if wire_type != ::protobuf::wire_format::WireTypeVarint { + return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); + } + self.block_production_slot_oneof = ::std::option::Option::Some(ValidatorAssignment_oneof_block_production_slot_oneof::block_production_slot_none(is.read_bool()?)); + }, + 2 => { + if wire_type != ::protobuf::wire_format::WireTypeVarint { + return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); + } + self.block_production_slot_oneof = ::std::option::Option::Some(ValidatorAssignment_oneof_block_production_slot_oneof::block_production_slot(is.read_uint64()?)); + }, + _ => { + ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; + }, + }; + } + ::std::result::Result::Ok(()) + } + + // Compute sizes of nested messages + #[allow(unused_variables)] + fn compute_size(&self) -> u32 { + let mut my_size = 0; + if let ::std::option::Option::Some(ref v) = self.block_production_slot_oneof { + match v { + &ValidatorAssignment_oneof_block_production_slot_oneof::block_production_slot_none(v) => { + my_size += 2; + }, + &ValidatorAssignment_oneof_block_production_slot_oneof::block_production_slot(v) => { + my_size += ::protobuf::rt::value_size(2, v, ::protobuf::wire_format::WireTypeVarint); + }, + }; + } + my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); + self.cached_size.set(my_size); + my_size + } + + fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream) -> ::protobuf::ProtobufResult<()> { + if let ::std::option::Option::Some(ref v) = self.block_production_slot_oneof { + match v { + &ValidatorAssignment_oneof_block_production_slot_oneof::block_production_slot_none(v) => { + os.write_bool(1, v)?; + }, + &ValidatorAssignment_oneof_block_production_slot_oneof::block_production_slot(v) => { + os.write_uint64(2, v)?; + }, + }; + } + os.write_unknown_fields(self.get_unknown_fields())?; + ::std::result::Result::Ok(()) + } + + fn get_cached_size(&self) -> u32 { + self.cached_size.get() + } + + fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { + &self.unknown_fields + } + + fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { + &mut self.unknown_fields + } + + fn as_any(&self) -> &::std::any::Any { + self as &::std::any::Any + } + fn as_any_mut(&mut self) -> &mut ::std::any::Any { + self as &mut ::std::any::Any + } + fn into_any(self: Box) -> ::std::boxed::Box<::std::any::Any> { + self + } + + fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { + Self::descriptor_static() + } + + fn new() -> ValidatorAssignment { + ValidatorAssignment::new() + } + + fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { + static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::lazy::Lazy { + lock: ::protobuf::lazy::ONCE_INIT, + ptr: 0 as *const ::protobuf::reflect::MessageDescriptor, + }; + unsafe { + descriptor.get(|| { + let mut fields = ::std::vec::Vec::new(); + fields.push(::protobuf::reflect::accessor::make_singular_bool_accessor::<_>( + "block_production_slot_none", + ValidatorAssignment::has_block_production_slot_none, + ValidatorAssignment::get_block_production_slot_none, + )); + fields.push(::protobuf::reflect::accessor::make_singular_u64_accessor::<_>( + "block_production_slot", + ValidatorAssignment::has_block_production_slot, + ValidatorAssignment::get_block_production_slot, + )); + ::protobuf::reflect::MessageDescriptor::new::( + "ValidatorAssignment", + fields, + file_descriptor_proto() + ) + }) + } + } + + fn default_instance() -> &'static ValidatorAssignment { + static mut instance: ::protobuf::lazy::Lazy = ::protobuf::lazy::Lazy { + lock: ::protobuf::lazy::ONCE_INIT, + ptr: 0 as *const ValidatorAssignment, + }; + unsafe { + instance.get(ValidatorAssignment::new) + } + } +} + +impl ::protobuf::Clear for ValidatorAssignment { + fn clear(&mut self) { + self.clear_block_production_slot_none(); + self.clear_block_production_slot(); + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for ValidatorAssignment { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for ValidatorAssignment { + fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef { + ::protobuf::reflect::ProtobufValueRef::Message(self) + } +} + +#[derive(PartialEq,Clone,Default)] +pub struct ValidatorAssignmentRequest { + // message fields + pub epoch: u64, + pub public_key: ::std::vec::Vec, + // special fields + unknown_fields: ::protobuf::UnknownFields, + cached_size: ::protobuf::CachedSize, +} + +impl ValidatorAssignmentRequest { + pub fn new() -> ValidatorAssignmentRequest { + ::std::default::Default::default() + } + + // uint64 epoch = 1; + + pub fn clear_epoch(&mut self) { + self.epoch = 0; + } + + // Param is passed by value, moved + pub fn set_epoch(&mut self, v: u64) { + self.epoch = v; + } + + pub fn get_epoch(&self) -> u64 { + self.epoch + } + + // bytes public_key = 2; + + pub fn clear_public_key(&mut self) { + self.public_key.clear(); + } + + // Param is passed by value, moved + pub fn set_public_key(&mut self, v: ::std::vec::Vec) { + self.public_key = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_public_key(&mut self) -> &mut ::std::vec::Vec { + &mut self.public_key + } + + // Take field + pub fn take_public_key(&mut self) -> ::std::vec::Vec { + ::std::mem::replace(&mut self.public_key, ::std::vec::Vec::new()) + } + + pub fn get_public_key(&self) -> &[u8] { + &self.public_key + } +} + +impl ::protobuf::Message for ValidatorAssignmentRequest { + fn is_initialized(&self) -> bool { + true + } + + fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream) -> ::protobuf::ProtobufResult<()> { + while !is.eof()? { + let (field_number, wire_type) = is.read_tag_unpack()?; + match field_number { + 1 => { + if wire_type != ::protobuf::wire_format::WireTypeVarint { + return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); + } + let tmp = is.read_uint64()?; + self.epoch = tmp; + }, + 2 => { + ::protobuf::rt::read_singular_proto3_bytes_into(wire_type, is, &mut self.public_key)?; + }, + _ => { + ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; + }, + }; + } + ::std::result::Result::Ok(()) + } + + // Compute sizes of nested messages + #[allow(unused_variables)] + fn compute_size(&self) -> u32 { + let mut my_size = 0; + if self.epoch != 0 { + my_size += ::protobuf::rt::value_size(1, self.epoch, ::protobuf::wire_format::WireTypeVarint); + } + if !self.public_key.is_empty() { + my_size += ::protobuf::rt::bytes_size(2, &self.public_key); + } + my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); + self.cached_size.set(my_size); + my_size + } + + fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream) -> ::protobuf::ProtobufResult<()> { + if self.epoch != 0 { + os.write_uint64(1, self.epoch)?; + } + if !self.public_key.is_empty() { + os.write_bytes(2, &self.public_key)?; + } + os.write_unknown_fields(self.get_unknown_fields())?; + ::std::result::Result::Ok(()) + } + + fn get_cached_size(&self) -> u32 { + self.cached_size.get() + } + + fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { + &self.unknown_fields + } + + fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { + &mut self.unknown_fields + } + + fn as_any(&self) -> &::std::any::Any { + self as &::std::any::Any + } + fn as_any_mut(&mut self) -> &mut ::std::any::Any { + self as &mut ::std::any::Any + } + fn into_any(self: Box) -> ::std::boxed::Box<::std::any::Any> { + self + } + + fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { + Self::descriptor_static() + } + + fn new() -> ValidatorAssignmentRequest { + ValidatorAssignmentRequest::new() + } + + fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { + static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::lazy::Lazy { + lock: ::protobuf::lazy::ONCE_INIT, + ptr: 0 as *const ::protobuf::reflect::MessageDescriptor, + }; + unsafe { + descriptor.get(|| { + let mut fields = ::std::vec::Vec::new(); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeUint64>( + "epoch", + |m: &ValidatorAssignmentRequest| { &m.epoch }, + |m: &mut ValidatorAssignmentRequest| { &mut m.epoch }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>( + "public_key", + |m: &ValidatorAssignmentRequest| { &m.public_key }, + |m: &mut ValidatorAssignmentRequest| { &mut m.public_key }, + )); + ::protobuf::reflect::MessageDescriptor::new::( + "ValidatorAssignmentRequest", + fields, + file_descriptor_proto() + ) + }) + } + } + + fn default_instance() -> &'static ValidatorAssignmentRequest { + static mut instance: ::protobuf::lazy::Lazy = ::protobuf::lazy::Lazy { + lock: ::protobuf::lazy::ONCE_INIT, + ptr: 0 as *const ValidatorAssignmentRequest, + }; + unsafe { + instance.get(ValidatorAssignmentRequest::new) + } + } +} + +impl ::protobuf::Clear for ValidatorAssignmentRequest { + fn clear(&mut self) { + self.clear_epoch(); + self.clear_public_key(); + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for ValidatorAssignmentRequest { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for ValidatorAssignmentRequest { + fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef { + ::protobuf::reflect::ProtobufValueRef::Message(self) + } +} + +#[derive(PartialEq,Clone,Default)] +pub struct ValidatorAssignmentResponse { + // message fields + pub validator_assignment: ::protobuf::SingularPtrField, + // special fields + unknown_fields: ::protobuf::UnknownFields, + cached_size: ::protobuf::CachedSize, +} + +impl ValidatorAssignmentResponse { + pub fn new() -> ValidatorAssignmentResponse { + ::std::default::Default::default() + } + + // .ethereum.beacon.rpc.v1.ValidatorAssignment validator_assignment = 1; + + pub fn clear_validator_assignment(&mut self) { + self.validator_assignment.clear(); + } + + pub fn has_validator_assignment(&self) -> bool { + self.validator_assignment.is_some() + } + + // Param is passed by value, moved + pub fn set_validator_assignment(&mut self, v: ValidatorAssignment) { + self.validator_assignment = ::protobuf::SingularPtrField::some(v); + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_validator_assignment(&mut self) -> &mut ValidatorAssignment { + if self.validator_assignment.is_none() { + self.validator_assignment.set_default(); + } + self.validator_assignment.as_mut().unwrap() + } + + // Take field + pub fn take_validator_assignment(&mut self) -> ValidatorAssignment { + self.validator_assignment.take().unwrap_or_else(|| ValidatorAssignment::new()) + } + + pub fn get_validator_assignment(&self) -> &ValidatorAssignment { + self.validator_assignment.as_ref().unwrap_or_else(|| ValidatorAssignment::default_instance()) + } +} + +impl ::protobuf::Message for ValidatorAssignmentResponse { + fn is_initialized(&self) -> bool { + for v in &self.validator_assignment { + if !v.is_initialized() { + return false; + } + }; + true + } + + fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream) -> ::protobuf::ProtobufResult<()> { + while !is.eof()? { + let (field_number, wire_type) = is.read_tag_unpack()?; + match field_number { + 1 => { + ::protobuf::rt::read_singular_message_into(wire_type, is, &mut self.validator_assignment)?; + }, + _ => { + ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; + }, + }; + } + ::std::result::Result::Ok(()) + } + + // Compute sizes of nested messages + #[allow(unused_variables)] + fn compute_size(&self) -> u32 { + let mut my_size = 0; + if let Some(ref v) = self.validator_assignment.as_ref() { + let len = v.compute_size(); + my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; + } + my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); + self.cached_size.set(my_size); + my_size + } + + fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream) -> ::protobuf::ProtobufResult<()> { + if let Some(ref v) = self.validator_assignment.as_ref() { + os.write_tag(1, ::protobuf::wire_format::WireTypeLengthDelimited)?; + os.write_raw_varint32(v.get_cached_size())?; + v.write_to_with_cached_sizes(os)?; + } + os.write_unknown_fields(self.get_unknown_fields())?; + ::std::result::Result::Ok(()) + } + + fn get_cached_size(&self) -> u32 { + self.cached_size.get() + } + + fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { + &self.unknown_fields + } + + fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { + &mut self.unknown_fields + } + + fn as_any(&self) -> &::std::any::Any { + self as &::std::any::Any + } + fn as_any_mut(&mut self) -> &mut ::std::any::Any { + self as &mut ::std::any::Any + } + fn into_any(self: Box) -> ::std::boxed::Box<::std::any::Any> { + self + } + + fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { + Self::descriptor_static() + } + + fn new() -> ValidatorAssignmentResponse { + ValidatorAssignmentResponse::new() + } + + fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { + static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::lazy::Lazy { + lock: ::protobuf::lazy::ONCE_INIT, + ptr: 0 as *const ::protobuf::reflect::MessageDescriptor, + }; + unsafe { + descriptor.get(|| { + let mut fields = ::std::vec::Vec::new(); + fields.push(::protobuf::reflect::accessor::make_singular_ptr_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( + "validator_assignment", + |m: &ValidatorAssignmentResponse| { &m.validator_assignment }, + |m: &mut ValidatorAssignmentResponse| { &mut m.validator_assignment }, + )); + ::protobuf::reflect::MessageDescriptor::new::( + "ValidatorAssignmentResponse", + fields, + file_descriptor_proto() + ) + }) + } + } + + fn default_instance() -> &'static ValidatorAssignmentResponse { + static mut instance: ::protobuf::lazy::Lazy = ::protobuf::lazy::Lazy { + lock: ::protobuf::lazy::ONCE_INIT, + ptr: 0 as *const ValidatorAssignmentResponse, + }; + unsafe { + instance.get(ValidatorAssignmentResponse::new) + } + } +} + +impl ::protobuf::Clear for ValidatorAssignmentResponse { + fn clear(&mut self) { + self.clear_validator_assignment(); + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for ValidatorAssignmentResponse { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for ValidatorAssignmentResponse { + fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef { + ::protobuf::reflect::ProtobufValueRef::Message(self) + } +} + static file_descriptor_proto_data: &'static [u8] = b"\ \n\x0eservices.proto\x12\x16ethereum.beacon.rpc.v1\"\x83\x01\n\x0bBeacon\ Block\x12\x12\n\x04slot\x18\x01\x20\x01(\x04R\x04slot\x12\x1d\n\nblock_r\ @@ -1024,11 +1622,21 @@ static file_descriptor_proto_data: &'static [u8] = b"\ \n\x19PublishBeaconBlockRequest\x129\n\x05block\x18\x01\x20\x01(\x0b2#.e\ thereum.beacon.rpc.v1.BeaconBlockR\x05block\"H\n\x1aPublishBeaconBlockRe\ sponse\x12\x18\n\x07success\x18\x01\x20\x01(\x08R\x07success\x12\x10\n\ - \x03msg\x18\x02\x20\x01(\x0cR\x03msg2\x8e\x02\n\x12BeaconBlockService\ - \x12{\n\x12ProduceBeaconBlock\x121.ethereum.beacon.rpc.v1.ProduceBeaconB\ - lockRequest\x1a2.ethereum.beacon.rpc.v1.ProduceBeaconBlockResponse\x12{\ - \n\x12PublishBeaconBlock\x121.ethereum.beacon.rpc.v1.PublishBeaconBlockR\ - equest\x1a2.ethereum.beacon.rpc.v1.PublishBeaconBlockResponseb\x06proto3\ + \x03msg\x18\x02\x20\x01(\x0cR\x03msg\"\xa9\x01\n\x13ValidatorAssignment\ + \x12=\n\x1ablock_production_slot_none\x18\x01\x20\x01(\x08H\0R\x17blockP\ + roductionSlotNone\x124\n\x15block_production_slot\x18\x02\x20\x01(\x04H\ + \0R\x13blockProductionSlotB\x1d\n\x1bblock_production_slot_oneof\"Q\n\ + \x1aValidatorAssignmentRequest\x12\x14\n\x05epoch\x18\x01\x20\x01(\x04R\ + \x05epoch\x12\x1d\n\npublic_key\x18\x02\x20\x01(\x0cR\tpublicKey\"}\n\ + \x1bValidatorAssignmentResponse\x12^\n\x14validator_assignment\x18\x01\ + \x20\x01(\x0b2+.ethereum.beacon.rpc.v1.ValidatorAssignmentR\x13validator\ + Assignment2\x8e\x03\n\x12BeaconBlockService\x12{\n\x12ProduceBeaconBlock\ + \x121.ethereum.beacon.rpc.v1.ProduceBeaconBlockRequest\x1a2.ethereum.bea\ + con.rpc.v1.ProduceBeaconBlockResponse\x12{\n\x12PublishBeaconBlock\x121.\ + ethereum.beacon.rpc.v1.PublishBeaconBlockRequest\x1a2.ethereum.beacon.rp\ + c.v1.PublishBeaconBlockResponse\x12~\n\x13ValidatorAssignment\x122.ether\ + eum.beacon.rpc.v1.ValidatorAssignmentRequest\x1a3.ethereum.beacon.rpc.v1\ + .ValidatorAssignmentResponseb\x06proto3\ "; static mut file_descriptor_proto_lazy: ::protobuf::lazy::Lazy<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::lazy::Lazy { diff --git a/protos/src/services_grpc.rs b/protos/src/services_grpc.rs index 701c59d0d..2103f73c4 100644 --- a/protos/src/services_grpc.rs +++ b/protos/src/services_grpc.rs @@ -32,6 +32,13 @@ const METHOD_BEACON_BLOCK_SERVICE_PUBLISH_BEACON_BLOCK: ::grpcio::Method = ::grpcio::Method { + ty: ::grpcio::MethodType::Unary, + name: "/ethereum.beacon.rpc.v1.BeaconBlockService/ValidatorAssignment", + req_mar: ::grpcio::Marshaller { ser: ::grpcio::pb_ser, de: ::grpcio::pb_de }, + resp_mar: ::grpcio::Marshaller { ser: ::grpcio::pb_ser, de: ::grpcio::pb_de }, +}; + #[derive(Clone)] pub struct BeaconBlockServiceClient { client: ::grpcio::Client, @@ -75,6 +82,22 @@ impl BeaconBlockServiceClient { pub fn publish_beacon_block_async(&self, req: &super::services::PublishBeaconBlockRequest) -> ::grpcio::Result<::grpcio::ClientUnaryReceiver> { self.publish_beacon_block_async_opt(req, ::grpcio::CallOption::default()) } + + pub fn validator_assignment_opt(&self, req: &super::services::ValidatorAssignmentRequest, opt: ::grpcio::CallOption) -> ::grpcio::Result { + self.client.unary_call(&METHOD_BEACON_BLOCK_SERVICE_VALIDATOR_ASSIGNMENT, req, opt) + } + + pub fn validator_assignment(&self, req: &super::services::ValidatorAssignmentRequest) -> ::grpcio::Result { + self.validator_assignment_opt(req, ::grpcio::CallOption::default()) + } + + pub fn validator_assignment_async_opt(&self, req: &super::services::ValidatorAssignmentRequest, opt: ::grpcio::CallOption) -> ::grpcio::Result<::grpcio::ClientUnaryReceiver> { + self.client.unary_call_async(&METHOD_BEACON_BLOCK_SERVICE_VALIDATOR_ASSIGNMENT, req, opt) + } + + pub fn validator_assignment_async(&self, req: &super::services::ValidatorAssignmentRequest) -> ::grpcio::Result<::grpcio::ClientUnaryReceiver> { + self.validator_assignment_async_opt(req, ::grpcio::CallOption::default()) + } pub fn spawn(&self, f: F) where F: ::futures::Future + Send + 'static { self.client.spawn(f) } @@ -83,6 +106,7 @@ impl BeaconBlockServiceClient { pub trait BeaconBlockService { fn produce_beacon_block(&mut self, ctx: ::grpcio::RpcContext, req: super::services::ProduceBeaconBlockRequest, sink: ::grpcio::UnarySink); fn publish_beacon_block(&mut self, ctx: ::grpcio::RpcContext, req: super::services::PublishBeaconBlockRequest, sink: ::grpcio::UnarySink); + fn validator_assignment(&mut self, ctx: ::grpcio::RpcContext, req: super::services::ValidatorAssignmentRequest, sink: ::grpcio::UnarySink); } pub fn create_beacon_block_service(s: S) -> ::grpcio::Service { @@ -95,5 +119,9 @@ pub fn create_beacon_block_service Date: Mon, 21 Jan 2019 18:29:50 +1100 Subject: [PATCH 11/28] Add validator duties gRPC service to val. client --- validator_client/src/block_producer/mod.rs | 3 +- validator_client/src/duties/grpc.rs | 67 ++++++---------------- validator_client/src/duties/mod.rs | 10 ++-- validator_client/src/duties/traits.rs | 1 - validator_client/src/main.rs | 23 +++++++- 5 files changed, 49 insertions(+), 55 deletions(-) diff --git a/validator_client/src/block_producer/mod.rs b/validator_client/src/block_producer/mod.rs index 2efcbd6ef..db65ee789 100644 --- a/validator_client/src/block_producer/mod.rs +++ b/validator_client/src/block_producer/mod.rs @@ -1,11 +1,11 @@ mod grpc; mod service; +#[cfg(test)] mod test_node; mod traits; use self::traits::{BeaconNode, BeaconNodeError}; use super::EpochDutiesMap; -use crate::duties::EpochDuties; use slot_clock::SlotClock; use spec::ChainSpec; use std::sync::{Arc, RwLock}; @@ -139,6 +139,7 @@ mod tests { use super::*; use slot_clock::TestingSlotClock; use types::test_utils::{SeedableRng, TestRandom, XorShiftRng}; + use crate::duties::EpochDuties; // TODO: implement more thorough testing. // diff --git a/validator_client/src/duties/grpc.rs b/validator_client/src/duties/grpc.rs index 4032d49f3..4ea9c6d41 100644 --- a/validator_client/src/duties/grpc.rs +++ b/validator_client/src/duties/grpc.rs @@ -1,63 +1,34 @@ +use super::EpochDuties; use super::traits::{BeaconNode, BeaconNodeError}; -use protos::services::{ - BeaconBlock as GrpcBeaconBlock, ProduceBeaconBlockRequest, PublishBeaconBlockRequest, -}; +use protos::services::ValidatorAssignmentRequest; use protos::services_grpc::BeaconBlockServiceClient; -use ssz::{ssz_encode, Decodable}; -use types::{BeaconBlock, BeaconBlockBody, Hash256, Signature}; +use ssz::ssz_encode; +use types::{PublicKey}; impl BeaconNode for BeaconBlockServiceClient { - fn produce_beacon_block(&self, slot: u64) -> Result, BeaconNodeError> { - let mut req = ProduceBeaconBlockRequest::new(); - req.set_slot(slot); + fn request_shuffling(&self, epoch: u64, public_key: &PublicKey) -> Result, BeaconNodeError> { + let mut req = ValidatorAssignmentRequest::new(); + req.set_epoch(epoch); + req.set_public_key(ssz_encode(public_key).to_vec()); let reply = self - .produce_beacon_block(&req) + .validator_assignment(&req) .map_err(|err| BeaconNodeError::RemoteFailure(format!("{:?}", err)))?; - if reply.has_block() { - let block = reply.get_block(); + if reply.has_validator_assignment() { + let assignment = reply.get_validator_assignment(); - let (signature, _) = Signature::ssz_decode(block.get_signature(), 0) - .map_err(|_| BeaconNodeError::DecodeFailure)?; + let block_production_slot = if assignment.has_block_production_slot() { + Some(assignment.get_block_production_slot()) + } else { + None + }; - // TODO: this conversion is incomplete; fix it. - Ok(Some(BeaconBlock { - slot: block.get_slot(), - parent_root: Hash256::zero(), - state_root: Hash256::zero(), - randao_reveal: Hash256::from(block.get_randao_reveal()), - candidate_pow_receipt_root: Hash256::zero(), - signature, - body: BeaconBlockBody { - proposer_slashings: vec![], - casper_slashings: vec![], - attestations: vec![], - deposits: vec![], - exits: vec![], - }, - })) + let duties = EpochDuties { block_production_slot }; + + Ok(Some(duties)) } else { Ok(None) } } - - fn publish_beacon_block(&self, block: BeaconBlock) -> Result { - let mut req = PublishBeaconBlockRequest::new(); - - // TODO: this conversion is incomplete; fix it. - let mut grpc_block = GrpcBeaconBlock::new(); - grpc_block.set_slot(block.slot); - grpc_block.set_block_root(vec![0]); - grpc_block.set_randao_reveal(block.randao_reveal.to_vec()); - grpc_block.set_signature(ssz_encode(&block.signature)); - - req.set_block(grpc_block); - - let reply = self - .publish_beacon_block(&req) - .map_err(|err| BeaconNodeError::RemoteFailure(format!("{:?}", err)))?; - - Ok(reply.get_success()) - } } diff --git a/validator_client/src/duties/mod.rs b/validator_client/src/duties/mod.rs index d401d350e..0ac14b07f 100644 --- a/validator_client/src/duties/mod.rs +++ b/validator_client/src/duties/mod.rs @@ -1,3 +1,9 @@ +mod grpc; +mod service; +#[cfg(test)] +mod test_node; +mod traits; + use self::traits::{BeaconNode, BeaconNodeError}; use bls::PublicKey; use slot_clock::SlotClock; @@ -5,10 +11,6 @@ use spec::ChainSpec; use std::collections::HashMap; use std::sync::{Arc, RwLock}; -mod service; -mod test_node; -mod traits; - pub use self::service::DutiesManagerService; #[derive(Debug, PartialEq, Clone, Copy, Default)] diff --git a/validator_client/src/duties/traits.rs b/validator_client/src/duties/traits.rs index eb0f1583e..14c2adf95 100644 --- a/validator_client/src/duties/traits.rs +++ b/validator_client/src/duties/traits.rs @@ -4,7 +4,6 @@ use bls::PublicKey; #[derive(Debug, PartialEq, Clone)] pub enum BeaconNodeError { RemoteFailure(String), - DecodeFailure, } pub trait BeaconNode: Send + Sync { diff --git a/validator_client/src/main.rs b/validator_client/src/main.rs index 179146897..187b40f04 100644 --- a/validator_client/src/main.rs +++ b/validator_client/src/main.rs @@ -96,6 +96,25 @@ fn main() { for keypair in keypairs { let duties_map = Arc::new(RwLock::new(EpochDutiesMap::new())); + let duties_manager_thread = { + let spec = spec.clone(); + let duties_map = duties_map.clone(); + let slot_clock = slot_clock.clone(); + let log = log.clone(); + let beacon_node = client.clone(); + let pubkey = keypair.pk.clone(); + thread::spawn(move || { + let manager = DutiesManager { duties_map, pubkey, spec, slot_clock, beacon_node }; + let mut duties_manager_service = DutiesManagerService { + manager, + poll_interval_millis, + log, + }; + + duties_manager_service.run(); + }) + }; + let producer_thread = { let spec = spec.clone(); let duties_map = duties_map.clone(); @@ -113,11 +132,13 @@ fn main() { block_producer_service.run(); }) }; - threads.push(((), producer_thread)); + + threads.push((duties_manager_thread, producer_thread)); } for tuple in threads { let (manager, producer) = tuple; let _ = producer.join(); + let _ = manager.join(); } } From 24a27891b878de5f18ff5656ac1c777b673b3725 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Mon, 21 Jan 2019 18:41:07 +1100 Subject: [PATCH 12/28] Run rustfmt on entire codebase Signed-off-by: Paul Hauner --- .../attestation_validation/src/lib.rs | 6 +- beacon_chain/genesis/src/lib.rs | 2 +- beacon_chain/types/src/test_utils/mod.rs | 10 +-- beacon_chain/types/src/validator_record.rs | 6 +- beacon_chain/utils/bls/src/lib.rs | 2 +- .../validator_induction/src/inductor.rs | 69 ++++++++++++------- beacon_chain/validator_induction/src/lib.rs | 4 +- beacon_node/db/src/disk_db.rs | 3 +- .../db/src/stores/beacon_state_store.rs | 4 +- validator_client/src/block_producer/mod.rs | 2 +- .../src/block_producer/service.rs | 4 +- .../src/block_producer/test_node.rs | 6 +- validator_client/src/duties/grpc.rs | 14 ++-- validator_client/src/main.rs | 8 ++- 14 files changed, 90 insertions(+), 50 deletions(-) diff --git a/beacon_chain/attestation_validation/src/lib.rs b/beacon_chain/attestation_validation/src/lib.rs index 254d6134e..825371ed0 100644 --- a/beacon_chain/attestation_validation/src/lib.rs +++ b/beacon_chain/attestation_validation/src/lib.rs @@ -14,9 +14,9 @@ mod justified_slot; mod shard_block; mod signature; -pub use crate::enums::{Invalid, Outcome, Error}; pub use crate::block_inclusion::validate_attestation_for_block; -pub use crate::justified_slot::validate_attestation_justified_slot; +pub use crate::enums::{Error, Invalid, Outcome}; pub use crate::justified_block::validate_attestation_justified_block_hash; -pub use crate::signature::validate_attestation_signature; +pub use crate::justified_slot::validate_attestation_justified_slot; pub use crate::shard_block::validate_attestation_data_shard_block_hash; +pub use crate::signature::validate_attestation_signature; diff --git a/beacon_chain/genesis/src/lib.rs b/beacon_chain/genesis/src/lib.rs index e590fa8be..6f45863aa 100644 --- a/beacon_chain/genesis/src/lib.rs +++ b/beacon_chain/genesis/src/lib.rs @@ -3,8 +3,8 @@ extern crate types; extern crate validator_induction; extern crate validator_shuffling; -mod beacon_state; mod beacon_block; +mod beacon_state; pub use crate::beacon_block::genesis_beacon_block; pub use crate::beacon_state::{genesis_beacon_state, Error as GenesisError}; diff --git a/beacon_chain/types/src/test_utils/mod.rs b/beacon_chain/types/src/test_utils/mod.rs index f3e382e6e..eb54f2a53 100644 --- a/beacon_chain/types/src/test_utils/mod.rs +++ b/beacon_chain/types/src/test_utils/mod.rs @@ -6,12 +6,13 @@ pub mod address; pub mod aggregate_signature; pub mod bitfield; pub mod hash256; -pub mod signature; -pub mod secret_key; pub mod public_key; +pub mod secret_key; +pub mod signature; pub trait TestRandom -where T: RngCore +where + T: RngCore, { fn random_for_test(rng: &mut T) -> Self; } @@ -35,7 +36,8 @@ impl TestRandom for usize { } impl TestRandom for Vec -where U: TestRandom +where + U: TestRandom, { fn random_for_test(rng: &mut T) -> Self { vec![ diff --git a/beacon_chain/types/src/validator_record.rs b/beacon_chain/types/src/validator_record.rs index 5f74d28d2..3f4a43261 100644 --- a/beacon_chain/types/src/validator_record.rs +++ b/beacon_chain/types/src/validator_record.rs @@ -1,5 +1,5 @@ use super::bls::PublicKey; -use super::{Hash256}; +use super::Hash256; use crate::test_utils::TestRandom; use rand::RngCore; use ssz::{Decodable, DecodeError, Encodable, SszStream}; @@ -40,7 +40,7 @@ pub struct ValidatorRecord { pub exit_count: u64, pub custody_commitment: Hash256, pub latest_custody_reseed_slot: u64, - pub penultimate_custody_reseed_slot: u64 + pub penultimate_custody_reseed_slot: u64, } impl ValidatorRecord { @@ -132,7 +132,7 @@ impl Decodable for ValidatorRecord { exit_count, custody_commitment, latest_custody_reseed_slot, - penultimate_custody_reseed_slot + penultimate_custody_reseed_slot, }, i, )) diff --git a/beacon_chain/utils/bls/src/lib.rs b/beacon_chain/utils/bls/src/lib.rs index 9d27d870b..d7a3ff15d 100644 --- a/beacon_chain/utils/bls/src/lib.rs +++ b/beacon_chain/utils/bls/src/lib.rs @@ -19,8 +19,8 @@ pub use self::bls_aggregates::AggregatePublicKey; pub const BLS_AGG_SIG_BYTE_SIZE: usize = 97; use hashing::canonical_hash; -use std::default::Default; use ssz::ssz_encode; +use std::default::Default; fn extend_if_needed(hash: &mut Vec) { // NOTE: bls_aggregates crate demands 48 bytes, this may be removed as we get closer to production diff --git a/beacon_chain/validator_induction/src/inductor.rs b/beacon_chain/validator_induction/src/inductor.rs index 720e38fa4..f00c9ec55 100644 --- a/beacon_chain/validator_induction/src/inductor.rs +++ b/beacon_chain/validator_induction/src/inductor.rs @@ -1,19 +1,19 @@ -use bls::{verify_proof_of_possession}; -use types::{BeaconState, Deposit, ValidatorRecord, ValidatorStatus}; +use bls::verify_proof_of_possession; use spec::ChainSpec; +use types::{BeaconState, Deposit, ValidatorRecord, ValidatorStatus}; #[derive(Debug, PartialEq, Clone)] pub enum ValidatorInductionError { InvalidShard, InvaidProofOfPossession, - InvalidWithdrawalCredentials + InvalidWithdrawalCredentials, } pub fn process_deposit( state: &mut BeaconState, deposit: &Deposit, - spec: &ChainSpec) --> Result { + spec: &ChainSpec, +) -> Result { let deposit_input = &deposit.deposit_data.deposit_input; let deposit_data = &deposit.deposit_data; @@ -22,18 +22,22 @@ pub fn process_deposit( return Err(ValidatorInductionError::InvaidProofOfPossession); } - let validator_index = state.validator_registry.iter() + let validator_index = state + .validator_registry + .iter() .position(|validator| validator.pubkey == deposit_input.pubkey); match validator_index { Some(i) => { - if state.validator_registry[i].withdrawal_credentials == deposit_input.withdrawal_credentials { + if state.validator_registry[i].withdrawal_credentials + == deposit_input.withdrawal_credentials + { state.validator_balances[i] += deposit_data.value; return Ok(i); } Err(ValidatorInductionError::InvalidWithdrawalCredentials) - }, + } None => { let validator = ValidatorRecord { pubkey: deposit_input.pubkey.clone(), @@ -45,7 +49,7 @@ pub fn process_deposit( exit_count: 0, custody_commitment: deposit_input.custody_commitment, latest_custody_reseed_slot: 0, - penultimate_custody_reseed_slot: 0 + penultimate_custody_reseed_slot: 0, }; match min_empty_validator_index(state, spec) { @@ -53,7 +57,7 @@ pub fn process_deposit( state.validator_registry[i] = validator; state.validator_balances[i] = deposit_data.value; Ok(i) - }, + } None => { state.validator_registry.push(validator); state.validator_balances.push(deposit_data.value); @@ -64,14 +68,13 @@ pub fn process_deposit( } } -fn min_empty_validator_index( - state: &BeaconState, - spec: &ChainSpec -) -> Option { +fn min_empty_validator_index(state: &BeaconState, spec: &ChainSpec) -> Option { for i in 0..state.validator_registry.len() { if state.validator_balances[i] == 0 && state.validator_registry[i].latest_status_change_slot - + spec.zero_balance_validator_ttl <= state.slot { + + spec.zero_balance_validator_ttl + <= state.slot + { return Some(i); } } @@ -107,7 +110,10 @@ mod tests { (dep.deposit_data.deposit_input.pubkey == val.pubkey) & (dep.deposit_data.deposit_input.withdrawal_credentials == val.withdrawal_credentials) & (dep.deposit_data.deposit_input.randao_commitment == val.randao_commitment) - & (verify_proof_of_possession(&dep.deposit_data.deposit_input.proof_of_possession, &val.pubkey)) + & (verify_proof_of_possession( + &dep.deposit_data.deposit_input.proof_of_possession, + &val.pubkey, + )) } #[test] @@ -120,7 +126,10 @@ mod tests { let result = process_deposit(&mut state, &deposit, &spec); assert_eq!(result.unwrap(), 0); - assert!(deposit_equals_record(&deposit, &state.validator_registry[0])); + assert!(deposit_equals_record( + &deposit, + &state.validator_registry[0] + )); assert_eq!(state.validator_registry.len(), 1); assert_eq!(state.validator_balances.len(), 1); } @@ -135,7 +144,10 @@ mod tests { let result = process_deposit(&mut state, &deposit, &spec); deposit.deposit_data.value = DEPOSIT_GWEI; assert_eq!(result.unwrap(), i); - assert!(deposit_equals_record(&deposit, &state.validator_registry[i])); + assert!(deposit_equals_record( + &deposit, + &state.validator_registry[i] + )); assert_eq!(state.validator_registry.len(), i + 1); assert_eq!(state.validator_balances.len(), i + 1); } @@ -151,7 +163,8 @@ mod tests { deposit.deposit_data.value = DEPOSIT_GWEI; validator.pubkey = deposit.deposit_data.deposit_input.pubkey.clone(); - validator.withdrawal_credentials = deposit.deposit_data.deposit_input.withdrawal_credentials; + validator.withdrawal_credentials = + deposit.deposit_data.deposit_input.withdrawal_credentials; validator.randao_commitment = deposit.deposit_data.deposit_input.randao_commitment; state.validator_registry.push(validator); @@ -160,7 +173,10 @@ mod tests { let result = process_deposit(&mut state, &deposit, &spec); assert_eq!(result.unwrap(), 0); - assert!(deposit_equals_record(&deposit, &state.validator_registry[0])); + assert!(deposit_equals_record( + &deposit, + &state.validator_registry[0] + )); assert_eq!(state.validator_balances[0], DEPOSIT_GWEI * 2); assert_eq!(state.validator_registry.len(), 1); assert_eq!(state.validator_balances.len(), 1); @@ -183,7 +199,10 @@ mod tests { let result = process_deposit(&mut state, &deposit, &spec); assert_eq!(result.unwrap(), 0); - assert!(deposit_equals_record(&deposit, &state.validator_registry[0])); + assert!(deposit_equals_record( + &deposit, + &state.validator_registry[0] + )); assert_eq!(state.validator_balances[0], DEPOSIT_GWEI); assert_eq!(state.validator_registry.len(), 1); assert_eq!(state.validator_balances.len(), 1); @@ -195,11 +214,15 @@ mod tests { let mut deposit = get_deposit(); let spec = ChainSpec::foundation(); deposit.deposit_data.value = DEPOSIT_GWEI; - deposit.deposit_data.deposit_input.proof_of_possession = create_proof_of_possession(&Keypair::random()); + deposit.deposit_data.deposit_input.proof_of_possession = + create_proof_of_possession(&Keypair::random()); let result = process_deposit(&mut state, &deposit, &spec); - assert_eq!(result, Err(ValidatorInductionError::InvaidProofOfPossession)); + assert_eq!( + result, + Err(ValidatorInductionError::InvaidProofOfPossession) + ); assert_eq!(state.validator_registry.len(), 0); assert_eq!(state.validator_balances.len(), 0); } diff --git a/beacon_chain/validator_induction/src/lib.rs b/beacon_chain/validator_induction/src/lib.rs index f6dec3cfa..7119d6c2e 100644 --- a/beacon_chain/validator_induction/src/lib.rs +++ b/beacon_chain/validator_induction/src/lib.rs @@ -1,8 +1,8 @@ extern crate bls; extern crate hashing; -extern crate types; extern crate spec; +extern crate types; mod inductor; -pub use crate::inductor::{ValidatorInductionError, process_deposit}; +pub use crate::inductor::{process_deposit, ValidatorInductionError}; diff --git a/beacon_node/db/src/disk_db.rs b/beacon_node/db/src/disk_db.rs index b084f483f..9d8a71bc4 100644 --- a/beacon_node/db/src/disk_db.rs +++ b/beacon_node/db/src/disk_db.rs @@ -44,7 +44,8 @@ impl DiskDB { let db = match columns { None => DB::open(&options, db_path), Some(columns) => DB::open_cf(&options, db_path, columns), - }.expect("Unable to open local database");; + } + .expect("Unable to open local database");; Self { db } } diff --git a/beacon_node/db/src/stores/beacon_state_store.rs b/beacon_node/db/src/stores/beacon_state_store.rs index 122b22509..a54e19249 100644 --- a/beacon_node/db/src/stores/beacon_state_store.rs +++ b/beacon_node/db/src/stores/beacon_state_store.rs @@ -42,10 +42,10 @@ mod tests { use super::super::super::MemoryDB; use super::*; - use std::sync::Arc; use ssz::ssz_encode; - use types::Hash256; + use std::sync::Arc; use types::test_utils::{SeedableRng, TestRandom, XorShiftRng}; + use types::Hash256; test_crud_for_store!(BeaconStateStore, DB_COLUMN); diff --git a/validator_client/src/block_producer/mod.rs b/validator_client/src/block_producer/mod.rs index db65ee789..aa4c088f3 100644 --- a/validator_client/src/block_producer/mod.rs +++ b/validator_client/src/block_producer/mod.rs @@ -137,9 +137,9 @@ impl From for Error { mod tests { use super::test_node::TestBeaconNode; use super::*; + use crate::duties::EpochDuties; use slot_clock::TestingSlotClock; use types::test_utils::{SeedableRng, TestRandom, XorShiftRng}; - use crate::duties::EpochDuties; // TODO: implement more thorough testing. // diff --git a/validator_client/src/block_producer/service.rs b/validator_client/src/block_producer/service.rs index aef1e3c28..222e54d47 100644 --- a/validator_client/src/block_producer/service.rs +++ b/validator_client/src/block_producer/service.rs @@ -16,7 +16,9 @@ impl BlockProducerService { Err(error) => { error!(self.log, "Block producer poll error"; "error" => format!("{:?}", error)) } - Ok(BlockProducerPollOutcome::BlockProduced(slot)) => info!(self.log, "Produced block"; "slot" => slot), + Ok(BlockProducerPollOutcome::BlockProduced(slot)) => { + info!(self.log, "Produced block"; "slot" => slot) + } Ok(BlockProducerPollOutcome::SlashableBlockNotProduced(slot)) => { warn!(self.log, "Slashable block was not signed"; "slot" => slot) } diff --git a/validator_client/src/block_producer/test_node.rs b/validator_client/src/block_producer/test_node.rs index fdb179b5c..36d47e3c3 100644 --- a/validator_client/src/block_producer/test_node.rs +++ b/validator_client/src/block_producer/test_node.rs @@ -1,6 +1,6 @@ use super::traits::{BeaconNode, BeaconNodeError}; -use types::BeaconBlock; use std::sync::RwLock; +use types::BeaconBlock; type ProduceResult = Result, BeaconNodeError>; type PublishResult = Result; @@ -28,7 +28,7 @@ impl BeaconNode for TestBeaconNode { *self.produce_input.write().unwrap() = Some(slot); match *self.produce_result.read().unwrap() { Some(ref r) => r.clone(), - None => panic!("TestBeaconNode: produce_result == None") + None => panic!("TestBeaconNode: produce_result == None"), } } @@ -36,7 +36,7 @@ impl BeaconNode for TestBeaconNode { *self.publish_input.write().unwrap() = Some(block); match *self.publish_result.read().unwrap() { Some(ref r) => r.clone(), - None => panic!("TestBeaconNode: publish_result == None") + None => panic!("TestBeaconNode: publish_result == None"), } } } diff --git a/validator_client/src/duties/grpc.rs b/validator_client/src/duties/grpc.rs index 4ea9c6d41..c5d817dd7 100644 --- a/validator_client/src/duties/grpc.rs +++ b/validator_client/src/duties/grpc.rs @@ -1,12 +1,16 @@ -use super::EpochDuties; use super::traits::{BeaconNode, BeaconNodeError}; +use super::EpochDuties; use protos::services::ValidatorAssignmentRequest; use protos::services_grpc::BeaconBlockServiceClient; use ssz::ssz_encode; -use types::{PublicKey}; +use types::PublicKey; impl BeaconNode for BeaconBlockServiceClient { - fn request_shuffling(&self, epoch: u64, public_key: &PublicKey) -> Result, BeaconNodeError> { + fn request_shuffling( + &self, + epoch: u64, + public_key: &PublicKey, + ) -> Result, BeaconNodeError> { let mut req = ValidatorAssignmentRequest::new(); req.set_epoch(epoch); req.set_public_key(ssz_encode(public_key).to_vec()); @@ -24,7 +28,9 @@ impl BeaconNode for BeaconBlockServiceClient { None }; - let duties = EpochDuties { block_production_slot }; + let duties = EpochDuties { + block_production_slot, + }; Ok(Some(duties)) } else { diff --git a/validator_client/src/main.rs b/validator_client/src/main.rs index 187b40f04..63d2137b2 100644 --- a/validator_client/src/main.rs +++ b/validator_client/src/main.rs @@ -104,7 +104,13 @@ fn main() { let beacon_node = client.clone(); let pubkey = keypair.pk.clone(); thread::spawn(move || { - let manager = DutiesManager { duties_map, pubkey, spec, slot_clock, beacon_node }; + let manager = DutiesManager { + duties_map, + pubkey, + spec, + slot_clock, + beacon_node, + }; let mut duties_manager_service = DutiesManagerService { manager, poll_interval_millis, From 053a9b1c318f3a78f51942d726f1c567f23784d2 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Mon, 21 Jan 2019 18:46:01 +1100 Subject: [PATCH 13/28] Remove auto-generated grpc files --- protos/.gitignore | 2 + protos/src/services.rs | 1657 ----------------------------------- protos/src/services_grpc.rs | 127 --- 3 files changed, 2 insertions(+), 1784 deletions(-) create mode 100644 protos/.gitignore delete mode 100644 protos/src/services.rs delete mode 100644 protos/src/services_grpc.rs diff --git a/protos/.gitignore b/protos/.gitignore new file mode 100644 index 000000000..7104339d9 --- /dev/null +++ b/protos/.gitignore @@ -0,0 +1,2 @@ +src/services.rs +src/services_grpc.rs diff --git a/protos/src/services.rs b/protos/src/services.rs deleted file mode 100644 index 4273d9663..000000000 --- a/protos/src/services.rs +++ /dev/null @@ -1,1657 +0,0 @@ -// This file is generated by rust-protobuf 2.0.6. Do not edit -// @generated - -// https://github.com/Manishearth/rust-clippy/issues/702 -#![allow(unknown_lints)] -#![allow(clippy)] - -#![cfg_attr(rustfmt, rustfmt_skip)] - -#![allow(box_pointers)] -#![allow(dead_code)] -#![allow(missing_docs)] -#![allow(non_camel_case_types)] -#![allow(non_snake_case)] -#![allow(non_upper_case_globals)] -#![allow(trivial_casts)] -#![allow(unsafe_code)] -#![allow(unused_imports)] -#![allow(unused_results)] - -use protobuf::Message as Message_imported_for_functions; -use protobuf::ProtobufEnum as ProtobufEnum_imported_for_functions; - -#[derive(PartialEq,Clone,Default)] -pub struct BeaconBlock { - // message fields - pub slot: u64, - pub block_root: ::std::vec::Vec, - pub randao_reveal: ::std::vec::Vec, - pub signature: ::std::vec::Vec, - // special fields - unknown_fields: ::protobuf::UnknownFields, - cached_size: ::protobuf::CachedSize, -} - -impl BeaconBlock { - pub fn new() -> BeaconBlock { - ::std::default::Default::default() - } - - // uint64 slot = 1; - - pub fn clear_slot(&mut self) { - self.slot = 0; - } - - // Param is passed by value, moved - pub fn set_slot(&mut self, v: u64) { - self.slot = v; - } - - pub fn get_slot(&self) -> u64 { - self.slot - } - - // bytes block_root = 2; - - pub fn clear_block_root(&mut self) { - self.block_root.clear(); - } - - // Param is passed by value, moved - pub fn set_block_root(&mut self, v: ::std::vec::Vec) { - self.block_root = v; - } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_block_root(&mut self) -> &mut ::std::vec::Vec { - &mut self.block_root - } - - // Take field - pub fn take_block_root(&mut self) -> ::std::vec::Vec { - ::std::mem::replace(&mut self.block_root, ::std::vec::Vec::new()) - } - - pub fn get_block_root(&self) -> &[u8] { - &self.block_root - } - - // bytes randao_reveal = 3; - - pub fn clear_randao_reveal(&mut self) { - self.randao_reveal.clear(); - } - - // Param is passed by value, moved - pub fn set_randao_reveal(&mut self, v: ::std::vec::Vec) { - self.randao_reveal = v; - } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_randao_reveal(&mut self) -> &mut ::std::vec::Vec { - &mut self.randao_reveal - } - - // Take field - pub fn take_randao_reveal(&mut self) -> ::std::vec::Vec { - ::std::mem::replace(&mut self.randao_reveal, ::std::vec::Vec::new()) - } - - pub fn get_randao_reveal(&self) -> &[u8] { - &self.randao_reveal - } - - // bytes signature = 4; - - pub fn clear_signature(&mut self) { - self.signature.clear(); - } - - // Param is passed by value, moved - pub fn set_signature(&mut self, v: ::std::vec::Vec) { - self.signature = v; - } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_signature(&mut self) -> &mut ::std::vec::Vec { - &mut self.signature - } - - // Take field - pub fn take_signature(&mut self) -> ::std::vec::Vec { - ::std::mem::replace(&mut self.signature, ::std::vec::Vec::new()) - } - - pub fn get_signature(&self) -> &[u8] { - &self.signature - } -} - -impl ::protobuf::Message for BeaconBlock { - fn is_initialized(&self) -> bool { - true - } - - fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream) -> ::protobuf::ProtobufResult<()> { - while !is.eof()? { - let (field_number, wire_type) = is.read_tag_unpack()?; - match field_number { - 1 => { - if wire_type != ::protobuf::wire_format::WireTypeVarint { - return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); - } - let tmp = is.read_uint64()?; - self.slot = tmp; - }, - 2 => { - ::protobuf::rt::read_singular_proto3_bytes_into(wire_type, is, &mut self.block_root)?; - }, - 3 => { - ::protobuf::rt::read_singular_proto3_bytes_into(wire_type, is, &mut self.randao_reveal)?; - }, - 4 => { - ::protobuf::rt::read_singular_proto3_bytes_into(wire_type, is, &mut self.signature)?; - }, - _ => { - ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; - }, - }; - } - ::std::result::Result::Ok(()) - } - - // Compute sizes of nested messages - #[allow(unused_variables)] - fn compute_size(&self) -> u32 { - let mut my_size = 0; - if self.slot != 0 { - my_size += ::protobuf::rt::value_size(1, self.slot, ::protobuf::wire_format::WireTypeVarint); - } - if !self.block_root.is_empty() { - my_size += ::protobuf::rt::bytes_size(2, &self.block_root); - } - if !self.randao_reveal.is_empty() { - my_size += ::protobuf::rt::bytes_size(3, &self.randao_reveal); - } - if !self.signature.is_empty() { - my_size += ::protobuf::rt::bytes_size(4, &self.signature); - } - my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); - self.cached_size.set(my_size); - my_size - } - - fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream) -> ::protobuf::ProtobufResult<()> { - if self.slot != 0 { - os.write_uint64(1, self.slot)?; - } - if !self.block_root.is_empty() { - os.write_bytes(2, &self.block_root)?; - } - if !self.randao_reveal.is_empty() { - os.write_bytes(3, &self.randao_reveal)?; - } - if !self.signature.is_empty() { - os.write_bytes(4, &self.signature)?; - } - os.write_unknown_fields(self.get_unknown_fields())?; - ::std::result::Result::Ok(()) - } - - fn get_cached_size(&self) -> u32 { - self.cached_size.get() - } - - fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { - &self.unknown_fields - } - - fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { - &mut self.unknown_fields - } - - fn as_any(&self) -> &::std::any::Any { - self as &::std::any::Any - } - fn as_any_mut(&mut self) -> &mut ::std::any::Any { - self as &mut ::std::any::Any - } - fn into_any(self: Box) -> ::std::boxed::Box<::std::any::Any> { - self - } - - fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { - Self::descriptor_static() - } - - fn new() -> BeaconBlock { - BeaconBlock::new() - } - - fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { - static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::lazy::Lazy { - lock: ::protobuf::lazy::ONCE_INIT, - ptr: 0 as *const ::protobuf::reflect::MessageDescriptor, - }; - unsafe { - descriptor.get(|| { - let mut fields = ::std::vec::Vec::new(); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeUint64>( - "slot", - |m: &BeaconBlock| { &m.slot }, - |m: &mut BeaconBlock| { &mut m.slot }, - )); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>( - "block_root", - |m: &BeaconBlock| { &m.block_root }, - |m: &mut BeaconBlock| { &mut m.block_root }, - )); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>( - "randao_reveal", - |m: &BeaconBlock| { &m.randao_reveal }, - |m: &mut BeaconBlock| { &mut m.randao_reveal }, - )); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>( - "signature", - |m: &BeaconBlock| { &m.signature }, - |m: &mut BeaconBlock| { &mut m.signature }, - )); - ::protobuf::reflect::MessageDescriptor::new::( - "BeaconBlock", - fields, - file_descriptor_proto() - ) - }) - } - } - - fn default_instance() -> &'static BeaconBlock { - static mut instance: ::protobuf::lazy::Lazy = ::protobuf::lazy::Lazy { - lock: ::protobuf::lazy::ONCE_INIT, - ptr: 0 as *const BeaconBlock, - }; - unsafe { - instance.get(BeaconBlock::new) - } - } -} - -impl ::protobuf::Clear for BeaconBlock { - fn clear(&mut self) { - self.clear_slot(); - self.clear_block_root(); - self.clear_randao_reveal(); - self.clear_signature(); - self.unknown_fields.clear(); - } -} - -impl ::std::fmt::Debug for BeaconBlock { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - ::protobuf::text_format::fmt(self, f) - } -} - -impl ::protobuf::reflect::ProtobufValue for BeaconBlock { - fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef { - ::protobuf::reflect::ProtobufValueRef::Message(self) - } -} - -#[derive(PartialEq,Clone,Default)] -pub struct ProduceBeaconBlockRequest { - // message fields - pub slot: u64, - // special fields - unknown_fields: ::protobuf::UnknownFields, - cached_size: ::protobuf::CachedSize, -} - -impl ProduceBeaconBlockRequest { - pub fn new() -> ProduceBeaconBlockRequest { - ::std::default::Default::default() - } - - // uint64 slot = 1; - - pub fn clear_slot(&mut self) { - self.slot = 0; - } - - // Param is passed by value, moved - pub fn set_slot(&mut self, v: u64) { - self.slot = v; - } - - pub fn get_slot(&self) -> u64 { - self.slot - } -} - -impl ::protobuf::Message for ProduceBeaconBlockRequest { - fn is_initialized(&self) -> bool { - true - } - - fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream) -> ::protobuf::ProtobufResult<()> { - while !is.eof()? { - let (field_number, wire_type) = is.read_tag_unpack()?; - match field_number { - 1 => { - if wire_type != ::protobuf::wire_format::WireTypeVarint { - return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); - } - let tmp = is.read_uint64()?; - self.slot = tmp; - }, - _ => { - ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; - }, - }; - } - ::std::result::Result::Ok(()) - } - - // Compute sizes of nested messages - #[allow(unused_variables)] - fn compute_size(&self) -> u32 { - let mut my_size = 0; - if self.slot != 0 { - my_size += ::protobuf::rt::value_size(1, self.slot, ::protobuf::wire_format::WireTypeVarint); - } - my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); - self.cached_size.set(my_size); - my_size - } - - fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream) -> ::protobuf::ProtobufResult<()> { - if self.slot != 0 { - os.write_uint64(1, self.slot)?; - } - os.write_unknown_fields(self.get_unknown_fields())?; - ::std::result::Result::Ok(()) - } - - fn get_cached_size(&self) -> u32 { - self.cached_size.get() - } - - fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { - &self.unknown_fields - } - - fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { - &mut self.unknown_fields - } - - fn as_any(&self) -> &::std::any::Any { - self as &::std::any::Any - } - fn as_any_mut(&mut self) -> &mut ::std::any::Any { - self as &mut ::std::any::Any - } - fn into_any(self: Box) -> ::std::boxed::Box<::std::any::Any> { - self - } - - fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { - Self::descriptor_static() - } - - fn new() -> ProduceBeaconBlockRequest { - ProduceBeaconBlockRequest::new() - } - - fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { - static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::lazy::Lazy { - lock: ::protobuf::lazy::ONCE_INIT, - ptr: 0 as *const ::protobuf::reflect::MessageDescriptor, - }; - unsafe { - descriptor.get(|| { - let mut fields = ::std::vec::Vec::new(); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeUint64>( - "slot", - |m: &ProduceBeaconBlockRequest| { &m.slot }, - |m: &mut ProduceBeaconBlockRequest| { &mut m.slot }, - )); - ::protobuf::reflect::MessageDescriptor::new::( - "ProduceBeaconBlockRequest", - fields, - file_descriptor_proto() - ) - }) - } - } - - fn default_instance() -> &'static ProduceBeaconBlockRequest { - static mut instance: ::protobuf::lazy::Lazy = ::protobuf::lazy::Lazy { - lock: ::protobuf::lazy::ONCE_INIT, - ptr: 0 as *const ProduceBeaconBlockRequest, - }; - unsafe { - instance.get(ProduceBeaconBlockRequest::new) - } - } -} - -impl ::protobuf::Clear for ProduceBeaconBlockRequest { - fn clear(&mut self) { - self.clear_slot(); - self.unknown_fields.clear(); - } -} - -impl ::std::fmt::Debug for ProduceBeaconBlockRequest { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - ::protobuf::text_format::fmt(self, f) - } -} - -impl ::protobuf::reflect::ProtobufValue for ProduceBeaconBlockRequest { - fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef { - ::protobuf::reflect::ProtobufValueRef::Message(self) - } -} - -#[derive(PartialEq,Clone,Default)] -pub struct ProduceBeaconBlockResponse { - // message fields - pub block: ::protobuf::SingularPtrField, - // special fields - unknown_fields: ::protobuf::UnknownFields, - cached_size: ::protobuf::CachedSize, -} - -impl ProduceBeaconBlockResponse { - pub fn new() -> ProduceBeaconBlockResponse { - ::std::default::Default::default() - } - - // .ethereum.beacon.rpc.v1.BeaconBlock block = 1; - - pub fn clear_block(&mut self) { - self.block.clear(); - } - - pub fn has_block(&self) -> bool { - self.block.is_some() - } - - // Param is passed by value, moved - pub fn set_block(&mut self, v: BeaconBlock) { - self.block = ::protobuf::SingularPtrField::some(v); - } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_block(&mut self) -> &mut BeaconBlock { - if self.block.is_none() { - self.block.set_default(); - } - self.block.as_mut().unwrap() - } - - // Take field - pub fn take_block(&mut self) -> BeaconBlock { - self.block.take().unwrap_or_else(|| BeaconBlock::new()) - } - - pub fn get_block(&self) -> &BeaconBlock { - self.block.as_ref().unwrap_or_else(|| BeaconBlock::default_instance()) - } -} - -impl ::protobuf::Message for ProduceBeaconBlockResponse { - fn is_initialized(&self) -> bool { - for v in &self.block { - if !v.is_initialized() { - return false; - } - }; - true - } - - fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream) -> ::protobuf::ProtobufResult<()> { - while !is.eof()? { - let (field_number, wire_type) = is.read_tag_unpack()?; - match field_number { - 1 => { - ::protobuf::rt::read_singular_message_into(wire_type, is, &mut self.block)?; - }, - _ => { - ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; - }, - }; - } - ::std::result::Result::Ok(()) - } - - // Compute sizes of nested messages - #[allow(unused_variables)] - fn compute_size(&self) -> u32 { - let mut my_size = 0; - if let Some(ref v) = self.block.as_ref() { - let len = v.compute_size(); - my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; - } - my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); - self.cached_size.set(my_size); - my_size - } - - fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream) -> ::protobuf::ProtobufResult<()> { - if let Some(ref v) = self.block.as_ref() { - os.write_tag(1, ::protobuf::wire_format::WireTypeLengthDelimited)?; - os.write_raw_varint32(v.get_cached_size())?; - v.write_to_with_cached_sizes(os)?; - } - os.write_unknown_fields(self.get_unknown_fields())?; - ::std::result::Result::Ok(()) - } - - fn get_cached_size(&self) -> u32 { - self.cached_size.get() - } - - fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { - &self.unknown_fields - } - - fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { - &mut self.unknown_fields - } - - fn as_any(&self) -> &::std::any::Any { - self as &::std::any::Any - } - fn as_any_mut(&mut self) -> &mut ::std::any::Any { - self as &mut ::std::any::Any - } - fn into_any(self: Box) -> ::std::boxed::Box<::std::any::Any> { - self - } - - fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { - Self::descriptor_static() - } - - fn new() -> ProduceBeaconBlockResponse { - ProduceBeaconBlockResponse::new() - } - - fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { - static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::lazy::Lazy { - lock: ::protobuf::lazy::ONCE_INIT, - ptr: 0 as *const ::protobuf::reflect::MessageDescriptor, - }; - unsafe { - descriptor.get(|| { - let mut fields = ::std::vec::Vec::new(); - fields.push(::protobuf::reflect::accessor::make_singular_ptr_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( - "block", - |m: &ProduceBeaconBlockResponse| { &m.block }, - |m: &mut ProduceBeaconBlockResponse| { &mut m.block }, - )); - ::protobuf::reflect::MessageDescriptor::new::( - "ProduceBeaconBlockResponse", - fields, - file_descriptor_proto() - ) - }) - } - } - - fn default_instance() -> &'static ProduceBeaconBlockResponse { - static mut instance: ::protobuf::lazy::Lazy = ::protobuf::lazy::Lazy { - lock: ::protobuf::lazy::ONCE_INIT, - ptr: 0 as *const ProduceBeaconBlockResponse, - }; - unsafe { - instance.get(ProduceBeaconBlockResponse::new) - } - } -} - -impl ::protobuf::Clear for ProduceBeaconBlockResponse { - fn clear(&mut self) { - self.clear_block(); - self.unknown_fields.clear(); - } -} - -impl ::std::fmt::Debug for ProduceBeaconBlockResponse { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - ::protobuf::text_format::fmt(self, f) - } -} - -impl ::protobuf::reflect::ProtobufValue for ProduceBeaconBlockResponse { - fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef { - ::protobuf::reflect::ProtobufValueRef::Message(self) - } -} - -#[derive(PartialEq,Clone,Default)] -pub struct PublishBeaconBlockRequest { - // message fields - pub block: ::protobuf::SingularPtrField, - // special fields - unknown_fields: ::protobuf::UnknownFields, - cached_size: ::protobuf::CachedSize, -} - -impl PublishBeaconBlockRequest { - pub fn new() -> PublishBeaconBlockRequest { - ::std::default::Default::default() - } - - // .ethereum.beacon.rpc.v1.BeaconBlock block = 1; - - pub fn clear_block(&mut self) { - self.block.clear(); - } - - pub fn has_block(&self) -> bool { - self.block.is_some() - } - - // Param is passed by value, moved - pub fn set_block(&mut self, v: BeaconBlock) { - self.block = ::protobuf::SingularPtrField::some(v); - } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_block(&mut self) -> &mut BeaconBlock { - if self.block.is_none() { - self.block.set_default(); - } - self.block.as_mut().unwrap() - } - - // Take field - pub fn take_block(&mut self) -> BeaconBlock { - self.block.take().unwrap_or_else(|| BeaconBlock::new()) - } - - pub fn get_block(&self) -> &BeaconBlock { - self.block.as_ref().unwrap_or_else(|| BeaconBlock::default_instance()) - } -} - -impl ::protobuf::Message for PublishBeaconBlockRequest { - fn is_initialized(&self) -> bool { - for v in &self.block { - if !v.is_initialized() { - return false; - } - }; - true - } - - fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream) -> ::protobuf::ProtobufResult<()> { - while !is.eof()? { - let (field_number, wire_type) = is.read_tag_unpack()?; - match field_number { - 1 => { - ::protobuf::rt::read_singular_message_into(wire_type, is, &mut self.block)?; - }, - _ => { - ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; - }, - }; - } - ::std::result::Result::Ok(()) - } - - // Compute sizes of nested messages - #[allow(unused_variables)] - fn compute_size(&self) -> u32 { - let mut my_size = 0; - if let Some(ref v) = self.block.as_ref() { - let len = v.compute_size(); - my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; - } - my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); - self.cached_size.set(my_size); - my_size - } - - fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream) -> ::protobuf::ProtobufResult<()> { - if let Some(ref v) = self.block.as_ref() { - os.write_tag(1, ::protobuf::wire_format::WireTypeLengthDelimited)?; - os.write_raw_varint32(v.get_cached_size())?; - v.write_to_with_cached_sizes(os)?; - } - os.write_unknown_fields(self.get_unknown_fields())?; - ::std::result::Result::Ok(()) - } - - fn get_cached_size(&self) -> u32 { - self.cached_size.get() - } - - fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { - &self.unknown_fields - } - - fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { - &mut self.unknown_fields - } - - fn as_any(&self) -> &::std::any::Any { - self as &::std::any::Any - } - fn as_any_mut(&mut self) -> &mut ::std::any::Any { - self as &mut ::std::any::Any - } - fn into_any(self: Box) -> ::std::boxed::Box<::std::any::Any> { - self - } - - fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { - Self::descriptor_static() - } - - fn new() -> PublishBeaconBlockRequest { - PublishBeaconBlockRequest::new() - } - - fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { - static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::lazy::Lazy { - lock: ::protobuf::lazy::ONCE_INIT, - ptr: 0 as *const ::protobuf::reflect::MessageDescriptor, - }; - unsafe { - descriptor.get(|| { - let mut fields = ::std::vec::Vec::new(); - fields.push(::protobuf::reflect::accessor::make_singular_ptr_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( - "block", - |m: &PublishBeaconBlockRequest| { &m.block }, - |m: &mut PublishBeaconBlockRequest| { &mut m.block }, - )); - ::protobuf::reflect::MessageDescriptor::new::( - "PublishBeaconBlockRequest", - fields, - file_descriptor_proto() - ) - }) - } - } - - fn default_instance() -> &'static PublishBeaconBlockRequest { - static mut instance: ::protobuf::lazy::Lazy = ::protobuf::lazy::Lazy { - lock: ::protobuf::lazy::ONCE_INIT, - ptr: 0 as *const PublishBeaconBlockRequest, - }; - unsafe { - instance.get(PublishBeaconBlockRequest::new) - } - } -} - -impl ::protobuf::Clear for PublishBeaconBlockRequest { - fn clear(&mut self) { - self.clear_block(); - self.unknown_fields.clear(); - } -} - -impl ::std::fmt::Debug for PublishBeaconBlockRequest { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - ::protobuf::text_format::fmt(self, f) - } -} - -impl ::protobuf::reflect::ProtobufValue for PublishBeaconBlockRequest { - fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef { - ::protobuf::reflect::ProtobufValueRef::Message(self) - } -} - -#[derive(PartialEq,Clone,Default)] -pub struct PublishBeaconBlockResponse { - // message fields - pub success: bool, - pub msg: ::std::vec::Vec, - // special fields - unknown_fields: ::protobuf::UnknownFields, - cached_size: ::protobuf::CachedSize, -} - -impl PublishBeaconBlockResponse { - pub fn new() -> PublishBeaconBlockResponse { - ::std::default::Default::default() - } - - // bool success = 1; - - pub fn clear_success(&mut self) { - self.success = false; - } - - // Param is passed by value, moved - pub fn set_success(&mut self, v: bool) { - self.success = v; - } - - pub fn get_success(&self) -> bool { - self.success - } - - // bytes msg = 2; - - pub fn clear_msg(&mut self) { - self.msg.clear(); - } - - // Param is passed by value, moved - pub fn set_msg(&mut self, v: ::std::vec::Vec) { - self.msg = v; - } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_msg(&mut self) -> &mut ::std::vec::Vec { - &mut self.msg - } - - // Take field - pub fn take_msg(&mut self) -> ::std::vec::Vec { - ::std::mem::replace(&mut self.msg, ::std::vec::Vec::new()) - } - - pub fn get_msg(&self) -> &[u8] { - &self.msg - } -} - -impl ::protobuf::Message for PublishBeaconBlockResponse { - fn is_initialized(&self) -> bool { - true - } - - fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream) -> ::protobuf::ProtobufResult<()> { - while !is.eof()? { - let (field_number, wire_type) = is.read_tag_unpack()?; - match field_number { - 1 => { - if wire_type != ::protobuf::wire_format::WireTypeVarint { - return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); - } - let tmp = is.read_bool()?; - self.success = tmp; - }, - 2 => { - ::protobuf::rt::read_singular_proto3_bytes_into(wire_type, is, &mut self.msg)?; - }, - _ => { - ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; - }, - }; - } - ::std::result::Result::Ok(()) - } - - // Compute sizes of nested messages - #[allow(unused_variables)] - fn compute_size(&self) -> u32 { - let mut my_size = 0; - if self.success != false { - my_size += 2; - } - if !self.msg.is_empty() { - my_size += ::protobuf::rt::bytes_size(2, &self.msg); - } - my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); - self.cached_size.set(my_size); - my_size - } - - fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream) -> ::protobuf::ProtobufResult<()> { - if self.success != false { - os.write_bool(1, self.success)?; - } - if !self.msg.is_empty() { - os.write_bytes(2, &self.msg)?; - } - os.write_unknown_fields(self.get_unknown_fields())?; - ::std::result::Result::Ok(()) - } - - fn get_cached_size(&self) -> u32 { - self.cached_size.get() - } - - fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { - &self.unknown_fields - } - - fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { - &mut self.unknown_fields - } - - fn as_any(&self) -> &::std::any::Any { - self as &::std::any::Any - } - fn as_any_mut(&mut self) -> &mut ::std::any::Any { - self as &mut ::std::any::Any - } - fn into_any(self: Box) -> ::std::boxed::Box<::std::any::Any> { - self - } - - fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { - Self::descriptor_static() - } - - fn new() -> PublishBeaconBlockResponse { - PublishBeaconBlockResponse::new() - } - - fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { - static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::lazy::Lazy { - lock: ::protobuf::lazy::ONCE_INIT, - ptr: 0 as *const ::protobuf::reflect::MessageDescriptor, - }; - unsafe { - descriptor.get(|| { - let mut fields = ::std::vec::Vec::new(); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBool>( - "success", - |m: &PublishBeaconBlockResponse| { &m.success }, - |m: &mut PublishBeaconBlockResponse| { &mut m.success }, - )); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>( - "msg", - |m: &PublishBeaconBlockResponse| { &m.msg }, - |m: &mut PublishBeaconBlockResponse| { &mut m.msg }, - )); - ::protobuf::reflect::MessageDescriptor::new::( - "PublishBeaconBlockResponse", - fields, - file_descriptor_proto() - ) - }) - } - } - - fn default_instance() -> &'static PublishBeaconBlockResponse { - static mut instance: ::protobuf::lazy::Lazy = ::protobuf::lazy::Lazy { - lock: ::protobuf::lazy::ONCE_INIT, - ptr: 0 as *const PublishBeaconBlockResponse, - }; - unsafe { - instance.get(PublishBeaconBlockResponse::new) - } - } -} - -impl ::protobuf::Clear for PublishBeaconBlockResponse { - fn clear(&mut self) { - self.clear_success(); - self.clear_msg(); - self.unknown_fields.clear(); - } -} - -impl ::std::fmt::Debug for PublishBeaconBlockResponse { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - ::protobuf::text_format::fmt(self, f) - } -} - -impl ::protobuf::reflect::ProtobufValue for PublishBeaconBlockResponse { - fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef { - ::protobuf::reflect::ProtobufValueRef::Message(self) - } -} - -#[derive(PartialEq,Clone,Default)] -pub struct ValidatorAssignment { - // message oneof groups - pub block_production_slot_oneof: ::std::option::Option, - // special fields - unknown_fields: ::protobuf::UnknownFields, - cached_size: ::protobuf::CachedSize, -} - -#[derive(Clone,PartialEq)] -pub enum ValidatorAssignment_oneof_block_production_slot_oneof { - block_production_slot_none(bool), - block_production_slot(u64), -} - -impl ValidatorAssignment { - pub fn new() -> ValidatorAssignment { - ::std::default::Default::default() - } - - // bool block_production_slot_none = 1; - - pub fn clear_block_production_slot_none(&mut self) { - self.block_production_slot_oneof = ::std::option::Option::None; - } - - pub fn has_block_production_slot_none(&self) -> bool { - match self.block_production_slot_oneof { - ::std::option::Option::Some(ValidatorAssignment_oneof_block_production_slot_oneof::block_production_slot_none(..)) => true, - _ => false, - } - } - - // Param is passed by value, moved - pub fn set_block_production_slot_none(&mut self, v: bool) { - self.block_production_slot_oneof = ::std::option::Option::Some(ValidatorAssignment_oneof_block_production_slot_oneof::block_production_slot_none(v)) - } - - pub fn get_block_production_slot_none(&self) -> bool { - match self.block_production_slot_oneof { - ::std::option::Option::Some(ValidatorAssignment_oneof_block_production_slot_oneof::block_production_slot_none(v)) => v, - _ => false, - } - } - - // uint64 block_production_slot = 2; - - pub fn clear_block_production_slot(&mut self) { - self.block_production_slot_oneof = ::std::option::Option::None; - } - - pub fn has_block_production_slot(&self) -> bool { - match self.block_production_slot_oneof { - ::std::option::Option::Some(ValidatorAssignment_oneof_block_production_slot_oneof::block_production_slot(..)) => true, - _ => false, - } - } - - // Param is passed by value, moved - pub fn set_block_production_slot(&mut self, v: u64) { - self.block_production_slot_oneof = ::std::option::Option::Some(ValidatorAssignment_oneof_block_production_slot_oneof::block_production_slot(v)) - } - - pub fn get_block_production_slot(&self) -> u64 { - match self.block_production_slot_oneof { - ::std::option::Option::Some(ValidatorAssignment_oneof_block_production_slot_oneof::block_production_slot(v)) => v, - _ => 0, - } - } -} - -impl ::protobuf::Message for ValidatorAssignment { - fn is_initialized(&self) -> bool { - true - } - - fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream) -> ::protobuf::ProtobufResult<()> { - while !is.eof()? { - let (field_number, wire_type) = is.read_tag_unpack()?; - match field_number { - 1 => { - if wire_type != ::protobuf::wire_format::WireTypeVarint { - return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); - } - self.block_production_slot_oneof = ::std::option::Option::Some(ValidatorAssignment_oneof_block_production_slot_oneof::block_production_slot_none(is.read_bool()?)); - }, - 2 => { - if wire_type != ::protobuf::wire_format::WireTypeVarint { - return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); - } - self.block_production_slot_oneof = ::std::option::Option::Some(ValidatorAssignment_oneof_block_production_slot_oneof::block_production_slot(is.read_uint64()?)); - }, - _ => { - ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; - }, - }; - } - ::std::result::Result::Ok(()) - } - - // Compute sizes of nested messages - #[allow(unused_variables)] - fn compute_size(&self) -> u32 { - let mut my_size = 0; - if let ::std::option::Option::Some(ref v) = self.block_production_slot_oneof { - match v { - &ValidatorAssignment_oneof_block_production_slot_oneof::block_production_slot_none(v) => { - my_size += 2; - }, - &ValidatorAssignment_oneof_block_production_slot_oneof::block_production_slot(v) => { - my_size += ::protobuf::rt::value_size(2, v, ::protobuf::wire_format::WireTypeVarint); - }, - }; - } - my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); - self.cached_size.set(my_size); - my_size - } - - fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream) -> ::protobuf::ProtobufResult<()> { - if let ::std::option::Option::Some(ref v) = self.block_production_slot_oneof { - match v { - &ValidatorAssignment_oneof_block_production_slot_oneof::block_production_slot_none(v) => { - os.write_bool(1, v)?; - }, - &ValidatorAssignment_oneof_block_production_slot_oneof::block_production_slot(v) => { - os.write_uint64(2, v)?; - }, - }; - } - os.write_unknown_fields(self.get_unknown_fields())?; - ::std::result::Result::Ok(()) - } - - fn get_cached_size(&self) -> u32 { - self.cached_size.get() - } - - fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { - &self.unknown_fields - } - - fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { - &mut self.unknown_fields - } - - fn as_any(&self) -> &::std::any::Any { - self as &::std::any::Any - } - fn as_any_mut(&mut self) -> &mut ::std::any::Any { - self as &mut ::std::any::Any - } - fn into_any(self: Box) -> ::std::boxed::Box<::std::any::Any> { - self - } - - fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { - Self::descriptor_static() - } - - fn new() -> ValidatorAssignment { - ValidatorAssignment::new() - } - - fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { - static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::lazy::Lazy { - lock: ::protobuf::lazy::ONCE_INIT, - ptr: 0 as *const ::protobuf::reflect::MessageDescriptor, - }; - unsafe { - descriptor.get(|| { - let mut fields = ::std::vec::Vec::new(); - fields.push(::protobuf::reflect::accessor::make_singular_bool_accessor::<_>( - "block_production_slot_none", - ValidatorAssignment::has_block_production_slot_none, - ValidatorAssignment::get_block_production_slot_none, - )); - fields.push(::protobuf::reflect::accessor::make_singular_u64_accessor::<_>( - "block_production_slot", - ValidatorAssignment::has_block_production_slot, - ValidatorAssignment::get_block_production_slot, - )); - ::protobuf::reflect::MessageDescriptor::new::( - "ValidatorAssignment", - fields, - file_descriptor_proto() - ) - }) - } - } - - fn default_instance() -> &'static ValidatorAssignment { - static mut instance: ::protobuf::lazy::Lazy = ::protobuf::lazy::Lazy { - lock: ::protobuf::lazy::ONCE_INIT, - ptr: 0 as *const ValidatorAssignment, - }; - unsafe { - instance.get(ValidatorAssignment::new) - } - } -} - -impl ::protobuf::Clear for ValidatorAssignment { - fn clear(&mut self) { - self.clear_block_production_slot_none(); - self.clear_block_production_slot(); - self.unknown_fields.clear(); - } -} - -impl ::std::fmt::Debug for ValidatorAssignment { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - ::protobuf::text_format::fmt(self, f) - } -} - -impl ::protobuf::reflect::ProtobufValue for ValidatorAssignment { - fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef { - ::protobuf::reflect::ProtobufValueRef::Message(self) - } -} - -#[derive(PartialEq,Clone,Default)] -pub struct ValidatorAssignmentRequest { - // message fields - pub epoch: u64, - pub public_key: ::std::vec::Vec, - // special fields - unknown_fields: ::protobuf::UnknownFields, - cached_size: ::protobuf::CachedSize, -} - -impl ValidatorAssignmentRequest { - pub fn new() -> ValidatorAssignmentRequest { - ::std::default::Default::default() - } - - // uint64 epoch = 1; - - pub fn clear_epoch(&mut self) { - self.epoch = 0; - } - - // Param is passed by value, moved - pub fn set_epoch(&mut self, v: u64) { - self.epoch = v; - } - - pub fn get_epoch(&self) -> u64 { - self.epoch - } - - // bytes public_key = 2; - - pub fn clear_public_key(&mut self) { - self.public_key.clear(); - } - - // Param is passed by value, moved - pub fn set_public_key(&mut self, v: ::std::vec::Vec) { - self.public_key = v; - } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_public_key(&mut self) -> &mut ::std::vec::Vec { - &mut self.public_key - } - - // Take field - pub fn take_public_key(&mut self) -> ::std::vec::Vec { - ::std::mem::replace(&mut self.public_key, ::std::vec::Vec::new()) - } - - pub fn get_public_key(&self) -> &[u8] { - &self.public_key - } -} - -impl ::protobuf::Message for ValidatorAssignmentRequest { - fn is_initialized(&self) -> bool { - true - } - - fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream) -> ::protobuf::ProtobufResult<()> { - while !is.eof()? { - let (field_number, wire_type) = is.read_tag_unpack()?; - match field_number { - 1 => { - if wire_type != ::protobuf::wire_format::WireTypeVarint { - return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); - } - let tmp = is.read_uint64()?; - self.epoch = tmp; - }, - 2 => { - ::protobuf::rt::read_singular_proto3_bytes_into(wire_type, is, &mut self.public_key)?; - }, - _ => { - ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; - }, - }; - } - ::std::result::Result::Ok(()) - } - - // Compute sizes of nested messages - #[allow(unused_variables)] - fn compute_size(&self) -> u32 { - let mut my_size = 0; - if self.epoch != 0 { - my_size += ::protobuf::rt::value_size(1, self.epoch, ::protobuf::wire_format::WireTypeVarint); - } - if !self.public_key.is_empty() { - my_size += ::protobuf::rt::bytes_size(2, &self.public_key); - } - my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); - self.cached_size.set(my_size); - my_size - } - - fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream) -> ::protobuf::ProtobufResult<()> { - if self.epoch != 0 { - os.write_uint64(1, self.epoch)?; - } - if !self.public_key.is_empty() { - os.write_bytes(2, &self.public_key)?; - } - os.write_unknown_fields(self.get_unknown_fields())?; - ::std::result::Result::Ok(()) - } - - fn get_cached_size(&self) -> u32 { - self.cached_size.get() - } - - fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { - &self.unknown_fields - } - - fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { - &mut self.unknown_fields - } - - fn as_any(&self) -> &::std::any::Any { - self as &::std::any::Any - } - fn as_any_mut(&mut self) -> &mut ::std::any::Any { - self as &mut ::std::any::Any - } - fn into_any(self: Box) -> ::std::boxed::Box<::std::any::Any> { - self - } - - fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { - Self::descriptor_static() - } - - fn new() -> ValidatorAssignmentRequest { - ValidatorAssignmentRequest::new() - } - - fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { - static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::lazy::Lazy { - lock: ::protobuf::lazy::ONCE_INIT, - ptr: 0 as *const ::protobuf::reflect::MessageDescriptor, - }; - unsafe { - descriptor.get(|| { - let mut fields = ::std::vec::Vec::new(); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeUint64>( - "epoch", - |m: &ValidatorAssignmentRequest| { &m.epoch }, - |m: &mut ValidatorAssignmentRequest| { &mut m.epoch }, - )); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>( - "public_key", - |m: &ValidatorAssignmentRequest| { &m.public_key }, - |m: &mut ValidatorAssignmentRequest| { &mut m.public_key }, - )); - ::protobuf::reflect::MessageDescriptor::new::( - "ValidatorAssignmentRequest", - fields, - file_descriptor_proto() - ) - }) - } - } - - fn default_instance() -> &'static ValidatorAssignmentRequest { - static mut instance: ::protobuf::lazy::Lazy = ::protobuf::lazy::Lazy { - lock: ::protobuf::lazy::ONCE_INIT, - ptr: 0 as *const ValidatorAssignmentRequest, - }; - unsafe { - instance.get(ValidatorAssignmentRequest::new) - } - } -} - -impl ::protobuf::Clear for ValidatorAssignmentRequest { - fn clear(&mut self) { - self.clear_epoch(); - self.clear_public_key(); - self.unknown_fields.clear(); - } -} - -impl ::std::fmt::Debug for ValidatorAssignmentRequest { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - ::protobuf::text_format::fmt(self, f) - } -} - -impl ::protobuf::reflect::ProtobufValue for ValidatorAssignmentRequest { - fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef { - ::protobuf::reflect::ProtobufValueRef::Message(self) - } -} - -#[derive(PartialEq,Clone,Default)] -pub struct ValidatorAssignmentResponse { - // message fields - pub validator_assignment: ::protobuf::SingularPtrField, - // special fields - unknown_fields: ::protobuf::UnknownFields, - cached_size: ::protobuf::CachedSize, -} - -impl ValidatorAssignmentResponse { - pub fn new() -> ValidatorAssignmentResponse { - ::std::default::Default::default() - } - - // .ethereum.beacon.rpc.v1.ValidatorAssignment validator_assignment = 1; - - pub fn clear_validator_assignment(&mut self) { - self.validator_assignment.clear(); - } - - pub fn has_validator_assignment(&self) -> bool { - self.validator_assignment.is_some() - } - - // Param is passed by value, moved - pub fn set_validator_assignment(&mut self, v: ValidatorAssignment) { - self.validator_assignment = ::protobuf::SingularPtrField::some(v); - } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_validator_assignment(&mut self) -> &mut ValidatorAssignment { - if self.validator_assignment.is_none() { - self.validator_assignment.set_default(); - } - self.validator_assignment.as_mut().unwrap() - } - - // Take field - pub fn take_validator_assignment(&mut self) -> ValidatorAssignment { - self.validator_assignment.take().unwrap_or_else(|| ValidatorAssignment::new()) - } - - pub fn get_validator_assignment(&self) -> &ValidatorAssignment { - self.validator_assignment.as_ref().unwrap_or_else(|| ValidatorAssignment::default_instance()) - } -} - -impl ::protobuf::Message for ValidatorAssignmentResponse { - fn is_initialized(&self) -> bool { - for v in &self.validator_assignment { - if !v.is_initialized() { - return false; - } - }; - true - } - - fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream) -> ::protobuf::ProtobufResult<()> { - while !is.eof()? { - let (field_number, wire_type) = is.read_tag_unpack()?; - match field_number { - 1 => { - ::protobuf::rt::read_singular_message_into(wire_type, is, &mut self.validator_assignment)?; - }, - _ => { - ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; - }, - }; - } - ::std::result::Result::Ok(()) - } - - // Compute sizes of nested messages - #[allow(unused_variables)] - fn compute_size(&self) -> u32 { - let mut my_size = 0; - if let Some(ref v) = self.validator_assignment.as_ref() { - let len = v.compute_size(); - my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; - } - my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); - self.cached_size.set(my_size); - my_size - } - - fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream) -> ::protobuf::ProtobufResult<()> { - if let Some(ref v) = self.validator_assignment.as_ref() { - os.write_tag(1, ::protobuf::wire_format::WireTypeLengthDelimited)?; - os.write_raw_varint32(v.get_cached_size())?; - v.write_to_with_cached_sizes(os)?; - } - os.write_unknown_fields(self.get_unknown_fields())?; - ::std::result::Result::Ok(()) - } - - fn get_cached_size(&self) -> u32 { - self.cached_size.get() - } - - fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { - &self.unknown_fields - } - - fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { - &mut self.unknown_fields - } - - fn as_any(&self) -> &::std::any::Any { - self as &::std::any::Any - } - fn as_any_mut(&mut self) -> &mut ::std::any::Any { - self as &mut ::std::any::Any - } - fn into_any(self: Box) -> ::std::boxed::Box<::std::any::Any> { - self - } - - fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { - Self::descriptor_static() - } - - fn new() -> ValidatorAssignmentResponse { - ValidatorAssignmentResponse::new() - } - - fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { - static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::lazy::Lazy { - lock: ::protobuf::lazy::ONCE_INIT, - ptr: 0 as *const ::protobuf::reflect::MessageDescriptor, - }; - unsafe { - descriptor.get(|| { - let mut fields = ::std::vec::Vec::new(); - fields.push(::protobuf::reflect::accessor::make_singular_ptr_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( - "validator_assignment", - |m: &ValidatorAssignmentResponse| { &m.validator_assignment }, - |m: &mut ValidatorAssignmentResponse| { &mut m.validator_assignment }, - )); - ::protobuf::reflect::MessageDescriptor::new::( - "ValidatorAssignmentResponse", - fields, - file_descriptor_proto() - ) - }) - } - } - - fn default_instance() -> &'static ValidatorAssignmentResponse { - static mut instance: ::protobuf::lazy::Lazy = ::protobuf::lazy::Lazy { - lock: ::protobuf::lazy::ONCE_INIT, - ptr: 0 as *const ValidatorAssignmentResponse, - }; - unsafe { - instance.get(ValidatorAssignmentResponse::new) - } - } -} - -impl ::protobuf::Clear for ValidatorAssignmentResponse { - fn clear(&mut self) { - self.clear_validator_assignment(); - self.unknown_fields.clear(); - } -} - -impl ::std::fmt::Debug for ValidatorAssignmentResponse { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - ::protobuf::text_format::fmt(self, f) - } -} - -impl ::protobuf::reflect::ProtobufValue for ValidatorAssignmentResponse { - fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef { - ::protobuf::reflect::ProtobufValueRef::Message(self) - } -} - -static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x0eservices.proto\x12\x16ethereum.beacon.rpc.v1\"\x83\x01\n\x0bBeacon\ - Block\x12\x12\n\x04slot\x18\x01\x20\x01(\x04R\x04slot\x12\x1d\n\nblock_r\ - oot\x18\x02\x20\x01(\x0cR\tblockRoot\x12#\n\rrandao_reveal\x18\x03\x20\ - \x01(\x0cR\x0crandaoReveal\x12\x1c\n\tsignature\x18\x04\x20\x01(\x0cR\ts\ - ignature\"/\n\x19ProduceBeaconBlockRequest\x12\x12\n\x04slot\x18\x01\x20\ - \x01(\x04R\x04slot\"W\n\x1aProduceBeaconBlockResponse\x129\n\x05block\ - \x18\x01\x20\x01(\x0b2#.ethereum.beacon.rpc.v1.BeaconBlockR\x05block\"V\ - \n\x19PublishBeaconBlockRequest\x129\n\x05block\x18\x01\x20\x01(\x0b2#.e\ - thereum.beacon.rpc.v1.BeaconBlockR\x05block\"H\n\x1aPublishBeaconBlockRe\ - sponse\x12\x18\n\x07success\x18\x01\x20\x01(\x08R\x07success\x12\x10\n\ - \x03msg\x18\x02\x20\x01(\x0cR\x03msg\"\xa9\x01\n\x13ValidatorAssignment\ - \x12=\n\x1ablock_production_slot_none\x18\x01\x20\x01(\x08H\0R\x17blockP\ - roductionSlotNone\x124\n\x15block_production_slot\x18\x02\x20\x01(\x04H\ - \0R\x13blockProductionSlotB\x1d\n\x1bblock_production_slot_oneof\"Q\n\ - \x1aValidatorAssignmentRequest\x12\x14\n\x05epoch\x18\x01\x20\x01(\x04R\ - \x05epoch\x12\x1d\n\npublic_key\x18\x02\x20\x01(\x0cR\tpublicKey\"}\n\ - \x1bValidatorAssignmentResponse\x12^\n\x14validator_assignment\x18\x01\ - \x20\x01(\x0b2+.ethereum.beacon.rpc.v1.ValidatorAssignmentR\x13validator\ - Assignment2\x8e\x03\n\x12BeaconBlockService\x12{\n\x12ProduceBeaconBlock\ - \x121.ethereum.beacon.rpc.v1.ProduceBeaconBlockRequest\x1a2.ethereum.bea\ - con.rpc.v1.ProduceBeaconBlockResponse\x12{\n\x12PublishBeaconBlock\x121.\ - ethereum.beacon.rpc.v1.PublishBeaconBlockRequest\x1a2.ethereum.beacon.rp\ - c.v1.PublishBeaconBlockResponse\x12~\n\x13ValidatorAssignment\x122.ether\ - eum.beacon.rpc.v1.ValidatorAssignmentRequest\x1a3.ethereum.beacon.rpc.v1\ - .ValidatorAssignmentResponseb\x06proto3\ -"; - -static mut file_descriptor_proto_lazy: ::protobuf::lazy::Lazy<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::lazy::Lazy { - lock: ::protobuf::lazy::ONCE_INIT, - ptr: 0 as *const ::protobuf::descriptor::FileDescriptorProto, -}; - -fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto { - ::protobuf::parse_from_bytes(file_descriptor_proto_data).unwrap() -} - -pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto { - unsafe { - file_descriptor_proto_lazy.get(|| { - parse_descriptor_proto() - }) - } -} diff --git a/protos/src/services_grpc.rs b/protos/src/services_grpc.rs deleted file mode 100644 index 2103f73c4..000000000 --- a/protos/src/services_grpc.rs +++ /dev/null @@ -1,127 +0,0 @@ -// This file is generated. Do not edit -// @generated - -// https://github.com/Manishearth/rust-clippy/issues/702 -#![allow(unknown_lints)] -#![allow(clippy)] - -#![cfg_attr(rustfmt, rustfmt_skip)] - -#![allow(box_pointers)] -#![allow(dead_code)] -#![allow(missing_docs)] -#![allow(non_camel_case_types)] -#![allow(non_snake_case)] -#![allow(non_upper_case_globals)] -#![allow(trivial_casts)] -#![allow(unsafe_code)] -#![allow(unused_imports)] -#![allow(unused_results)] - -const METHOD_BEACON_BLOCK_SERVICE_PRODUCE_BEACON_BLOCK: ::grpcio::Method = ::grpcio::Method { - ty: ::grpcio::MethodType::Unary, - name: "/ethereum.beacon.rpc.v1.BeaconBlockService/ProduceBeaconBlock", - req_mar: ::grpcio::Marshaller { ser: ::grpcio::pb_ser, de: ::grpcio::pb_de }, - resp_mar: ::grpcio::Marshaller { ser: ::grpcio::pb_ser, de: ::grpcio::pb_de }, -}; - -const METHOD_BEACON_BLOCK_SERVICE_PUBLISH_BEACON_BLOCK: ::grpcio::Method = ::grpcio::Method { - ty: ::grpcio::MethodType::Unary, - name: "/ethereum.beacon.rpc.v1.BeaconBlockService/PublishBeaconBlock", - req_mar: ::grpcio::Marshaller { ser: ::grpcio::pb_ser, de: ::grpcio::pb_de }, - resp_mar: ::grpcio::Marshaller { ser: ::grpcio::pb_ser, de: ::grpcio::pb_de }, -}; - -const METHOD_BEACON_BLOCK_SERVICE_VALIDATOR_ASSIGNMENT: ::grpcio::Method = ::grpcio::Method { - ty: ::grpcio::MethodType::Unary, - name: "/ethereum.beacon.rpc.v1.BeaconBlockService/ValidatorAssignment", - req_mar: ::grpcio::Marshaller { ser: ::grpcio::pb_ser, de: ::grpcio::pb_de }, - resp_mar: ::grpcio::Marshaller { ser: ::grpcio::pb_ser, de: ::grpcio::pb_de }, -}; - -#[derive(Clone)] -pub struct BeaconBlockServiceClient { - client: ::grpcio::Client, -} - -impl BeaconBlockServiceClient { - pub fn new(channel: ::grpcio::Channel) -> Self { - BeaconBlockServiceClient { - client: ::grpcio::Client::new(channel), - } - } - - pub fn produce_beacon_block_opt(&self, req: &super::services::ProduceBeaconBlockRequest, opt: ::grpcio::CallOption) -> ::grpcio::Result { - self.client.unary_call(&METHOD_BEACON_BLOCK_SERVICE_PRODUCE_BEACON_BLOCK, req, opt) - } - - pub fn produce_beacon_block(&self, req: &super::services::ProduceBeaconBlockRequest) -> ::grpcio::Result { - self.produce_beacon_block_opt(req, ::grpcio::CallOption::default()) - } - - pub fn produce_beacon_block_async_opt(&self, req: &super::services::ProduceBeaconBlockRequest, opt: ::grpcio::CallOption) -> ::grpcio::Result<::grpcio::ClientUnaryReceiver> { - self.client.unary_call_async(&METHOD_BEACON_BLOCK_SERVICE_PRODUCE_BEACON_BLOCK, req, opt) - } - - pub fn produce_beacon_block_async(&self, req: &super::services::ProduceBeaconBlockRequest) -> ::grpcio::Result<::grpcio::ClientUnaryReceiver> { - self.produce_beacon_block_async_opt(req, ::grpcio::CallOption::default()) - } - - pub fn publish_beacon_block_opt(&self, req: &super::services::PublishBeaconBlockRequest, opt: ::grpcio::CallOption) -> ::grpcio::Result { - self.client.unary_call(&METHOD_BEACON_BLOCK_SERVICE_PUBLISH_BEACON_BLOCK, req, opt) - } - - pub fn publish_beacon_block(&self, req: &super::services::PublishBeaconBlockRequest) -> ::grpcio::Result { - self.publish_beacon_block_opt(req, ::grpcio::CallOption::default()) - } - - pub fn publish_beacon_block_async_opt(&self, req: &super::services::PublishBeaconBlockRequest, opt: ::grpcio::CallOption) -> ::grpcio::Result<::grpcio::ClientUnaryReceiver> { - self.client.unary_call_async(&METHOD_BEACON_BLOCK_SERVICE_PUBLISH_BEACON_BLOCK, req, opt) - } - - pub fn publish_beacon_block_async(&self, req: &super::services::PublishBeaconBlockRequest) -> ::grpcio::Result<::grpcio::ClientUnaryReceiver> { - self.publish_beacon_block_async_opt(req, ::grpcio::CallOption::default()) - } - - pub fn validator_assignment_opt(&self, req: &super::services::ValidatorAssignmentRequest, opt: ::grpcio::CallOption) -> ::grpcio::Result { - self.client.unary_call(&METHOD_BEACON_BLOCK_SERVICE_VALIDATOR_ASSIGNMENT, req, opt) - } - - pub fn validator_assignment(&self, req: &super::services::ValidatorAssignmentRequest) -> ::grpcio::Result { - self.validator_assignment_opt(req, ::grpcio::CallOption::default()) - } - - pub fn validator_assignment_async_opt(&self, req: &super::services::ValidatorAssignmentRequest, opt: ::grpcio::CallOption) -> ::grpcio::Result<::grpcio::ClientUnaryReceiver> { - self.client.unary_call_async(&METHOD_BEACON_BLOCK_SERVICE_VALIDATOR_ASSIGNMENT, req, opt) - } - - pub fn validator_assignment_async(&self, req: &super::services::ValidatorAssignmentRequest) -> ::grpcio::Result<::grpcio::ClientUnaryReceiver> { - self.validator_assignment_async_opt(req, ::grpcio::CallOption::default()) - } - pub fn spawn(&self, f: F) where F: ::futures::Future + Send + 'static { - self.client.spawn(f) - } -} - -pub trait BeaconBlockService { - fn produce_beacon_block(&mut self, ctx: ::grpcio::RpcContext, req: super::services::ProduceBeaconBlockRequest, sink: ::grpcio::UnarySink); - fn publish_beacon_block(&mut self, ctx: ::grpcio::RpcContext, req: super::services::PublishBeaconBlockRequest, sink: ::grpcio::UnarySink); - fn validator_assignment(&mut self, ctx: ::grpcio::RpcContext, req: super::services::ValidatorAssignmentRequest, sink: ::grpcio::UnarySink); -} - -pub fn create_beacon_block_service(s: S) -> ::grpcio::Service { - let mut builder = ::grpcio::ServiceBuilder::new(); - let mut instance = s.clone(); - builder = builder.add_unary_handler(&METHOD_BEACON_BLOCK_SERVICE_PRODUCE_BEACON_BLOCK, move |ctx, req, resp| { - instance.produce_beacon_block(ctx, req, resp) - }); - let mut instance = s.clone(); - builder = builder.add_unary_handler(&METHOD_BEACON_BLOCK_SERVICE_PUBLISH_BEACON_BLOCK, move |ctx, req, resp| { - instance.publish_beacon_block(ctx, req, resp) - }); - let mut instance = s.clone(); - builder = builder.add_unary_handler(&METHOD_BEACON_BLOCK_SERVICE_VALIDATOR_ASSIGNMENT, move |ctx, req, resp| { - instance.validator_assignment(ctx, req, resp) - }); - builder.build() -} From c8fc92e63ebc012f908d8b0d59cb9166e7652b4f Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Mon, 21 Jan 2019 18:52:22 +1100 Subject: [PATCH 14/28] Add description to `protos` crate. --- protos/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/protos/Cargo.toml b/protos/Cargo.toml index 8a2bf6245..92a33c1f4 100644 --- a/protos/Cargo.toml +++ b/protos/Cargo.toml @@ -3,6 +3,7 @@ name = "protos" version = "0.1.0" authors = ["Paul Hauner "] edition = "2018" +description = "Google protobuf message and service definitions used in Lighthouse APIs." [dependencies] futures = "0.1.16" From ad6ae2167657f099df5509d8d9bc622b2e840d43 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Mon, 21 Jan 2019 19:37:30 +1100 Subject: [PATCH 15/28] Remove PATCH versions from cargo deps --- protos/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/protos/Cargo.toml b/protos/Cargo.toml index 92a33c1f4..56364d188 100644 --- a/protos/Cargo.toml +++ b/protos/Cargo.toml @@ -6,9 +6,9 @@ edition = "2018" description = "Google protobuf message and service definitions used in Lighthouse APIs." [dependencies] -futures = "0.1.16" +futures = "0.1" grpcio = { version = "0.4", default-features = false, features = ["protobuf-codec"] } -protobuf = "2.0.2" +protobuf = "2.0" [build-dependencies] protoc-grpcio = "0.3.1" From 158ffd7d1c004767a9c169a93bd9de5765f82eb1 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Mon, 21 Jan 2019 19:38:28 +1100 Subject: [PATCH 16/28] Separate validator fns into new proto service --- protos/src/services.proto | 3 +++ validator_client/src/duties/grpc.rs | 4 ++-- validator_client/src/main.rs | 23 ++++++++++++++++------- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/protos/src/services.proto b/protos/src/services.proto index 6d1d8f911..216ef7b2f 100644 --- a/protos/src/services.proto +++ b/protos/src/services.proto @@ -15,6 +15,9 @@ package ethereum.beacon.rpc.v1; service BeaconBlockService { rpc ProduceBeaconBlock(ProduceBeaconBlockRequest) returns (ProduceBeaconBlockResponse); rpc PublishBeaconBlock(PublishBeaconBlockRequest) returns (PublishBeaconBlockResponse); +} + +service ValidatorService { rpc ValidatorAssignment(ValidatorAssignmentRequest) returns (ValidatorAssignmentResponse); } diff --git a/validator_client/src/duties/grpc.rs b/validator_client/src/duties/grpc.rs index c5d817dd7..4b9c8288e 100644 --- a/validator_client/src/duties/grpc.rs +++ b/validator_client/src/duties/grpc.rs @@ -1,11 +1,11 @@ use super::traits::{BeaconNode, BeaconNodeError}; use super::EpochDuties; use protos::services::ValidatorAssignmentRequest; -use protos::services_grpc::BeaconBlockServiceClient; +use protos::services_grpc::ValidatorServiceClient; use ssz::ssz_encode; use types::PublicKey; -impl BeaconNode for BeaconBlockServiceClient { +impl BeaconNode for ValidatorServiceClient { fn request_shuffling( &self, epoch: u64, diff --git a/validator_client/src/main.rs b/validator_client/src/main.rs index 63d2137b2..6210557dd 100644 --- a/validator_client/src/main.rs +++ b/validator_client/src/main.rs @@ -4,7 +4,7 @@ use crate::config::ClientConfig; use bls::Keypair; use clap::{App, Arg}; use grpcio::{ChannelBuilder, EnvBuilder}; -use protos::services_grpc::BeaconBlockServiceClient; +use protos::services_grpc::{BeaconBlockServiceClient, ValidatorServiceClient}; use slog::{error, info, o, Drain}; use slot_clock::SystemTimeSlotClock; use spec::ChainSpec; @@ -66,10 +66,19 @@ fn main() { "data_dir" => &config.data_dir.to_str(), "server" => &config.server); - // gRPC - let env = Arc::new(EnvBuilder::new().build()); - let ch = ChannelBuilder::new(env).connect(&config.server); - let client = Arc::new(BeaconBlockServiceClient::new(ch)); + // Beacon node gRPC beacon block endpoints. + let beacon_block_grpc_client = { + let env = Arc::new(EnvBuilder::new().build()); + let ch = ChannelBuilder::new(env).connect(&config.server); + Arc::new(BeaconBlockServiceClient::new(ch)) + }; + + // Beacon node gRPC validator endpoints. + let validator_grpc_client = { + let env = Arc::new(EnvBuilder::new().build()); + let ch = ChannelBuilder::new(env).connect(&config.server); + Arc::new(ValidatorServiceClient::new(ch)) + }; // Ethereum // @@ -101,7 +110,7 @@ fn main() { let duties_map = duties_map.clone(); let slot_clock = slot_clock.clone(); let log = log.clone(); - let beacon_node = client.clone(); + let beacon_node = validator_grpc_client.clone(); let pubkey = keypair.pk.clone(); thread::spawn(move || { let manager = DutiesManager { @@ -126,7 +135,7 @@ fn main() { let duties_map = duties_map.clone(); let slot_clock = slot_clock.clone(); let log = log.clone(); - let client = client.clone(); + let client = beacon_block_grpc_client.clone(); thread::spawn(move || { let block_producer = BlockProducer::new(spec, duties_map, slot_clock, client); let mut block_producer_service = BlockProducerService { From b8ba0cd6982af9b0a1e6b82cd7ab8a796f82f15c Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Mon, 21 Jan 2019 22:10:43 +1100 Subject: [PATCH 17/28] Split out validator index gRPC call --- beacon_node/src/rpc/beacon_block.rs | 57 ++++++++++++++++++ beacon_node/src/rpc/mod.rs | 81 ++++++-------------------- beacon_node/src/rpc/validator.rs | 52 +++++++++++++++++ protos/src/services.proto | 36 ++++++++++-- validator_client/src/duties/grpc.rs | 45 +++++++------- validator_client/src/duties/mod.rs | 19 +++--- validator_client/src/duties/service.rs | 16 +++-- 7 files changed, 206 insertions(+), 100 deletions(-) create mode 100644 beacon_node/src/rpc/beacon_block.rs create mode 100644 beacon_node/src/rpc/validator.rs diff --git a/beacon_node/src/rpc/beacon_block.rs b/beacon_node/src/rpc/beacon_block.rs new file mode 100644 index 000000000..a047365ef --- /dev/null +++ b/beacon_node/src/rpc/beacon_block.rs @@ -0,0 +1,57 @@ +use futures::Future; +use grpcio::{RpcContext, UnarySink}; +use protos::services::{ + BeaconBlock as BeaconBlockProto, ProduceBeaconBlockRequest, ProduceBeaconBlockResponse, + PublishBeaconBlockRequest, PublishBeaconBlockResponse, +}; +use protos::services_grpc::BeaconBlockService; +use slog::Logger; + +#[derive(Clone)] +pub struct BeaconBlockServiceInstance { + pub log: Logger, +} + +impl BeaconBlockService for BeaconBlockServiceInstance { + /// Produce a `BeaconBlock` for signing by a validator. + fn produce_beacon_block( + &mut self, + ctx: RpcContext, + req: ProduceBeaconBlockRequest, + sink: UnarySink, + ) { + println!("producing at slot {}", req.get_slot()); + + // TODO: build a legit block. + let mut block = BeaconBlockProto::new(); + block.set_slot(req.get_slot()); + block.set_block_root("cats".as_bytes().to_vec()); + + let mut resp = ProduceBeaconBlockResponse::new(); + resp.set_block(block); + + let f = sink + .success(resp) + .map_err(move |e| println!("failed to reply {:?}: {:?}", req, e)); + ctx.spawn(f) + } + + /// Accept some fully-formed `BeaconBlock`, process and publish it. + fn publish_beacon_block( + &mut self, + ctx: RpcContext, + req: PublishBeaconBlockRequest, + sink: UnarySink, + ) { + println!("publishing {:?}", req.get_block()); + + // TODO: actually process the block. + let mut resp = PublishBeaconBlockResponse::new(); + resp.set_success(true); + + let f = sink + .success(resp) + .map_err(move |e| println!("failed to reply {:?}: {:?}", req, e)); + ctx.spawn(f) + } +} diff --git a/beacon_node/src/rpc/mod.rs b/beacon_node/src/rpc/mod.rs index 38fc049c7..6a18a4aa8 100644 --- a/beacon_node/src/rpc/mod.rs +++ b/beacon_node/src/rpc/mod.rs @@ -1,73 +1,30 @@ +mod beacon_block; +mod validator; + +use self::beacon_block::BeaconBlockServiceInstance; +use self::validator::ValidatorServiceInstance; +use grpcio::{Environment, Server, ServerBuilder}; +use protos::services_grpc::{create_beacon_block_service, create_validator_service}; use std::sync::Arc; -use futures::Future; -use grpcio::{Environment, RpcContext, Server, ServerBuilder, UnarySink}; - -use protos::services::{ - BeaconBlock as BeaconBlockProto, ProduceBeaconBlockRequest, ProduceBeaconBlockResponse, - PublishBeaconBlockRequest, PublishBeaconBlockResponse, -}; -use protos::services_grpc::{create_beacon_block_service, BeaconBlockService}; - use slog::{info, Logger}; -#[derive(Clone)] -struct BeaconBlockServiceInstance { - log: Logger, -} - -impl BeaconBlockService for BeaconBlockServiceInstance { - /// Produce a `BeaconBlock` for signing by a validator. - fn produce_beacon_block( - &mut self, - ctx: RpcContext, - req: ProduceBeaconBlockRequest, - sink: UnarySink, - ) { - println!("producing at slot {}", req.get_slot()); - - // TODO: build a legit block. - let mut block = BeaconBlockProto::new(); - block.set_slot(req.get_slot()); - block.set_block_root("cats".as_bytes().to_vec()); - - let mut resp = ProduceBeaconBlockResponse::new(); - resp.set_block(block); - - let f = sink - .success(resp) - .map_err(move |e| println!("failed to reply {:?}: {:?}", req, e)); - ctx.spawn(f) - } - - /// Accept some fully-formed `BeaconBlock`, process and publish it. - fn publish_beacon_block( - &mut self, - ctx: RpcContext, - req: PublishBeaconBlockRequest, - sink: UnarySink, - ) { - println!("publishing {:?}", req.get_block()); - - // TODO: actually process the block. - let mut resp = PublishBeaconBlockResponse::new(); - resp.set_success(true); - - let f = sink - .success(resp) - .map_err(move |e| println!("failed to reply {:?}: {:?}", req, e)); - ctx.spawn(f) - } -} - pub fn start_server(log: Logger) -> Server { let log_clone = log.clone(); - let env = Arc::new(Environment::new(1)); - let instance = BeaconBlockServiceInstance { log }; - let service = create_beacon_block_service(instance); + + let beacon_block_service = { + let instance = BeaconBlockServiceInstance { log: log.clone() }; + create_beacon_block_service(instance) + }; + let validator_service = { + let instance = ValidatorServiceInstance { log: log.clone() }; + create_validator_service(instance) + }; + let mut server = ServerBuilder::new(env) - .register_service(service) + .register_service(beacon_block_service) + .register_service(validator_service) .bind("127.0.0.1", 50_051) .build() .unwrap(); diff --git a/beacon_node/src/rpc/validator.rs b/beacon_node/src/rpc/validator.rs new file mode 100644 index 000000000..f0c828872 --- /dev/null +++ b/beacon_node/src/rpc/validator.rs @@ -0,0 +1,52 @@ +use futures::Future; +use grpcio::{RpcContext, UnarySink}; +use protos::services::{ + IndexResponse, ProposeBlockSlotRequest, ProposeBlockSlotResponse, PublicKey as PublicKeyRequest, +}; +use protos::services_grpc::ValidatorService; +use slog::{debug, Logger}; + +#[derive(Clone)] +pub struct ValidatorServiceInstance { + pub log: Logger, +} + +impl ValidatorService for ValidatorServiceInstance { + fn validator_index( + &mut self, + ctx: RpcContext, + req: PublicKeyRequest, + sink: UnarySink, + ) { + debug!(self.log, "RPC got ValidatorIndex"; "public_key" => format!("{:x?}", req.get_public_key())); + + let mut resp = IndexResponse::new(); + + // TODO: return a legit value. + resp.set_index(1); + + let f = sink + .success(resp) + .map_err(move |e| println!("failed to reply {:?}: {:?}", req, e)); + ctx.spawn(f) + } + + fn propose_block_slot( + &mut self, + ctx: RpcContext, + req: ProposeBlockSlotRequest, + sink: UnarySink, + ) { + debug!(self.log, "RPC got ProposeBlockSlot"; "epoch" => req.get_epoch(), "validator_index" => req.get_validator_index()); + + let mut resp = ProposeBlockSlotResponse::new(); + + // TODO: return a legit value. + resp.set_slot(1); + + let f = sink + .success(resp) + .map_err(move |e| println!("failed to reply {:?}: {:?}", req, e)); + ctx.spawn(f) + } +} diff --git a/protos/src/services.proto b/protos/src/services.proto index 216ef7b2f..16e2d4dba 100644 --- a/protos/src/services.proto +++ b/protos/src/services.proto @@ -18,7 +18,9 @@ service BeaconBlockService { } service ValidatorService { - rpc ValidatorAssignment(ValidatorAssignmentRequest) returns (ValidatorAssignmentResponse); + // rpc ValidatorAssignment(ValidatorAssignmentRequest) returns (ValidatorAssignmentResponse); + rpc ProposeBlockSlot(ProposeBlockSlotRequest) returns (ProposeBlockSlotResponse); + rpc ValidatorIndex(PublicKey) returns (IndexResponse); } message BeaconBlock { @@ -49,6 +51,8 @@ message PublishBeaconBlockResponse { bytes msg = 2; } +// A validators duties for some epoch. +// TODO: add shard duties. message ValidatorAssignment { oneof block_production_slot_oneof { bool block_production_slot_none = 1; @@ -58,9 +62,33 @@ message ValidatorAssignment { message ValidatorAssignmentRequest { uint64 epoch = 1; - bytes public_key = 2; + bytes validator_index = 2; } -message ValidatorAssignmentResponse { - ValidatorAssignment validator_assignment = 1; +/* + * Propose slot + */ + +message ProposeBlockSlotRequest { + uint64 epoch = 1; + uint64 validator_index = 2; +} + +message ProposeBlockSlotResponse { + oneof slot_oneof { + bool none = 1; + uint64 slot = 2; + } +} + +/* + * Validator Assignment + */ + +message PublicKey { + bytes public_key = 1; +} + +message IndexResponse { + uint64 index = 1; } diff --git a/validator_client/src/duties/grpc.rs b/validator_client/src/duties/grpc.rs index 4b9c8288e..fc552516d 100644 --- a/validator_client/src/duties/grpc.rs +++ b/validator_client/src/duties/grpc.rs @@ -1,6 +1,8 @@ use super::traits::{BeaconNode, BeaconNodeError}; use super::EpochDuties; -use protos::services::ValidatorAssignmentRequest; +use protos::services::{ + IndexResponse, ProposeBlockSlotRequest, ProposeBlockSlotResponse, PublicKey as IndexRequest, +}; use protos::services_grpc::ValidatorServiceClient; use ssz::ssz_encode; use types::PublicKey; @@ -11,30 +13,33 @@ impl BeaconNode for ValidatorServiceClient { epoch: u64, public_key: &PublicKey, ) -> Result, BeaconNodeError> { - let mut req = ValidatorAssignmentRequest::new(); + // Lookup the validator index for the supplied public key. + let validator_index = { + let mut req = IndexRequest::new(); + req.set_public_key(ssz_encode(public_key).to_vec()); + let resp = self + .validator_index(&req) + .map_err(|err| BeaconNodeError::RemoteFailure(format!("{:?}", err)))?; + resp.get_index() + }; + + let mut req = ProposeBlockSlotRequest::new(); + req.set_validator_index(validator_index); req.set_epoch(epoch); - req.set_public_key(ssz_encode(public_key).to_vec()); let reply = self - .validator_assignment(&req) + .propose_block_slot(&req) .map_err(|err| BeaconNodeError::RemoteFailure(format!("{:?}", err)))?; - if reply.has_validator_assignment() { - let assignment = reply.get_validator_assignment(); - - let block_production_slot = if assignment.has_block_production_slot() { - Some(assignment.get_block_production_slot()) - } else { - None - }; - - let duties = EpochDuties { - block_production_slot, - }; - - Ok(Some(duties)) + let block_production_slot = if reply.has_slot() { + Some(reply.get_slot()) } else { - Ok(None) - } + None + }; + + Ok(Some(EpochDuties { + validator_index, + block_production_slot, + })) } } diff --git a/validator_client/src/duties/mod.rs b/validator_client/src/duties/mod.rs index 0ac14b07f..acfe108ee 100644 --- a/validator_client/src/duties/mod.rs +++ b/validator_client/src/duties/mod.rs @@ -15,6 +15,7 @@ pub use self::service::DutiesManagerService; #[derive(Debug, PartialEq, Clone, Copy, Default)] pub struct EpochDuties { + pub validator_index: u64, pub block_production_slot: Option, // Future shard info } @@ -32,10 +33,10 @@ pub type EpochDutiesMap = HashMap; #[derive(Debug, PartialEq, Clone, Copy)] pub enum PollOutcome { - NoChange, - NewDuties, - DutiesChanged, - UnknownValidatorOrEpoch, + NoChange(u64, EpochDuties), + NewDuties(u64, EpochDuties), + DutiesChanged(u64, EpochDuties), + UnknownValidatorOrEpoch(u64), } #[derive(Debug, PartialEq)] @@ -79,17 +80,17 @@ impl DutiesManager { // If these duties were known, check to see if they're updates or identical. let result = if let Some(known_duties) = map.get(&epoch) { if *known_duties == duties { - Ok(PollOutcome::NoChange) + Ok(PollOutcome::NoChange(epoch, duties)) } else { - Ok(PollOutcome::DutiesChanged) + Ok(PollOutcome::DutiesChanged(epoch, duties)) } } else { - Ok(PollOutcome::NewDuties) + Ok(PollOutcome::NewDuties(epoch, duties)) }; map.insert(epoch, duties); result } else { - Ok(PollOutcome::UnknownValidatorOrEpoch) + Ok(PollOutcome::UnknownValidatorOrEpoch(epoch)) } } } @@ -129,6 +130,7 @@ mod tests { // Configure response from the BeaconNode. beacon_node.set_next_shuffling_result(Ok(Some(EpochDuties { + validator_index: 0, block_production_slot: Some(10), }))); @@ -139,6 +141,7 @@ mod tests { // Return new duties. beacon_node.set_next_shuffling_result(Ok(Some(EpochDuties { + validator_index: 0, block_production_slot: Some(11), }))); assert_eq!(manager.poll(), Ok(PollOutcome::DutiesChanged)); diff --git a/validator_client/src/duties/service.rs b/validator_client/src/duties/service.rs index bedfd69ca..c51db0960 100644 --- a/validator_client/src/duties/service.rs +++ b/validator_client/src/duties/service.rs @@ -17,13 +17,17 @@ impl DutiesManagerService { Err(error) => { error!(self.log, "Epoch duties poll error"; "error" => format!("{:?}", error)) } - Ok(PollOutcome::NoChange) => debug!(self.log, "No change in duties"), - Ok(PollOutcome::DutiesChanged) => { - info!(self.log, "Duties changed (potential re-org)") + Ok(PollOutcome::NoChange(epoch, _)) => { + debug!(self.log, "No change in duties"; "epoch" => epoch) } - Ok(PollOutcome::NewDuties) => info!(self.log, "New duties obtained"), - Ok(PollOutcome::UnknownValidatorOrEpoch) => { - error!(self.log, "Epoch or validator unknown") + Ok(PollOutcome::DutiesChanged(epoch, duties)) => { + info!(self.log, "Duties changed (potential re-org)"; "epoch" => epoch, "duties" => format!("{:?}", duties)) + } + Ok(PollOutcome::NewDuties(epoch, duties)) => { + info!(self.log, "New duties obtained"; "epoch" => epoch, "duties" => format!("{:?}", duties)) + } + Ok(PollOutcome::UnknownValidatorOrEpoch(epoch)) => { + error!(self.log, "Epoch or validator unknown"; "epoch" => epoch) } }; From 87ffeaa833f3e815de29a2193ef81c6d9b532612 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Tue, 22 Jan 2019 09:04:57 +1100 Subject: [PATCH 18/28] Add method to bls::PublicKey for short ID --- beacon_chain/utils/bls/Cargo.toml | 1 + beacon_chain/utils/bls/src/public_key.rs | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/beacon_chain/utils/bls/Cargo.toml b/beacon_chain/utils/bls/Cargo.toml index 9e782b059..0dc64e483 100644 --- a/beacon_chain/utils/bls/Cargo.toml +++ b/beacon_chain/utils/bls/Cargo.toml @@ -7,4 +7,5 @@ edition = "2018" [dependencies] bls-aggregates = { git = "https://github.com/sigp/signature-schemes" } hashing = { path = "../hashing" } +hex = "0.3" ssz = { path = "../ssz" } diff --git a/beacon_chain/utils/bls/src/public_key.rs b/beacon_chain/utils/bls/src/public_key.rs index be260bf79..d3c735e8b 100644 --- a/beacon_chain/utils/bls/src/public_key.rs +++ b/beacon_chain/utils/bls/src/public_key.rs @@ -1,5 +1,6 @@ use super::SecretKey; use bls_aggregates::PublicKey as RawPublicKey; +use hex::encode as hex_encode; use ssz::{decode_ssz_list, ssz_encode, Decodable, DecodeError, Encodable, SszStream}; use std::hash::{Hash, Hasher}; @@ -19,6 +20,15 @@ impl PublicKey { pub fn as_raw(&self) -> &RawPublicKey { &self.0 } + + /// Returns the last 6 bytes of the SSZ encoding of the public key, as a hex string. + /// + /// Useful for providing a short identifier to the user. + pub fn concatenated_hex_id(&self) -> String { + let bytes = ssz_encode(self); + let end_bytes = &bytes[bytes.len().saturating_sub(6)..bytes.len()]; + hex_encode(end_bytes) + } } impl Encodable for PublicKey { From 992f2101c259627cb85c188a612a4afa722592d0 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Tue, 22 Jan 2019 09:05:34 +1100 Subject: [PATCH 19/28] Add short ID to logging for BLS public keys --- beacon_node/Cargo.toml | 2 ++ beacon_node/src/rpc/validator.rs | 32 ++++++++++++++++++-------- validator_client/src/duties/grpc.rs | 4 +--- validator_client/src/duties/mod.rs | 22 ++++++++++-------- validator_client/src/duties/service.rs | 2 +- validator_client/src/main.rs | 1 + 6 files changed, 39 insertions(+), 24 deletions(-) diff --git a/beacon_node/Cargo.toml b/beacon_node/Cargo.toml index 002a266b8..ca78a4767 100644 --- a/beacon_node/Cargo.toml +++ b/beacon_node/Cargo.toml @@ -5,6 +5,7 @@ authors = ["Paul Hauner "] edition = "2018" [dependencies] +bls = { path = "../beacon_chain/utils/bls" } grpcio = { version = "0.4", default-features = false, features = ["protobuf-codec"] } protobuf = "2.0.2" protos = { path = "../protos" } @@ -15,4 +16,5 @@ futures = "0.1.23" slog = "^2.2.3" slog-term = "^2.4.0" slog-async = "^2.3.0" +ssz = { path = "../beacon_chain/utils/ssz" } tokio = "0.1" diff --git a/beacon_node/src/rpc/validator.rs b/beacon_node/src/rpc/validator.rs index f0c828872..f894deca6 100644 --- a/beacon_node/src/rpc/validator.rs +++ b/beacon_node/src/rpc/validator.rs @@ -1,10 +1,12 @@ +use bls::PublicKey; use futures::Future; -use grpcio::{RpcContext, UnarySink}; +use grpcio::{RpcContext, RpcStatus, RpcStatusCode, UnarySink}; use protos::services::{ IndexResponse, ProposeBlockSlotRequest, ProposeBlockSlotResponse, PublicKey as PublicKeyRequest, }; use protos::services_grpc::ValidatorService; use slog::{debug, Logger}; +use ssz::Decodable; #[derive(Clone)] pub struct ValidatorServiceInstance { @@ -18,17 +20,27 @@ impl ValidatorService for ValidatorServiceInstance { req: PublicKeyRequest, sink: UnarySink, ) { - debug!(self.log, "RPC got ValidatorIndex"; "public_key" => format!("{:x?}", req.get_public_key())); + if let Ok((public_key, _)) = PublicKey::ssz_decode(req.get_public_key(), 0) { + debug!(self.log, "RPC request"; "endpoint" => "ValidatorIndex", "public_key" => public_key.concatenated_hex_id()); - let mut resp = IndexResponse::new(); + let mut resp = IndexResponse::new(); - // TODO: return a legit value. - resp.set_index(1); + // TODO: return a legit value. + resp.set_index(1); - let f = sink - .success(resp) - .map_err(move |e| println!("failed to reply {:?}: {:?}", req, e)); - ctx.spawn(f) + let f = sink + .success(resp) + .map_err(move |e| println!("failed to reply {:?}: {:?}", req, e)); + ctx.spawn(f) + } else { + let f = sink + .fail(RpcStatus::new( + RpcStatusCode::InvalidArgument, + Some("Invalid public_key".to_string()), + )) + .map_err(move |e| println!("failed to reply {:?}: {:?}", req, e)); + ctx.spawn(f) + } } fn propose_block_slot( @@ -37,7 +49,7 @@ impl ValidatorService for ValidatorServiceInstance { req: ProposeBlockSlotRequest, sink: UnarySink, ) { - debug!(self.log, "RPC got ProposeBlockSlot"; "epoch" => req.get_epoch(), "validator_index" => req.get_validator_index()); + debug!(self.log, "RPC request"; "endpoint" => "ProposeBlockSlot", "epoch" => req.get_epoch(), "validator_index" => req.get_validator_index()); let mut resp = ProposeBlockSlotResponse::new(); diff --git a/validator_client/src/duties/grpc.rs b/validator_client/src/duties/grpc.rs index fc552516d..7b4e1e617 100644 --- a/validator_client/src/duties/grpc.rs +++ b/validator_client/src/duties/grpc.rs @@ -1,8 +1,6 @@ use super::traits::{BeaconNode, BeaconNodeError}; use super::EpochDuties; -use protos::services::{ - IndexResponse, ProposeBlockSlotRequest, ProposeBlockSlotResponse, PublicKey as IndexRequest, -}; +use protos::services::{ProposeBlockSlotRequest, PublicKey as IndexRequest}; use protos::services_grpc::ValidatorServiceClient; use ssz::ssz_encode; use types::PublicKey; diff --git a/validator_client/src/duties/mod.rs b/validator_client/src/duties/mod.rs index acfe108ee..e8438b3db 100644 --- a/validator_client/src/duties/mod.rs +++ b/validator_client/src/duties/mod.rs @@ -33,7 +33,7 @@ pub type EpochDutiesMap = HashMap; #[derive(Debug, PartialEq, Clone, Copy)] pub enum PollOutcome { - NoChange(u64, EpochDuties), + NoChange(u64), NewDuties(u64, EpochDuties), DutiesChanged(u64, EpochDuties), UnknownValidatorOrEpoch(u64), @@ -80,7 +80,7 @@ impl DutiesManager { // If these duties were known, check to see if they're updates or identical. let result = if let Some(known_duties) = map.get(&epoch) { if *known_duties == duties { - Ok(PollOutcome::NoChange(epoch, duties)) + Ok(PollOutcome::NoChange(epoch)) } else { Ok(PollOutcome::DutiesChanged(epoch, duties)) } @@ -129,25 +129,27 @@ mod tests { }; // Configure response from the BeaconNode. - beacon_node.set_next_shuffling_result(Ok(Some(EpochDuties { + let duties = EpochDuties { validator_index: 0, block_production_slot: Some(10), - }))); + }; + beacon_node.set_next_shuffling_result(Ok(Some(duties))); // Get the duties for the first time... - assert_eq!(manager.poll(), Ok(PollOutcome::NewDuties)); + assert_eq!(manager.poll(), Ok(PollOutcome::NewDuties(0, duties))); // Get the same duties again... - assert_eq!(manager.poll(), Ok(PollOutcome::NoChange)); + assert_eq!(manager.poll(), Ok(PollOutcome::NoChange(0))); // Return new duties. - beacon_node.set_next_shuffling_result(Ok(Some(EpochDuties { + let duties = EpochDuties { validator_index: 0, block_production_slot: Some(11), - }))); - assert_eq!(manager.poll(), Ok(PollOutcome::DutiesChanged)); + }; + beacon_node.set_next_shuffling_result(Ok(Some(duties))); + assert_eq!(manager.poll(), Ok(PollOutcome::DutiesChanged(0, duties))); // Return no duties. beacon_node.set_next_shuffling_result(Ok(None)); - assert_eq!(manager.poll(), Ok(PollOutcome::UnknownValidatorOrEpoch)); + assert_eq!(manager.poll(), Ok(PollOutcome::UnknownValidatorOrEpoch(0))); } } diff --git a/validator_client/src/duties/service.rs b/validator_client/src/duties/service.rs index c51db0960..401b7dddd 100644 --- a/validator_client/src/duties/service.rs +++ b/validator_client/src/duties/service.rs @@ -17,7 +17,7 @@ impl DutiesManagerService { Err(error) => { error!(self.log, "Epoch duties poll error"; "error" => format!("{:?}", error)) } - Ok(PollOutcome::NoChange(epoch, _)) => { + Ok(PollOutcome::NoChange(epoch)) => { debug!(self.log, "No change in duties"; "epoch" => epoch) } Ok(PollOutcome::DutiesChanged(epoch, duties)) => { diff --git a/validator_client/src/main.rs b/validator_client/src/main.rs index 6210557dd..a52ffe124 100644 --- a/validator_client/src/main.rs +++ b/validator_client/src/main.rs @@ -103,6 +103,7 @@ fn main() { let mut threads = vec![]; for keypair in keypairs { + info!(log, "Starting validator services"; "validator" => keypair.pk.concatenated_hex_id()); let duties_map = Arc::new(RwLock::new(EpochDutiesMap::new())); let duties_manager_thread = { From 4499ffe5c32201f1e563c11817a8f1230849a988 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Tue, 22 Jan 2019 09:09:21 +1100 Subject: [PATCH 20/28] Add protobuf-compiler to travis.yml --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 3337de420..b82abc5ee 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,6 @@ language: rust +before_install: + - sudo apt-get install -y protobuf-compiler script: - cargo build --verbose --all - cargo test --verbose --all From 3d06bf9d2de8761511798c67f6faeff14c5b4fc5 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Tue, 22 Jan 2019 09:38:31 +1100 Subject: [PATCH 21/28] Add validator client readme --- validator_client/README.md | 67 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 validator_client/README.md diff --git a/validator_client/README.md b/validator_client/README.md new file mode 100644 index 000000000..aa84fe013 --- /dev/null +++ b/validator_client/README.md @@ -0,0 +1,67 @@ +# Lighthouse Validator Client + +The Validator Client (VC) is a stand-alone binary which connects to a Beacon +Node (BN) and fulfils the roles of a validator. + +## Roles + +The VC is responsible for the following tasks: + +- Requesting validator duties (a.k.a. shuffling) from the BN. +- Prompting the BN to produce a new block, when a validators block production + duties require. +- Completing all the fields on a new block (e.g., RANDAO reveal, signature) and + publishing the block to a BN. +- Prompting the BN to produce a new shard atteststation as per a validators + duties. +- Ensuring that no slashable messages are signed by a validator private key. +- Keeping track of the system clock and how it relates to slots/epochs. + +The VC is capable of managing multiple validators in the same process tree. + +## Implementation + +_This section describes the present implementation of this VC binary._ + +### Services + +Each validator is represented by two services, one which tracks the validator +duties and another which performs block production duties. + +A separate thread is maintained for each service, for each validator. As such, +a single validator utilises three (3) threads (one for the base VC and two for +each service) and two validators utilise five (5) threads. + +#### `DutiesManagerService` + +Polls a BN and requests validator responsibilities, as well as a validator +index. The outcome of a successful poll is a `EpochDuties` struct: + +```rust +EpochDuties { + validator_index: u64, + block_prodcution_slot: u64, +} +``` + +This is stored in the `EpochDutiesMap`, a `HashMap` mapping `epoch -> +EpochDuties`. + +#### `BlockProducerService` + +Polls the system clock and determines if a block needs to be produced. Reads +from the `EpochDutiesMap` maintained by the `DutiesManagerService`. + +If block production is required, performs all the necessary duties to request, +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). + +## BN Communication + +The VC communicates with the BN via a gRPC/protobuf connection. From 52561323e54f56fd3dfa6985431b6542de8add6d Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Tue, 22 Jan 2019 09:42:45 +1100 Subject: [PATCH 22/28] Move travis to ubuntu xenial to obtain proto3 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index b82abc5ee..5b4f1a46d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ language: rust +dist: xenial before_install: - sudo apt-get install -y protobuf-compiler script: From fc3c94f66d47eadf35ae205e317bba06567a6766 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Tue, 22 Jan 2019 10:02:48 +1100 Subject: [PATCH 23/28] Add custom proto install to travis --- .travis.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5b4f1a46d..67b4d1140 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,11 @@ language: rust -dist: xenial before_install: - - sudo apt-get install -y protobuf-compiler + - curl -OL https://github.com/google/protobuf/releases/download/v3.4.0/protoc-3.4.0-linux-x86_64.zip + - unzip protoc-3.2.0-linux-x86_64.zip -d protoc3 + - sudo mv protoc3/bin/* /usr/local/bin/ + - sudo mv protoc3/include/* /usr/local/include/ + - sudo chown $USER /usr/local/bin/protoc + - sudo chown -R $USER /usr/local/include/google script: - cargo build --verbose --all - cargo test --verbose --all From 4fd5424fca352d90e2402cee007342da23839b86 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Tue, 22 Jan 2019 10:07:28 +1100 Subject: [PATCH 24/28] Fix bad zip name in travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 67b4d1140..25135e279 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: rust before_install: - curl -OL https://github.com/google/protobuf/releases/download/v3.4.0/protoc-3.4.0-linux-x86_64.zip - - unzip protoc-3.2.0-linux-x86_64.zip -d protoc3 + - unzip protoc-3.4.0-linux-x86_64.zip -d protoc3 - sudo mv protoc3/bin/* /usr/local/bin/ - sudo mv protoc3/include/* /usr/local/include/ - sudo chown $USER /usr/local/bin/protoc From 14dfc3223ae560cc70a69d907bdaad27b1dab076 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Tue, 22 Jan 2019 12:38:11 +1100 Subject: [PATCH 25/28] Add doc comments for validator service. --- validator_client/src/block_producer/grpc.rs | 8 ++++ validator_client/src/block_producer/mod.rs | 41 +++++++++++++++++++ .../src/block_producer/service.rs | 3 ++ .../src/block_producer/test_node.rs | 5 +++ validator_client/src/block_producer/traits.rs | 7 ++++ validator_client/src/config.rs | 2 +- validator_client/src/duties/grpc.rs | 6 +++ validator_client/src/duties/mod.rs | 24 +++++++++++ validator_client/src/duties/service.rs | 3 ++ validator_client/src/duties/test_node.rs | 3 ++ validator_client/src/duties/traits.rs | 4 ++ validator_client/src/main.rs | 8 +++- 12 files changed, 112 insertions(+), 2 deletions(-) diff --git a/validator_client/src/block_producer/grpc.rs b/validator_client/src/block_producer/grpc.rs index 4032d49f3..f3156ab9f 100644 --- a/validator_client/src/block_producer/grpc.rs +++ b/validator_client/src/block_producer/grpc.rs @@ -7,6 +7,10 @@ use ssz::{ssz_encode, Decodable}; use types::{BeaconBlock, BeaconBlockBody, Hash256, Signature}; impl BeaconNode for BeaconBlockServiceClient { + /// Request a Beacon Node (BN) to produce a new block at the supplied slot. + /// + /// Returns `None` if it is not possible to produce at the supplied slot. For example, if the + /// BN is unable to find a parent block. fn produce_beacon_block(&self, slot: u64) -> Result, BeaconNodeError> { let mut req = ProduceBeaconBlockRequest::new(); req.set_slot(slot); @@ -42,6 +46,10 @@ impl BeaconNode for BeaconBlockServiceClient { } } + /// Request a Beacon Node (BN) to publish a block. + /// + /// Generally, this will be called after a `produce_beacon_block` call with a block that has + /// been completed (signed) by the validator client. fn publish_beacon_block(&self, block: BeaconBlock) -> Result { let mut req = PublishBeaconBlockRequest::new(); diff --git a/validator_client/src/block_producer/mod.rs b/validator_client/src/block_producer/mod.rs index aa4c088f3..f3cd0199b 100644 --- a/validator_client/src/block_producer/mod.rs +++ b/validator_client/src/block_producer/mod.rs @@ -15,11 +15,17 @@ pub use self::service::BlockProducerService; #[derive(Debug, PartialEq)] pub enum PollOutcome { + /// A new block was produced. BlockProduced(u64), + /// A block was not produced as it would have been slashable. SlashableBlockNotProduced(u64), + /// The validator duties did not require a block to be produced. BlockProductionNotRequired(u64), + /// The duties for the present epoch were not found. ProducerDutiesUnknown(u64), + /// The slot has already been processed, execution was skipped. SlotAlreadyProcessed(u64), + /// The Beacon Node was unable to produce a block at that slot. BeaconNodeUnableToProduceBlock(u64), } @@ -33,6 +39,12 @@ pub enum Error { BeaconNodeError(BeaconNodeError), } +/// A polling state machine which performs block production duties, based upon some epoch duties +/// (`EpochDutiesMap`) and a concept of time (`SlotClock`). +/// +/// Ensures that messages are not slashable. +/// +/// Relies upon an external service to keep the `EpochDutiesMap` updated. pub struct BlockProducer { pub last_processed_slot: u64, spec: Arc, @@ -42,6 +54,7 @@ pub struct BlockProducer { } impl BlockProducer { + /// Returns a new instance where `last_processed_slot == 0`. pub fn new( spec: Arc, epoch_map: Arc>, @@ -97,6 +110,16 @@ impl BlockProducer { } } + /// Produce a block at some slot. + /// + /// Assumes that a block is required at this slot (does not check the duties). + /// + /// Ensures the message is not slashable. + /// + /// !!! UNSAFE !!! + /// + /// The slash-protection code is not yet implemented. There is zero protection against + /// slashing. fn produce_block(&mut self, slot: u64) -> Result { if let Some(block) = self.beacon_node.produce_beacon_block(slot)? { if self.safe_to_produce(&block) { @@ -111,19 +134,36 @@ impl BlockProducer { } } + /// Consumes a block, returning that block signed by the validators private key. + /// + /// Important: this function will not check to ensure the block is not slashable. This must be + /// done upstream. fn sign_block(&mut self, block: BeaconBlock) -> BeaconBlock { // TODO: sign the block + // https://github.com/sigp/lighthouse/issues/160 self.store_produce(&block); block } + /// Returns `true` if signing a block is safe (non-slashable). + /// + /// !!! UNSAFE !!! + /// + /// Important: this function is presently stubbed-out. It provides ZERO SAFETY. fn safe_to_produce(&self, _block: &BeaconBlock) -> bool { // TODO: ensure the producer doesn't produce slashable blocks. + // https://github.com/sigp/lighthouse/issues/160 true } + /// Record that a block was produced so that slashable votes may not be made in the future. + /// + /// !!! UNSAFE !!! + /// + /// Important: this function is presently stubbed-out. It provides ZERO SAFETY. fn store_produce(&mut self, _block: &BeaconBlock) { // TODO: record this block production to prevent future slashings. + // https://github.com/sigp/lighthouse/issues/160 } } @@ -142,6 +182,7 @@ mod tests { use types::test_utils::{SeedableRng, TestRandom, XorShiftRng}; // TODO: implement more thorough testing. + // https://github.com/sigp/lighthouse/issues/160 // // These tests should serve as a good example for future tests. diff --git a/validator_client/src/block_producer/service.rs b/validator_client/src/block_producer/service.rs index 222e54d47..ffdb33029 100644 --- a/validator_client/src/block_producer/service.rs +++ b/validator_client/src/block_producer/service.rs @@ -10,6 +10,9 @@ pub struct BlockProducerService { } impl BlockProducerService { + /// Run a loop which polls the block producer each `poll_interval_millis` millseconds. + /// + /// Logs the results of the polls. pub fn run(&mut self) { loop { match self.block_producer.poll() { diff --git a/validator_client/src/block_producer/test_node.rs b/validator_client/src/block_producer/test_node.rs index 36d47e3c3..e99613e8f 100644 --- a/validator_client/src/block_producer/test_node.rs +++ b/validator_client/src/block_producer/test_node.rs @@ -5,6 +5,7 @@ use types::BeaconBlock; type ProduceResult = Result, BeaconNodeError>; type PublishResult = Result; +/// A test-only struct used to simulate a Beacon Node. #[derive(Default)] pub struct TestBeaconNode { pub produce_input: RwLock>, @@ -14,16 +15,19 @@ pub struct TestBeaconNode { } impl TestBeaconNode { + /// Set the result to be returned when `produce_beacon_block` is called. pub fn set_next_produce_result(&self, result: ProduceResult) { *self.produce_result.write().unwrap() = Some(result); } + /// Set the result to be returned when `publish_beacon_block` is called. pub fn set_next_publish_result(&self, result: PublishResult) { *self.publish_result.write().unwrap() = Some(result); } } impl BeaconNode for TestBeaconNode { + /// Returns the value specified by the `set_next_produce_result`. fn produce_beacon_block(&self, slot: u64) -> ProduceResult { *self.produce_input.write().unwrap() = Some(slot); match *self.produce_result.read().unwrap() { @@ -32,6 +36,7 @@ impl BeaconNode for TestBeaconNode { } } + /// Returns the value specified by the `set_next_publish_result`. fn publish_beacon_block(&self, block: BeaconBlock) -> PublishResult { *self.publish_input.write().unwrap() = Some(block); match *self.publish_result.read().unwrap() { diff --git a/validator_client/src/block_producer/traits.rs b/validator_client/src/block_producer/traits.rs index aaae031ec..be1c73bda 100644 --- a/validator_client/src/block_producer/traits.rs +++ b/validator_client/src/block_producer/traits.rs @@ -6,7 +6,14 @@ pub enum BeaconNodeError { DecodeFailure, } +/// Defines the methods required to produce and publish blocks on a Beacon Node. pub trait BeaconNode: Send + Sync { + /// Request that the node produces a block. + /// + /// Returns Ok(None) if the Beacon Node is unable to produce at the given slot. fn produce_beacon_block(&self, slot: u64) -> Result, BeaconNodeError>; + /// Request that the node publishes a block. + /// + /// Returns `true` if the publish was sucessful. fn publish_beacon_block(&self, block: BeaconBlock) -> Result; } diff --git a/validator_client/src/config.rs b/validator_client/src/config.rs index 4b646074d..104a4bbe6 100644 --- a/validator_client/src/config.rs +++ b/validator_client/src/config.rs @@ -11,7 +11,7 @@ pub struct ClientConfig { const DEFAULT_LIGHTHOUSE_DIR: &str = ".lighthouse-validators"; impl ClientConfig { - /// Build a new lighthouse configuration from defaults. + /// Build a new configuration from defaults. pub fn default() -> Self { let data_dir = { let home = dirs::home_dir().expect("Unable to determine home dir."); diff --git a/validator_client/src/duties/grpc.rs b/validator_client/src/duties/grpc.rs index 7b4e1e617..b4a2fac51 100644 --- a/validator_client/src/duties/grpc.rs +++ b/validator_client/src/duties/grpc.rs @@ -6,6 +6,12 @@ use ssz::ssz_encode; use types::PublicKey; impl BeaconNode for ValidatorServiceClient { + /// Request the shuffling from the Beacon Node (BN). + /// + /// As this function takes a `PublicKey`, it will first attempt to resolve the public key into + /// a validator index, then call the BN for production/attestation duties. + /// + /// Note: presently only block production information is returned. fn request_shuffling( &self, epoch: u64, diff --git a/validator_client/src/duties/mod.rs b/validator_client/src/duties/mod.rs index e8438b3db..4656715ba 100644 --- a/validator_client/src/duties/mod.rs +++ b/validator_client/src/duties/mod.rs @@ -13,6 +13,11 @@ use std::sync::{Arc, RwLock}; pub use self::service::DutiesManagerService; +/// The information required for a validator to propose and attest during some epoch. +/// +/// Generally obtained from a Beacon Node, this information contains the validators canonical index +/// (thier sequence in the global validator induction process) and the "shuffling" for that index +/// for some epoch. #[derive(Debug, PartialEq, Clone, Copy, Default)] pub struct EpochDuties { pub validator_index: u64, @@ -21,6 +26,8 @@ pub struct EpochDuties { } impl EpochDuties { + /// Returns `true` if the supplied `slot` is a slot in which the validator should produce a + /// block. pub fn is_block_production_slot(&self, slot: u64) -> bool { match self.block_production_slot { Some(s) if s == slot => true, @@ -29,13 +36,20 @@ impl EpochDuties { } } +/// Maps an `epoch` to some `EpochDuties` for a single validator. pub type EpochDutiesMap = HashMap; #[derive(Debug, PartialEq, Clone, Copy)] pub enum PollOutcome { + /// The `EpochDuties` were not updated during this poll. NoChange(u64), + /// The `EpochDuties` for the `epoch` were previously unknown, but obtained in the poll. NewDuties(u64, EpochDuties), + /// New `EpochDuties` were obtained, different to those which were previously known. This is + /// likely to be the result of chain re-organisation. DutiesChanged(u64, EpochDuties), + /// The Beacon Node was unable to return the duties as the validator is unknown, or the + /// shuffling for the epoch is unknown. UnknownValidatorOrEpoch(u64), } @@ -49,8 +63,13 @@ pub enum Error { BeaconNodeError(BeaconNodeError), } +/// A polling state machine which ensures the latest `EpochDuties` are obtained from the Beacon +/// Node. +/// +/// There is a single `DutiesManager` per validator instance. pub struct DutiesManager { pub duties_map: Arc>, + /// The validator's public key. pub pubkey: PublicKey, pub spec: Arc, pub slot_clock: Arc>, @@ -58,6 +77,10 @@ pub struct DutiesManager { } impl DutiesManager { + /// Poll the Beacon Node for `EpochDuties`. + /// + /// The present `epoch` will be learned from the supplied `SlotClock`. In production this will + /// be a wall-clock (e.g., system time, remote server time, etc.). pub fn poll(&self) -> Result { let slot = self .slot_clock @@ -109,6 +132,7 @@ mod tests { use slot_clock::TestingSlotClock; // TODO: implement more thorough testing. + // https://github.com/sigp/lighthouse/issues/160 // // These tests should serve as a good example for future tests. diff --git a/validator_client/src/duties/service.rs b/validator_client/src/duties/service.rs index 401b7dddd..bdb6faefa 100644 --- a/validator_client/src/duties/service.rs +++ b/validator_client/src/duties/service.rs @@ -11,6 +11,9 @@ pub struct DutiesManagerService { } impl DutiesManagerService { + /// Run a loop which polls the manager each `poll_interval_millis` milliseconds. + /// + /// Logs the results of the polls. pub fn run(&mut self) { loop { match self.manager.poll() { diff --git a/validator_client/src/duties/test_node.rs b/validator_client/src/duties/test_node.rs index 4ec002224..2b1d65172 100644 --- a/validator_client/src/duties/test_node.rs +++ b/validator_client/src/duties/test_node.rs @@ -5,6 +5,7 @@ use std::sync::RwLock; type ShufflingResult = Result, BeaconNodeError>; +/// A test-only struct used to simulate a Beacon Node. #[derive(Default)] pub struct TestBeaconNode { pub request_shuffling_input: RwLock>, @@ -12,12 +13,14 @@ pub struct TestBeaconNode { } impl TestBeaconNode { + /// Set the result to be returned when `request_shuffling` is called. pub fn set_next_shuffling_result(&self, result: ShufflingResult) { *self.request_shuffling_result.write().unwrap() = Some(result); } } impl BeaconNode for TestBeaconNode { + /// Returns the value specified by the `set_next_shuffling_result`. fn request_shuffling(&self, epoch: u64, public_key: &PublicKey) -> ShufflingResult { *self.request_shuffling_input.write().unwrap() = Some((epoch, public_key.clone())); match *self.request_shuffling_result.read().unwrap() { diff --git a/validator_client/src/duties/traits.rs b/validator_client/src/duties/traits.rs index 14c2adf95..38d61f967 100644 --- a/validator_client/src/duties/traits.rs +++ b/validator_client/src/duties/traits.rs @@ -6,7 +6,11 @@ pub enum BeaconNodeError { RemoteFailure(String), } +/// Defines the methods required to obtain a validators shuffling from a Beacon Node. pub trait BeaconNode: Send + Sync { + /// Get the shuffling for the given epoch and public key. + /// + /// Returns Ok(None) if the public key is unknown, or the shuffling for that epoch is unknown. fn request_shuffling( &self, epoch: u64, diff --git a/validator_client/src/main.rs b/validator_client/src/main.rs index a52ffe124..bbbc0b4c3 100644 --- a/validator_client/src/main.rs +++ b/validator_client/src/main.rs @@ -83,6 +83,7 @@ fn main() { // Ethereum // // TODO: Permit loading a custom spec from file. + // https://github.com/sigp/lighthouse/issues/160 let spec = Arc::new(ChainSpec::foundation()); // Clock for determining the present slot. @@ -99,13 +100,16 @@ fn main() { /* * Start threads. */ - let keypairs = vec![Keypair::random()]; let mut threads = vec![]; + // TODO: keypairs are randomly generated; they should be loaded from a file or generated. + // https://github.com/sigp/lighthouse/issues/160 + let keypairs = vec![Keypair::random()]; for keypair in keypairs { info!(log, "Starting validator services"; "validator" => keypair.pk.concatenated_hex_id()); let duties_map = Arc::new(RwLock::new(EpochDutiesMap::new())); + // Spawn a new thread to maintain the validator's `EpochDuties`. let duties_manager_thread = { let spec = spec.clone(); let duties_map = duties_map.clone(); @@ -131,6 +135,7 @@ fn main() { }) }; + // Spawn a new thread to perform block production for the validator. let producer_thread = { let spec = spec.clone(); let duties_map = duties_map.clone(); @@ -152,6 +157,7 @@ fn main() { threads.push((duties_manager_thread, producer_thread)); } + // Naively wait for all the threads to complete. for tuple in threads { let (manager, producer) = tuple; let _ = producer.join(); From df3c45072303455c9dfc008f9dc4e0e5e442b57d Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Tue, 22 Jan 2019 14:54:51 +1100 Subject: [PATCH 26/28] Update validator client for block body update --- validator_client/src/block_producer/grpc.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/validator_client/src/block_producer/grpc.rs b/validator_client/src/block_producer/grpc.rs index f3156ab9f..033965b16 100644 --- a/validator_client/src/block_producer/grpc.rs +++ b/validator_client/src/block_producer/grpc.rs @@ -37,6 +37,9 @@ impl BeaconNode for BeaconBlockServiceClient { proposer_slashings: vec![], casper_slashings: vec![], attestations: vec![], + custody_reseeds: vec![], + custody_challenges: vec![], + custody_responses: vec![], deposits: vec![], exits: vec![], }, From bf1795a94e9a39677e6e3b35a7ebf585a084dcd5 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Tue, 22 Jan 2019 15:14:04 +1100 Subject: [PATCH 27/28] Move rustfmt check down in travis yml This is because we need to make sure the protos build before rustfmt runs. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d1d383670..d43d21a00 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,9 +7,9 @@ before_install: - sudo chown $USER /usr/local/bin/protoc - sudo chown -R $USER /usr/local/include/google script: - - cargo fmt --all -- --check - cargo build --verbose --all - cargo test --verbose --all + - cargo fmt --all -- --check rust: - stable - beta From eb4723fee5475a73eddd43d6a303ceb4e3748ae0 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Tue, 22 Jan 2019 15:18:02 +1100 Subject: [PATCH 28/28] Add sleep to beacon_node run loop --- beacon_node/src/main.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/beacon_node/src/main.rs b/beacon_node/src/main.rs index 86329c4a2..08660cbc4 100644 --- a/beacon_node/src/main.rs +++ b/beacon_node/src/main.rs @@ -60,7 +60,7 @@ fn main() { let _server = start_server(log.clone()); - loop {} - - // info!(log, "Exiting."); + loop { + std::thread::sleep(std::time::Duration::from_secs(1)); + } }