From 40cf65056319213ded91fdf64c57fb0f68abec68 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Mon, 14 Jan 2019 12:55:55 +1100 Subject: [PATCH] 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() + } +}