Testnet compatible network upgrade (#587)

* Create libp2p instance

* Change logger to stdlog

* test_connection initial commit

* Add gossipsub test

* Delete tests in network crate

* Add test module

* Clean tests

* Remove dependency on discovery

* Working publish between 2 nodes
TODO: Publish should be called just once

* Working 2 peer gossipsub test with additional events

* Cleanup test

* Add rpc test

* Star topology discovery WIP

* build_nodes builds and connects n nodes. Increase nodes in gossipsub test

* Add unsubscribe method and expose reference to gossipsub object for gossipsub tests

* Add gossipsub message forwarding test

* Fix gossipsub forward test

* Test improvements
* Remove discovery tests
* Simplify gossipsub forward test topology
* Add helper functions for topology building

* Clean up tests

* Update naming to new network spec

* Correct ssz encoding of protocol names

* Further additions to network upgrade

* Initial network spec update WIP

* Temp commit

* Builds one side of the streamed RPC responses

* Temporary commit

* Propagates streaming changes up into message handler

* Intermediate network update

* Partial update in upgrading to the new network spec

* Update dependencies, remove redundant deps

* Correct sync manager for block stream handling

* Re-write of RPC handler, improves efficiency and corrects bugs

* Stream termination update

* Completed refactor of rpc handler

* Remove crates

* Correct compile issues associated with test merge

* Build basic tests and testing structure for eth2-libp2p

* Enhance RPC tests and add logging

* Complete RPC testing framework and STATUS test

* Decoding bug fixes, log improvements, stream test

* Clean up RPC handler logging

* Decoder bug fix, empty block stream test

* Add BlocksByRoot RPC test

* Add Goodbye RPC test

* Syncing and stream handling bug fixes and performance improvements

* Applies discv5 bug fixes

* Adds DHT IP filtering for lighthouse - currently disabled

* Adds randomized network propagation as a CLI arg

* Add disconnect functionality

* Adds attestation handling and parent lookup

* Adds RPC error handling for the sync manager

* Allow parent's blocks to be already processed

* Update github workflow

* Adds reviewer suggestions
This commit is contained in:
Age Manning
2019-11-27 12:47:46 +11:00
committed by Paul Hauner
parent bf2eeae3f2
commit 97aa8b75b8
25 changed files with 2239 additions and 659 deletions

View File

@@ -1,8 +1,11 @@
use super::methods::*;
use crate::rpc::codec::{
base::{BaseInboundCodec, BaseOutboundCodec},
ssz::{SSZInboundCodec, SSZOutboundCodec},
InboundCodec, OutboundCodec,
use crate::rpc::{
codec::{
base::{BaseInboundCodec, BaseOutboundCodec},
ssz::{SSZInboundCodec, SSZOutboundCodec},
InboundCodec, OutboundCodec,
},
methods::ResponseTermination,
};
use futures::{
future::{self, FutureResult},
@@ -37,10 +40,10 @@ impl UpgradeInfo for RPCProtocol {
fn protocol_info(&self) -> Self::InfoIter {
vec![
ProtocolId::new("hello", "1", "ssz"),
ProtocolId::new("status", "1", "ssz"),
ProtocolId::new("goodbye", "1", "ssz"),
ProtocolId::new("beacon_blocks", "1", "ssz"),
ProtocolId::new("recent_beacon_blocks", "1", "ssz"),
ProtocolId::new("blocks_by_range", "1", "ssz"),
ProtocolId::new("blocks_by_root", "1", "ssz"),
]
}
}
@@ -145,12 +148,12 @@ where
// Combines all the RPC requests into a single enum to implement `UpgradeInfo` and
// `OutboundUpgrade`
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq)]
pub enum RPCRequest {
Hello(HelloMessage),
Status(StatusMessage),
Goodbye(GoodbyeReason),
BeaconBlocks(BeaconBlocksRequest),
RecentBeaconBlocks(RecentBeaconBlocksRequest),
BlocksByRange(BlocksByRangeRequest),
BlocksByRoot(BlocksByRootRequest),
}
impl UpgradeInfo for RPCRequest {
@@ -168,21 +171,47 @@ impl RPCRequest {
pub fn supported_protocols(&self) -> Vec<ProtocolId> {
match self {
// add more protocols when versions/encodings are supported
RPCRequest::Hello(_) => vec![ProtocolId::new("hello", "1", "ssz")],
RPCRequest::Status(_) => vec![ProtocolId::new("status", "1", "ssz")],
RPCRequest::Goodbye(_) => vec![ProtocolId::new("goodbye", "1", "ssz")],
RPCRequest::BeaconBlocks(_) => vec![ProtocolId::new("beacon_blocks", "1", "ssz")],
RPCRequest::RecentBeaconBlocks(_) => {
vec![ProtocolId::new("recent_beacon_blocks", "1", "ssz")]
}
RPCRequest::BlocksByRange(_) => vec![ProtocolId::new("blocks_by_range", "1", "ssz")],
RPCRequest::BlocksByRoot(_) => vec![ProtocolId::new("blocks_by_root", "1", "ssz")],
}
}
/* These functions are used in the handler for stream management */
/// This specifies whether a stream should remain open and await a response, given a request.
/// A GOODBYE request has no response.
pub fn expect_response(&self) -> bool {
match self {
RPCRequest::Status(_) => true,
RPCRequest::Goodbye(_) => false,
_ => true,
RPCRequest::BlocksByRange(_) => true,
RPCRequest::BlocksByRoot(_) => true,
}
}
/// Returns which methods expect multiple responses from the stream. If this is false and
/// the stream terminates, an error is given.
pub fn multiple_responses(&self) -> bool {
match self {
RPCRequest::Status(_) => false,
RPCRequest::Goodbye(_) => false,
RPCRequest::BlocksByRange(_) => true,
RPCRequest::BlocksByRoot(_) => true,
}
}
/// Returns the `ResponseTermination` type associated with the request if a stream gets
/// terminated.
pub fn stream_termination(&self) -> ResponseTermination {
match self {
// this only gets called after `multiple_responses()` returns true. Therefore, only
// variants that have `multiple_responses()` can have values.
RPCRequest::BlocksByRange(_) => ResponseTermination::BlocksByRange,
RPCRequest::BlocksByRoot(_) => ResponseTermination::BlocksByRoot,
RPCRequest::Status(_) => unreachable!(),
RPCRequest::Goodbye(_) => unreachable!(),
}
}
}
@@ -229,6 +258,8 @@ pub enum RPCError {
IoError(io::Error),
/// Waiting for a request/response timed out, or timer error'd.
StreamTimeout,
/// The peer returned a valid RPCErrorResponse but the response was an error.
RPCErrorResponse,
/// Custom message.
Custom(String),
}
@@ -256,6 +287,12 @@ impl<T> From<tokio::timer::timeout::Error<T>> for RPCError {
}
}
impl From<()> for RPCError {
fn from(_err: ()) -> Self {
RPCError::Custom("".into())
}
}
impl From<io::Error> for RPCError {
fn from(err: io::Error) -> Self {
RPCError::IoError(err)
@@ -270,6 +307,7 @@ impl std::fmt::Display for RPCError {
RPCError::SSZDecodeError(ref err) => write!(f, "Error while decoding ssz: {:?}", err),
RPCError::InvalidProtocol(ref err) => write!(f, "Invalid Protocol: {}", err),
RPCError::IoError(ref err) => write!(f, "IO Error: {}", err),
RPCError::RPCErrorResponse => write!(f, "RPC Response Error"),
RPCError::StreamTimeout => write!(f, "Stream Timeout"),
RPCError::Custom(ref err) => write!(f, "{}", err),
}
@@ -284,6 +322,7 @@ impl std::error::Error for RPCError {
RPCError::InvalidProtocol(_) => None,
RPCError::IoError(ref err) => Some(err),
RPCError::StreamTimeout => None,
RPCError::RPCErrorResponse => None,
RPCError::Custom(_) => None,
}
}
@@ -292,10 +331,10 @@ impl std::error::Error for RPCError {
impl std::fmt::Display for RPCRequest {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
RPCRequest::Hello(hello) => write!(f, "Hello Message: {}", hello),
RPCRequest::Status(status) => write!(f, "Status Message: {}", status),
RPCRequest::Goodbye(reason) => write!(f, "Goodbye: {}", reason),
RPCRequest::BeaconBlocks(req) => write!(f, "Beacon Blocks: {}", req),
RPCRequest::RecentBeaconBlocks(req) => write!(f, "Recent Beacon Blocks: {:?}", req),
RPCRequest::BlocksByRange(req) => write!(f, "Blocks by range: {}", req),
RPCRequest::BlocksByRoot(req) => write!(f, "Blocks by root: {:?}", req),
}
}
}