referrerpolicy=no-referrer-when-downgrade

sc_network/service/
traits.rs

1// This file is part of Substrate.
2//
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
5//
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10//
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15//
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <https://www.gnu.org/licenses/>.
18//
19// If you read this, you are very thorough, congratulations.
20
21//! Traits defined by `sc-network`.
22
23use crate::{
24	config::{IncomingRequest, MultiaddrWithPeerId, NotificationHandshake, Params, SetConfig},
25	error::{self, Error},
26	event::Event,
27	network_state::NetworkState,
28	request_responses::{IfDisconnected, RequestFailure},
29	service::{metrics::NotificationMetrics, signature::Signature, PeerStoreProvider},
30	types::ProtocolName,
31	ReputationChange,
32};
33
34use futures::{channel::oneshot, Stream};
35use prometheus_endpoint::Registry;
36
37use sc_client_api::BlockBackend;
38use sc_network_common::{role::ObservedRole, ExHashT};
39pub use sc_network_types::{
40	kad::{Key as KademliaKey, Record},
41	multiaddr::Multiaddr,
42	PeerId,
43};
44use sp_runtime::traits::Block as BlockT;
45
46use std::{
47	collections::HashSet,
48	fmt::Debug,
49	future::Future,
50	pin::Pin,
51	sync::Arc,
52	time::{Duration, Instant},
53};
54
55pub use libp2p::identity::SigningError;
56
57/// Supertrait defining the services provided by [`NetworkBackend`] service handle.
58pub trait NetworkService:
59	NetworkSigner
60	+ NetworkDHTProvider
61	+ NetworkStatusProvider
62	+ NetworkPeers
63	+ NetworkEventStream
64	+ NetworkStateInfo
65	+ NetworkRequest
66	+ Send
67	+ Sync
68	+ 'static
69{
70}
71
72impl<T> NetworkService for T where
73	T: NetworkSigner
74		+ NetworkDHTProvider
75		+ NetworkStatusProvider
76		+ NetworkPeers
77		+ NetworkEventStream
78		+ NetworkStateInfo
79		+ NetworkRequest
80		+ Send
81		+ Sync
82		+ 'static
83{
84}
85
86/// Trait defining the required functionality from a notification protocol configuration.
87pub trait NotificationConfig: Debug {
88	/// Get access to the `SetConfig` of the notification protocol.
89	fn set_config(&self) -> &SetConfig;
90
91	/// Get protocol name.
92	fn protocol_name(&self) -> &ProtocolName;
93}
94
95/// Trait defining the required functionality from a request-response protocol configuration.
96pub trait RequestResponseConfig: Debug {
97	/// Get protocol name.
98	fn protocol_name(&self) -> &ProtocolName;
99}
100
101/// Trait defining required functionality from `PeerStore`.
102#[async_trait::async_trait]
103pub trait PeerStore {
104	/// Get handle to `PeerStore`.
105	fn handle(&self) -> Arc<dyn PeerStoreProvider>;
106
107	/// Start running `PeerStore` event loop.
108	async fn run(self);
109}
110
111/// Networking backend.
112#[async_trait::async_trait]
113pub trait NetworkBackend<B: BlockT + 'static, H: ExHashT>: Send + 'static {
114	/// Type representing notification protocol-related configuration.
115	type NotificationProtocolConfig: NotificationConfig;
116
117	/// Type representing request-response protocol-related configuration.
118	type RequestResponseProtocolConfig: RequestResponseConfig;
119
120	/// Type implementing `NetworkService` for the networking backend.
121	///
122	/// `NetworkService` allows other subsystems of the blockchain to interact with `sc-network`
123	/// using `NetworkService`.
124	type NetworkService<Block, Hash>: NetworkService + Clone;
125
126	/// Type implementing [`PeerStore`].
127	type PeerStore: PeerStore;
128
129	/// Bitswap config.
130	type BitswapConfig;
131
132	/// Create new `NetworkBackend`.
133	fn new(params: Params<B, H, Self>) -> Result<Self, Error>
134	where
135		Self: Sized;
136
137	/// Get handle to `NetworkService` of the `NetworkBackend`.
138	fn network_service(&self) -> Arc<dyn NetworkService>;
139
140	/// Create [`PeerStore`].
141	fn peer_store(bootnodes: Vec<PeerId>, metrics_registry: Option<Registry>) -> Self::PeerStore;
142
143	/// Register metrics that are used by the notification protocols.
144	fn register_notification_metrics(registry: Option<&Registry>) -> NotificationMetrics;
145
146	/// Create Bitswap server.
147	fn bitswap_server(
148		client: Arc<dyn BlockBackend<B> + Send + Sync>,
149	) -> (Pin<Box<dyn Future<Output = ()> + Send>>, Self::BitswapConfig);
150
151	/// Create notification protocol configuration and an associated `NotificationService`
152	/// for the protocol.
153	fn notification_config(
154		protocol_name: ProtocolName,
155		fallback_names: Vec<ProtocolName>,
156		max_notification_size: u64,
157		handshake: Option<NotificationHandshake>,
158		set_config: SetConfig,
159		metrics: NotificationMetrics,
160		peerstore_handle: Arc<dyn PeerStoreProvider>,
161	) -> (Self::NotificationProtocolConfig, Box<dyn NotificationService>);
162
163	/// Create request-response protocol configuration.
164	fn request_response_config(
165		protocol_name: ProtocolName,
166		fallback_names: Vec<ProtocolName>,
167		max_request_size: u64,
168		max_response_size: u64,
169		request_timeout: Duration,
170		inbound_queue: Option<async_channel::Sender<IncomingRequest>>,
171	) -> Self::RequestResponseProtocolConfig;
172
173	/// Start [`NetworkBackend`] event loop.
174	async fn run(mut self);
175}
176
177/// Signer with network identity
178pub trait NetworkSigner {
179	/// Signs the message with the `KeyPair` that defines the local [`PeerId`].
180	fn sign_with_local_identity(&self, msg: Vec<u8>) -> Result<Signature, SigningError>;
181
182	/// Verify signature using peer's public key.
183	///
184	/// `public_key` must be Protobuf-encoded ed25519 public key.
185	///
186	/// Returns `Err(())` if public cannot be parsed into a valid ed25519 public key.
187	fn verify(
188		&self,
189		peer_id: sc_network_types::PeerId,
190		public_key: &Vec<u8>,
191		signature: &Vec<u8>,
192		message: &Vec<u8>,
193	) -> Result<bool, String>;
194}
195
196impl<T> NetworkSigner for Arc<T>
197where
198	T: ?Sized,
199	T: NetworkSigner,
200{
201	fn sign_with_local_identity(&self, msg: Vec<u8>) -> Result<Signature, SigningError> {
202		T::sign_with_local_identity(self, msg)
203	}
204
205	fn verify(
206		&self,
207		peer_id: sc_network_types::PeerId,
208		public_key: &Vec<u8>,
209		signature: &Vec<u8>,
210		message: &Vec<u8>,
211	) -> Result<bool, String> {
212		T::verify(self, peer_id, public_key, signature, message)
213	}
214}
215
216/// Provides access to the networking DHT.
217pub trait NetworkDHTProvider {
218	/// Start finding closest peers to the target.
219	fn find_closest_peers(&self, target: PeerId);
220
221	/// Start getting a value from the DHT.
222	fn get_value(&self, key: &KademliaKey);
223
224	/// Start putting a value in the DHT.
225	fn put_value(&self, key: KademliaKey, value: Vec<u8>);
226
227	/// Start putting the record to `peers`.
228	///
229	/// If `update_local_storage` is true the local storage is udpated as well.
230	fn put_record_to(&self, record: Record, peers: HashSet<PeerId>, update_local_storage: bool);
231
232	/// Store a record in the DHT memory store.
233	fn store_record(
234		&self,
235		key: KademliaKey,
236		value: Vec<u8>,
237		publisher: Option<PeerId>,
238		expires: Option<Instant>,
239	);
240
241	/// Register this node as a provider for `key` on the DHT.
242	fn start_providing(&self, key: KademliaKey);
243
244	/// Deregister this node as a provider for `key` on the DHT.
245	fn stop_providing(&self, key: KademliaKey);
246
247	/// Start getting the list of providers for `key` on the DHT.
248	fn get_providers(&self, key: KademliaKey);
249}
250
251impl<T> NetworkDHTProvider for Arc<T>
252where
253	T: ?Sized,
254	T: NetworkDHTProvider,
255{
256	fn find_closest_peers(&self, target: PeerId) {
257		T::find_closest_peers(self, target)
258	}
259
260	fn get_value(&self, key: &KademliaKey) {
261		T::get_value(self, key)
262	}
263
264	fn put_value(&self, key: KademliaKey, value: Vec<u8>) {
265		T::put_value(self, key, value)
266	}
267
268	fn put_record_to(&self, record: Record, peers: HashSet<PeerId>, update_local_storage: bool) {
269		T::put_record_to(self, record, peers, update_local_storage)
270	}
271
272	fn store_record(
273		&self,
274		key: KademliaKey,
275		value: Vec<u8>,
276		publisher: Option<PeerId>,
277		expires: Option<Instant>,
278	) {
279		T::store_record(self, key, value, publisher, expires)
280	}
281
282	fn start_providing(&self, key: KademliaKey) {
283		T::start_providing(self, key)
284	}
285
286	fn stop_providing(&self, key: KademliaKey) {
287		T::stop_providing(self, key)
288	}
289
290	fn get_providers(&self, key: KademliaKey) {
291		T::get_providers(self, key)
292	}
293}
294
295/// Provides an ability to set a fork sync request for a particular block.
296pub trait NetworkSyncForkRequest<BlockHash, BlockNumber> {
297	/// Notifies the sync service to try and sync the given block from the given
298	/// peers.
299	///
300	/// If the given vector of peers is empty then the underlying implementation
301	/// should make a best effort to fetch the block from any peers it is
302	/// connected to (NOTE: this assumption will change in the future #3629).
303	fn set_sync_fork_request(&self, peers: Vec<PeerId>, hash: BlockHash, number: BlockNumber);
304}
305
306impl<T, BlockHash, BlockNumber> NetworkSyncForkRequest<BlockHash, BlockNumber> for Arc<T>
307where
308	T: ?Sized,
309	T: NetworkSyncForkRequest<BlockHash, BlockNumber>,
310{
311	fn set_sync_fork_request(&self, peers: Vec<PeerId>, hash: BlockHash, number: BlockNumber) {
312		T::set_sync_fork_request(self, peers, hash, number)
313	}
314}
315
316/// Overview status of the network.
317#[derive(Clone)]
318pub struct NetworkStatus {
319	/// Total number of connected peers.
320	pub num_connected_peers: usize,
321	/// The total number of bytes received.
322	pub total_bytes_inbound: u64,
323	/// The total number of bytes sent.
324	pub total_bytes_outbound: u64,
325}
326
327/// Provides high-level status information about network.
328#[async_trait::async_trait]
329pub trait NetworkStatusProvider {
330	/// High-level network status information.
331	///
332	/// Returns an error if the `NetworkWorker` is no longer running.
333	async fn status(&self) -> Result<NetworkStatus, ()>;
334
335	/// Get the network state.
336	///
337	/// Returns an error if the `NetworkWorker` is no longer running.
338	async fn network_state(&self) -> Result<NetworkState, ()>;
339}
340
341// Manual implementation to avoid extra boxing here
342impl<T> NetworkStatusProvider for Arc<T>
343where
344	T: ?Sized,
345	T: NetworkStatusProvider,
346{
347	fn status<'life0, 'async_trait>(
348		&'life0 self,
349	) -> Pin<Box<dyn Future<Output = Result<NetworkStatus, ()>> + Send + 'async_trait>>
350	where
351		'life0: 'async_trait,
352		Self: 'async_trait,
353	{
354		T::status(self)
355	}
356
357	fn network_state<'life0, 'async_trait>(
358		&'life0 self,
359	) -> Pin<Box<dyn Future<Output = Result<NetworkState, ()>> + Send + 'async_trait>>
360	where
361		'life0: 'async_trait,
362		Self: 'async_trait,
363	{
364		T::network_state(self)
365	}
366}
367
368/// Provides low-level API for manipulating network peers.
369#[async_trait::async_trait]
370pub trait NetworkPeers {
371	/// Set authorized peers.
372	///
373	/// Need a better solution to manage authorized peers, but now just use reserved peers for
374	/// prototyping.
375	fn set_authorized_peers(&self, peers: HashSet<PeerId>);
376
377	/// Set authorized_only flag.
378	///
379	/// Need a better solution to decide authorized_only, but now just use reserved_only flag for
380	/// prototyping.
381	fn set_authorized_only(&self, reserved_only: bool);
382
383	/// Adds an address known to a node.
384	fn add_known_address(&self, peer_id: PeerId, addr: Multiaddr);
385
386	/// Report a given peer as either beneficial (+) or costly (-) according to the
387	/// given scalar.
388	fn report_peer(&self, peer_id: PeerId, cost_benefit: ReputationChange);
389
390	/// Get peer reputation.
391	fn peer_reputation(&self, peer_id: &PeerId) -> i32;
392
393	/// Disconnect from a node as soon as possible.
394	///
395	/// This triggers the same effects as if the connection had closed itself spontaneously.
396	fn disconnect_peer(&self, peer_id: PeerId, protocol: ProtocolName);
397
398	/// Connect to unreserved peers and allow unreserved peers to connect for syncing purposes.
399	fn accept_unreserved_peers(&self);
400
401	/// Disconnect from unreserved peers and deny new unreserved peers to connect for syncing
402	/// purposes.
403	fn deny_unreserved_peers(&self);
404
405	/// Adds a `PeerId` and its `Multiaddr` as reserved for a sync protocol (default peer set).
406	///
407	/// Returns an `Err` if the given string is not a valid multiaddress
408	/// or contains an invalid peer ID (which includes the local peer ID).
409	fn add_reserved_peer(&self, peer: MultiaddrWithPeerId) -> Result<(), String>;
410
411	/// Removes a `PeerId` from the list of reserved peers for a sync protocol (default peer set).
412	fn remove_reserved_peer(&self, peer_id: PeerId);
413
414	/// Sets the reserved set of a protocol to the given set of peers.
415	///
416	/// Each `Multiaddr` must end with a `/p2p/` component containing the `PeerId`. It can also
417	/// consist of only `/p2p/<peerid>`.
418	///
419	/// The node will start establishing/accepting connections and substreams to/from peers in this
420	/// set, if it doesn't have any substream open with them yet.
421	///
422	/// Note however, if a call to this function results in less peers on the reserved set, they
423	/// will not necessarily get disconnected (depending on available free slots in the peer set).
424	/// If you want to also disconnect those removed peers, you will have to call
425	/// `remove_from_peers_set` on those in addition to updating the reserved set. You can omit
426	/// this step if the peer set is in reserved only mode.
427	///
428	/// Returns an `Err` if one of the given addresses is invalid or contains an
429	/// invalid peer ID (which includes the local peer ID), or if `protocol` does not
430	/// refer to a known protocol.
431	fn set_reserved_peers(
432		&self,
433		protocol: ProtocolName,
434		peers: HashSet<Multiaddr>,
435	) -> Result<(), String>;
436
437	/// Add peers to a peer set.
438	///
439	/// Each `Multiaddr` must end with a `/p2p/` component containing the `PeerId`. It can also
440	/// consist of only `/p2p/<peerid>`.
441	///
442	/// Returns an `Err` if one of the given addresses is invalid or contains an
443	/// invalid peer ID (which includes the local peer ID), or if `protocol` does not
444	/// refer to a know protocol.
445	fn add_peers_to_reserved_set(
446		&self,
447		protocol: ProtocolName,
448		peers: HashSet<Multiaddr>,
449	) -> Result<(), String>;
450
451	/// Remove peers from a peer set.
452	///
453	/// Returns `Err` if `protocol` does not refer to a known protocol.
454	fn remove_peers_from_reserved_set(
455		&self,
456		protocol: ProtocolName,
457		peers: Vec<PeerId>,
458	) -> Result<(), String>;
459
460	/// Returns the number of peers in the sync peer set we're connected to.
461	fn sync_num_connected(&self) -> usize;
462
463	/// Attempt to get peer role.
464	///
465	/// Right now the peer role is decoded from the received handshake for all protocols
466	/// (`/block-announces/1` has other information as well). If the handshake cannot be
467	/// decoded into a role, the role queried from `PeerStore` and if the role is not stored
468	/// there either, `None` is returned and the peer should be discarded.
469	fn peer_role(&self, peer_id: PeerId, handshake: Vec<u8>) -> Option<ObservedRole>;
470
471	/// Get the list of reserved peers.
472	///
473	/// Returns an error if the `NetworkWorker` is no longer running.
474	async fn reserved_peers(&self) -> Result<Vec<PeerId>, ()>;
475}
476
477// Manual implementation to avoid extra boxing here
478#[async_trait::async_trait]
479impl<T> NetworkPeers for Arc<T>
480where
481	T: ?Sized,
482	T: NetworkPeers,
483{
484	fn set_authorized_peers(&self, peers: HashSet<PeerId>) {
485		T::set_authorized_peers(self, peers)
486	}
487
488	fn set_authorized_only(&self, reserved_only: bool) {
489		T::set_authorized_only(self, reserved_only)
490	}
491
492	fn add_known_address(&self, peer_id: PeerId, addr: Multiaddr) {
493		T::add_known_address(self, peer_id, addr)
494	}
495
496	fn report_peer(&self, peer_id: PeerId, cost_benefit: ReputationChange) {
497		T::report_peer(self, peer_id, cost_benefit)
498	}
499
500	fn peer_reputation(&self, peer_id: &PeerId) -> i32 {
501		T::peer_reputation(self, peer_id)
502	}
503
504	fn disconnect_peer(&self, peer_id: PeerId, protocol: ProtocolName) {
505		T::disconnect_peer(self, peer_id, protocol)
506	}
507
508	fn accept_unreserved_peers(&self) {
509		T::accept_unreserved_peers(self)
510	}
511
512	fn deny_unreserved_peers(&self) {
513		T::deny_unreserved_peers(self)
514	}
515
516	fn add_reserved_peer(&self, peer: MultiaddrWithPeerId) -> Result<(), String> {
517		T::add_reserved_peer(self, peer)
518	}
519
520	fn remove_reserved_peer(&self, peer_id: PeerId) {
521		T::remove_reserved_peer(self, peer_id)
522	}
523
524	fn set_reserved_peers(
525		&self,
526		protocol: ProtocolName,
527		peers: HashSet<Multiaddr>,
528	) -> Result<(), String> {
529		T::set_reserved_peers(self, protocol, peers)
530	}
531
532	fn add_peers_to_reserved_set(
533		&self,
534		protocol: ProtocolName,
535		peers: HashSet<Multiaddr>,
536	) -> Result<(), String> {
537		T::add_peers_to_reserved_set(self, protocol, peers)
538	}
539
540	fn remove_peers_from_reserved_set(
541		&self,
542		protocol: ProtocolName,
543		peers: Vec<PeerId>,
544	) -> Result<(), String> {
545		T::remove_peers_from_reserved_set(self, protocol, peers)
546	}
547
548	fn sync_num_connected(&self) -> usize {
549		T::sync_num_connected(self)
550	}
551
552	fn peer_role(&self, peer_id: PeerId, handshake: Vec<u8>) -> Option<ObservedRole> {
553		T::peer_role(self, peer_id, handshake)
554	}
555
556	fn reserved_peers<'life0, 'async_trait>(
557		&'life0 self,
558	) -> Pin<Box<dyn Future<Output = Result<Vec<PeerId>, ()>> + Send + 'async_trait>>
559	where
560		'life0: 'async_trait,
561		Self: 'async_trait,
562	{
563		T::reserved_peers(self)
564	}
565}
566
567/// Provides access to network-level event stream.
568pub trait NetworkEventStream {
569	/// Returns a stream containing the events that happen on the network.
570	///
571	/// If this method is called multiple times, the events are duplicated.
572	///
573	/// The stream never ends (unless the `NetworkWorker` gets shut down).
574	///
575	/// The name passed is used to identify the channel in the Prometheus metrics. Note that the
576	/// parameter is a `&'static str`, and not a `String`, in order to avoid accidentally having
577	/// an unbounded set of Prometheus metrics, which would be quite bad in terms of memory
578	fn event_stream(&self, name: &'static str) -> Pin<Box<dyn Stream<Item = Event> + Send>>;
579}
580
581impl<T> NetworkEventStream for Arc<T>
582where
583	T: ?Sized,
584	T: NetworkEventStream,
585{
586	fn event_stream(&self, name: &'static str) -> Pin<Box<dyn Stream<Item = Event> + Send>> {
587		T::event_stream(self, name)
588	}
589}
590
591/// Trait for providing information about the local network state
592pub trait NetworkStateInfo {
593	/// Returns the local external addresses.
594	fn external_addresses(&self) -> Vec<Multiaddr>;
595
596	/// Returns the listening addresses (without trailing `/p2p/` with our `PeerId`).
597	fn listen_addresses(&self) -> Vec<Multiaddr>;
598
599	/// Returns the local Peer ID.
600	fn local_peer_id(&self) -> PeerId;
601}
602
603impl<T> NetworkStateInfo for Arc<T>
604where
605	T: ?Sized,
606	T: NetworkStateInfo,
607{
608	fn external_addresses(&self) -> Vec<Multiaddr> {
609		T::external_addresses(self)
610	}
611
612	fn listen_addresses(&self) -> Vec<Multiaddr> {
613		T::listen_addresses(self)
614	}
615
616	fn local_peer_id(&self) -> PeerId {
617		T::local_peer_id(self)
618	}
619}
620
621/// Reserved slot in the notifications buffer, ready to accept data.
622pub trait NotificationSenderReady {
623	/// Consumes this slots reservation and actually queues the notification.
624	///
625	/// NOTE: Traits can't consume itself, but calling this method second time will return an error.
626	fn send(&mut self, notification: Vec<u8>) -> Result<(), NotificationSenderError>;
627}
628
629/// A `NotificationSender` allows for sending notifications to a peer with a chosen protocol.
630#[async_trait::async_trait]
631pub trait NotificationSender: Send + Sync + 'static {
632	/// Returns a future that resolves when the `NotificationSender` is ready to send a
633	/// notification.
634	async fn ready(&self)
635		-> Result<Box<dyn NotificationSenderReady + '_>, NotificationSenderError>;
636}
637
638/// Error returned by the notification sink.
639#[derive(Debug, thiserror::Error)]
640pub enum NotificationSenderError {
641	/// The notification receiver has been closed, usually because the underlying connection
642	/// closed.
643	///
644	/// Some of the notifications most recently sent may not have been received. However,
645	/// the peer may still be connected and a new notification sink for the same
646	/// protocol obtained from [`NotificationService::message_sink()`].
647	#[error("The notification receiver has been closed")]
648	Closed,
649	/// Protocol name hasn't been registered.
650	#[error("Protocol name hasn't been registered")]
651	BadProtocol,
652}
653
654/// Provides ability to send network requests.
655#[async_trait::async_trait]
656pub trait NetworkRequest {
657	/// Sends a single targeted request to a specific peer. On success, returns the response of
658	/// the peer.
659	///
660	/// Request-response protocols are a way to complement notifications protocols, but
661	/// notifications should remain the default ways of communicating information. For example, a
662	/// peer can announce something through a notification, after which the recipient can obtain
663	/// more information by performing a request.
664	/// As such, call this function with `IfDisconnected::ImmediateError` for `connect`. This way
665	/// you will get an error immediately for disconnected peers, instead of waiting for a
666	/// potentially very long connection attempt, which would suggest that something is wrong
667	/// anyway, as you are supposed to be connected because of the notification protocol.
668	///
669	/// No limit or throttling of concurrent outbound requests per peer and protocol are enforced.
670	/// Such restrictions, if desired, need to be enforced at the call site(s).
671	///
672	/// The protocol must have been registered through
673	/// `NetworkConfiguration::request_response_protocols`.
674	async fn request(
675		&self,
676		target: PeerId,
677		protocol: ProtocolName,
678		request: Vec<u8>,
679		fallback_request: Option<(Vec<u8>, ProtocolName)>,
680		connect: IfDisconnected,
681	) -> Result<(Vec<u8>, ProtocolName), RequestFailure>;
682
683	/// Variation of `request` which starts a request whose response is delivered on a provided
684	/// channel.
685	///
686	/// Instead of blocking and waiting for a reply, this function returns immediately, sending
687	/// responses via the passed in sender. This alternative API exists to make it easier to
688	/// integrate with message passing APIs.
689	///
690	/// Keep in mind that the connected receiver might receive a `Canceled` event in case of a
691	/// closing connection. This is expected behaviour. With `request` you would get a
692	/// `RequestFailure::Network(OutboundFailure::ConnectionClosed)` in that case.
693	fn start_request(
694		&self,
695		target: PeerId,
696		protocol: ProtocolName,
697		request: Vec<u8>,
698		fallback_request: Option<(Vec<u8>, ProtocolName)>,
699		tx: oneshot::Sender<Result<(Vec<u8>, ProtocolName), RequestFailure>>,
700		connect: IfDisconnected,
701	);
702}
703
704// Manual implementation to avoid extra boxing here
705impl<T> NetworkRequest for Arc<T>
706where
707	T: ?Sized,
708	T: NetworkRequest,
709{
710	fn request<'life0, 'async_trait>(
711		&'life0 self,
712		target: PeerId,
713		protocol: ProtocolName,
714		request: Vec<u8>,
715		fallback_request: Option<(Vec<u8>, ProtocolName)>,
716		connect: IfDisconnected,
717	) -> Pin<
718		Box<
719			dyn Future<Output = Result<(Vec<u8>, ProtocolName), RequestFailure>>
720				+ Send
721				+ 'async_trait,
722		>,
723	>
724	where
725		'life0: 'async_trait,
726		Self: 'async_trait,
727	{
728		T::request(self, target, protocol, request, fallback_request, connect)
729	}
730
731	fn start_request(
732		&self,
733		target: PeerId,
734		protocol: ProtocolName,
735		request: Vec<u8>,
736		fallback_request: Option<(Vec<u8>, ProtocolName)>,
737		tx: oneshot::Sender<Result<(Vec<u8>, ProtocolName), RequestFailure>>,
738		connect: IfDisconnected,
739	) {
740		T::start_request(self, target, protocol, request, fallback_request, tx, connect)
741	}
742}
743
744/// Provides ability to announce blocks to the network.
745pub trait NetworkBlock<BlockHash, BlockNumber> {
746	/// Make sure an important block is propagated to peers.
747	///
748	/// In chain-based consensus, we often need to make sure non-best forks are
749	/// at least temporarily synced. This function forces such an announcement.
750	fn announce_block(&self, hash: BlockHash, data: Option<Vec<u8>>);
751
752	/// Inform the network service about new best imported block.
753	fn new_best_block_imported(&self, hash: BlockHash, number: BlockNumber);
754}
755
756impl<T, BlockHash, BlockNumber> NetworkBlock<BlockHash, BlockNumber> for Arc<T>
757where
758	T: ?Sized,
759	T: NetworkBlock<BlockHash, BlockNumber>,
760{
761	fn announce_block(&self, hash: BlockHash, data: Option<Vec<u8>>) {
762		T::announce_block(self, hash, data)
763	}
764
765	fn new_best_block_imported(&self, hash: BlockHash, number: BlockNumber) {
766		T::new_best_block_imported(self, hash, number)
767	}
768}
769
770/// Substream acceptance result.
771#[derive(Debug, PartialEq, Eq)]
772pub enum ValidationResult {
773	/// Accept inbound substream.
774	Accept,
775
776	/// Reject inbound substream.
777	Reject,
778}
779
780/// Substream direction.
781#[derive(Debug, Copy, Clone, PartialEq, Eq)]
782pub enum Direction {
783	/// Substream opened by the remote node.
784	Inbound,
785
786	/// Substream opened by the local node.
787	Outbound,
788}
789
790impl From<litep2p::protocol::notification::Direction> for Direction {
791	fn from(direction: litep2p::protocol::notification::Direction) -> Self {
792		match direction {
793			litep2p::protocol::notification::Direction::Inbound => Direction::Inbound,
794			litep2p::protocol::notification::Direction::Outbound => Direction::Outbound,
795		}
796	}
797}
798
799impl Direction {
800	/// Is the direction inbound.
801	pub fn is_inbound(&self) -> bool {
802		std::matches!(self, Direction::Inbound)
803	}
804}
805
806/// Events received by the protocol from `Notifications`.
807#[derive(Debug)]
808pub enum NotificationEvent {
809	/// Validate inbound substream.
810	ValidateInboundSubstream {
811		/// Peer ID.
812		peer: PeerId,
813
814		/// Received handshake.
815		handshake: Vec<u8>,
816
817		/// `oneshot::Sender` for sending validation result back to `Notifications`
818		result_tx: tokio::sync::oneshot::Sender<ValidationResult>,
819	},
820
821	/// Remote identified by `PeerId` opened a substream and sent `Handshake`.
822	/// Validate `Handshake` and report status (accept/reject) to `Notifications`.
823	NotificationStreamOpened {
824		/// Peer ID.
825		peer: PeerId,
826
827		/// Is the substream inbound or outbound.
828		direction: Direction,
829
830		/// Received handshake.
831		handshake: Vec<u8>,
832
833		/// Negotiated fallback.
834		negotiated_fallback: Option<ProtocolName>,
835	},
836
837	/// Substream was closed.
838	NotificationStreamClosed {
839		/// Peer Id.
840		peer: PeerId,
841	},
842
843	/// Notification was received from the substream.
844	NotificationReceived {
845		/// Peer ID.
846		peer: PeerId,
847
848		/// Received notification.
849		notification: Vec<u8>,
850	},
851}
852
853/// Notification service
854///
855/// Defines behaviors that both the protocol implementations and `Notifications` can expect from
856/// each other.
857///
858/// `Notifications` can send two different kinds of information to protocol:
859///  * substream-related information
860///  * notification-related information
861///
862/// When an unvalidated, inbound substream is received by `Notifications`, it sends the inbound
863/// stream information (peer ID, handshake) to protocol for validation. Protocol must then verify
864/// that the handshake is valid (and in the future that it has a slot it can allocate for the peer)
865/// and then report back the `ValidationResult` which is either `Accept` or `Reject`.
866///
867/// After the validation result has been received by `Notifications`, it prepares the
868/// substream for communication by initializing the necessary sinks and emits
869/// `NotificationStreamOpened` which informs the protocol that the remote peer is ready to receive
870/// notifications.
871///
872/// Two different flavors of sending options are provided:
873///  * synchronous sending ([`NotificationService::send_sync_notification()`])
874///  * asynchronous sending ([`NotificationService::send_async_notification()`])
875///
876/// The former is used by the protocols not ready to exercise backpressure and the latter by the
877/// protocols that can do it.
878///
879/// Both local and remote peer can close the substream at any time. Local peer can do so by calling
880/// [`NotificationService::close_substream()`] which instructs `Notifications` to close the
881/// substream. Remote closing the substream is indicated to the local peer by receiving
882/// [`NotificationEvent::NotificationStreamClosed`] event.
883///
884/// In case the protocol must update its handshake while it's operating (such as updating the best
885/// block information), it can do so by calling [`NotificationService::set_handshake()`]
886/// which instructs `Notifications` to update the handshake it stored during protocol
887/// initialization.
888///
889/// All peer events are multiplexed on the same incoming event stream from `Notifications` and thus
890/// each event carries a `PeerId` so the protocol knows whose information to update when receiving
891/// an event.
892#[async_trait::async_trait]
893pub trait NotificationService: Debug + Send {
894	/// Instruct `Notifications` to open a new substream for `peer`.
895	///
896	/// `dial_if_disconnected` informs `Notifications` whether to dial
897	// the peer if there is currently no active connection to it.
898	//
899	// NOTE: not offered by the current implementation
900	async fn open_substream(&mut self, peer: PeerId) -> Result<(), ()>;
901
902	/// Instruct `Notifications` to close substream for `peer`.
903	//
904	// NOTE: not offered by the current implementation
905	async fn close_substream(&mut self, peer: PeerId) -> Result<(), ()>;
906
907	/// Send synchronous `notification` to `peer`.
908	fn send_sync_notification(&mut self, peer: &PeerId, notification: Vec<u8>);
909
910	/// Send asynchronous `notification` to `peer`, allowing sender to exercise backpressure.
911	///
912	/// Returns an error if the peer doesn't exist.
913	async fn send_async_notification(
914		&mut self,
915		peer: &PeerId,
916		notification: Vec<u8>,
917	) -> Result<(), error::Error>;
918
919	/// Set handshake for the notification protocol replacing the old handshake.
920	async fn set_handshake(&mut self, handshake: Vec<u8>) -> Result<(), ()>;
921
922	/// Non-blocking variant of `set_handshake()` that attempts to update the handshake
923	/// and returns an error if the channel is blocked.
924	///
925	/// Technically the function can return an error if the channel to `Notifications` is closed
926	/// but that doesn't happen under normal operation.
927	fn try_set_handshake(&mut self, handshake: Vec<u8>) -> Result<(), ()>;
928
929	/// Get next event from the `Notifications` event stream.
930	async fn next_event(&mut self) -> Option<NotificationEvent>;
931
932	/// Make a copy of the object so it can be shared between protocol components
933	/// who wish to have access to the same underlying notification protocol.
934	fn clone(&mut self) -> Result<Box<dyn NotificationService>, ()>;
935
936	/// Get protocol name of the `NotificationService`.
937	fn protocol(&self) -> &ProtocolName;
938
939	/// Get message sink of the peer.
940	fn message_sink(&self, peer: &PeerId) -> Option<Box<dyn MessageSink>>;
941}
942
943/// Message sink for peers.
944///
945/// If protocol cannot use [`NotificationService`] to send notifications to peers and requires,
946/// e.g., notifications to be sent in another task, the protocol may acquire a [`MessageSink`]
947/// object for each peer by calling [`NotificationService::message_sink()`]. Calling this
948/// function returns an object which allows the protocol to send notifications to the remote peer.
949///
950/// Use of this API is discouraged as it's not as performant as sending notifications through
951/// [`NotificationService`] due to synchronization required to keep the underlying notification
952/// sink up to date with possible sink replacement events.
953#[async_trait::async_trait]
954pub trait MessageSink: Send + Sync {
955	/// Send synchronous `notification` to the peer associated with this [`MessageSink`].
956	fn send_sync_notification(&self, notification: Vec<u8>);
957
958	/// Send an asynchronous `notification` to to the peer associated with this [`MessageSink`],
959	/// allowing sender to exercise backpressure.
960	///
961	/// Returns an error if the peer does not exist.
962	async fn send_async_notification(&self, notification: Vec<u8>) -> Result<(), error::Error>;
963}
964
965/// Trait defining the behavior of a bandwidth sink.
966pub trait BandwidthSink: Send + Sync {
967	/// Get the number of bytes received.
968	fn total_inbound(&self) -> u64;
969
970	/// Get the number of bytes sent.
971	fn total_outbound(&self) -> u64;
972}