use crate::error::Error;
use crate::types::ProtocolMessage;
use crate::{
blueprint_protocol::{BlueprintProtocolBehaviour, BlueprintProtocolEvent},
discovery::{
PeerInfo, PeerManager,
behaviour::{DiscoveryBehaviour, DiscoveryEvent},
config::DiscoveryConfig,
},
};
use blueprint_core::{debug, info};
use blueprint_crypto::KeyType;
use crossbeam_channel::Sender;
use libp2p::{
Multiaddr, PeerId,
connection_limits::{self, ConnectionLimits},
identity::Keypair,
kad::QueryId,
ping,
swarm::NetworkBehaviour,
};
use std::{
collections::{HashMap, HashSet},
sync::Arc,
time::Duration,
};
#[derive(Debug)]
pub enum BlueprintEvent<K: KeyType> {
Discovery(DiscoveryEvent),
Ping(ping::Event),
Blueprint(BlueprintProtocolEvent<K>),
}
#[derive(NetworkBehaviour)]
pub struct BlueprintBehaviour<K: KeyType> {
connection_limits: connection_limits::Behaviour,
pub(super) discovery: DiscoveryBehaviour<K>,
pub(super) blueprint_protocol: BlueprintProtocolBehaviour<K>,
ping: ping::Behaviour,
}
pub struct BlueprintBehaviourConfig<K: KeyType> {
pub network_name: String,
pub blueprint_protocol_name: String,
pub local_key: Keypair,
pub instance_key_pair: K::Secret,
pub target_peer_count: u32,
pub peer_manager: Arc<PeerManager<K>>,
pub protocol_message_sender: Sender<ProtocolMessage>,
pub using_evm_address_for_handshake_verification: bool,
}
impl<K: KeyType> BlueprintBehaviour<K> {
pub fn new(config: BlueprintBehaviourConfig<K>) -> Result<Self, Error> {
let connection_limits = connection_limits::Behaviour::new(
ConnectionLimits::default()
.with_max_pending_incoming(Some(config.target_peer_count))
.with_max_pending_outgoing(Some(config.target_peer_count))
.with_max_established_incoming(Some(config.target_peer_count))
.with_max_established_outgoing(Some(config.target_peer_count))
.with_max_established_per_peer(Some(config.target_peer_count)),
);
let ping = ping::Behaviour::new(ping::Config::new().with_interval(Duration::from_secs(30)));
info!(
"Setting up discovery behavior with network name: {}",
config.network_name
);
let discovery = DiscoveryConfig::new(config.local_key.public(), config.network_name)
.mdns(true)
.kademlia(true)
.target_peer_count(config.target_peer_count)
.build()?;
info!(
"Setting up blueprint protocol with name: {}",
config.blueprint_protocol_name
);
let blueprint_protocol = BlueprintProtocolBehaviour::new(
&config.local_key,
&config.instance_key_pair,
config.peer_manager,
&config.blueprint_protocol_name,
config.protocol_message_sender,
config.using_evm_address_for_handshake_verification,
);
debug!("Created BlueprintBehaviour with all components initialized");
Ok(Self {
connection_limits,
discovery,
blueprint_protocol,
ping,
})
}
pub fn bootstrap(&mut self) -> Result<QueryId, Error> {
self.discovery.bootstrap()
}
#[must_use]
pub fn peers(&self) -> &HashSet<PeerId> {
self.discovery.get_peers()
}
#[must_use]
pub fn peer_addresses(&self) -> HashMap<PeerId, HashSet<Multiaddr>> {
self.discovery.get_peer_addresses()
}
#[must_use]
pub fn peer_info(&self, peer_id: &PeerId) -> Option<&PeerInfo> {
self.discovery.get_peer_info(peer_id)
}
}