mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-14 10:22:38 +00:00
* 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
165 lines
5.0 KiB
Rust
165 lines
5.0 KiB
Rust
//! The Ethereum 2.0 Wire Protocol
|
|
//!
|
|
//! This protocol is a purpose built Ethereum 2.0 libp2p protocol. It's role is to facilitate
|
|
//! direct peer-to-peer communication primarily for sending/receiving chain information for
|
|
//! syncing.
|
|
|
|
use futures::prelude::*;
|
|
use handler::RPCHandler;
|
|
use libp2p::core::ConnectedPoint;
|
|
use libp2p::swarm::{
|
|
protocols_handler::ProtocolsHandler, NetworkBehaviour, NetworkBehaviourAction, PollParameters,
|
|
SubstreamProtocol,
|
|
};
|
|
use libp2p::{Multiaddr, PeerId};
|
|
pub use methods::{
|
|
ErrorMessage, RPCErrorResponse, RPCResponse, RequestId, ResponseTermination, StatusMessage,
|
|
};
|
|
pub use protocol::{RPCError, RPCProtocol, RPCRequest};
|
|
use slog::o;
|
|
use std::marker::PhantomData;
|
|
use std::time::Duration;
|
|
use tokio::io::{AsyncRead, AsyncWrite};
|
|
|
|
pub(crate) mod codec;
|
|
mod handler;
|
|
pub mod methods;
|
|
mod protocol;
|
|
|
|
/// The return type used in the behaviour and the resultant event from the protocols handler.
|
|
#[derive(Debug)]
|
|
pub enum RPCEvent {
|
|
/// An inbound/outbound request for RPC protocol. The first parameter is a sequential
|
|
/// id which tracks an awaiting substream for the response.
|
|
Request(RequestId, RPCRequest),
|
|
/// A response that is being sent or has been received from the RPC protocol. The first parameter returns
|
|
/// that which was sent with the corresponding request, the second is a single chunk of a
|
|
/// response.
|
|
Response(RequestId, RPCErrorResponse),
|
|
/// An Error occurred.
|
|
Error(RequestId, RPCError),
|
|
}
|
|
|
|
impl RPCEvent {
|
|
pub fn id(&self) -> usize {
|
|
match *self {
|
|
RPCEvent::Request(id, _) => id,
|
|
RPCEvent::Response(id, _) => id,
|
|
RPCEvent::Error(id, _) => id,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Display for RPCEvent {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
RPCEvent::Request(id, req) => write!(f, "RPC Request(id: {}, {})", id, req),
|
|
RPCEvent::Response(id, res) => write!(f, "RPC Response(id: {}, {})", id, res),
|
|
RPCEvent::Error(id, err) => write!(f, "RPC Request(id: {}, error: {:?})", id, err),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Implements the libp2p `NetworkBehaviour` trait and therefore manages network-level
|
|
/// logic.
|
|
pub struct RPC<TSubstream> {
|
|
/// Queue of events to processed.
|
|
events: Vec<NetworkBehaviourAction<RPCEvent, RPCMessage>>,
|
|
/// Pins the generic substream.
|
|
marker: PhantomData<(TSubstream)>,
|
|
/// Slog logger for RPC behaviour.
|
|
log: slog::Logger,
|
|
}
|
|
|
|
impl<TSubstream> RPC<TSubstream> {
|
|
pub fn new(log: slog::Logger) -> Self {
|
|
let log = log.new(o!("service" => "libp2p_rpc"));
|
|
RPC {
|
|
events: Vec::new(),
|
|
marker: PhantomData,
|
|
log: log,
|
|
}
|
|
}
|
|
|
|
/// Submits an RPC request.
|
|
///
|
|
/// The peer must be connected for this to succeed.
|
|
pub fn send_rpc(&mut self, peer_id: PeerId, rpc_event: RPCEvent) {
|
|
self.events.push(NetworkBehaviourAction::SendEvent {
|
|
peer_id,
|
|
event: rpc_event,
|
|
});
|
|
}
|
|
}
|
|
|
|
impl<TSubstream> NetworkBehaviour for RPC<TSubstream>
|
|
where
|
|
TSubstream: AsyncRead + AsyncWrite,
|
|
{
|
|
type ProtocolsHandler = RPCHandler<TSubstream>;
|
|
type OutEvent = RPCMessage;
|
|
|
|
fn new_handler(&mut self) -> Self::ProtocolsHandler {
|
|
RPCHandler::new(
|
|
SubstreamProtocol::new(RPCProtocol),
|
|
Duration::from_secs(30),
|
|
&self.log,
|
|
)
|
|
}
|
|
|
|
// handled by discovery
|
|
fn addresses_of_peer(&mut self, _peer_id: &PeerId) -> Vec<Multiaddr> {
|
|
Vec::new()
|
|
}
|
|
|
|
fn inject_connected(&mut self, peer_id: PeerId, connected_point: ConnectedPoint) {
|
|
// if initialised the connection, report this upwards to send the HELLO request
|
|
if let ConnectedPoint::Dialer { .. } = connected_point {
|
|
self.events.push(NetworkBehaviourAction::GenerateEvent(
|
|
RPCMessage::PeerDialed(peer_id),
|
|
));
|
|
}
|
|
}
|
|
|
|
fn inject_disconnected(&mut self, peer_id: &PeerId, _: ConnectedPoint) {
|
|
// inform the rpc handler that the peer has disconnected
|
|
self.events.push(NetworkBehaviourAction::GenerateEvent(
|
|
RPCMessage::PeerDisconnected(peer_id.clone()),
|
|
));
|
|
}
|
|
|
|
fn inject_node_event(
|
|
&mut self,
|
|
source: PeerId,
|
|
event: <Self::ProtocolsHandler as ProtocolsHandler>::OutEvent,
|
|
) {
|
|
// send the event to the user
|
|
self.events
|
|
.push(NetworkBehaviourAction::GenerateEvent(RPCMessage::RPC(
|
|
source, event,
|
|
)));
|
|
}
|
|
|
|
fn poll(
|
|
&mut self,
|
|
_: &mut impl PollParameters,
|
|
) -> Async<
|
|
NetworkBehaviourAction<
|
|
<Self::ProtocolsHandler as ProtocolsHandler>::InEvent,
|
|
Self::OutEvent,
|
|
>,
|
|
> {
|
|
if !self.events.is_empty() {
|
|
return Async::Ready(self.events.remove(0));
|
|
}
|
|
Async::NotReady
|
|
}
|
|
}
|
|
|
|
/// Messages sent to the user from the RPC protocol.
|
|
pub enum RPCMessage {
|
|
RPC(PeerId, RPCEvent),
|
|
PeerDialed(PeerId),
|
|
PeerDisconnected(PeerId),
|
|
}
|