subspace_networking/
behavior.rs

1pub(crate) mod persistent_parameters;
2#[cfg(test)]
3mod tests;
4
5use crate::constructor::DummyRecordStore;
6use crate::protocols::autonat_wrapper::{
7    Behaviour as AutonatWrapper, Config as AutonatWrapperConfig,
8};
9use crate::protocols::request_response::request_response_factory::{
10    Event as RequestResponseEvent, RequestHandler, RequestResponseFactoryBehaviour,
11};
12use crate::protocols::reserved_peers::{
13    Behaviour as ReservedPeersBehaviour, Config as ReservedPeersConfig, Event as ReservedPeersEvent,
14};
15use crate::protocols::subspace_connection_limits::Behaviour as ConnectionLimitsBehaviour;
16use derive_more::From;
17use libp2p::allow_block_list::{Behaviour as AllowBlockListBehaviour, BlockedPeers};
18use libp2p::autonat::Event as AutonatEvent;
19use libp2p::connection_limits::ConnectionLimits;
20use libp2p::gossipsub::{
21    Behaviour as Gossipsub, Config as GossipsubConfig, Event as GossipsubEvent, MessageAuthenticity,
22};
23use libp2p::identify::{Behaviour as Identify, Config as IdentifyConfig, Event as IdentifyEvent};
24use libp2p::kad::{Behaviour as Kademlia, Config as KademliaConfig, Event as KademliaEvent};
25use libp2p::ping::{Behaviour as Ping, Event as PingEvent};
26use libp2p::swarm::behaviour::toggle::Toggle;
27use libp2p::swarm::NetworkBehaviour;
28use libp2p::PeerId;
29use std::convert::Infallible;
30use void::Void as VoidEvent;
31
32type BlockListBehaviour = AllowBlockListBehaviour<BlockedPeers>;
33
34pub(crate) struct BehaviorConfig {
35    /// Identity keypair of a node used for authenticated connections.
36    pub(crate) peer_id: PeerId,
37    /// The configuration for the [`Identify`] behaviour.
38    pub(crate) identify: IdentifyConfig,
39    /// The configuration for the [`Kademlia`] behaviour.
40    pub(crate) kademlia: KademliaConfig,
41    /// The configuration for the [`Gossipsub`] behaviour.
42    pub(crate) gossipsub: Option<GossipsubConfig>,
43    /// The configuration for the [`RequestResponsesBehaviour`] protocol.
44    pub(crate) request_response_protocols: Vec<Box<dyn RequestHandler>>,
45    /// The upper bound for the number of concurrent inbound + outbound streams for request/response
46    /// protocols.
47    pub(crate) request_response_max_concurrent_streams: usize,
48    /// Connection limits for the swarm.
49    pub(crate) connection_limits: ConnectionLimits,
50    /// The configuration for the [`ReservedPeersBehaviour`].
51    pub(crate) reserved_peers: ReservedPeersConfig,
52    /// Autonat configuration.
53    pub(crate) autonat: AutonatWrapperConfig,
54}
55
56#[derive(NetworkBehaviour)]
57#[behaviour(to_swarm = "Event")]
58pub(crate) struct Behavior {
59    // TODO: Connection limits must be the first protocol due to https://github.com/libp2p/rust-libp2p/issues/4773 as
60    //  suggested in https://github.com/libp2p/rust-libp2p/issues/4898#issuecomment-1818013483
61    pub(crate) connection_limits: ConnectionLimitsBehaviour,
62    pub(crate) identify: Identify,
63    pub(crate) kademlia: Kademlia<DummyRecordStore>,
64    pub(crate) gossipsub: Toggle<Gossipsub>,
65    pub(crate) ping: Ping,
66    pub(crate) request_response: RequestResponseFactoryBehaviour,
67    pub(crate) block_list: BlockListBehaviour,
68    pub(crate) reserved_peers: ReservedPeersBehaviour,
69    pub(crate) autonat: AutonatWrapper,
70}
71
72impl Behavior {
73    pub(crate) fn new(config: BehaviorConfig) -> Self {
74        let kademlia = Kademlia::with_config(config.peer_id, DummyRecordStore, config.kademlia);
75
76        let gossipsub = config
77            .gossipsub
78            .map(|gossip_config| {
79                Gossipsub::new(
80                    // TODO: Do we want message signing?
81                    MessageAuthenticity::Anonymous,
82                    gossip_config,
83                )
84                .expect("Correct configuration")
85            })
86            .into();
87
88        Self {
89            connection_limits: ConnectionLimitsBehaviour::new(config.connection_limits),
90            identify: Identify::new(config.identify),
91            kademlia,
92            gossipsub,
93            ping: Ping::default(),
94            request_response: RequestResponseFactoryBehaviour::new(
95                config.request_response_protocols,
96                config.request_response_max_concurrent_streams,
97            )
98            //TODO: Convert to an error.
99            .expect("RequestResponse protocols registration failed."),
100            block_list: BlockListBehaviour::default(),
101            reserved_peers: ReservedPeersBehaviour::new(config.reserved_peers),
102            autonat: AutonatWrapper::new(config.autonat),
103        }
104    }
105}
106
107#[derive(Debug, From)]
108pub(crate) enum Event {
109    Identify(IdentifyEvent),
110    Kademlia(KademliaEvent),
111    Gossipsub(GossipsubEvent),
112    Ping(PingEvent),
113    RequestResponse(RequestResponseEvent),
114    /// Event stub for connection limits and block list behaviours. We won't receive such events.
115    VoidEventStub(VoidEvent),
116    ReservedPeers(ReservedPeersEvent),
117    Autonat(AutonatEvent),
118}
119
120// Infallible instances can never be created.
121impl From<Infallible> for Event {
122    fn from(_: Infallible) -> Self {
123        unreachable!()
124    }
125}