mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat(net): draft for sending status updates through NetworkHandle (#436)
* feat(net): draft for sending status updates through `NetworkHandle` * feat(net): draft for sending status updates through `NetworkHandle` * fix(net): remove unused import * feat(net): implement getters for status update sender half * docs(net): document methods * chore: cargo fmt * feat(net): move status updating logic to NetworkManager and NetworkHandle * feat(net): move status updating logic to NetworkManager and NetworkHandle * fix(net): fix headers stage testing * fix: derive default * fix: remove StatusUpdate struct Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -3635,6 +3635,7 @@ dependencies = [
|
|||||||
"reth-eth-wire",
|
"reth-eth-wire",
|
||||||
"reth-executor",
|
"reth-executor",
|
||||||
"reth-interfaces",
|
"reth-interfaces",
|
||||||
|
"reth-network",
|
||||||
"reth-primitives",
|
"reth-primitives",
|
||||||
"reth-provider",
|
"reth-provider",
|
||||||
"reth-rlp",
|
"reth-rlp",
|
||||||
|
|||||||
@ -63,6 +63,7 @@ impl Command {
|
|||||||
.build(consensus.clone(), fetch_client.clone()),
|
.build(consensus.clone(), fetch_client.clone()),
|
||||||
consensus: consensus.clone(),
|
consensus: consensus.clone(),
|
||||||
client: fetch_client.clone(),
|
client: fetch_client.clone(),
|
||||||
|
network_handle: network.clone(),
|
||||||
commit_threshold: 100,
|
commit_threshold: 100,
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
|
|||||||
@ -20,12 +20,13 @@ pub struct HeadersRequest {
|
|||||||
#[async_trait]
|
#[async_trait]
|
||||||
#[auto_impl::auto_impl(&, Arc, Box)]
|
#[auto_impl::auto_impl(&, Arc, Box)]
|
||||||
pub trait HeadersClient: Send + Sync + Debug {
|
pub trait HeadersClient: Send + Sync + Debug {
|
||||||
/// Update the node's Status message.
|
|
||||||
///
|
|
||||||
/// The updated Status message will be used during any new eth/65 handshakes.
|
|
||||||
fn update_status(&self, height: u64, hash: H256, td: U256);
|
|
||||||
|
|
||||||
/// Sends the header request to the p2p network and returns the header response received from a
|
/// Sends the header request to the p2p network and returns the header response received from a
|
||||||
/// peer.
|
/// peer.
|
||||||
async fn get_headers(&self, request: HeadersRequest) -> PeerRequestResult<BlockHeaders>;
|
async fn get_headers(&self, request: HeadersRequest) -> PeerRequestResult<BlockHeaders>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The status updater for updating the status of the p2p node
|
||||||
|
pub trait StatusUpdater: Send + Sync {
|
||||||
|
/// Updates the status of the p2p node
|
||||||
|
fn update_status(&self, height: u64, hash: H256, total_difficulty: U256);
|
||||||
|
}
|
||||||
|
|||||||
@ -5,7 +5,7 @@ use crate::{
|
|||||||
downloader::{DownloadStream, Downloader},
|
downloader::{DownloadStream, Downloader},
|
||||||
error::{PeerRequestResult, RequestError},
|
error::{PeerRequestResult, RequestError},
|
||||||
headers::{
|
headers::{
|
||||||
client::{HeadersClient, HeadersRequest},
|
client::{HeadersClient, HeadersRequest, StatusUpdater},
|
||||||
downloader::HeaderDownloader,
|
downloader::HeaderDownloader,
|
||||||
error::DownloadError,
|
error::DownloadError,
|
||||||
},
|
},
|
||||||
@ -14,7 +14,7 @@ use crate::{
|
|||||||
use futures::{Future, FutureExt, Stream};
|
use futures::{Future, FutureExt, Stream};
|
||||||
use reth_eth_wire::BlockHeaders;
|
use reth_eth_wire::BlockHeaders;
|
||||||
use reth_primitives::{
|
use reth_primitives::{
|
||||||
BlockLocked, BlockNumber, Header, HeadersDirection, PeerId, SealedHeader, H256, U256,
|
BlockLocked, BlockNumber, Header, HeadersDirection, PeerId, SealedHeader, H256,
|
||||||
};
|
};
|
||||||
use reth_rpc_types::engine::ForkchoiceState;
|
use reth_rpc_types::engine::ForkchoiceState;
|
||||||
use std::{
|
use std::{
|
||||||
@ -170,8 +170,6 @@ impl TestHeadersClient {
|
|||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl HeadersClient for TestHeadersClient {
|
impl HeadersClient for TestHeadersClient {
|
||||||
fn update_status(&self, _height: u64, _hash: H256, _td: U256) {}
|
|
||||||
|
|
||||||
async fn get_headers(&self, request: HeadersRequest) -> PeerRequestResult<BlockHeaders> {
|
async fn get_headers(&self, request: HeadersRequest) -> PeerRequestResult<BlockHeaders> {
|
||||||
if let Some(err) = &mut *self.error.lock().await {
|
if let Some(err) = &mut *self.error.lock().await {
|
||||||
return Err(err.clone())
|
return Err(err.clone())
|
||||||
@ -228,6 +226,14 @@ impl TestConsensus {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Nil status updater for testing
|
||||||
|
#[derive(Debug, Clone, Default)]
|
||||||
|
pub struct TestStatusUpdater;
|
||||||
|
|
||||||
|
impl StatusUpdater for TestStatusUpdater {
|
||||||
|
fn update_status(&self, _height: u64, _hash: H256, _total_difficulty: reth_primitives::U256) {}
|
||||||
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl Consensus for TestConsensus {
|
impl Consensus for TestConsensus {
|
||||||
fn fork_choice_state(&self) -> watch::Receiver<ForkchoiceState> {
|
fn fork_choice_state(&self) -> watch::Receiver<ForkchoiceState> {
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
//! A client implementation that can interact with the network and download data.
|
//! A client implementation that can interact with the network and download data.
|
||||||
|
|
||||||
use crate::fetch::{DownloadRequest, StatusUpdate};
|
use crate::fetch::DownloadRequest;
|
||||||
use reth_eth_wire::{BlockBody, BlockHeaders};
|
use reth_eth_wire::{BlockBody, BlockHeaders};
|
||||||
use reth_interfaces::p2p::{
|
use reth_interfaces::p2p::{
|
||||||
bodies::client::BodiesClient,
|
bodies::client::BodiesClient,
|
||||||
error::PeerRequestResult,
|
error::PeerRequestResult,
|
||||||
headers::client::{HeadersClient, HeadersRequest},
|
headers::client::{HeadersClient, HeadersRequest},
|
||||||
};
|
};
|
||||||
use reth_primitives::{WithPeerId, H256, U256};
|
use reth_primitives::{WithPeerId, H256};
|
||||||
use tokio::sync::{mpsc::UnboundedSender, oneshot};
|
use tokio::sync::{mpsc::UnboundedSender, oneshot};
|
||||||
|
|
||||||
/// Front-end API for fetching data from the network.
|
/// Front-end API for fetching data from the network.
|
||||||
@ -15,16 +15,10 @@ use tokio::sync::{mpsc::UnboundedSender, oneshot};
|
|||||||
pub struct FetchClient {
|
pub struct FetchClient {
|
||||||
/// Sender half of the request channel.
|
/// Sender half of the request channel.
|
||||||
pub(crate) request_tx: UnboundedSender<DownloadRequest>,
|
pub(crate) request_tx: UnboundedSender<DownloadRequest>,
|
||||||
/// Sender for sending Status updates
|
|
||||||
pub(crate) status_tx: UnboundedSender<StatusUpdate>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl HeadersClient for FetchClient {
|
impl HeadersClient for FetchClient {
|
||||||
fn update_status(&self, height: u64, hash: H256, total_difficulty: U256) {
|
|
||||||
let _ = self.status_tx.send(StatusUpdate { height, hash, total_difficulty });
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sends a `GetBlockHeaders` request to an available peer.
|
/// Sends a `GetBlockHeaders` request to an available peer.
|
||||||
async fn get_headers(&self, request: HeadersRequest) -> PeerRequestResult<BlockHeaders> {
|
async fn get_headers(&self, request: HeadersRequest) -> PeerRequestResult<BlockHeaders> {
|
||||||
let (response, rx) = oneshot::channel();
|
let (response, rx) = oneshot::channel();
|
||||||
|
|||||||
@ -7,7 +7,7 @@ use reth_interfaces::p2p::{
|
|||||||
error::{PeerRequestResult, RequestError, RequestResult},
|
error::{PeerRequestResult, RequestError, RequestResult},
|
||||||
headers::client::HeadersRequest,
|
headers::client::HeadersRequest,
|
||||||
};
|
};
|
||||||
use reth_primitives::{Header, PeerId, H256, U256};
|
use reth_primitives::{Header, PeerId, H256};
|
||||||
use std::{
|
use std::{
|
||||||
collections::{HashMap, VecDeque},
|
collections::{HashMap, VecDeque},
|
||||||
task::{Context, Poll},
|
task::{Context, Poll},
|
||||||
@ -38,10 +38,6 @@ pub struct StateFetcher {
|
|||||||
download_requests_rx: UnboundedReceiverStream<DownloadRequest>,
|
download_requests_rx: UnboundedReceiverStream<DownloadRequest>,
|
||||||
/// Sender for download requests, used to detach a [`FetchClient`]
|
/// Sender for download requests, used to detach a [`FetchClient`]
|
||||||
download_requests_tx: UnboundedSender<DownloadRequest>,
|
download_requests_tx: UnboundedSender<DownloadRequest>,
|
||||||
/// Receiver for new incoming [`StatusUpdate`] requests.
|
|
||||||
status_rx: UnboundedReceiverStream<StatusUpdate>,
|
|
||||||
/// Sender for updating the status, used to detach a [`FetchClient`]
|
|
||||||
status_tx: UnboundedSender<StatusUpdate>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// === impl StateSyncer ===
|
// === impl StateSyncer ===
|
||||||
@ -120,10 +116,6 @@ impl StateFetcher {
|
|||||||
PollAction::NoPeersAvailable => true,
|
PollAction::NoPeersAvailable => true,
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Poll::Ready(Some(status)) = self.status_rx.poll_next_unpin(cx) {
|
|
||||||
return Poll::Ready(FetchAction::StatusUpdate(status))
|
|
||||||
}
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
// poll incoming requests
|
// poll incoming requests
|
||||||
match self.download_requests_rx.poll_next_unpin(cx) {
|
match self.download_requests_rx.poll_next_unpin(cx) {
|
||||||
@ -229,17 +221,13 @@ impl StateFetcher {
|
|||||||
|
|
||||||
/// Returns a new [`FetchClient`] that can send requests to this type.
|
/// Returns a new [`FetchClient`] that can send requests to this type.
|
||||||
pub(crate) fn client(&self) -> FetchClient {
|
pub(crate) fn client(&self) -> FetchClient {
|
||||||
FetchClient {
|
FetchClient { request_tx: self.download_requests_tx.clone() }
|
||||||
request_tx: self.download_requests_tx.clone(),
|
|
||||||
status_tx: self.status_tx.clone(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for StateFetcher {
|
impl Default for StateFetcher {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let (download_requests_tx, download_requests_rx) = mpsc::unbounded_channel();
|
let (download_requests_tx, download_requests_rx) = mpsc::unbounded_channel();
|
||||||
let (status_tx, status_rx) = mpsc::unbounded_channel();
|
|
||||||
Self {
|
Self {
|
||||||
inflight_headers_requests: Default::default(),
|
inflight_headers_requests: Default::default(),
|
||||||
inflight_bodies_requests: Default::default(),
|
inflight_bodies_requests: Default::default(),
|
||||||
@ -247,8 +235,6 @@ impl Default for StateFetcher {
|
|||||||
queued_requests: Default::default(),
|
queued_requests: Default::default(),
|
||||||
download_requests_rx: UnboundedReceiverStream::new(download_requests_rx),
|
download_requests_rx: UnboundedReceiverStream::new(download_requests_rx),
|
||||||
download_requests_tx,
|
download_requests_tx,
|
||||||
status_rx: UnboundedReceiverStream::new(status_rx),
|
|
||||||
status_tx,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -314,14 +300,6 @@ struct Request<Req, Resp> {
|
|||||||
response: oneshot::Sender<Resp>,
|
response: oneshot::Sender<Resp>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A message to update the status.
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub(crate) struct StatusUpdate {
|
|
||||||
pub(crate) height: u64,
|
|
||||||
pub(crate) hash: H256,
|
|
||||||
pub(crate) total_difficulty: U256,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Requests that can be sent to the Syncer from a [`FetchClient`]
|
/// Requests that can be sent to the Syncer from a [`FetchClient`]
|
||||||
pub(crate) enum DownloadRequest {
|
pub(crate) enum DownloadRequest {
|
||||||
/// Download the requested headers and send response through channel
|
/// Download the requested headers and send response through channel
|
||||||
@ -357,8 +335,6 @@ pub(crate) enum FetchAction {
|
|||||||
/// The request to send
|
/// The request to send
|
||||||
request: BlockRequest,
|
request: BlockRequest,
|
||||||
},
|
},
|
||||||
/// Propagate a received status update for the node
|
|
||||||
StatusUpdate(StatusUpdate),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Outcome of a processed response.
|
/// Outcome of a processed response.
|
||||||
|
|||||||
@ -456,6 +456,9 @@ where
|
|||||||
NetworkHandleMessage::FetchClient(tx) => {
|
NetworkHandleMessage::FetchClient(tx) => {
|
||||||
let _ = tx.send(self.fetch_client());
|
let _ = tx.send(self.fetch_client());
|
||||||
}
|
}
|
||||||
|
NetworkHandleMessage::StatusUpdate { height, hash, total_difficulty } => {
|
||||||
|
self.swarm.sessions_mut().on_status_update(height, hash, total_difficulty);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -612,14 +615,6 @@ where
|
|||||||
.peers_mut()
|
.peers_mut()
|
||||||
.apply_reputation_change(&peer_id, ReputationChangeKind::FailedToConnect);
|
.apply_reputation_change(&peer_id, ReputationChangeKind::FailedToConnect);
|
||||||
}
|
}
|
||||||
SwarmEvent::StatusUpdate(status) => {
|
|
||||||
trace!(
|
|
||||||
target : "net",
|
|
||||||
?status,
|
|
||||||
"Status Update received"
|
|
||||||
);
|
|
||||||
this.swarm.sessions_mut().on_status_update(status.clone())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,8 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use reth_eth_wire::{NewBlock, NewPooledTransactionHashes, SharedTransactions};
|
use reth_eth_wire::{NewBlock, NewPooledTransactionHashes, SharedTransactions};
|
||||||
use reth_primitives::{PeerId, TransactionSigned, TxHash, H256};
|
use reth_interfaces::p2p::headers::client::StatusUpdater;
|
||||||
|
use reth_primitives::{PeerId, TransactionSigned, TxHash, H256, U256};
|
||||||
use std::{
|
use std::{
|
||||||
net::SocketAddr,
|
net::SocketAddr,
|
||||||
sync::{
|
sync::{
|
||||||
@ -21,7 +22,7 @@ use tokio_stream::wrappers::UnboundedReceiverStream;
|
|||||||
/// A _shareable_ network frontend. Used to interact with the network.
|
/// A _shareable_ network frontend. Used to interact with the network.
|
||||||
///
|
///
|
||||||
/// See also [`NetworkManager`](crate::NetworkManager).
|
/// See also [`NetworkManager`](crate::NetworkManager).
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct NetworkHandle {
|
pub struct NetworkHandle {
|
||||||
/// The Arc'ed delegate that contains the state.
|
/// The Arc'ed delegate that contains the state.
|
||||||
inner: Arc<NetworkInner>,
|
inner: Arc<NetworkInner>,
|
||||||
@ -102,6 +103,11 @@ impl NetworkHandle {
|
|||||||
let _ = self.inner.to_manager_tx.send(msg);
|
let _ = self.inner.to_manager_tx.send(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Update the status of the node.
|
||||||
|
pub fn update_status(&self, height: u64, hash: H256, total_difficulty: U256) {
|
||||||
|
self.send_message(NetworkHandleMessage::StatusUpdate { height, hash, total_difficulty });
|
||||||
|
}
|
||||||
|
|
||||||
/// Announce a block over devp2p
|
/// Announce a block over devp2p
|
||||||
///
|
///
|
||||||
/// Caution: in PoS this is a noop, since new block propagation will happen over devp2p
|
/// Caution: in PoS this is a noop, since new block propagation will happen over devp2p
|
||||||
@ -148,6 +154,14 @@ impl NetworkHandle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl StatusUpdater for NetworkHandle {
|
||||||
|
/// Update the status of the node.
|
||||||
|
fn update_status(&self, height: u64, hash: H256, total_difficulty: U256) {
|
||||||
|
self.send_message(NetworkHandleMessage::StatusUpdate { height, hash, total_difficulty });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
struct NetworkInner {
|
struct NetworkInner {
|
||||||
/// Number of active peer sessions the node's currently handling.
|
/// Number of active peer sessions the node's currently handling.
|
||||||
num_active_peers: Arc<AtomicUsize>,
|
num_active_peers: Arc<AtomicUsize>,
|
||||||
@ -189,4 +203,6 @@ pub(crate) enum NetworkHandleMessage {
|
|||||||
ReputationChange(PeerId, ReputationChangeKind),
|
ReputationChange(PeerId, ReputationChangeKind),
|
||||||
/// Returns the client that can be used to interact with the network.
|
/// Returns the client that can be used to interact with the network.
|
||||||
FetchClient(oneshot::Sender<FetchClient>),
|
FetchClient(oneshot::Sender<FetchClient>),
|
||||||
|
/// Apply a status update.
|
||||||
|
StatusUpdate { height: u64, hash: H256, total_difficulty: U256 },
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,7 +22,7 @@ use tokio_stream::wrappers::UnboundedReceiverStream;
|
|||||||
use tracing::trace;
|
use tracing::trace;
|
||||||
|
|
||||||
/// A communication channel to the [`PeersManager`] to apply manual changes to the peer set.
|
/// A communication channel to the [`PeersManager`] to apply manual changes to the peer set.
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct PeersHandle {
|
pub struct PeersHandle {
|
||||||
/// Sender half of command channel back to the [`PeersManager`]
|
/// Sender half of command channel back to the [`PeersManager`]
|
||||||
manager_tx: mpsc::UnboundedSender<PeerCommand>,
|
manager_tx: mpsc::UnboundedSender<PeerCommand>,
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
//! Support for handling peer sessions.
|
//! Support for handling peer sessions.
|
||||||
pub use crate::message::PeerRequestSender;
|
pub use crate::message::PeerRequestSender;
|
||||||
use crate::{
|
use crate::{
|
||||||
fetch::StatusUpdate,
|
|
||||||
message::PeerMessage,
|
message::PeerMessage,
|
||||||
session::{
|
session::{
|
||||||
active::ActiveSession,
|
active::ActiveSession,
|
||||||
@ -20,7 +19,7 @@ use reth_eth_wire::{
|
|||||||
error::EthStreamError,
|
error::EthStreamError,
|
||||||
DisconnectReason, HelloMessage, Status, UnauthedEthStream, UnauthedP2PStream,
|
DisconnectReason, HelloMessage, Status, UnauthedEthStream, UnauthedP2PStream,
|
||||||
};
|
};
|
||||||
use reth_primitives::{ForkFilter, Hardfork, PeerId};
|
use reth_primitives::{ForkFilter, Hardfork, PeerId, H256, U256};
|
||||||
use secp256k1::SecretKey;
|
use secp256k1::SecretKey;
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
@ -150,10 +149,10 @@ impl SessionManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Invoked on a received status update
|
/// Invoked on a received status update
|
||||||
pub(crate) fn on_status_update(&mut self, status: StatusUpdate) {
|
pub(crate) fn on_status_update(&mut self, height: u64, hash: H256, total_difficulty: U256) {
|
||||||
self.status.blockhash = status.hash;
|
self.status.blockhash = hash;
|
||||||
self.status.total_difficulty = status.total_difficulty;
|
self.status.total_difficulty = total_difficulty;
|
||||||
self.fork_filter.set_head(status.height);
|
self.fork_filter.set_head(height);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An incoming TCP connection was received. This starts the authentication process to turn this
|
/// An incoming TCP connection was received. This starts the authentication process to turn this
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
cache::LruCache,
|
cache::LruCache,
|
||||||
discovery::{Discovery, DiscoveryEvent},
|
discovery::{Discovery, DiscoveryEvent},
|
||||||
fetch::{BlockResponseOutcome, FetchAction, StateFetcher, StatusUpdate},
|
fetch::{BlockResponseOutcome, FetchAction, StateFetcher},
|
||||||
message::{
|
message::{
|
||||||
BlockRequest, NewBlockMessage, PeerRequest, PeerRequestSender, PeerResponse,
|
BlockRequest, NewBlockMessage, PeerRequest, PeerRequestSender, PeerResponse,
|
||||||
PeerResponseResult,
|
PeerResponseResult,
|
||||||
@ -353,10 +353,6 @@ where
|
|||||||
FetchAction::BlockRequest { peer_id, request } => {
|
FetchAction::BlockRequest { peer_id, request } => {
|
||||||
self.handle_block_request(peer_id, request)
|
self.handle_block_request(peer_id, request)
|
||||||
}
|
}
|
||||||
FetchAction::StatusUpdate(status) => {
|
|
||||||
// we want to return this directly
|
|
||||||
return Poll::Ready(StateAction::StatusUpdate(status))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -427,8 +423,6 @@ pub(crate) struct ActivePeer {
|
|||||||
|
|
||||||
/// Message variants triggered by the [`State`]
|
/// Message variants triggered by the [`State`]
|
||||||
pub(crate) enum StateAction {
|
pub(crate) enum StateAction {
|
||||||
/// Received a node status update.
|
|
||||||
StatusUpdate(StatusUpdate),
|
|
||||||
/// Dispatch a `NewBlock` message to the peer
|
/// Dispatch a `NewBlock` message to the peer
|
||||||
NewBlock {
|
NewBlock {
|
||||||
/// Target of the message
|
/// Target of the message
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
fetch::StatusUpdate,
|
|
||||||
listener::{ConnectionListener, ListenerEvent},
|
listener::{ConnectionListener, ListenerEvent},
|
||||||
message::{PeerMessage, PeerRequestSender},
|
message::{PeerMessage, PeerRequestSender},
|
||||||
peers::InboundConnectionError,
|
peers::InboundConnectionError,
|
||||||
@ -221,7 +220,6 @@ where
|
|||||||
let msg = PeerMessage::NewBlockHashes(hashes);
|
let msg = PeerMessage::NewBlockHashes(hashes);
|
||||||
self.sessions.send_message(&peer_id, msg);
|
self.sessions.send_message(&peer_id, msg);
|
||||||
}
|
}
|
||||||
StateAction::StatusUpdate(status) => return Some(SwarmEvent::StatusUpdate(status)),
|
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -279,8 +277,6 @@ where
|
|||||||
/// All events created or delegated by the [`Swarm`] that represents changes to the state of the
|
/// All events created or delegated by the [`Swarm`] that represents changes to the state of the
|
||||||
/// network.
|
/// network.
|
||||||
pub(crate) enum SwarmEvent {
|
pub(crate) enum SwarmEvent {
|
||||||
/// Received a node status update.
|
|
||||||
StatusUpdate(StatusUpdate),
|
|
||||||
/// Events related to the actual network protocol.
|
/// Events related to the actual network protocol.
|
||||||
ValidMessage {
|
ValidMessage {
|
||||||
/// The peer that sent the message
|
/// The peer that sent the message
|
||||||
|
|||||||
@ -14,7 +14,8 @@ reth-interfaces = { path = "../interfaces" }
|
|||||||
reth-executor = { path = "../executor" }
|
reth-executor = { path = "../executor" }
|
||||||
reth-rlp = { path = "../common/rlp" }
|
reth-rlp = { path = "../common/rlp" }
|
||||||
reth-db = { path = "../storage/db" }
|
reth-db = { path = "../storage/db" }
|
||||||
reth-provider = { path = "../storage/provider"}
|
reth-provider = { path = "../storage/provider" }
|
||||||
|
reth-network = { path = "../net/network" }
|
||||||
|
|
||||||
#async
|
#async
|
||||||
tokio = { version = "1.21.2", features = ["sync"] }
|
tokio = { version = "1.21.2", features = ["sync"] }
|
||||||
@ -34,7 +35,7 @@ rayon = "1.6.0"
|
|||||||
reth-db = { path = "../storage/db", features = ["test-utils", "mdbx"] }
|
reth-db = { path = "../storage/db", features = ["test-utils", "mdbx"] }
|
||||||
reth-interfaces = { path = "../interfaces", features = ["test-utils"] }
|
reth-interfaces = { path = "../interfaces", features = ["test-utils"] }
|
||||||
reth-downloaders = { path = "../net/downloaders" }
|
reth-downloaders = { path = "../net/downloaders" }
|
||||||
reth-eth-wire = { path = "../net/eth-wire" } # TODO(onbjerg): We only need this for [BlockBody]
|
reth-eth-wire = { path = "../net/eth-wire" } # TODO(onbjerg): We only need this for [BlockBody]
|
||||||
tokio = { version = "*", features = ["rt", "sync", "macros"] }
|
tokio = { version = "*", features = ["rt", "sync", "macros"] }
|
||||||
tokio-stream = "0.1.10"
|
tokio-stream = "0.1.10"
|
||||||
tempfile = "3.3.0"
|
tempfile = "3.3.0"
|
||||||
|
|||||||
@ -13,7 +13,7 @@ use reth_db::{
|
|||||||
use reth_interfaces::{
|
use reth_interfaces::{
|
||||||
consensus::{Consensus, ForkchoiceState},
|
consensus::{Consensus, ForkchoiceState},
|
||||||
p2p::headers::{
|
p2p::headers::{
|
||||||
client::HeadersClient,
|
client::{HeadersClient, StatusUpdater},
|
||||||
downloader::{ensure_parent, HeaderDownloader},
|
downloader::{ensure_parent, HeaderDownloader},
|
||||||
error::DownloadError,
|
error::DownloadError,
|
||||||
},
|
},
|
||||||
@ -40,20 +40,22 @@ const HEADERS: StageId = StageId("Headers");
|
|||||||
/// [`HeaderTD`][reth_interfaces::db::tables::HeaderTD] table). The stage does not return the
|
/// [`HeaderTD`][reth_interfaces::db::tables::HeaderTD] table). The stage does not return the
|
||||||
/// control flow to the pipeline in order to preserve the context of the chain tip.
|
/// control flow to the pipeline in order to preserve the context of the chain tip.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct HeaderStage<D: HeaderDownloader, C: Consensus, H: HeadersClient> {
|
pub struct HeaderStage<D: HeaderDownloader, C: Consensus, H: HeadersClient, S: StatusUpdater> {
|
||||||
/// Strategy for downloading the headers
|
/// Strategy for downloading the headers
|
||||||
pub downloader: D,
|
pub downloader: D,
|
||||||
/// Consensus client implementation
|
/// Consensus client implementation
|
||||||
pub consensus: Arc<C>,
|
pub consensus: Arc<C>,
|
||||||
/// Downloader client implementation
|
/// Downloader client implementation
|
||||||
pub client: Arc<H>,
|
pub client: Arc<H>,
|
||||||
|
/// Network handle for updating status
|
||||||
|
pub network_handle: S,
|
||||||
/// The number of block headers to commit at once
|
/// The number of block headers to commit at once
|
||||||
pub commit_threshold: usize,
|
pub commit_threshold: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl<DB: Database, D: HeaderDownloader, C: Consensus, H: HeadersClient> Stage<DB>
|
impl<DB: Database, D: HeaderDownloader, C: Consensus, H: HeadersClient, S: StatusUpdater> Stage<DB>
|
||||||
for HeaderStage<D, C, H>
|
for HeaderStage<D, C, H, S>
|
||||||
{
|
{
|
||||||
/// Return the id of the stage
|
/// Return the id of the stage
|
||||||
fn id(&self) -> StageId {
|
fn id(&self) -> StageId {
|
||||||
@ -146,7 +148,9 @@ impl<DB: Database, D: HeaderDownloader, C: Consensus, H: HeadersClient> Stage<DB
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: HeaderDownloader, C: Consensus, H: HeadersClient> HeaderStage<D, C, H> {
|
impl<D: HeaderDownloader, C: Consensus, H: HeadersClient, S: StatusUpdater>
|
||||||
|
HeaderStage<D, C, H, S>
|
||||||
|
{
|
||||||
async fn update_head<DB: Database>(
|
async fn update_head<DB: Database>(
|
||||||
&self,
|
&self,
|
||||||
db: &StageDB<'_, DB>,
|
db: &StageDB<'_, DB>,
|
||||||
@ -156,7 +160,8 @@ impl<D: HeaderDownloader, C: Consensus, H: HeadersClient> HeaderStage<D, C, H> {
|
|||||||
let td: U256 = *db
|
let td: U256 = *db
|
||||||
.get::<tables::HeaderTD>(block_key)?
|
.get::<tables::HeaderTD>(block_key)?
|
||||||
.ok_or(DatabaseIntegrityError::TotalDifficulty { number: height })?;
|
.ok_or(DatabaseIntegrityError::TotalDifficulty { number: height })?;
|
||||||
self.client.update_status(height, block_key.hash(), td);
|
// self.client.update_status(height, block_key.hash(), td);
|
||||||
|
self.network_handle.update_status(height, block_key.hash(), td);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -366,7 +371,7 @@ mod tests {
|
|||||||
p2p::headers::downloader::HeaderDownloader,
|
p2p::headers::downloader::HeaderDownloader,
|
||||||
test_utils::{
|
test_utils::{
|
||||||
generators::{random_header, random_header_range},
|
generators::{random_header, random_header_range},
|
||||||
TestConsensus, TestHeaderDownloader, TestHeadersClient,
|
TestConsensus, TestHeaderDownloader, TestHeadersClient, TestStatusUpdater,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use reth_primitives::{BlockNumber, SealedHeader, U256};
|
use reth_primitives::{BlockNumber, SealedHeader, U256};
|
||||||
@ -376,6 +381,7 @@ mod tests {
|
|||||||
pub(crate) consensus: Arc<TestConsensus>,
|
pub(crate) consensus: Arc<TestConsensus>,
|
||||||
pub(crate) client: Arc<TestHeadersClient>,
|
pub(crate) client: Arc<TestHeadersClient>,
|
||||||
downloader: Arc<D>,
|
downloader: Arc<D>,
|
||||||
|
network_handle: TestStatusUpdater,
|
||||||
db: TestStageDB,
|
db: TestStageDB,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -387,13 +393,14 @@ mod tests {
|
|||||||
client: client.clone(),
|
client: client.clone(),
|
||||||
consensus: consensus.clone(),
|
consensus: consensus.clone(),
|
||||||
downloader: Arc::new(TestHeaderDownloader::new(client, consensus, 1000)),
|
downloader: Arc::new(TestHeaderDownloader::new(client, consensus, 1000)),
|
||||||
|
network_handle: TestStatusUpdater::default(),
|
||||||
db: TestStageDB::default(),
|
db: TestStageDB::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: HeaderDownloader + 'static> StageTestRunner for HeadersTestRunner<D> {
|
impl<D: HeaderDownloader + 'static> StageTestRunner for HeadersTestRunner<D> {
|
||||||
type S = HeaderStage<Arc<D>, TestConsensus, TestHeadersClient>;
|
type S = HeaderStage<Arc<D>, TestConsensus, TestHeadersClient, TestStatusUpdater>;
|
||||||
|
|
||||||
fn db(&self) -> &TestStageDB {
|
fn db(&self) -> &TestStageDB {
|
||||||
&self.db
|
&self.db
|
||||||
@ -404,6 +411,7 @@ mod tests {
|
|||||||
consensus: self.consensus.clone(),
|
consensus: self.consensus.clone(),
|
||||||
client: self.client.clone(),
|
client: self.client.clone(),
|
||||||
downloader: self.downloader.clone(),
|
downloader: self.downloader.clone(),
|
||||||
|
network_handle: self.network_handle.clone(),
|
||||||
commit_threshold: 100,
|
commit_threshold: 100,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -504,7 +512,13 @@ mod tests {
|
|||||||
let downloader = Arc::new(
|
let downloader = Arc::new(
|
||||||
LinearDownloadBuilder::default().build(consensus.clone(), client.clone()),
|
LinearDownloadBuilder::default().build(consensus.clone(), client.clone()),
|
||||||
);
|
);
|
||||||
Self { client, consensus, downloader, db: TestStageDB::default() }
|
Self {
|
||||||
|
client,
|
||||||
|
consensus,
|
||||||
|
downloader,
|
||||||
|
network_handle: TestStatusUpdater::default(),
|
||||||
|
db: TestStageDB::default(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user