From 6e254551af043f39dadbb7070220f81dc3d0f7f5 Mon Sep 17 00:00:00 2001 From: Age Manning Date: Sat, 30 Mar 2019 15:58:31 +1100 Subject: [PATCH] Implement produce beacon block on gRPC beacon node server --- beacon_node/beacon_chain/src/lib.rs | 2 +- beacon_node/rpc/src/beacon_block.rs | 58 +++++++++++++++---- beacon_node/rpc/src/beacon_chain.rs | 15 ++++- .../testing_beacon_state_builder.rs | 2 +- validator_client/src/block_producer/mod.rs | 24 +++++++- validator_client/src/service.rs | 7 ++- 6 files changed, 90 insertions(+), 18 deletions(-) diff --git a/beacon_node/beacon_chain/src/lib.rs b/beacon_node/beacon_chain/src/lib.rs index 48a42b941e..234a960945 100644 --- a/beacon_node/beacon_chain/src/lib.rs +++ b/beacon_node/beacon_chain/src/lib.rs @@ -7,7 +7,7 @@ pub mod test_utils; pub use self::beacon_chain::{BeaconChain, BlockProcessingOutcome, InvalidBlock, ValidBlock}; pub use self::checkpoint::CheckPoint; -pub use self::errors::BeaconChainError; +pub use self::errors::{BeaconChainError, BlockProductionError}; pub use attestation_aggregator::Outcome as AggregationOutcome; pub use db; pub use fork_choice; diff --git a/beacon_node/rpc/src/beacon_block.rs b/beacon_node/rpc/src/beacon_block.rs index f6b426c18f..e8b3cb01b4 100644 --- a/beacon_node/rpc/src/beacon_block.rs +++ b/beacon_node/rpc/src/beacon_block.rs @@ -3,7 +3,7 @@ use crossbeam_channel; use eth2_libp2p::rpc::methods::BlockRootSlot; use eth2_libp2p::PubsubMessage; use futures::Future; -use grpcio::{RpcContext, UnarySink}; +use grpcio::{RpcContext, RpcStatus, RpcStatusCode, UnarySink}; use network::NetworkMessage; use protos::services::{ BeaconBlock as BeaconBlockProto, ProduceBeaconBlockRequest, ProduceBeaconBlockResponse, @@ -11,10 +11,10 @@ use protos::services::{ }; use protos::services_grpc::BeaconBlockService; use slog::Logger; -use slog::{debug, error, info, warn}; -use ssz::{Decodable, TreeHash}; +use slog::{error, info, trace, warn}; +use ssz::{ssz_encode, Decodable, TreeHash}; use std::sync::Arc; -use types::{BeaconBlock, Hash256, Slot}; +use types::{BeaconBlock, Hash256, Signature, Slot}; #[derive(Clone)] pub struct BeaconBlockServiceInstance { @@ -31,11 +31,44 @@ impl BeaconBlockService for BeaconBlockServiceInstance { req: ProduceBeaconBlockRequest, sink: UnarySink, ) { - println!("producing at slot {}", req.get_slot()); + trace!(self.log, "Generating a beacon block"; "req" => format!("{:?}", req)); + + // decode the request + // TODO: requested slot currently unused, see: https://github.com/sigp/lighthouse/issues/336 + let _requested_slot = Slot::from(req.get_slot()); + let (randao_reveal, _index) = match Signature::ssz_decode(req.get_randao_reveal(), 0) { + Ok(v) => v, + Err(_) => { + // decode error, incorrect signature + let log_clone = self.log.clone(); + let f = sink + .fail(RpcStatus::new( + RpcStatusCode::InvalidArgument, + Some(format!("Invalid randao reveal signature")), + )) + .map_err(move |e| warn!(log_clone, "failed to reply {:?}: {:?}", req, e)); + return ctx.spawn(f); + } + }; + + let produced_block = match self.chain.produce_block(randao_reveal) { + Ok((block, _state)) => block, + Err(e) => { + // could not produce a block + let log_clone = self.log.clone(); + warn!(self.log, "RPC Error"; "Error" => format!("Could not produce a block:{:?}",e)); + let f = sink + .fail(RpcStatus::new( + RpcStatusCode::Unknown, + Some(format!("Could not produce a block: {:?}", e)), + )) + .map_err(move |e| warn!(log_clone, "failed to reply {:?}: {:?}", req, e)); + return ctx.spawn(f); + } + }; - // TODO: build a legit block. let mut block = BeaconBlockProto::new(); - block.set_ssz(b"cats".to_vec()); + block.set_ssz(ssz_encode(&produced_block)); let mut resp = ProduceBeaconBlockResponse::new(); resp.set_block(block); @@ -81,11 +114,16 @@ impl BeaconBlockService for BeaconBlockServiceInstance { slot: block.slot, }); - println!("Sending beacon block to gossipsub"); - self.network_chan.send(NetworkMessage::Publish { + match self.network_chan.send(NetworkMessage::Publish { topics: vec![topic], message, - }); + }) { + Ok(_) => {} + Err(_) => warn!( + self.log, + "Could not send published block to the network service" + ), + } resp.set_success(true); } else if outcome.is_invalid() { diff --git a/beacon_node/rpc/src/beacon_chain.rs b/beacon_node/rpc/src/beacon_chain.rs index 0551a80246..f21b8df7b4 100644 --- a/beacon_node/rpc/src/beacon_chain.rs +++ b/beacon_node/rpc/src/beacon_chain.rs @@ -4,7 +4,8 @@ use beacon_chain::{ fork_choice::ForkChoice, parking_lot::RwLockReadGuard, slot_clock::SlotClock, - types::{BeaconState, ChainSpec}, + types::{BeaconState, ChainSpec, Signature}, + BlockProductionError, }; pub use beacon_chain::{BeaconChainError, BlockProcessingOutcome}; use types::BeaconBlock; @@ -17,6 +18,11 @@ pub trait BeaconChain: Send + Sync { fn process_block(&self, block: BeaconBlock) -> Result; + + fn produce_block( + &self, + randao_reveal: Signature, + ) -> Result<(BeaconBlock, BeaconState), BlockProductionError>; } impl BeaconChain for RawBeaconChain @@ -39,4 +45,11 @@ where ) -> Result { self.process_block(block) } + + fn produce_block( + &self, + randao_reveal: Signature, + ) -> Result<(BeaconBlock, BeaconState), BlockProductionError> { + self.produce_block(randao_reveal) + } } diff --git a/eth2/types/src/test_utils/testing_beacon_state_builder.rs b/eth2/types/src/test_utils/testing_beacon_state_builder.rs index 5e4cebd576..7c231b20b0 100644 --- a/eth2/types/src/test_utils/testing_beacon_state_builder.rs +++ b/eth2/types/src/test_utils/testing_beacon_state_builder.rs @@ -120,7 +120,7 @@ impl TestingBeaconStateBuilder { }) .collect(); - let genesis_time = 1553776331; // arbitrary + let genesis_time = 1553918534; // arbitrary let mut state = BeaconState::genesis( genesis_time, diff --git a/validator_client/src/block_producer/mod.rs b/validator_client/src/block_producer/mod.rs index 77b7196667..7def97e03c 100644 --- a/validator_client/src/block_producer/mod.rs +++ b/validator_client/src/block_producer/mod.rs @@ -4,6 +4,7 @@ mod grpc; use self::beacon_block_node::{BeaconBlockNode, BeaconBlockNodeError}; pub use self::grpc::BeaconBlockGrpcClient; use crate::signer::Signer; +use slog::{error, info}; use ssz::{SignedRoot, TreeHash}; use std::sync::Arc; use types::{BeaconBlock, ChainSpec, Domain, Fork, Slot}; @@ -23,8 +24,6 @@ pub enum ValidatorEvent { BeaconNodeUnableToProduceBlock(Slot), /// The signer failed to sign the message. SignerRejection(Slot), - /// The public key for this validator is not an active validator. - ValidatorIsUnknown(Slot), } /// This struct contains the logic for requesting and signing beacon blocks for a validator. The @@ -43,6 +42,25 @@ pub struct BlockProducer<'a, B: BeaconBlockNode, S: Signer> { } impl<'a, B: BeaconBlockNode, S: Signer> BlockProducer<'a, B, S> { + /// Handle outputs and results from block production. + pub fn handle_produce_block(&mut self, log: slog::Logger) { + match self.produce_block() { + Ok(ValidatorEvent::BlockProduced(_slot)) => { + info!(log, "Block produced"; "Validator" => format!("{}", self.signer)) + } + Err(e) => error!(log, "Block production error"; "Error" => format!("{:?}", e)), + Ok(ValidatorEvent::SignerRejection(_slot)) => { + error!(log, "Block production error"; "Error" => format!("Signer Could not sign the block")) + } + Ok(ValidatorEvent::SlashableBlockNotProduced(_slot)) => { + error!(log, "Block production error"; "Error" => format!("Rejected the block as it could have been slashed")) + } + Ok(ValidatorEvent::BeaconNodeUnableToProduceBlock(_slot)) => { + error!(log, "Block production error"; "Error" => format!("Beacon node was unable to produce a block")) + } + } + } + /// Produce a block at some slot. /// /// Assumes that a block is required at this slot (does not check the duties). @@ -53,7 +71,7 @@ impl<'a, B: BeaconBlockNode, S: Signer> BlockProducer<'a, B, S> { /// /// The slash-protection code is not yet implemented. There is zero protection against /// slashing. - fn produce_block(&mut self) -> Result { + pub fn produce_block(&mut self) -> Result { let epoch = self.slot.epoch(self.spec.slots_per_epoch); let randao_reveal = { diff --git a/validator_client/src/service.rs b/validator_client/src/service.rs index 4c01d89671..621fb03a31 100644 --- a/validator_client/src/service.rs +++ b/validator_client/src/service.rs @@ -302,20 +302,23 @@ impl Service { for (signer_index, work_type) in work { if work_type.produce_block { // spawns a thread to produce a beacon block - let signers = self.duties_manager.signers.clone(); + let signers = self.duties_manager.signers.clone(); // this is an arc let fork = self.fork.clone(); let slot = self.current_slot.clone(); let spec = self.spec.clone(); let beacon_node = self.beacon_block_client.clone(); + let log = self.log.clone(); std::thread::spawn(move || { + info!(log, "Producing a block"; "Validator"=> format!("{}", signers[signer_index])); let signer = &signers[signer_index]; - let block_producer = BlockProducer { + let mut block_producer = BlockProducer { fork, slot, spec, beacon_node, signer, }; + block_producer.handle_produce_block(log); }); // TODO: Produce a beacon block in a new thread