From 4cdeb6abe50f96860921eaab58d938e75793b423 Mon Sep 17 00:00:00 2001 From: Luke Anderson Date: Mon, 25 Mar 2019 18:32:27 +1100 Subject: [PATCH] Progress towards validator signing attestations. - Added a 'beacon_attester' RPC endpoint, so the BeaconNode can supply attestation data. - Renamed 'attestation_data' to just 'attestation' throughout (except where it is actually just the data structure). --- beacon_node/beacon_chain/src/beacon_chain.rs | 4 +- .../validator_harness/direct_beacon_node.rs | 6 +- beacon_node/rpc/src/beacon_attester.rs | 61 +++++++++++++++++++ eth2/attester/src/lib.rs | 4 +- .../src/test_utils/simulated_beacon_node.rs | 4 +- eth2/attester/src/traits.rs | 4 +- protos/src/services.proto | 18 +++--- .../attestation_grpc_client.rs | 12 ++-- 8 files changed, 87 insertions(+), 26 deletions(-) create mode 100644 beacon_node/rpc/src/beacon_attester.rs diff --git a/beacon_node/beacon_chain/src/beacon_chain.rs b/beacon_node/beacon_chain/src/beacon_chain.rs index 816a570c0..61b5fb58b 100644 --- a/beacon_node/beacon_chain/src/beacon_chain.rs +++ b/beacon_node/beacon_chain/src/beacon_chain.rs @@ -280,8 +280,8 @@ where } /// Produce an `AttestationData` that is valid for the present `slot` and given `shard`. - pub fn produce_attestation_data(&self, shard: u64) -> Result { - trace!("BeaconChain::produce_attestation_data: shard: {}", shard); + pub fn produce_attestation(&self, shard: u64) -> Result { + trace!("BeaconChain::produce_attestation: shard: {}", shard); let source_epoch = self.state.read().current_justified_epoch; let source_root = *self.state.read().get_block_root( source_epoch.start_slot(self.spec.slots_per_epoch), diff --git a/beacon_node/beacon_chain/test_harness/src/validator_harness/direct_beacon_node.rs b/beacon_node/beacon_chain/test_harness/src/validator_harness/direct_beacon_node.rs index d2de354d7..fde8211ab 100644 --- a/beacon_node/beacon_chain/test_harness/src/validator_harness/direct_beacon_node.rs +++ b/beacon_node/beacon_chain/test_harness/src/validator_harness/direct_beacon_node.rs @@ -50,18 +50,18 @@ impl DirectBeaconNode { } impl AttesterBeaconNode for DirectBeaconNode { - fn produce_attestation_data( + fn produce_attestation( &self, _slot: Slot, shard: u64, ) -> Result, NodeError> { - match self.beacon_chain.produce_attestation_data(shard) { + match self.beacon_chain.produce_attestation(shard) { Ok(attestation_data) => Ok(Some(attestation_data)), Err(e) => Err(NodeError::RemoteFailure(format!("{:?}", e))), } } - fn publish_attestation_data( + fn publish_attestation( &self, free_attestation: FreeAttestation, ) -> Result { diff --git a/beacon_node/rpc/src/beacon_attester.rs b/beacon_node/rpc/src/beacon_attester.rs new file mode 100644 index 000000000..36b6a40b2 --- /dev/null +++ b/beacon_node/rpc/src/beacon_attester.rs @@ -0,0 +1,61 @@ +use futures::Future; +use grpcio::{RpcContext, UnarySink}; +use protos::services::{ + Attestation as AttestationProto, ProduceAttestation, ProduceAttestationResponse, + ProduceAttestationRequest, PublishAttestationResponse, PublishAttestationRequest, + PublishAttestation +}; +use protos::services_grpc::BeaconBlockService; +use slog::Logger; + +#[derive(Clone)] +pub struct AttestationServiceInstance { + pub log: Logger, +} + +impl AttestationService for AttestationServiceInstance { + /// Produce a `BeaconBlock` for signing by a validator. + fn produce_attestation( + &mut self, + ctx: RpcContext, + req: ProduceAttestationRequest, + sink: UnarySink, + ) { + println!("producing attestation at slot {}", req.get_slot()); + + // TODO: build a legit block. + let mut attestation = AttestationProto::new(); + attestation.set_slot(req.get_slot()); + // TODO Set the shard to something legit. + attestation.set_shard(0); + attestation.set_block_root(b"cats".to_vec()); + + let mut resp = ProduceAttestationResponse::new(); + resp.set_attestation_data(attestation); + + 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_attestation( + &mut self, + ctx: RpcContext, + req: PublishAttestationRequest, + sink: UnarySink, + ) { + println!("publishing attestation {:?}", req.get_block()); + + // TODO: actually process the block. + let mut resp = PublishAttestationResponse::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/eth2/attester/src/lib.rs b/eth2/attester/src/lib.rs index 8838f022d..065fdc923 100644 --- a/eth2/attester/src/lib.rs +++ b/eth2/attester/src/lib.rs @@ -94,7 +94,7 @@ impl Attester Result { - let attestation_data = match self.beacon_node.produce_attestation_data(slot, shard)? { + let attestation_data = match self.beacon_node.produce_attestation(slot, shard)? { Some(attestation_data) => attestation_data, None => return Ok(PollOutcome::BeaconNodeUnableToProduceAttestation(slot)), }; @@ -120,7 +120,7 @@ impl Attester ProduceResult { + fn produce_attestation(&self, slot: Slot, shard: u64) -> ProduceResult { *self.produce_input.write().unwrap() = Some((slot, shard)); match *self.produce_result.read().unwrap() { Some(ref r) => r.clone(), @@ -34,7 +34,7 @@ impl BeaconNode for SimulatedBeaconNode { } } - fn publish_attestation_data(&self, free_attestation: FreeAttestation) -> PublishResult { + fn publish_attestation(&self, free_attestation: FreeAttestation) -> PublishResult { *self.publish_input.write().unwrap() = Some(free_attestation.clone()); match *self.publish_result.read().unwrap() { Some(ref r) => r.clone(), diff --git a/eth2/attester/src/traits.rs b/eth2/attester/src/traits.rs index 6062460cb..749c6e1a2 100644 --- a/eth2/attester/src/traits.rs +++ b/eth2/attester/src/traits.rs @@ -14,13 +14,13 @@ pub enum PublishOutcome { /// Defines the methods required to produce and publish blocks on a Beacon Node. pub trait BeaconNode: Send + Sync { - fn produce_attestation_data( + fn produce_attestation( &self, slot: Slot, shard: u64, ) -> Result, BeaconNodeError>; - fn publish_attestation_data( + fn publish_attestation( &self, free_attestation: FreeAttestation, ) -> Result; diff --git a/protos/src/services.proto b/protos/src/services.proto index fbcde922d..80d512c54 100644 --- a/protos/src/services.proto +++ b/protos/src/services.proto @@ -33,8 +33,8 @@ service ValidatorService { /// Service that handles validator attestations service AttestationService { - rpc ProduceAttestationData (ProduceAttestationDataRequest) returns (ProduceAttestationDataResponse); - rpc PublishAttestationData (PublishAttestationDataRequest) returns (PublishAttestationDataResponse); + rpc ProduceAttestation(ProduceAttestationRequest) returns (ProduceAttestationResponse); + rpc PublishAttestation(PublishAttestationRequest) returns (PublishAttestationResponse); } /* @@ -138,20 +138,20 @@ message ProposeBlockSlotResponse { * Attestation Service Messages */ -message ProduceAttestationDataRequest { +message ProduceAttestationRequest { uint64 slot = 1; uint64 shard = 2; } -message ProduceAttestationDataResponse { - AttestationData attestation_data = 1; +message ProduceAttestationResponse { + Attestation attestation_data = 1; } -message PublishAttestationDataRequest { +message PublishAttestationRequest { FreeAttestation free_attestation = 1; } -message PublishAttestationDataResponse { +message PublishAttestationResponse { bool success = 1; bytes msg = 2; } @@ -162,7 +162,7 @@ message Crosslink { } -message AttestationData { +message Attestation { uint64 slot = 1; uint64 shard = 2; bytes beacon_block_root = 3; @@ -175,7 +175,7 @@ message AttestationData { } message FreeAttestation { - AttestationData attestation_data = 1; + Attestation attestation_data = 1; bytes signature = 2; uint64 validator_index = 3; } diff --git a/validator_client/src/attester_service/attestation_grpc_client.rs b/validator_client/src/attester_service/attestation_grpc_client.rs index 566d74a39..5a4701ba9 100644 --- a/validator_client/src/attester_service/attestation_grpc_client.rs +++ b/validator_client/src/attester_service/attestation_grpc_client.rs @@ -2,7 +2,7 @@ use protos::services_grpc::AttestationServiceClient; use std::sync::Arc; use attester::{BeaconNode, BeaconNodeError, PublishOutcome}; -use protos::services::ProduceAttestationDataRequest; +use protos::services::ProduceAttestationRequest; use types::{AttestationData, FreeAttestation, Slot}; pub struct AttestationGrpcClient { @@ -16,25 +16,25 @@ impl AttestationGrpcClient { } impl BeaconNode for AttestationGrpcClient { - fn produce_attestation_data( + fn produce_attestation( &self, slot: Slot, shard: u64, ) -> Result, BeaconNodeError> { - let mut req = ProduceAttestationDataRequest::new(); + let mut req = ProduceAttestationRequest::new(); req.set_slot(slot.as_u64()); req.set_shard(shard); let reply = self .client - .produce_attestation_data(&req) + .produce_attestation(&req) .map_err(|err| BeaconNodeError::RemoteFailure(format!("{:?}", err)))?; - // TODO: return correct AttestationData + // TODO: return correct Attestation Err(BeaconNodeError::DecodeFailure) } - fn publish_attestation_data( + fn publish_attestation( &self, free_attestation: FreeAttestation, ) -> Result {