mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
chore(net): deny unused and cleanup (#289)
This commit is contained in:
@ -24,11 +24,11 @@ pub struct Discovery {
|
||||
/// Local ENR of the discovery service.
|
||||
local_enr: NodeRecord,
|
||||
/// Handler to interact with the Discovery v4 service
|
||||
discv4: Discv4,
|
||||
_discv4: Discv4,
|
||||
/// All KAD table updates from the discv4 service.
|
||||
discv4_updates: ReceiverStream<TableUpdate>,
|
||||
/// The initial config for the discv4 service
|
||||
dsicv4_config: Discv4Config,
|
||||
_dsicv4_config: Discv4Config,
|
||||
/// Events buffered until polled.
|
||||
queued_events: VecDeque<DiscoveryEvent>,
|
||||
/// The handle to the spawned discv4 service
|
||||
@ -57,9 +57,9 @@ impl Discovery {
|
||||
|
||||
Ok(Self {
|
||||
local_enr,
|
||||
discv4,
|
||||
_discv4: discv4,
|
||||
discv4_updates,
|
||||
dsicv4_config,
|
||||
_dsicv4_config: dsicv4_config,
|
||||
_discv4_service,
|
||||
discovered_nodes: Default::default(),
|
||||
queued_events: Default::default(),
|
||||
@ -71,23 +71,6 @@ impl Discovery {
|
||||
self.local_enr.id
|
||||
}
|
||||
|
||||
/// Manually adds an address to the set.
|
||||
///
|
||||
/// This has the same effect as adding node discovered via network gossip.
|
||||
pub(crate) fn add_node_address(&mut self, peer_id: PeerId, addr: SocketAddr) {
|
||||
self.on_discv4_update(TableUpdate::Added(NodeRecord {
|
||||
address: addr.ip(),
|
||||
tcp_port: addr.port(),
|
||||
udp_port: addr.port(),
|
||||
id: peer_id,
|
||||
}))
|
||||
}
|
||||
|
||||
/// Returns all nodes we know exist in the network.
|
||||
pub fn nodes(&mut self) -> &HashMap<PeerId, SocketAddr> {
|
||||
&self.discovered_nodes
|
||||
}
|
||||
|
||||
fn on_discv4_update(&mut self, update: TableUpdate) {
|
||||
match update {
|
||||
TableUpdate::Added(node) => {
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
use crate::message::BlockRequest;
|
||||
use futures::StreamExt;
|
||||
use reth_eth_wire::{BlockBody, GetBlockBodies};
|
||||
use reth_eth_wire::{BlockBody, GetBlockBodies, GetBlockHeaders};
|
||||
use reth_interfaces::p2p::{
|
||||
error::{RequestError, RequestResult},
|
||||
headers::client::HeadersRequest,
|
||||
@ -161,18 +161,15 @@ impl StateFetcher {
|
||||
|
||||
match req {
|
||||
DownloadRequest::GetBlockHeaders { request, response } => {
|
||||
let inflight = Request { request, response };
|
||||
let inflight = Request { request: request.clone(), response };
|
||||
self.inflight_headers_requests.insert(peer_id, inflight);
|
||||
|
||||
unimplemented!("unify start types");
|
||||
|
||||
// BlockRequest::GetBlockHeaders(GetBlockHeaders {
|
||||
// // TODO: this should be converted
|
||||
// start_block: BlockHashOrNumber::Number(0),
|
||||
// limit: request.limit,
|
||||
// skip: 0,
|
||||
// reverse: request.reverse,
|
||||
// })
|
||||
let HeadersRequest { start, limit, reverse } = request;
|
||||
BlockRequest::GetBlockHeaders(GetBlockHeaders {
|
||||
start_block: start,
|
||||
limit,
|
||||
skip: 0,
|
||||
reverse,
|
||||
})
|
||||
}
|
||||
DownloadRequest::GetBlockBodies { request, response } => {
|
||||
let inflight = Request { request: request.clone(), response };
|
||||
@ -307,9 +304,12 @@ impl PeerState {
|
||||
}
|
||||
}
|
||||
|
||||
/// A request that waits for a response from the network so it can send it back through the response
|
||||
/// channel.
|
||||
/// A request that waits for a response from the network, so it can send it back through the
|
||||
/// response channel.
|
||||
struct Request<Req, Resp> {
|
||||
/// The issued request object
|
||||
/// TODO: this can be attached to the response in error case
|
||||
#[allow(unused)]
|
||||
request: Req,
|
||||
response: oneshot::Sender<Resp>,
|
||||
}
|
||||
|
||||
@ -4,8 +4,6 @@
|
||||
no_crate_inject,
|
||||
attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables))
|
||||
))]
|
||||
// TODO remove later
|
||||
#![allow(dead_code, clippy::too_many_arguments)]
|
||||
|
||||
//! reth P2P networking.
|
||||
//!
|
||||
@ -25,11 +23,11 @@ mod listener;
|
||||
mod manager;
|
||||
mod message;
|
||||
mod network;
|
||||
mod peers;
|
||||
pub mod peers;
|
||||
mod session;
|
||||
mod state;
|
||||
mod swarm;
|
||||
mod transactions;
|
||||
pub mod transactions;
|
||||
|
||||
pub use config::NetworkConfig;
|
||||
pub use fetch::FetchClient;
|
||||
|
||||
@ -23,11 +23,12 @@ use crate::{
|
||||
listener::ConnectionListener,
|
||||
message::{NewBlockMessage, PeerMessage, PeerRequest, PeerRequestSender},
|
||||
network::{NetworkHandle, NetworkHandleMessage},
|
||||
peers::{PeersManager, ReputationChangeKind},
|
||||
peers::{PeersHandle, PeersManager, ReputationChangeKind},
|
||||
session::SessionManager,
|
||||
state::NetworkState,
|
||||
swarm::{Swarm, SwarmEvent},
|
||||
transactions::NetworkTransactionEvent,
|
||||
FetchClient,
|
||||
};
|
||||
use futures::{Future, StreamExt};
|
||||
use parking_lot::Mutex;
|
||||
@ -36,7 +37,7 @@ use reth_eth_wire::{
|
||||
DisconnectReason,
|
||||
};
|
||||
use reth_interfaces::provider::BlockProvider;
|
||||
use reth_primitives::PeerId;
|
||||
use reth_primitives::{PeerId, H256};
|
||||
use std::{
|
||||
net::SocketAddr,
|
||||
pin::Pin,
|
||||
@ -48,7 +49,7 @@ use std::{
|
||||
};
|
||||
use tokio::sync::mpsc;
|
||||
use tokio_stream::wrappers::UnboundedReceiverStream;
|
||||
use tracing::{error, trace};
|
||||
use tracing::{error, trace, warn};
|
||||
|
||||
/// Manages the _entire_ state of the network.
|
||||
///
|
||||
@ -84,8 +85,6 @@ pub struct NetworkManager<C> {
|
||||
from_handle_rx: UnboundedReceiverStream<NetworkHandleMessage>,
|
||||
/// Handles block imports according to the `eth` protocol.
|
||||
block_import: Box<dyn BlockImport>,
|
||||
/// The address of this node that listens for incoming connections.
|
||||
listener_address: Arc<Mutex<SocketAddr>>,
|
||||
/// All listeners for [`Network`] events.
|
||||
event_listeners: NetworkEventListeners,
|
||||
/// Sender half to send events to the [`TransactionsManager`] task, if configured.
|
||||
@ -142,7 +141,7 @@ where
|
||||
let num_active_peers = Arc::new(AtomicUsize::new(0));
|
||||
let handle = NetworkHandle::new(
|
||||
Arc::clone(&num_active_peers),
|
||||
Arc::clone(&listener_address),
|
||||
listener_address,
|
||||
to_manager_tx,
|
||||
local_peer_id,
|
||||
peers_handle,
|
||||
@ -154,7 +153,6 @@ where
|
||||
handle,
|
||||
from_handle_rx: UnboundedReceiverStream::new(from_handle_rx),
|
||||
block_import,
|
||||
listener_address,
|
||||
event_listeners: Default::default(),
|
||||
to_transactions: None,
|
||||
num_active_peers,
|
||||
@ -171,6 +169,11 @@ where
|
||||
self.swarm.listener().local_address()
|
||||
}
|
||||
|
||||
/// Returns the configured genesis hash
|
||||
pub fn genesis_hash(&self) -> H256 {
|
||||
self.swarm.state().genesis_hash()
|
||||
}
|
||||
|
||||
/// How many peers we're currently connected to.
|
||||
pub fn num_connected_peers(&self) -> usize {
|
||||
self.swarm.state().num_connected_peers()
|
||||
@ -188,6 +191,20 @@ where
|
||||
&self.handle
|
||||
}
|
||||
|
||||
/// Returns a new [`PeersHandle`] that can be cloned and shared.
|
||||
///
|
||||
/// The [`PeersHandle`] can be used to interact with the network's peer set.
|
||||
pub fn peers_handle(&self) -> PeersHandle {
|
||||
self.swarm.state().peers().handle()
|
||||
}
|
||||
|
||||
/// Returns a new [`FetchClient`] that can be cloned and shared.
|
||||
///
|
||||
/// The [`FetchClient`] is the entrypoint for sending requests to the network.
|
||||
pub fn fetch_client(&self) -> FetchClient {
|
||||
self.swarm.state().fetch_client()
|
||||
}
|
||||
|
||||
/// Event hook for an unexpected message from the peer.
|
||||
fn on_invalid_message(
|
||||
&mut self,
|
||||
@ -302,7 +319,9 @@ where
|
||||
PeerMessage::SendTransactions(_) => {
|
||||
unreachable!("Not emitted by session")
|
||||
}
|
||||
PeerMessage::Other(_) => {}
|
||||
PeerMessage::Other(other) => {
|
||||
error!(target : "net", message_id=%other.id, "Ignoring unsupported message");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -339,6 +358,9 @@ where
|
||||
NetworkHandleMessage::ReputationChange(peer_id, kind) => {
|
||||
self.swarm.state_mut().peers_mut().apply_reputation_change(&peer_id, kind);
|
||||
}
|
||||
NetworkHandleMessage::FetchClient(tx) => {
|
||||
let _ = tx.send(self.fetch_client());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -387,11 +409,11 @@ where
|
||||
SwarmEvent::TcpListenerError(err) => {
|
||||
trace!(target : "net", ?err, "TCP connection error.");
|
||||
}
|
||||
SwarmEvent::IncomingTcpConnection { remote_addr, .. } => {
|
||||
trace!(target : "net",?remote_addr, "Incoming connection");
|
||||
SwarmEvent::IncomingTcpConnection { remote_addr, session_id } => {
|
||||
trace!(target : "net", ?session_id, ?remote_addr, "Incoming connection");
|
||||
}
|
||||
SwarmEvent::OutgoingTcpConnection { remote_addr } => {
|
||||
trace!(target : "net", ?remote_addr,"Starting outbound connection.");
|
||||
SwarmEvent::OutgoingTcpConnection { remote_addr, peer_id } => {
|
||||
trace!(target : "net", ?remote_addr, ?peer_id, "Starting outbound connection.");
|
||||
}
|
||||
SwarmEvent::SessionEstablished {
|
||||
peer_id,
|
||||
@ -410,7 +432,10 @@ where
|
||||
);
|
||||
|
||||
if direction.is_incoming() {
|
||||
this.swarm.state_mut().peers_mut().on_active_session(peer_id, remote_addr);
|
||||
this.swarm
|
||||
.state_mut()
|
||||
.peers_mut()
|
||||
.on_active_inbound_session(peer_id, remote_addr);
|
||||
}
|
||||
|
||||
this.event_listeners.send(NetworkEvent::SessionEstablished {
|
||||
@ -440,14 +465,36 @@ where
|
||||
|
||||
this.event_listeners.send(NetworkEvent::SessionClosed { peer_id });
|
||||
}
|
||||
SwarmEvent::IncomingPendingSessionClosed { .. } => {}
|
||||
SwarmEvent::OutgoingPendingSessionClosed { peer_id, .. } => {
|
||||
SwarmEvent::IncomingPendingSessionClosed { remote_addr, error } => {
|
||||
warn!(
|
||||
target : "net",
|
||||
?remote_addr,
|
||||
?error,
|
||||
"Incoming pending session failed"
|
||||
);
|
||||
this.swarm.state_mut().peers_mut().on_closed_incoming_pending_session()
|
||||
}
|
||||
SwarmEvent::OutgoingPendingSessionClosed { remote_addr, peer_id, error } => {
|
||||
warn!(
|
||||
target : "net",
|
||||
?remote_addr,
|
||||
?peer_id,
|
||||
?error,
|
||||
"Outgoing pending session failed"
|
||||
);
|
||||
this.swarm
|
||||
.state_mut()
|
||||
.peers_mut()
|
||||
.apply_reputation_change(&peer_id, ReputationChangeKind::FailedToConnect);
|
||||
}
|
||||
SwarmEvent::OutgoingConnectionError { peer_id, .. } => {
|
||||
SwarmEvent::OutgoingConnectionError { remote_addr, peer_id, error } => {
|
||||
warn!(
|
||||
target : "net",
|
||||
?remote_addr,
|
||||
?peer_id,
|
||||
?error,
|
||||
"Outgoing connection error"
|
||||
);
|
||||
this.swarm
|
||||
.state_mut()
|
||||
.peers_mut()
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
|
||||
use futures::FutureExt;
|
||||
use reth_eth_wire::{
|
||||
capability::CapabilityMessage, message::RequestPair, BlockBodies, BlockBody, BlockHeaders,
|
||||
capability::RawCapabilityMessage, message::RequestPair, BlockBodies, BlockBody, BlockHeaders,
|
||||
EthMessage, GetBlockBodies, GetBlockHeaders, GetNodeData, GetPooledTransactions, GetReceipts,
|
||||
NewBlock, NewBlockHashes, NewPooledTransactionHashes, NodeData, PooledTransactions, Receipts,
|
||||
SharedTransactions, Transactions,
|
||||
@ -53,7 +53,8 @@ pub enum PeerMessage {
|
||||
/// All `eth` request variants.
|
||||
EthRequest(PeerRequest),
|
||||
/// Other than eth namespace message
|
||||
Other(CapabilityMessage),
|
||||
#[allow(unused)]
|
||||
Other(RawCapabilityMessage),
|
||||
}
|
||||
|
||||
/// Request Variants that only target block related data.
|
||||
@ -65,32 +66,6 @@ pub enum BlockRequest {
|
||||
GetBlockBodies(GetBlockBodies),
|
||||
}
|
||||
|
||||
/// All Request variants of an [`EthMessage`]
|
||||
///
|
||||
/// Note: These variants come without a request ID, as it's expected that the peer session will
|
||||
/// manage those
|
||||
#[derive(Debug, Clone)]
|
||||
#[allow(missing_docs)]
|
||||
#[allow(clippy::enum_variant_names)]
|
||||
pub enum EthRequest {
|
||||
GetBlockHeaders(GetBlockHeaders),
|
||||
GetBlockBodies(GetBlockBodies),
|
||||
GetPooledTransactions(GetPooledTransactions),
|
||||
GetNodeData(GetNodeData),
|
||||
GetReceipts(GetReceipts),
|
||||
}
|
||||
|
||||
/// Corresponding Response variants for [`EthRequest`]
|
||||
#[derive(Debug, Clone)]
|
||||
#[allow(missing_docs)]
|
||||
pub enum EthResponse {
|
||||
BlockHeaders(BlockHeaders),
|
||||
BlockBodies(BlockBodies),
|
||||
PooledTransactions(PooledTransactions),
|
||||
NodeData(NodeData),
|
||||
Receipts(Receipts),
|
||||
}
|
||||
|
||||
/// Protocol related request messages that expect a response
|
||||
#[derive(Debug)]
|
||||
#[allow(clippy::enum_variant_names)]
|
||||
@ -265,6 +240,7 @@ impl PeerResponseResult {
|
||||
}
|
||||
|
||||
/// Returns whether this result is an error.
|
||||
#[allow(unused)]
|
||||
pub fn is_err(&self) -> bool {
|
||||
match self {
|
||||
PeerResponseResult::BlockHeaders(res) => res.is_err(),
|
||||
@ -292,4 +268,9 @@ impl PeerRequestSender {
|
||||
pub fn try_send(&self, req: PeerRequest) -> Result<(), TrySendError<PeerRequest>> {
|
||||
self.to_session_tx.try_send(req)
|
||||
}
|
||||
|
||||
/// Returns the peer id of the remote peer.
|
||||
pub fn peer_id(&self) -> &PeerId {
|
||||
&self.peer_id
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ use crate::{
|
||||
manager::NetworkEvent,
|
||||
message::PeerRequest,
|
||||
peers::{PeersHandle, ReputationChangeKind},
|
||||
FetchClient,
|
||||
};
|
||||
use parking_lot::Mutex;
|
||||
use reth_eth_wire::{NewBlock, NewPooledTransactionHashes, SharedTransactions};
|
||||
@ -14,7 +15,7 @@ use std::{
|
||||
Arc,
|
||||
},
|
||||
};
|
||||
use tokio::sync::{mpsc, mpsc::UnboundedSender};
|
||||
use tokio::sync::{mpsc, mpsc::UnboundedSender, oneshot};
|
||||
use tokio_stream::wrappers::UnboundedReceiverStream;
|
||||
|
||||
/// A _shareable_ network frontend. Used to interact with the network.
|
||||
@ -64,6 +65,13 @@ impl NetworkHandle {
|
||||
&self.inner.local_peer_id
|
||||
}
|
||||
|
||||
/// Returns the [`PeersHandle`] that can be cloned and shared.
|
||||
///
|
||||
/// The [`PeersHandle`] can be used to interact with the network's peer set.
|
||||
pub fn peers_handle(&self) -> &PeersHandle {
|
||||
&self.inner.peers
|
||||
}
|
||||
|
||||
fn manager(&self) -> &UnboundedSender<NetworkHandleMessage> {
|
||||
&self.inner.to_manager_tx
|
||||
}
|
||||
@ -75,6 +83,15 @@ impl NetworkHandle {
|
||||
UnboundedReceiverStream::new(rx)
|
||||
}
|
||||
|
||||
/// Returns a new [`FetchClient`] that can be cloned and shared.
|
||||
///
|
||||
/// The [`FetchClient`] is the entrypoint for sending requests to the network.
|
||||
pub async fn fetch_client(&self) -> Result<FetchClient, oneshot::error::RecvError> {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
let _ = self.manager().send(NetworkHandleMessage::FetchClient(tx));
|
||||
rx.await
|
||||
}
|
||||
|
||||
/// Returns the mode of the network, either pow, or pos
|
||||
pub fn mode(&self) -> &NetworkMode {
|
||||
&self.inner.network_mode
|
||||
@ -85,6 +102,13 @@ impl NetworkHandle {
|
||||
let _ = self.inner.to_manager_tx.send(msg);
|
||||
}
|
||||
|
||||
/// Announce a block over devp2p
|
||||
///
|
||||
/// Caution: in PoS this is a noop, since new block propagation will happen over devp2p
|
||||
pub fn announce_block(&self, block: NewBlock, hash: H256) {
|
||||
self.send_message(NetworkHandleMessage::AnnounceBlock(block, hash))
|
||||
}
|
||||
|
||||
/// Sends a message to the [`NetworkManager`] to add a peer to the known set
|
||||
pub fn add_peer(&self, peer: PeerId, addr: SocketAddr) {
|
||||
let _ = self.inner.to_manager_tx.send(NetworkHandleMessage::AddPeerAddress(peer, addr));
|
||||
@ -154,4 +178,6 @@ pub(crate) enum NetworkHandleMessage {
|
||||
},
|
||||
/// Apply a reputation change to the given peer.
|
||||
ReputationChange(PeerId, ReputationChangeKind),
|
||||
/// Returns the client that can be used to interact with the network.
|
||||
FetchClient(oneshot::Sender<FetchClient>),
|
||||
}
|
||||
|
||||
@ -90,13 +90,32 @@ impl PeersManager {
|
||||
PeersHandle { manager_tx: self.manager_tx.clone() }
|
||||
}
|
||||
|
||||
/// Invoked when a new _incoming_ tcp connection is accepted.
|
||||
///
|
||||
/// Returns an Err with the configured limit with the number of accepted incoming connections
|
||||
/// exceeded the configured limit.
|
||||
pub(crate) fn on_inbound_pending_session(&mut self) -> Result<(), usize> {
|
||||
if !self.connection_info.has_in_capacity() {
|
||||
return Err(self.connection_info.max_inbound)
|
||||
}
|
||||
|
||||
// keep track of new connection
|
||||
self.connection_info.inc_in();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Invoked when a pending session was closed.
|
||||
pub(crate) fn on_closed_incoming_pending_session(&mut self) {
|
||||
self.connection_info.decr_in()
|
||||
}
|
||||
|
||||
/// Called when a new _incoming_ active session was established to the given peer.
|
||||
///
|
||||
/// This will update the state of the peer if not yet tracked.
|
||||
///
|
||||
/// If the reputation of the peer is below the `BANNED_REPUTATION` threshold, a disconnect will
|
||||
/// be scheduled.
|
||||
pub(crate) fn on_active_session(&mut self, peer_id: PeerId, addr: SocketAddr) {
|
||||
pub(crate) fn on_active_inbound_session(&mut self, peer_id: PeerId, addr: SocketAddr) {
|
||||
match self.peers.entry(peer_id) {
|
||||
Entry::Occupied(mut entry) => {
|
||||
let value = entry.get_mut();
|
||||
@ -110,9 +129,6 @@ impl PeersManager {
|
||||
entry.insert(Peer::with_state(addr, PeerConnectionState::In));
|
||||
}
|
||||
}
|
||||
|
||||
// keep track of new connection
|
||||
self.connection_info.inc_in();
|
||||
}
|
||||
|
||||
/// Apply the corresponding reputation change to the given peer
|
||||
@ -282,6 +298,11 @@ impl ConnectionInfo {
|
||||
self.num_outbound < self.max_outbound
|
||||
}
|
||||
|
||||
/// Returns `true` if there's still capacity for a new incoming connection.
|
||||
fn has_in_capacity(&self) -> bool {
|
||||
self.num_inbound < self.max_inbound
|
||||
}
|
||||
|
||||
fn decr_state(&mut self, state: PeerConnectionState) {
|
||||
match state {
|
||||
PeerConnectionState::Idle => {}
|
||||
|
||||
@ -106,16 +106,6 @@ pub(crate) struct ReputationChange(Reputation);
|
||||
// === impl ReputationChange ===
|
||||
|
||||
impl ReputationChange {
|
||||
/// Apply no reputation change.
|
||||
pub(crate) const fn none() -> Self {
|
||||
Self(0)
|
||||
}
|
||||
|
||||
/// Reputation change for a peer that dropped the connection.
|
||||
pub(crate) const fn dropped() -> Self {
|
||||
Self(REMOTE_DISCONNECT_REPUTATION_CHANGE)
|
||||
}
|
||||
|
||||
/// Helper type for easier conversion
|
||||
#[inline]
|
||||
pub(crate) fn as_i32(self) -> Reputation {
|
||||
|
||||
@ -42,6 +42,7 @@ use tracing::{error, warn};
|
||||
/// - incoming commands from the [`SessionsManager`]
|
||||
/// - incoming requests via the request channel
|
||||
/// - responses for handled ETH requests received from the remote peer.
|
||||
#[allow(unused)]
|
||||
pub(crate) struct ActiveSession {
|
||||
/// Keeps track of request ids.
|
||||
pub(crate) next_id: u64,
|
||||
@ -216,7 +217,9 @@ impl ActiveSession {
|
||||
PeerMessage::ReceivedTransaction(_) => {
|
||||
unreachable!("Not emitted by network")
|
||||
}
|
||||
PeerMessage::Other(_) => {}
|
||||
PeerMessage::Other(other) => {
|
||||
error!(target : "net::session", message_id=%other.id, "Ignoring unsupported message");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -432,6 +435,7 @@ pub(crate) struct ReceivedRequest {
|
||||
/// Receiver half of the channel that's supposed to receive the proper response.
|
||||
rx: PeerResponse,
|
||||
/// Timestamp when we read this msg from the wire.
|
||||
#[allow(unused)]
|
||||
received: Instant,
|
||||
}
|
||||
|
||||
@ -463,6 +467,7 @@ impl From<EthBroadcastMessage> for OutgoingMessage {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#![allow(dead_code)]
|
||||
use super::*;
|
||||
use crate::session::{
|
||||
config::REQUEST_TIMEOUT, handle::PendingSessionEvent, start_pending_incoming_session,
|
||||
|
||||
@ -155,6 +155,7 @@ impl SessionCounter {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub(crate) fn ensure_pending_outbound(&self) -> Result<(), ExceedsSessionLimit> {
|
||||
Self::ensure(self.pending_outbound, self.limits.max_pending_outbound)
|
||||
}
|
||||
|
||||
@ -23,7 +23,7 @@ use tokio::{
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct PendingSessionHandle {
|
||||
/// Can be used to tell the session to disconnect the connection/abort the handshake process.
|
||||
pub(crate) disconnect_tx: oneshot::Sender<()>,
|
||||
pub(crate) _disconnect_tx: oneshot::Sender<()>,
|
||||
/// The direction of the session
|
||||
pub(crate) direction: Direction,
|
||||
}
|
||||
@ -33,6 +33,7 @@ pub(crate) struct PendingSessionHandle {
|
||||
/// Within an active session that supports the `Ethereum Wire Protocol `, three high-level tasks can
|
||||
/// be performed: chain synchronization, block propagation and transaction exchange.
|
||||
#[derive(Debug)]
|
||||
#[allow(unused)]
|
||||
pub(crate) struct ActiveSessionHandle {
|
||||
/// The direction of the session
|
||||
pub(crate) direction: Direction,
|
||||
@ -65,8 +66,6 @@ impl ActiveSessionHandle {
|
||||
/// A session starts with a `Handshake`, followed by a `Hello` message which
|
||||
#[derive(Debug)]
|
||||
pub(crate) enum PendingSessionEvent {
|
||||
/// Initial handshake step was successful <https://github.com/ethereum/devp2p/blob/6b0abc3d956a626c28dce1307ee9f546db17b6bd/rlpx.md#initial-handshake>
|
||||
SuccessfulHandshake { remote_addr: SocketAddr, session_id: SessionId },
|
||||
/// Represents a successful `Hello` and `Status` exchange: <https://github.com/ethereum/devp2p/blob/6b0abc3d956a626c28dce1307ee9f546db17b6bd/rlpx.md#hello-0x00>
|
||||
Established {
|
||||
session_id: SessionId,
|
||||
@ -134,6 +133,7 @@ pub(crate) enum ActiveSessionMessage {
|
||||
message: PeerMessage,
|
||||
},
|
||||
/// Received a message that does not match the announced capabilities of the peer.
|
||||
#[allow(unused)]
|
||||
InvalidMessage {
|
||||
/// Identifier of the remote peer.
|
||||
peer_id: PeerId,
|
||||
|
||||
@ -43,6 +43,7 @@ mod config;
|
||||
mod handle;
|
||||
use crate::session::config::SessionCounter;
|
||||
pub use config::SessionsConfig;
|
||||
use reth_ecies::util::pk2id;
|
||||
|
||||
/// Internal identifier for active sessions.
|
||||
#[derive(Debug, Clone, Copy, PartialOrd, PartialEq, Eq, Hash)]
|
||||
@ -59,8 +60,6 @@ pub(crate) struct SessionManager {
|
||||
request_timeout: Duration,
|
||||
/// The secret key used for authenticating sessions.
|
||||
secret_key: SecretKey,
|
||||
/// The node id of node
|
||||
peer_id: PeerId,
|
||||
/// The `Status` message to send to peers.
|
||||
status: Status,
|
||||
/// THe `Hello` message to send to peers.
|
||||
@ -105,7 +104,7 @@ impl SessionManager {
|
||||
let (active_session_tx, active_session_rx) = mpsc::channel(config.session_event_buffer);
|
||||
|
||||
let pk = secret_key.public_key(SECP256K1);
|
||||
let peer_id = PeerId::from_slice(&pk.serialize_uncompressed()[1..]);
|
||||
let peer_id = pk2id(&pk);
|
||||
|
||||
// TODO: make sure this is the right place to put these builders - maybe per-Network rather
|
||||
// than per-Session?
|
||||
@ -118,7 +117,6 @@ impl SessionManager {
|
||||
counter: SessionCounter::new(config.limits),
|
||||
request_timeout: config.request_timeout,
|
||||
secret_key,
|
||||
peer_id,
|
||||
status,
|
||||
hello,
|
||||
fork_filter,
|
||||
@ -181,7 +179,8 @@ impl SessionManager {
|
||||
self.fork_filter.clone(),
|
||||
));
|
||||
|
||||
let handle = PendingSessionHandle { disconnect_tx, direction: Direction::Incoming };
|
||||
let handle =
|
||||
PendingSessionHandle { _disconnect_tx: disconnect_tx, direction: Direction::Incoming };
|
||||
self.pending_sessions.insert(session_id, handle);
|
||||
self.counter.inc_pending_inbound();
|
||||
Ok(session_id)
|
||||
@ -204,8 +203,10 @@ impl SessionManager {
|
||||
self.fork_filter.clone(),
|
||||
));
|
||||
|
||||
let handle =
|
||||
PendingSessionHandle { disconnect_tx, direction: Direction::Outgoing(remote_peer_id) };
|
||||
let handle = PendingSessionHandle {
|
||||
_disconnect_tx: disconnect_tx,
|
||||
direction: Direction::Outgoing(remote_peer_id),
|
||||
};
|
||||
self.pending_sessions.insert(session_id, handle);
|
||||
self.counter.inc_pending_outbound();
|
||||
}
|
||||
@ -289,21 +290,12 @@ impl SessionManager {
|
||||
}
|
||||
|
||||
// Poll the pending session event stream
|
||||
loop {
|
||||
let event = match self.pending_session_rx.poll_next_unpin(cx) {
|
||||
Poll::Pending => break,
|
||||
Poll::Pending => return Poll::Pending,
|
||||
Poll::Ready(None) => unreachable!("Manager holds both channel halves."),
|
||||
Poll::Ready(Some(event)) => event,
|
||||
};
|
||||
match event {
|
||||
PendingSessionEvent::SuccessfulHandshake { remote_addr, session_id } => {
|
||||
trace!(
|
||||
target : "net::session",
|
||||
?session_id,
|
||||
?remote_addr,
|
||||
"successful handshake"
|
||||
);
|
||||
}
|
||||
return match event {
|
||||
PendingSessionEvent::Established {
|
||||
session_id,
|
||||
remote_addr,
|
||||
@ -316,8 +308,7 @@ impl SessionManager {
|
||||
// move from pending to established.
|
||||
self.remove_pending_session(&session_id);
|
||||
|
||||
let (commands_to_session, commands_rx) =
|
||||
mpsc::channel(self.session_command_buffer);
|
||||
let (commands_to_session, commands_rx) = mpsc::channel(self.session_command_buffer);
|
||||
|
||||
let (to_session_tx, messages_rx) = mpsc::channel(self.session_command_buffer);
|
||||
|
||||
@ -354,7 +345,7 @@ impl SessionManager {
|
||||
self.active_sessions.insert(peer_id, handle);
|
||||
self.counter.inc_active(&direction);
|
||||
|
||||
return Poll::Ready(SessionEvent::SessionEstablished {
|
||||
Poll::Ready(SessionEvent::SessionEstablished {
|
||||
peer_id,
|
||||
remote_addr,
|
||||
capabilities,
|
||||
@ -371,7 +362,7 @@ impl SessionManager {
|
||||
"disconnected pending session"
|
||||
);
|
||||
self.remove_pending_session(&session_id);
|
||||
return match direction {
|
||||
match direction {
|
||||
Direction::Incoming => {
|
||||
Poll::Ready(SessionEvent::IncomingPendingSessionClosed {
|
||||
remote_addr,
|
||||
@ -402,18 +393,9 @@ impl SessionManager {
|
||||
"connection refused"
|
||||
);
|
||||
self.remove_pending_session(&session_id);
|
||||
return Poll::Ready(SessionEvent::OutgoingPendingSessionClosed {
|
||||
remote_addr,
|
||||
peer_id,
|
||||
error: None,
|
||||
})
|
||||
Poll::Ready(SessionEvent::OutgoingConnectionError { remote_addr, peer_id, error })
|
||||
}
|
||||
PendingSessionEvent::EciesAuthError {
|
||||
remote_addr,
|
||||
session_id,
|
||||
error,
|
||||
direction,
|
||||
} => {
|
||||
PendingSessionEvent::EciesAuthError { remote_addr, session_id, error, direction } => {
|
||||
self.remove_pending_session(&session_id);
|
||||
warn!(
|
||||
target : "net::session",
|
||||
@ -423,7 +405,7 @@ impl SessionManager {
|
||||
"ecies auth failed"
|
||||
);
|
||||
self.remove_pending_session(&session_id);
|
||||
return match direction {
|
||||
match direction {
|
||||
Direction::Incoming => {
|
||||
Poll::Ready(SessionEvent::IncomingPendingSessionClosed {
|
||||
remote_addr,
|
||||
@ -441,9 +423,6 @@ impl SessionManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
|
||||
/// Events produced by the [`SessionManager`]
|
||||
@ -501,6 +480,22 @@ pub(crate) enum SessionEvent {
|
||||
Disconnected { peer_id: PeerId, remote_addr: SocketAddr },
|
||||
}
|
||||
|
||||
/// The direction of the connection.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub(crate) enum Direction {
|
||||
/// Incoming connection.
|
||||
Incoming,
|
||||
/// Outgoing connection to a specific node.
|
||||
Outgoing(PeerId),
|
||||
}
|
||||
|
||||
impl Direction {
|
||||
/// Returns `true` if this an incoming connection.
|
||||
pub(crate) fn is_incoming(&self) -> bool {
|
||||
matches!(self, Direction::Incoming)
|
||||
}
|
||||
}
|
||||
|
||||
/// The error thrown when the max configured limit has been reached and no more connections are
|
||||
/// accepted.
|
||||
#[derive(Debug, Clone, thiserror::Error)]
|
||||
@ -510,6 +505,7 @@ pub struct ExceedsSessionLimit(pub(crate) u32);
|
||||
/// Starts the authentication process for a connection initiated by a remote peer.
|
||||
///
|
||||
/// This will wait for the _incoming_ handshake request and answer it.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) async fn start_pending_incoming_session(
|
||||
disconnect_rx: oneshot::Receiver<()>,
|
||||
session_id: SessionId,
|
||||
@ -538,6 +534,7 @@ pub(crate) async fn start_pending_incoming_session(
|
||||
|
||||
/// Starts the authentication process for a connection initiated by a remote peer.
|
||||
#[instrument(skip_all, fields(%remote_addr, peer_id), target = "net")]
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
async fn start_pending_outbound_session(
|
||||
disconnect_rx: oneshot::Receiver<()>,
|
||||
events: mpsc::Sender<PendingSessionEvent>,
|
||||
@ -578,23 +575,8 @@ async fn start_pending_outbound_session(
|
||||
.await
|
||||
}
|
||||
|
||||
/// The direction of the connection.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub(crate) enum Direction {
|
||||
/// Incoming connection.
|
||||
Incoming,
|
||||
/// Outgoing connection to a specific node.
|
||||
Outgoing(PeerId),
|
||||
}
|
||||
|
||||
impl Direction {
|
||||
/// Returns `true` if this an incoming connection.
|
||||
pub(crate) fn is_incoming(&self) -> bool {
|
||||
matches!(self, Direction::Incoming)
|
||||
}
|
||||
}
|
||||
|
||||
/// Authenticates a session
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
async fn authenticate(
|
||||
disconnect_rx: oneshot::Receiver<()>,
|
||||
events: mpsc::Sender<PendingSessionEvent>,
|
||||
@ -672,6 +654,7 @@ async fn authenticate(
|
||||
/// Authenticate the stream via handshake
|
||||
///
|
||||
/// On Success return the authenticated stream as [`PendingSessionEvent`]
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
async fn authenticate_stream(
|
||||
stream: UnauthedP2PStream<ECIESStream<TcpStream>>,
|
||||
session_id: SessionId,
|
||||
|
||||
@ -9,6 +9,7 @@ use crate::{
|
||||
PeerResponseResult,
|
||||
},
|
||||
peers::{PeerAction, PeersManager},
|
||||
FetchClient,
|
||||
};
|
||||
use reth_eth_wire::{
|
||||
capability::Capabilities, BlockHashNumber, DisconnectReason, NewBlockHashes, Status,
|
||||
@ -85,6 +86,21 @@ where
|
||||
&mut self.peers_manager
|
||||
}
|
||||
|
||||
/// Returns access to the [`PeersManager`]
|
||||
pub(crate) fn peers(&self) -> &PeersManager {
|
||||
&self.peers_manager
|
||||
}
|
||||
|
||||
/// Returns a new [`FetchClient`]
|
||||
pub(crate) fn fetch_client(&self) -> FetchClient {
|
||||
self.state_fetcher.client()
|
||||
}
|
||||
|
||||
/// How many peers we're currently connected to.
|
||||
pub fn genesis_hash(&self) -> H256 {
|
||||
self.genesis_hash
|
||||
}
|
||||
|
||||
/// How many peers we're currently connected to.
|
||||
pub fn num_connected_peers(&self) -> usize {
|
||||
self.connected_peers.len()
|
||||
@ -381,10 +397,11 @@ where
|
||||
/// Tracks the state of a Peer.
|
||||
///
|
||||
/// For example known blocks,so we can decide what to announce.
|
||||
pub struct ConnectedPeer {
|
||||
pub(crate) struct ConnectedPeer {
|
||||
/// Best block of the peer.
|
||||
pub(crate) best_hash: H256,
|
||||
/// The capabilities of the connected peer.
|
||||
#[allow(unused)]
|
||||
pub(crate) capabilities: Arc<Capabilities>,
|
||||
/// A communication channel directly to the session task.
|
||||
pub(crate) request_tx: PeerRequestSender,
|
||||
|
||||
@ -19,7 +19,7 @@ use std::{
|
||||
sync::Arc,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
use tracing::warn;
|
||||
use tracing::{trace, warn};
|
||||
|
||||
/// Contains the connectivity related state of the network.
|
||||
///
|
||||
@ -99,6 +99,7 @@ where
|
||||
pub(crate) fn listener(&self) -> &ConnectionListener {
|
||||
&self.incoming
|
||||
}
|
||||
|
||||
/// Mutable access to the [`SessionManager`].
|
||||
pub(crate) fn sessions_mut(&mut self) -> &mut SessionManager {
|
||||
&mut self.sessions
|
||||
@ -171,12 +172,19 @@ where
|
||||
return Some(SwarmEvent::TcpListenerClosed { remote_addr: address })
|
||||
}
|
||||
ListenerEvent::Incoming { stream, remote_addr } => {
|
||||
if let Err(limit) = self.state_mut().peers_mut().on_inbound_pending_session() {
|
||||
// We currently don't have additional capacity to establish a session from an
|
||||
// incoming connection, so we drop the connection.
|
||||
trace!(target: "net", %limit, ?remote_addr, "Exceeded incoming connection limit; dropping connection");
|
||||
return None
|
||||
}
|
||||
|
||||
match self.sessions.on_incoming(stream, remote_addr) {
|
||||
Ok(session_id) => {
|
||||
return Some(SwarmEvent::IncomingTcpConnection { session_id, remote_addr })
|
||||
}
|
||||
Err(err) => {
|
||||
warn!(?err, "Incoming connection rejected");
|
||||
warn!(target: "net", ?err, "Incoming connection rejected");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -188,7 +196,8 @@ where
|
||||
fn on_state_action(&mut self, event: StateAction) -> Option<SwarmEvent> {
|
||||
match event {
|
||||
StateAction::Connect { remote_addr, peer_id } => {
|
||||
self.sessions.dial_outbound(remote_addr, peer_id);
|
||||
self.dial_outbound(remote_addr, peer_id);
|
||||
return Some(SwarmEvent::OutgoingTcpConnection { remote_addr, peer_id })
|
||||
}
|
||||
StateAction::Disconnect { peer_id, reason } => {
|
||||
self.sessions.disconnect(peer_id, reason);
|
||||
@ -301,6 +310,7 @@ pub(crate) enum SwarmEvent {
|
||||
/// An outbound connection is initiated.
|
||||
OutgoingTcpConnection {
|
||||
/// Address of the remote peer.
|
||||
peer_id: PeerId,
|
||||
remote_addr: SocketAddr,
|
||||
},
|
||||
SessionEstablished {
|
||||
|
||||
@ -43,6 +43,19 @@ pub struct TransactionsHandle {
|
||||
manager_tx: mpsc::UnboundedSender<TransactionsCommand>,
|
||||
}
|
||||
|
||||
// === impl TransactionsHandle ===
|
||||
|
||||
impl TransactionsHandle {
|
||||
fn send(&self, cmd: TransactionsCommand) {
|
||||
let _ = self.manager_tx.send(cmd);
|
||||
}
|
||||
|
||||
/// Manually propagate the transaction that belongs to the hash.
|
||||
pub fn propagate(&self, hash: TxHash) {
|
||||
self.send(TransactionsCommand::PropagateHash(hash))
|
||||
}
|
||||
}
|
||||
|
||||
/// Manages transactions on top of the p2p network.
|
||||
///
|
||||
/// This can be spawned to another task and is supposed to be run as background service while
|
||||
@ -248,6 +261,15 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Handles a command received from a detached [`TransactionsHandle`]
|
||||
fn on_command(&mut self, cmd: TransactionsCommand) {
|
||||
match cmd {
|
||||
TransactionsCommand::PropagateHash(hash) => {
|
||||
self.on_new_transactions(std::iter::once(hash))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Handles a received event related to common network events.
|
||||
fn on_network_event(&mut self, event: NetworkEvent) {
|
||||
match event {
|
||||
@ -355,6 +377,11 @@ where
|
||||
this.on_network_event(event);
|
||||
}
|
||||
|
||||
// drain network/peer related events
|
||||
while let Poll::Ready(Some(cmd)) = this.command_rx.poll_next_unpin(cx) {
|
||||
this.on_command(cmd);
|
||||
}
|
||||
|
||||
// drain incoming transaction events
|
||||
while let Poll::Ready(Some(event)) = this.transaction_events.poll_next_unpin(cx) {
|
||||
this.on_network_tx_event(event);
|
||||
@ -424,11 +451,12 @@ struct Peer {
|
||||
|
||||
/// Commands to send to the [`TransactionManager`]
|
||||
enum TransactionsCommand {
|
||||
Propagate(H256),
|
||||
PropagateHash(H256),
|
||||
}
|
||||
|
||||
/// All events related to transactions emitted by the network
|
||||
/// All events related to transactions emitted by the network.
|
||||
#[derive(Debug)]
|
||||
#[allow(missing_docs)]
|
||||
pub enum NetworkTransactionEvent {
|
||||
/// Received list of transactions to the given peer.
|
||||
IncomingTransactions { peer_id: PeerId, msg: Transactions },
|
||||
|
||||
Reference in New Issue
Block a user