From 796b68dc042920a49336aa646cbb04ed16da1add Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Sun, 24 Mar 2019 17:51:32 +1100 Subject: [PATCH] Implement Goodbye and BeaconState msg handlers --- beacon_node/eth2-libp2p/src/rpc/methods.rs | 52 ++++++++++++++++++++- beacon_node/eth2-libp2p/src/rpc/protocol.rs | 4 +- beacon_node/network/src/message_handler.rs | 22 ++++++--- beacon_node/network/src/sync/simple_sync.rs | 10 ++++ 4 files changed, 79 insertions(+), 9 deletions(-) diff --git a/beacon_node/eth2-libp2p/src/rpc/methods.rs b/beacon_node/eth2-libp2p/src/rpc/methods.rs index f6a5f2829..85ef7e06f 100644 --- a/beacon_node/eth2-libp2p/src/rpc/methods.rs +++ b/beacon_node/eth2-libp2p/src/rpc/methods.rs @@ -1,3 +1,4 @@ +use ssz::{Decodable, DecodeError, Encodable, SszStream}; /// Available RPC methods types and ids. use ssz_derive::{Decode, Encode}; use types::{BeaconBlockBody, BeaconBlockHeader, Epoch, Hash256, Slot}; @@ -53,7 +54,7 @@ impl Into for RPCMethod { #[derive(Debug, Clone)] pub enum RPCRequest { Hello(HelloMessage), - Goodbye(u64), + Goodbye(GoodbyeReason), BeaconBlockRoots(BeaconBlockRootsRequest), BeaconBlockHeaders(BeaconBlockHeadersRequest), BeaconBlockBodies(BeaconBlockBodiesRequest), @@ -113,6 +114,55 @@ pub struct HelloMessage { pub best_slot: Slot, } +/// The reason given for a `Goodbye` message. +/// +/// Note: any unknown `u64::into(n)` will resolve to `GoodbyeReason::Unknown` for any unknown `n`, +/// however `GoodbyeReason::Unknown.into()` will go into `0_u64`. Therefore de-serializing then +/// re-serializing may not return the same bytes. +#[derive(Debug, Clone)] +pub enum GoodbyeReason { + ClientShutdown, + IrreleventNetwork, + Fault, + Unknown, +} + +impl From for GoodbyeReason { + fn from(id: u64) -> GoodbyeReason { + match id { + 1 => GoodbyeReason::ClientShutdown, + 2 => GoodbyeReason::IrreleventNetwork, + 3 => GoodbyeReason::Fault, + _ => GoodbyeReason::Unknown, + } + } +} + +impl Into for GoodbyeReason { + fn into(self) -> u64 { + match self { + GoodbyeReason::Unknown => 0, + GoodbyeReason::ClientShutdown => 1, + GoodbyeReason::IrreleventNetwork => 2, + GoodbyeReason::Fault => 3, + } + } +} + +impl Encodable for GoodbyeReason { + fn ssz_append(&self, s: &mut SszStream) { + let id: u64 = (*self).clone().into(); + id.ssz_append(s); + } +} + +impl Decodable for GoodbyeReason { + fn ssz_decode(bytes: &[u8], index: usize) -> Result<(Self, usize), DecodeError> { + let (id, index) = u64::ssz_decode(bytes, index)?; + Ok((Self::from(id), index)) + } +} + /// Request a number of beacon block roots from a peer. #[derive(Encode, Decode, Clone, Debug, PartialEq)] pub struct BeaconBlockRootsRequest { diff --git a/beacon_node/eth2-libp2p/src/rpc/protocol.rs b/beacon_node/eth2-libp2p/src/rpc/protocol.rs index f4fe26fac..b328dd0dd 100644 --- a/beacon_node/eth2-libp2p/src/rpc/protocol.rs +++ b/beacon_node/eth2-libp2p/src/rpc/protocol.rs @@ -82,8 +82,8 @@ fn decode(packet: Vec) -> Result { RPCRequest::Hello(hello_body) } RPCMethod::Goodbye => { - let (goodbye_code, _index) = u64::ssz_decode(&packet, index)?; - RPCRequest::Goodbye(goodbye_code) + let (goodbye_reason, _index) = GoodbyeReason::ssz_decode(&packet, index)?; + RPCRequest::Goodbye(goodbye_reason) } RPCMethod::BeaconBlockRoots => { let (block_roots_request, _index) = diff --git a/beacon_node/network/src/message_handler.rs b/beacon_node/network/src/message_handler.rs index 77a2ab8db..57923b2c3 100644 --- a/beacon_node/network/src/message_handler.rs +++ b/beacon_node/network/src/message_handler.rs @@ -107,13 +107,14 @@ impl MessageHandler { } /// A new RPC request has been received from the network. - fn handle_rpc_request(&mut self, peer_id: PeerId, id: u64, request: RPCRequest) { - // TODO: ensure the id is legit + fn handle_rpc_request(&mut self, peer_id: PeerId, _id: u64, request: RPCRequest) { + // TODO: process the `id`. match request { RPCRequest::Hello(hello_message) => { self.sync .on_hello_request(peer_id, hello_message, &mut self.network_context) } + RPCRequest::Goodbye(goodbye_reason) => self.sync.on_goodbye(peer_id, goodbye_reason), RPCRequest::BeaconBlockRoots(request) => { self.sync .on_beacon_block_roots_request(peer_id, request, &mut self.network_context) @@ -128,8 +129,11 @@ impl MessageHandler { request, &mut self.network_context, ), - // TODO: Handle all requests - _ => panic!("Unknown request: {:?}", request), + RPCRequest::BeaconChainState(_) => { + // We do not implement this endpoint, it is not required and will only likely be + // useful for light-client support in later phases. + warn!(self.log, "BeaconChainState RPC call is not supported."); + } } } @@ -172,8 +176,14 @@ impl MessageHandler { &mut self.network_context, ); } - // TODO: Handle all responses - _ => panic!("Unknown response: {:?}", response), + RPCResponse::BeaconChainState(_) => { + // We do not implement this endpoint, it is not required and will only likely be + // useful for light-client support in later phases. + // + // Theoretically, we shouldn't reach this code because we should never send a + // beacon state RPC request. + warn!(self.log, "BeaconChainState RPC call is not supported."); + } }; } } diff --git a/beacon_node/network/src/sync/simple_sync.rs b/beacon_node/network/src/sync/simple_sync.rs index 76d630b9a..14564aa37 100644 --- a/beacon_node/network/src/sync/simple_sync.rs +++ b/beacon_node/network/src/sync/simple_sync.rs @@ -119,6 +119,16 @@ impl SimpleSync { } } + pub fn on_goodbye(&mut self, peer_id: PeerId, reason: GoodbyeReason) { + info!( + self.log, "PeerGoodbye"; + "peer" => format!("{:?}", peer_id), + "reason" => format!("{:?}", reason), + ); + + self.known_peers.remove(&peer_id); + } + pub fn on_connect(&self, peer_id: PeerId, network: &mut NetworkContext) { info!(self.log, "PeerConnect"; "peer" => format!("{:?}", peer_id));