mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-11 18:04:18 +00:00
Remove network lock (#840)
* Initial work on removing libp2p lock * Removes lock from libp2p service * Completed network lock removal * Correct network termination future * Correct fmt issues * Remove Drop implementation for network service * Address reviewers suggestions * Fix dht persistence test (#844) * Fix persistence test * Block until dht is persisted * Fix libp2p test * Correct test ordering check * Remove expensive tests from debug testing Co-authored-by: Pawan Dhananjay <pawandhananjay@gmail.com>
This commit is contained in:
@@ -1,8 +1,6 @@
|
||||
use crate::discovery::Discovery;
|
||||
use crate::rpc::{RPCEvent, RPCMessage, RPC};
|
||||
use crate::GossipTopic;
|
||||
use crate::{error, NetworkConfig};
|
||||
use crate::{Topic, TopicHash};
|
||||
use crate::{error, GossipTopic, NetworkConfig, NetworkGlobals, Topic, TopicHash};
|
||||
use enr::Enr;
|
||||
use futures::prelude::*;
|
||||
use libp2p::{
|
||||
@@ -18,6 +16,7 @@ use libp2p::{
|
||||
use lru::LruCache;
|
||||
use slog::{debug, o};
|
||||
use std::num::NonZeroU32;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
const MAX_IDENTIFY_ADDRESSES: usize = 20;
|
||||
@@ -47,8 +46,8 @@ pub struct Behaviour<TSubstream: AsyncRead + AsyncWrite> {
|
||||
/// duplicates that may still be seen over gossipsub.
|
||||
#[behaviour(ignore)]
|
||||
seen_gossip_messages: LruCache<MessageId, ()>,
|
||||
/// Logger for behaviour actions.
|
||||
#[behaviour(ignore)]
|
||||
/// Logger for behaviour actions.
|
||||
log: slog::Logger,
|
||||
}
|
||||
|
||||
@@ -56,6 +55,7 @@ impl<TSubstream: AsyncRead + AsyncWrite> Behaviour<TSubstream> {
|
||||
pub fn new(
|
||||
local_key: &Keypair,
|
||||
net_conf: &NetworkConfig,
|
||||
network_globals: Arc<NetworkGlobals>,
|
||||
log: &slog::Logger,
|
||||
) -> error::Result<Self> {
|
||||
let local_peer_id = local_key.public().into_peer_id();
|
||||
@@ -76,11 +76,11 @@ impl<TSubstream: AsyncRead + AsyncWrite> Behaviour<TSubstream> {
|
||||
Ok(Behaviour {
|
||||
eth2_rpc: RPC::new(log.clone()),
|
||||
gossipsub: Gossipsub::new(local_peer_id, net_conf.gs_config.clone()),
|
||||
discovery: Discovery::new(local_key, net_conf, log)?,
|
||||
discovery: Discovery::new(local_key, net_conf, network_globals, log)?,
|
||||
ping: Ping::new(ping_config),
|
||||
identify,
|
||||
seen_gossip_messages: LruCache::new(100_000),
|
||||
events: Vec::new(),
|
||||
seen_gossip_messages: LruCache::new(100_000),
|
||||
log: behaviour_log,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::metrics;
|
||||
use crate::{error, NetworkConfig};
|
||||
use crate::{error, NetworkConfig, NetworkGlobals};
|
||||
/// This manages the discovery and management of peers.
|
||||
///
|
||||
/// Currently using discv5 for peer discovery.
|
||||
@@ -16,6 +16,7 @@ use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
use std::path::Path;
|
||||
use std::str::FromStr;
|
||||
use std::sync::{atomic::Ordering, Arc};
|
||||
use std::time::{Duration, Instant};
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
use tokio::timer::Delay;
|
||||
@@ -30,9 +31,6 @@ const ENR_FILENAME: &str = "enr.dat";
|
||||
/// Lighthouse discovery behaviour. This provides peer management and discovery using the Discv5
|
||||
/// libp2p protocol.
|
||||
pub struct Discovery<TSubstream> {
|
||||
/// The peers currently connected to libp2p streams.
|
||||
connected_peers: HashSet<PeerId>,
|
||||
|
||||
/// The currently banned peers.
|
||||
banned_peers: HashSet<PeerId>,
|
||||
|
||||
@@ -57,6 +55,9 @@ pub struct Discovery<TSubstream> {
|
||||
/// The discovery behaviour used to discover new peers.
|
||||
discovery: Discv5<TSubstream>,
|
||||
|
||||
/// A collection of network constants that can be read from other threads.
|
||||
network_globals: Arc<NetworkGlobals>,
|
||||
|
||||
/// Logger for the discovery behaviour.
|
||||
log: slog::Logger,
|
||||
}
|
||||
@@ -65,6 +66,7 @@ impl<TSubstream> Discovery<TSubstream> {
|
||||
pub fn new(
|
||||
local_key: &Keypair,
|
||||
config: &NetworkConfig,
|
||||
network_globals: Arc<NetworkGlobals>,
|
||||
log: &slog::Logger,
|
||||
) -> error::Result<Self> {
|
||||
let log = log.clone();
|
||||
@@ -72,6 +74,8 @@ impl<TSubstream> Discovery<TSubstream> {
|
||||
// checks if current ENR matches that found on disk
|
||||
let local_enr = load_enr(local_key, config, &log)?;
|
||||
|
||||
*network_globals.local_enr.write() = Some(local_enr.clone());
|
||||
|
||||
let enr_dir = match config.network_dir.to_str() {
|
||||
Some(path) => String::from(path),
|
||||
None => String::from(""),
|
||||
@@ -98,13 +102,13 @@ impl<TSubstream> Discovery<TSubstream> {
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
connected_peers: HashSet::new(),
|
||||
banned_peers: HashSet::new(),
|
||||
max_peers: config.max_peers,
|
||||
peer_discovery_delay: Delay::new(Instant::now()),
|
||||
past_discovery_delay: INITIAL_SEARCH_DELAY,
|
||||
tcp_port: config.libp2p_port,
|
||||
discovery,
|
||||
network_globals,
|
||||
log,
|
||||
enr_dir,
|
||||
})
|
||||
@@ -129,12 +133,17 @@ impl<TSubstream> Discovery<TSubstream> {
|
||||
|
||||
/// The current number of connected libp2p peers.
|
||||
pub fn connected_peers(&self) -> usize {
|
||||
self.connected_peers.len()
|
||||
self.network_globals.connected_peers.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
/// The current number of connected libp2p peers.
|
||||
pub fn connected_peer_set(&self) -> &HashSet<PeerId> {
|
||||
&self.connected_peers
|
||||
pub fn connected_peer_set(&self) -> Vec<PeerId> {
|
||||
self.network_globals
|
||||
.connected_peer_set
|
||||
.read()
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
/// The peer has been banned. Add this peer to the banned list to prevent any future
|
||||
@@ -180,7 +189,14 @@ where
|
||||
}
|
||||
|
||||
fn inject_connected(&mut self, peer_id: PeerId, _endpoint: ConnectedPoint) {
|
||||
self.connected_peers.insert(peer_id);
|
||||
self.network_globals
|
||||
.connected_peer_set
|
||||
.write()
|
||||
.insert(peer_id);
|
||||
self.network_globals.connected_peers.store(
|
||||
self.network_globals.connected_peer_set.read().len(),
|
||||
Ordering::Relaxed,
|
||||
);
|
||||
// TODO: Drop peers if over max_peer limit
|
||||
|
||||
metrics::inc_counter(&metrics::PEER_CONNECT_EVENT_COUNT);
|
||||
@@ -188,7 +204,14 @@ where
|
||||
}
|
||||
|
||||
fn inject_disconnected(&mut self, peer_id: &PeerId, _endpoint: ConnectedPoint) {
|
||||
self.connected_peers.remove(peer_id);
|
||||
self.network_globals
|
||||
.connected_peer_set
|
||||
.write()
|
||||
.remove(peer_id);
|
||||
self.network_globals.connected_peers.store(
|
||||
self.network_globals.connected_peer_set.read().len(),
|
||||
Ordering::Relaxed,
|
||||
);
|
||||
|
||||
metrics::inc_counter(&metrics::PEER_DISCONNECT_EVENT_COUNT);
|
||||
metrics::set_gauge(&metrics::PEERS_CONNECTED, self.connected_peers() as i64);
|
||||
@@ -224,7 +247,8 @@ where
|
||||
loop {
|
||||
match self.peer_discovery_delay.poll() {
|
||||
Ok(Async::Ready(_)) => {
|
||||
if self.connected_peers.len() < self.max_peers {
|
||||
if self.network_globals.connected_peers.load(Ordering::Relaxed) < self.max_peers
|
||||
{
|
||||
self.find_peers();
|
||||
}
|
||||
// Set to maximum, and update to earlier, once we get our results back.
|
||||
@@ -278,8 +302,15 @@ where
|
||||
}
|
||||
for peer_id in closer_peers {
|
||||
// if we need more peers, attempt a connection
|
||||
if self.connected_peers.len() < self.max_peers
|
||||
&& self.connected_peers.get(&peer_id).is_none()
|
||||
|
||||
if self.network_globals.connected_peers.load(Ordering::Relaxed)
|
||||
< self.max_peers
|
||||
&& self
|
||||
.network_globals
|
||||
.connected_peer_set
|
||||
.read()
|
||||
.get(&peer_id)
|
||||
.is_none()
|
||||
&& !self.banned_peers.contains(&peer_id)
|
||||
{
|
||||
debug!(self.log, "Peer discovered"; "peer_id"=> format!("{:?}", peer_id));
|
||||
|
||||
30
beacon_node/eth2-libp2p/src/globals.rs
Normal file
30
beacon_node/eth2-libp2p/src/globals.rs
Normal file
@@ -0,0 +1,30 @@
|
||||
//! A collection of variables that are accessible outside of the network thread itself.
|
||||
use crate::{Enr, Multiaddr, PeerId};
|
||||
use parking_lot::RwLock;
|
||||
use std::collections::HashSet;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
|
||||
pub struct NetworkGlobals {
|
||||
/// The current local ENR.
|
||||
pub local_enr: RwLock<Option<Enr>>,
|
||||
/// The local peer_id.
|
||||
pub peer_id: RwLock<PeerId>,
|
||||
/// Listening multiaddrs.
|
||||
pub listen_multiaddrs: RwLock<Vec<Multiaddr>>,
|
||||
/// Current number of connected libp2p peers.
|
||||
pub connected_peers: AtomicUsize,
|
||||
/// The collection of currently connected peers.
|
||||
pub connected_peer_set: RwLock<HashSet<PeerId>>,
|
||||
}
|
||||
|
||||
impl NetworkGlobals {
|
||||
pub fn new(peer_id: PeerId) -> Self {
|
||||
NetworkGlobals {
|
||||
local_enr: RwLock::new(None),
|
||||
peer_id: RwLock::new(peer_id),
|
||||
listen_multiaddrs: RwLock::new(Vec::new()),
|
||||
connected_peers: AtomicUsize::new(0),
|
||||
connected_peer_set: RwLock::new(HashSet::new()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ pub mod behaviour;
|
||||
mod config;
|
||||
mod discovery;
|
||||
pub mod error;
|
||||
mod globals;
|
||||
mod metrics;
|
||||
pub mod rpc;
|
||||
mod service;
|
||||
@@ -16,6 +17,7 @@ mod topics;
|
||||
|
||||
pub use behaviour::PubsubMessage;
|
||||
pub use config::Config as NetworkConfig;
|
||||
pub use globals::NetworkGlobals;
|
||||
pub use libp2p::enr::Enr;
|
||||
pub use libp2p::gossipsub::{MessageId, Topic, TopicHash};
|
||||
pub use libp2p::multiaddr;
|
||||
|
||||
@@ -3,7 +3,7 @@ use crate::error;
|
||||
use crate::multiaddr::Protocol;
|
||||
use crate::rpc::RPCEvent;
|
||||
use crate::NetworkConfig;
|
||||
use crate::{Topic, TopicHash};
|
||||
use crate::{NetworkGlobals, Topic, TopicHash};
|
||||
use futures::prelude::*;
|
||||
use futures::Stream;
|
||||
use libp2p::core::{
|
||||
@@ -16,6 +16,7 @@ use slog::{crit, debug, error, info, trace, warn};
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
use std::io::{Error, ErrorKind};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use tokio::timer::DelayQueue;
|
||||
|
||||
@@ -47,24 +48,30 @@ pub struct Service {
|
||||
}
|
||||
|
||||
impl Service {
|
||||
pub fn new(config: NetworkConfig, log: slog::Logger) -> error::Result<Self> {
|
||||
pub fn new(
|
||||
config: &NetworkConfig,
|
||||
log: slog::Logger,
|
||||
) -> error::Result<(Arc<NetworkGlobals>, Self)> {
|
||||
trace!(log, "Libp2p Service starting");
|
||||
|
||||
let local_keypair = if let Some(hex_bytes) = &config.secret_key_hex {
|
||||
keypair_from_hex(hex_bytes)?
|
||||
} else {
|
||||
load_private_key(&config, &log)
|
||||
load_private_key(config, &log)
|
||||
};
|
||||
|
||||
// load the private key from CLI flag, disk or generate a new one
|
||||
let local_peer_id = PeerId::from(local_keypair.public());
|
||||
info!(log, "Libp2p Service"; "peer_id" => format!("{:?}", local_peer_id));
|
||||
|
||||
// set up a collection of variables accessible outside of the network crate
|
||||
let network_globals = Arc::new(NetworkGlobals::new(local_peer_id.clone()));
|
||||
|
||||
let mut swarm = {
|
||||
// Set up the transport - tcp/ws with secio and mplex/yamux
|
||||
let transport = build_transport(local_keypair.clone());
|
||||
// Lighthouse network behaviour
|
||||
let behaviour = Behaviour::new(&local_keypair, &config, &log)?;
|
||||
let behaviour = Behaviour::new(&local_keypair, config, network_globals.clone(), &log)?;
|
||||
Swarm::new(transport, behaviour, local_peer_id.clone())
|
||||
};
|
||||
|
||||
@@ -93,7 +100,7 @@ impl Service {
|
||||
};
|
||||
|
||||
// helper closure for dialing peers
|
||||
let mut dial_addr = |multiaddr: Multiaddr| {
|
||||
let mut dial_addr = |multiaddr: &Multiaddr| {
|
||||
match Swarm::dial_addr(&mut swarm, multiaddr.clone()) {
|
||||
Ok(()) => debug!(log, "Dialing libp2p peer"; "address" => format!("{}", multiaddr)),
|
||||
Err(err) => debug!(
|
||||
@@ -104,13 +111,13 @@ impl Service {
|
||||
};
|
||||
|
||||
// attempt to connect to user-input libp2p nodes
|
||||
for multiaddr in config.libp2p_nodes {
|
||||
for multiaddr in &config.libp2p_nodes {
|
||||
dial_addr(multiaddr);
|
||||
}
|
||||
|
||||
// attempt to connect to any specified boot-nodes
|
||||
for bootnode_enr in config.boot_nodes {
|
||||
for multiaddr in bootnode_enr.multiaddr() {
|
||||
for bootnode_enr in &config.boot_nodes {
|
||||
for multiaddr in &bootnode_enr.multiaddr() {
|
||||
// ignore udp multiaddr if it exists
|
||||
let components = multiaddr.iter().collect::<Vec<_>>();
|
||||
if let Protocol::Udp(_) = components[1] {
|
||||
@@ -121,7 +128,7 @@ impl Service {
|
||||
}
|
||||
|
||||
let mut subscribed_topics: Vec<String> = vec![];
|
||||
for topic in config.topics {
|
||||
for topic in config.topics.clone() {
|
||||
let raw_topic: Topic = topic.into();
|
||||
let topic_string = raw_topic.no_hash();
|
||||
if swarm.subscribe(raw_topic.clone()) {
|
||||
@@ -133,13 +140,15 @@ impl Service {
|
||||
}
|
||||
info!(log, "Subscribed to topics"; "topics" => format!("{:?}", subscribed_topics));
|
||||
|
||||
Ok(Service {
|
||||
let service = Service {
|
||||
local_peer_id,
|
||||
swarm,
|
||||
peers_to_ban: DelayQueue::new(),
|
||||
peer_ban_timeout: DelayQueue::new(),
|
||||
log,
|
||||
})
|
||||
};
|
||||
|
||||
Ok((network_globals, service))
|
||||
}
|
||||
|
||||
/// Adds a peer to be banned for a period of time, specified by a timeout.
|
||||
|
||||
Reference in New Issue
Block a user