From d12ddae24763683eac3f9844719de8bcbc9e5ecb Mon Sep 17 00:00:00 2001 From: Age Manning Date: Sat, 30 Mar 2019 18:14:04 +1100 Subject: [PATCH] Builds attestation grpc implemention --- protos/src/services.proto | 28 +--- .../beacon_node_attestation.rs | 23 --- validator_client/src/attester_service/grpc.rs | 45 ----- validator_client/src/attester_service/mod.rs | 155 ------------------ validator_client/src/block_producer/grpc.rs | 1 + validator_client/src/main.rs | 2 +- 6 files changed, 8 insertions(+), 246 deletions(-) delete mode 100644 validator_client/src/attester_service/beacon_node_attestation.rs delete mode 100644 validator_client/src/attester_service/grpc.rs delete mode 100644 validator_client/src/attester_service/mod.rs diff --git a/protos/src/services.proto b/protos/src/services.proto index 7cd653a600..c5bd8a91d3 100644 --- a/protos/src/services.proto +++ b/protos/src/services.proto @@ -141,7 +141,11 @@ message ProduceAttestationDataResponse { } message PublishAttestationRequest { - FreeAttestation free_attestation = 1; + Attestation attestation = 1; +} + +message Attestation { + bytes ssz = 1; } message PublishAttestationResponse { @@ -149,26 +153,6 @@ message PublishAttestationResponse { bytes msg = 2; } -message Crosslink { - uint64 epoch = 1; - bytes crosslink_data_root = 2; - -} - message AttestationData { - uint64 slot = 1; - uint64 shard = 2; - bytes beacon_block_root = 3; - bytes epoch_boundary_root = 4; - bytes crosslink_data_root = 5; - Crosslink latest_crosslink = 6; - uint64 justified_epoch = 7; - bytes justified_block_root = 8; - -} - -message FreeAttestation { - AttestationData data = 1; - bytes signature = 2; - uint64 validator_index = 3; + bytes ssz = 1; } diff --git a/validator_client/src/attester_service/beacon_node_attestation.rs b/validator_client/src/attester_service/beacon_node_attestation.rs deleted file mode 100644 index b5ff777de8..0000000000 --- a/validator_client/src/attester_service/beacon_node_attestation.rs +++ /dev/null @@ -1,23 +0,0 @@ -//TODO: generalise these enums to the crate -use crate::block_producer::{BeaconNodeError, PublishOutcome}; -use types::{Attestation, AttestationData, Slot}; - -/// Defines the methods required to produce and publish attestations on a Beacon Node. Abstracts the -/// actual beacon node. -pub trait BeaconNodeAttestation: Send + Sync { - /// Request that the node produces the required attestation data. - /// - fn produce_attestation_data( - &self, - slot: Slot, - shard: u64, - ) -> Result; - - /// Request that the node publishes a attestation. - /// - /// Returns `true` if the publish was successful. - fn publish_attestation( - &self, - attestation: Attestation, - ) -> Result; -} diff --git a/validator_client/src/attester_service/grpc.rs b/validator_client/src/attester_service/grpc.rs deleted file mode 100644 index 502e51cac9..0000000000 --- a/validator_client/src/attester_service/grpc.rs +++ /dev/null @@ -1,45 +0,0 @@ -use protos::services_grpc::AttestationServiceClient; -use std::sync::Arc; - -use attester::{BeaconNode, BeaconNodeError, PublishOutcome}; -use protos::services::ProduceAttestationDataRequest; -use types::{Attestation, AttestationData, Slot}; - -pub struct AttestationGrpcClient { - client: Arc, -} - -impl AttestationGrpcClient { - pub fn new(client: Arc) -> Self { - Self { client } - } -} -/* -impl BeaconNode for AttestationGrpcClient { - fn produce_attestation_data( - &self, - slot: Slot, - shard: u64, - ) -> Result, BeaconNodeError> { - let mut req = ProduceAttestationDataRequest::new(); - req.set_slot(slot.as_u64()); - req.set_shard(shard); - - let reply = self - .client - .produce_attestation_data(&req) - .map_err(|err| BeaconNodeError::RemoteFailure(format!("{:?}", err)))?; - - // TODO: return correct Attestation - Err(BeaconNodeError::DecodeFailure) - } - - fn publish_attestation( - &self, - attestation: Attestation, - ) -> Result { - // TODO: return correct PublishOutcome - Err(BeaconNodeError::DecodeFailure) - } -} -*/ diff --git a/validator_client/src/attester_service/mod.rs b/validator_client/src/attester_service/mod.rs deleted file mode 100644 index 7b2174b0cd..0000000000 --- a/validator_client/src/attester_service/mod.rs +++ /dev/null @@ -1,155 +0,0 @@ -mod beacon_node_attestation; -mod grpc; - -use std::sync::Arc; -use types::{BeaconBlock, ChainSpec, Domain, Fork, Slot}; -//TODO: Move these higher up in the crate -use super::block_producer::{BeaconNodeError, ValidatorEvent}; -use crate::signer::Signer; -use beacon_node_attestation::BeaconNodeAttestation; -use slog::{error, info, warn}; -use ssz::TreeHash; -use types::{ - AggregateSignature, Attestation, AttestationData, AttestationDataAndCustodyBit, - AttestationDuty, Bitfield, -}; - -//TODO: Group these errors at a crate level -#[derive(Debug, PartialEq)] -pub enum Error { - BeaconNodeError(BeaconNodeError), -} - -impl From for Error { - fn from(e: BeaconNodeError) -> Error { - Error::BeaconNodeError(e) - } -} - -/// This struct contains the logic for requesting and signing beacon attestations for a validator. The -/// validator can abstractly sign via the Signer trait object. -pub struct AttestationProducer<'a, B: BeaconNodeAttestation, S: Signer> { - /// The current fork. - pub fork: Fork, - /// The attestation duty to perform. - pub duty: AttestationDuty, - /// The current epoch. - pub spec: Arc, - /// The beacon node to connect to. - pub beacon_node: Arc, - /// The signer to sign the block. - pub signer: &'a S, -} - -impl<'a, B: BeaconNodeAttestation, S: Signer> AttestationProducer<'a, B, S> { - /// Handle outputs and results from attestation production. - pub fn handle_produce_attestation(&mut self, log: slog::Logger) { - match self.produce_attestation() { - Ok(ValidatorEvent::AttestationProduced(_slot)) => { - info!(log, "Attestation produced"; "Validator" => format!("{}", self.signer)) - } - Err(e) => error!(log, "Attestation production error"; "Error" => format!("{:?}", e)), - Ok(ValidatorEvent::SignerRejection(_slot)) => { - error!(log, "Attestation production error"; "Error" => format!("Signer could not sign the attestation")) - } - Ok(ValidatorEvent::SlashableAttestationNotProduced(_slot)) => { - error!(log, "Attestation production error"; "Error" => format!("Rejected the attestation as it could have been slashed")) - } - Ok(ValidatorEvent::BeaconNodeUnableToProduceAttestation(_slot)) => { - error!(log, "Attestation production error"; "Error" => format!("Beacon node was unable to produce an attestation")) - } - Ok(v) => { - warn!(log, "Unknown result for attestation production"; "Error" => format!("{:?}",v)) - } - } - } - - /// Produce an attestation, sign it and send it back - /// - /// Assumes that an attestation 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. - pub fn produce_attestation(&mut self) -> Result { - let epoch = self.duty.slot.epoch(self.spec.slots_per_epoch); - - let attestation = self - .beacon_node - .produce_attestation_data(self.duty.slot, self.duty.shard)?; - if self.safe_to_produce(&attestation) { - let domain = self.spec.get_domain(epoch, Domain::Attestation, &self.fork); - if let Some(attestation) = self.sign_attestation(attestation, self.duty, domain) { - self.beacon_node.publish_attestation(attestation)?; - Ok(ValidatorEvent::AttestationProduced(self.duty.slot)) - } else { - Ok(ValidatorEvent::SignerRejection(self.duty.slot)) - } - } else { - Ok(ValidatorEvent::SlashableAttestationNotProduced( - self.duty.slot, - )) - } - } - - /// Consumes an attestation, returning the attestation signed by the validators private key. - /// - /// Important: this function will not check to ensure the attestation is not slashable. This must be - /// done upstream. - fn sign_attestation( - &mut self, - mut attestation: AttestationData, - duties: AttestationDuty, - domain: u64, - ) -> Option { - self.store_produce(&attestation); - - // build the aggregate signature - let aggregate_signature = { - let message = AttestationDataAndCustodyBit { - data: attestation.clone(), - custody_bit: false, - } - .hash_tree_root(); - - let sig = self.signer.sign_message(&message, domain)?; - - let mut agg_sig = AggregateSignature::new(); - agg_sig.add(&sig); - agg_sig - }; - - let mut aggregation_bitfield = Bitfield::with_capacity(duties.committee_len); - let custody_bitfield = Bitfield::with_capacity(duties.committee_len); - aggregation_bitfield.set(duties.committee_index, true); - - Some(Attestation { - aggregation_bitfield, - data: attestation, - custody_bitfield, - aggregate_signature, - }) - } - - /// Returns `true` if signing an attestation is safe (non-slashable). - /// - /// !!! UNSAFE !!! - /// - /// Important: this function is presently stubbed-out. It provides ZERO SAFETY. - fn safe_to_produce(&self, _attestation: &AttestationData) -> bool { - //TODO: Implement slash protection - true - } - - /// Record that an attestation 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, _attestation: &AttestationData) { - // TODO: Implement slash protection - } -} diff --git a/validator_client/src/block_producer/grpc.rs b/validator_client/src/block_producer/grpc.rs index ab0d5d4210..fd1a70fa2f 100644 --- a/validator_client/src/block_producer/grpc.rs +++ b/validator_client/src/block_producer/grpc.rs @@ -7,6 +7,7 @@ use ssz::{ssz_encode, Decodable}; use std::sync::Arc; use types::{BeaconBlock, Signature, Slot}; +//TODO: Remove this new type. Do not need to wrap /// A newtype designed to wrap the gRPC-generated service so the `BeaconNode` trait may be /// implemented upon it. pub struct BeaconBlockGrpcClient { diff --git a/validator_client/src/main.rs b/validator_client/src/main.rs index 4817667348..7a353e0dcc 100644 --- a/validator_client/src/main.rs +++ b/validator_client/src/main.rs @@ -1,4 +1,4 @@ -mod attester_service; +mod attestation_producer; mod block_producer; mod config; mod duties;