mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-19 21:04:41 +00:00
Initial Interop Updates (#492)
* Add interop chain spec and rename chain_id * Add ability to connect to raw libp2p nodes * Adds Identify protocol, clean up RPC protocol name handling * Update to latest libp2p, gossipsub improvements * Updates to latest interop branch. - Shifts decoding of objects into message handler. - Updates to latest interop gossipsub. - Adds interop spec constant. * Configuration updates allow for verbosity CLI flag and spec constants * Update submodules to master * Correct minimal chainspec modifications * Duplication of validator polls are no longer fatal * Apply PR suggestions
This commit is contained in:
@@ -5,23 +5,21 @@ use crate::rpc::protocol::{InboundFramed, OutboundFramed};
|
||||
use core::marker::PhantomData;
|
||||
use fnv::FnvHashMap;
|
||||
use futures::prelude::*;
|
||||
use libp2p::core::protocols_handler::{
|
||||
use libp2p::core::upgrade::{InboundUpgrade, OutboundUpgrade};
|
||||
use libp2p::swarm::protocols_handler::{
|
||||
KeepAlive, ProtocolsHandler, ProtocolsHandlerEvent, ProtocolsHandlerUpgrErr, SubstreamProtocol,
|
||||
};
|
||||
use libp2p::core::upgrade::{InboundUpgrade, OutboundUpgrade};
|
||||
use smallvec::SmallVec;
|
||||
use std::time::{Duration, Instant};
|
||||
use tokio_io::{AsyncRead, AsyncWrite};
|
||||
use types::EthSpec;
|
||||
|
||||
/// The time (in seconds) before a substream that is awaiting a response times out.
|
||||
pub const RESPONSE_TIMEOUT: u64 = 9;
|
||||
|
||||
/// Implementation of `ProtocolsHandler` for the RPC protocol.
|
||||
pub struct RPCHandler<TSubstream, E>
|
||||
pub struct RPCHandler<TSubstream>
|
||||
where
|
||||
TSubstream: AsyncRead + AsyncWrite,
|
||||
E: EthSpec,
|
||||
{
|
||||
/// The upgrade for inbound substreams.
|
||||
listen_protocol: SubstreamProtocol<RPCProtocol>,
|
||||
@@ -56,8 +54,8 @@ where
|
||||
/// After the given duration has elapsed, an inactive connection will shutdown.
|
||||
inactive_timeout: Duration,
|
||||
|
||||
/// Phantom EthSpec.
|
||||
_phantom: PhantomData<E>,
|
||||
/// Marker to pin the generic stream.
|
||||
_phantom: PhantomData<TSubstream>,
|
||||
}
|
||||
|
||||
/// An outbound substream is waiting a response from the user.
|
||||
@@ -90,10 +88,9 @@ where
|
||||
},
|
||||
}
|
||||
|
||||
impl<TSubstream, E> RPCHandler<TSubstream, E>
|
||||
impl<TSubstream> RPCHandler<TSubstream>
|
||||
where
|
||||
TSubstream: AsyncRead + AsyncWrite,
|
||||
E: EthSpec,
|
||||
{
|
||||
pub fn new(
|
||||
listen_protocol: SubstreamProtocol<RPCProtocol>,
|
||||
@@ -145,20 +142,18 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<TSubstream, E> Default for RPCHandler<TSubstream, E>
|
||||
impl<TSubstream> Default for RPCHandler<TSubstream>
|
||||
where
|
||||
TSubstream: AsyncRead + AsyncWrite,
|
||||
E: EthSpec,
|
||||
{
|
||||
fn default() -> Self {
|
||||
RPCHandler::new(SubstreamProtocol::new(RPCProtocol), Duration::from_secs(30))
|
||||
}
|
||||
}
|
||||
|
||||
impl<TSubstream, E> ProtocolsHandler for RPCHandler<TSubstream, E>
|
||||
impl<TSubstream> ProtocolsHandler for RPCHandler<TSubstream>
|
||||
where
|
||||
TSubstream: AsyncRead + AsyncWrite,
|
||||
E: EthSpec,
|
||||
{
|
||||
type InEvent = RPCEvent;
|
||||
type OutEvent = RPCEvent;
|
||||
@@ -273,7 +268,11 @@ where
|
||||
Self::Error,
|
||||
> {
|
||||
if let Some(err) = self.pending_error.take() {
|
||||
return Err(err);
|
||||
// Returning an error here will result in dropping any peer that doesn't support any of
|
||||
// the RPC protocols. For our immediate purposes we permit this and simply log that an
|
||||
// upgrade was not supported.
|
||||
// TODO: Add a logger to the handler for trace output.
|
||||
dbg!(&err);
|
||||
}
|
||||
|
||||
// return any events that need to be reported
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
|
||||
use futures::prelude::*;
|
||||
use handler::RPCHandler;
|
||||
use libp2p::core::protocols_handler::ProtocolsHandler;
|
||||
use libp2p::core::swarm::{
|
||||
ConnectedPoint, NetworkBehaviour, NetworkBehaviourAction, PollParameters,
|
||||
use libp2p::core::ConnectedPoint;
|
||||
use libp2p::swarm::{
|
||||
protocols_handler::ProtocolsHandler, NetworkBehaviour, NetworkBehaviourAction, PollParameters,
|
||||
};
|
||||
use libp2p::{Multiaddr, PeerId};
|
||||
pub use methods::{ErrorMessage, HelloMessage, RPCErrorResponse, RPCResponse, RequestId};
|
||||
@@ -16,7 +16,6 @@ pub use protocol::{RPCError, RPCProtocol, RPCRequest};
|
||||
use slog::o;
|
||||
use std::marker::PhantomData;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
use types::EthSpec;
|
||||
|
||||
pub(crate) mod codec;
|
||||
mod handler;
|
||||
@@ -50,16 +49,16 @@ impl RPCEvent {
|
||||
|
||||
/// Implements the libp2p `NetworkBehaviour` trait and therefore manages network-level
|
||||
/// logic.
|
||||
pub struct RPC<TSubstream, E: EthSpec> {
|
||||
pub struct RPC<TSubstream> {
|
||||
/// Queue of events to processed.
|
||||
events: Vec<NetworkBehaviourAction<RPCEvent, RPCMessage>>,
|
||||
/// Pins the generic substream.
|
||||
marker: PhantomData<(TSubstream, E)>,
|
||||
marker: PhantomData<(TSubstream)>,
|
||||
/// Slog logger for RPC behaviour.
|
||||
_log: slog::Logger,
|
||||
}
|
||||
|
||||
impl<TSubstream, E: EthSpec> RPC<TSubstream, E> {
|
||||
impl<TSubstream> RPC<TSubstream> {
|
||||
pub fn new(log: &slog::Logger) -> Self {
|
||||
let log = log.new(o!("Service" => "Libp2p-RPC"));
|
||||
RPC {
|
||||
@@ -80,12 +79,11 @@ impl<TSubstream, E: EthSpec> RPC<TSubstream, E> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<TSubstream, E> NetworkBehaviour for RPC<TSubstream, E>
|
||||
impl<TSubstream> NetworkBehaviour for RPC<TSubstream>
|
||||
where
|
||||
TSubstream: AsyncRead + AsyncWrite,
|
||||
E: EthSpec,
|
||||
{
|
||||
type ProtocolsHandler = RPCHandler<TSubstream, E>;
|
||||
type ProtocolsHandler = RPCHandler<TSubstream>;
|
||||
type OutEvent = RPCMessage;
|
||||
|
||||
fn new_handler(&mut self) -> Self::ProtocolsHandler {
|
||||
|
||||
@@ -8,7 +8,7 @@ use futures::{
|
||||
future::{self, FutureResult},
|
||||
sink, stream, Sink, Stream,
|
||||
};
|
||||
use libp2p::core::{upgrade, InboundUpgrade, OutboundUpgrade, UpgradeInfo};
|
||||
use libp2p::core::{upgrade, InboundUpgrade, OutboundUpgrade, ProtocolName, UpgradeInfo};
|
||||
use std::io;
|
||||
use std::time::Duration;
|
||||
use tokio::codec::Framed;
|
||||
@@ -28,24 +28,22 @@ const REQUEST_TIMEOUT: u64 = 3;
|
||||
pub struct RPCProtocol;
|
||||
|
||||
impl UpgradeInfo for RPCProtocol {
|
||||
type Info = RawProtocolId;
|
||||
type Info = ProtocolId;
|
||||
type InfoIter = Vec<Self::Info>;
|
||||
|
||||
fn protocol_info(&self) -> Self::InfoIter {
|
||||
vec![
|
||||
ProtocolId::new("hello", "1.0.0", "ssz").into(),
|
||||
ProtocolId::new("goodbye", "1.0.0", "ssz").into(),
|
||||
ProtocolId::new("beacon_block_roots", "1.0.0", "ssz").into(),
|
||||
ProtocolId::new("beacon_block_headers", "1.0.0", "ssz").into(),
|
||||
ProtocolId::new("beacon_block_bodies", "1.0.0", "ssz").into(),
|
||||
ProtocolId::new("hello", "1.0.0", "ssz"),
|
||||
ProtocolId::new("goodbye", "1.0.0", "ssz"),
|
||||
ProtocolId::new("beacon_block_roots", "1.0.0", "ssz"),
|
||||
ProtocolId::new("beacon_block_headers", "1.0.0", "ssz"),
|
||||
ProtocolId::new("beacon_block_bodies", "1.0.0", "ssz"),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/// The raw protocol id sent over the wire.
|
||||
type RawProtocolId = Vec<u8>;
|
||||
|
||||
/// Tracks the types in a protocol id.
|
||||
#[derive(Clone)]
|
||||
pub struct ProtocolId {
|
||||
/// The rpc message type/name.
|
||||
pub message_name: String,
|
||||
@@ -55,44 +53,31 @@ pub struct ProtocolId {
|
||||
|
||||
/// The encoding of the RPC.
|
||||
pub encoding: String,
|
||||
|
||||
/// The protocol id that is formed from the above fields.
|
||||
protocol_id: String,
|
||||
}
|
||||
|
||||
/// An RPC protocol ID.
|
||||
impl ProtocolId {
|
||||
pub fn new(message_name: &str, version: &str, encoding: &str) -> Self {
|
||||
let protocol_id = format!(
|
||||
"{}/{}/{}/{}",
|
||||
PROTOCOL_PREFIX, message_name, version, encoding
|
||||
);
|
||||
|
||||
ProtocolId {
|
||||
message_name: message_name.into(),
|
||||
version: version.into(),
|
||||
encoding: encoding.into(),
|
||||
protocol_id,
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a raw RPC protocol id string into an `RPCProtocolId`
|
||||
pub fn from_bytes(bytes: &[u8]) -> Result<Self, RPCError> {
|
||||
let protocol_string = String::from_utf8(bytes.to_vec())
|
||||
.map_err(|_| RPCError::InvalidProtocol("Invalid protocol Id"))?;
|
||||
let protocol_list: Vec<&str> = protocol_string.as_str().split('/').take(7).collect();
|
||||
|
||||
if protocol_list.len() != 7 {
|
||||
return Err(RPCError::InvalidProtocol("Not enough '/'"));
|
||||
}
|
||||
|
||||
Ok(ProtocolId {
|
||||
message_name: protocol_list[4].into(),
|
||||
version: protocol_list[5].into(),
|
||||
encoding: protocol_list[6].into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<RawProtocolId> for ProtocolId {
|
||||
fn into(self) -> RawProtocolId {
|
||||
format!(
|
||||
"{}/{}/{}/{}",
|
||||
PROTOCOL_PREFIX, self.message_name, self.version, self.encoding
|
||||
)
|
||||
.as_bytes()
|
||||
.to_vec()
|
||||
impl ProtocolName for ProtocolId {
|
||||
fn protocol_name(&self) -> &[u8] {
|
||||
self.protocol_id.as_bytes()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,16 +112,11 @@ where
|
||||
fn upgrade_inbound(
|
||||
self,
|
||||
socket: upgrade::Negotiated<TSocket>,
|
||||
protocol: RawProtocolId,
|
||||
protocol: ProtocolId,
|
||||
) -> Self::Future {
|
||||
// TODO: Verify this
|
||||
let protocol_id =
|
||||
ProtocolId::from_bytes(&protocol).expect("Can decode all supported protocols");
|
||||
|
||||
match protocol_id.encoding.as_str() {
|
||||
match protocol.encoding.as_str() {
|
||||
"ssz" | _ => {
|
||||
let ssz_codec =
|
||||
BaseInboundCodec::new(SSZInboundCodec::new(protocol_id, MAX_RPC_SIZE));
|
||||
let ssz_codec = BaseInboundCodec::new(SSZInboundCodec::new(protocol, MAX_RPC_SIZE));
|
||||
let codec = InboundCodec::SSZ(ssz_codec);
|
||||
Framed::new(socket, codec)
|
||||
.into_future()
|
||||
@@ -171,7 +151,7 @@ pub enum RPCRequest {
|
||||
}
|
||||
|
||||
impl UpgradeInfo for RPCRequest {
|
||||
type Info = RawProtocolId;
|
||||
type Info = ProtocolId;
|
||||
type InfoIter = Vec<Self::Info>;
|
||||
|
||||
// add further protocols as we support more encodings/versions
|
||||
@@ -182,22 +162,25 @@ impl UpgradeInfo for RPCRequest {
|
||||
|
||||
/// Implements the encoding per supported protocol for RPCRequest.
|
||||
impl RPCRequest {
|
||||
pub fn supported_protocols(&self) -> Vec<RawProtocolId> {
|
||||
pub fn supported_protocols(&self) -> Vec<ProtocolId> {
|
||||
match self {
|
||||
// add more protocols when versions/encodings are supported
|
||||
RPCRequest::Hello(_) => vec![ProtocolId::new("hello", "1.0.0", "ssz").into()],
|
||||
RPCRequest::Goodbye(_) => vec![ProtocolId::new("goodbye", "1.0.0", "ssz").into()],
|
||||
RPCRequest::Hello(_) => vec![
|
||||
ProtocolId::new("hello", "1.0.0", "ssz"),
|
||||
ProtocolId::new("goodbye", "1.0.0", "ssz"),
|
||||
],
|
||||
RPCRequest::Goodbye(_) => vec![ProtocolId::new("goodbye", "1.0.0", "ssz")],
|
||||
RPCRequest::BeaconBlockRoots(_) => {
|
||||
vec![ProtocolId::new("beacon_block_roots", "1.0.0", "ssz").into()]
|
||||
vec![ProtocolId::new("beacon_block_roots", "1.0.0", "ssz")]
|
||||
}
|
||||
RPCRequest::BeaconBlockHeaders(_) => {
|
||||
vec![ProtocolId::new("beacon_block_headers", "1.0.0", "ssz").into()]
|
||||
vec![ProtocolId::new("beacon_block_headers", "1.0.0", "ssz")]
|
||||
}
|
||||
RPCRequest::BeaconBlockBodies(_) => {
|
||||
vec![ProtocolId::new("beacon_block_bodies", "1.0.0", "ssz").into()]
|
||||
vec![ProtocolId::new("beacon_block_bodies", "1.0.0", "ssz")]
|
||||
}
|
||||
RPCRequest::BeaconChainState(_) => {
|
||||
vec![ProtocolId::new("beacon_block_state", "1.0.0", "ssz").into()]
|
||||
vec![ProtocolId::new("beacon_block_state", "1.0.0", "ssz")]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -230,12 +213,9 @@ where
|
||||
socket: upgrade::Negotiated<TSocket>,
|
||||
protocol: Self::Info,
|
||||
) -> Self::Future {
|
||||
let protocol_id =
|
||||
ProtocolId::from_bytes(&protocol).expect("Can decode all supported protocols");
|
||||
|
||||
match protocol_id.encoding.as_str() {
|
||||
match protocol.encoding.as_str() {
|
||||
"ssz" | _ => {
|
||||
let ssz_codec = BaseOutboundCodec::new(SSZOutboundCodec::new(protocol_id, 4096));
|
||||
let ssz_codec = BaseOutboundCodec::new(SSZOutboundCodec::new(protocol, 4096));
|
||||
let codec = OutboundCodec::SSZ(ssz_codec);
|
||||
Framed::new(socket, codec).send(self)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user