Update networking code to libp2p 0.14 (#4383)

* Entirely update substrate-telemetry to futures 0.3

* Add a Closed error

* Update to libp2p 0.14

* More work

* More work

* More work

* More work

* Fix warnings

* Remove unwrap()

* Work on tests fixing

* Fix network tests

* Fix external network tests

* Update libp2p and restore Yamux in discovery test

* Ignore DNS if initializatio nfails

* Restore variables ordering

* Forgot browser-utils

* Fix downfall after merge

* Fix tests
This commit is contained in:
Pierre Krieger
2020-01-09 19:01:23 +01:00
committed by Gavin Wood
parent 6e572a9477
commit ca997cf1e4
29 changed files with 842 additions and 812 deletions
+62 -67
View File
@@ -47,7 +47,6 @@
use futures::prelude::*;
use futures_timer::Delay;
use futures03::{compat::Compat, TryFutureExt as _};
use libp2p::core::{ConnectedPoint, Multiaddr, PeerId, PublicKey};
use libp2p::swarm::{ProtocolsHandler, NetworkBehaviour, NetworkBehaviourAction, PollParameters};
use libp2p::kad::{Kademlia, KademliaEvent, Quorum, Record};
@@ -62,7 +61,7 @@ use libp2p::mdns::{Mdns, MdnsEvent};
use libp2p::multiaddr::Protocol;
use log::{debug, info, trace, warn};
use std::{cmp, collections::VecDeque, time::Duration};
use tokio_io::{AsyncRead, AsyncWrite};
use std::task::{Context, Poll};
use sp_core::hexdisplay::HexDisplay;
/// Implementation of `NetworkBehaviour` that discovers the nodes on the network.
@@ -76,7 +75,7 @@ pub struct DiscoveryBehaviour<TSubstream> {
#[cfg(not(target_os = "unknown"))]
mdns: Toggle<Mdns<Substream<StreamMuxerBox>>>,
/// Stream that fires when we need to perform the next random Kademlia query.
next_kad_random_query: Compat<Delay>,
next_kad_random_query: Delay,
/// After `next_kad_random_query` triggers, the next one triggers after this duration.
duration_to_next_kad: Duration,
/// Discovered nodes to return.
@@ -94,7 +93,7 @@ impl<TSubstream> DiscoveryBehaviour<TSubstream> {
/// Builds a new `DiscoveryBehaviour`.
///
/// `user_defined` is a list of known address for nodes that never expire.
pub fn new(
pub async fn new(
local_public_key: PublicKey,
user_defined: Vec<(PeerId, Multiaddr)>,
enable_mdns: bool,
@@ -115,7 +114,7 @@ impl<TSubstream> DiscoveryBehaviour<TSubstream> {
DiscoveryBehaviour {
user_defined,
kademlia,
next_kad_random_query: Delay::new(Duration::new(0, 0)).compat(),
next_kad_random_query: Delay::new(Duration::new(0, 0)),
duration_to_next_kad: Duration::from_secs(1),
discoveries: VecDeque::new(),
local_peer_id: local_public_key.into_peer_id(),
@@ -123,7 +122,7 @@ impl<TSubstream> DiscoveryBehaviour<TSubstream> {
allow_private_ipv4,
#[cfg(not(target_os = "unknown"))]
mdns: if enable_mdns {
match Mdns::new() {
match Mdns::new().await {
Ok(mdns) => Some(mdns).into(),
Err(err) => {
warn!(target: "sub-libp2p", "Failed to initialize mDNS: {:?}", err);
@@ -206,7 +205,7 @@ pub enum DiscoveryOut {
impl<TSubstream> NetworkBehaviour for DiscoveryBehaviour<TSubstream>
where
TSubstream: AsyncRead + AsyncWrite,
TSubstream: AsyncRead + AsyncWrite + Unpin,
{
type ProtocolsHandler = <Kademlia<TSubstream, MemoryStore> as NetworkBehaviour>::ProtocolsHandler;
type OutEvent = DiscoveryOut;
@@ -287,8 +286,9 @@ where
fn poll(
&mut self,
cx: &mut Context,
params: &mut impl PollParameters,
) -> Async<
) -> Poll<
NetworkBehaviourAction<
<Self::ProtocolsHandler as ProtocolsHandler>::InEvent,
Self::OutEvent,
@@ -297,45 +297,35 @@ where
// Immediately process the content of `discovered`.
if let Some(peer_id) = self.discoveries.pop_front() {
let ev = DiscoveryOut::Discovered(peer_id);
return Async::Ready(NetworkBehaviourAction::GenerateEvent(ev));
return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev));
}
// Poll the stream that fires when we need to start a random Kademlia query.
loop {
match self.next_kad_random_query.poll() {
Ok(Async::NotReady) => break,
Ok(Async::Ready(_)) => {
let random_peer_id = PeerId::random();
debug!(target: "sub-libp2p", "Libp2p <= Starting random Kademlia request for \
{:?}", random_peer_id);
while let Poll::Ready(_) = self.next_kad_random_query.poll_unpin(cx) {
let random_peer_id = PeerId::random();
debug!(target: "sub-libp2p", "Libp2p <= Starting random Kademlia request for \
{:?}", random_peer_id);
self.kademlia.get_closest_peers(random_peer_id);
self.kademlia.get_closest_peers(random_peer_id);
// Schedule the next random query with exponentially increasing delay,
// capped at 60 seconds.
self.next_kad_random_query = Delay::new(self.duration_to_next_kad).compat();
self.duration_to_next_kad = cmp::min(self.duration_to_next_kad * 2,
Duration::from_secs(60));
},
Err(err) => {
warn!(target: "sub-libp2p", "Kademlia query timer errored: {:?}", err);
break
}
}
// Schedule the next random query with exponentially increasing delay,
// capped at 60 seconds.
self.next_kad_random_query = Delay::new(self.duration_to_next_kad);
self.duration_to_next_kad = cmp::min(self.duration_to_next_kad * 2,
Duration::from_secs(60));
}
// Poll Kademlia.
loop {
match self.kademlia.poll(params) {
Async::NotReady => break,
Async::Ready(NetworkBehaviourAction::GenerateEvent(ev)) => match ev {
while let Poll::Ready(ev) = self.kademlia.poll(cx, params) {
match ev {
NetworkBehaviourAction::GenerateEvent(ev) => match ev {
KademliaEvent::UnroutablePeer { peer, .. } => {
let ev = DiscoveryOut::UnroutablePeer(peer);
return Async::Ready(NetworkBehaviourAction::GenerateEvent(ev));
return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev));
}
KademliaEvent::RoutingUpdated { peer, .. } => {
let ev = DiscoveryOut::Discovered(peer);
return Async::Ready(NetworkBehaviourAction::GenerateEvent(ev));
return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev));
}
KademliaEvent::GetClosestPeersResult(res) => {
match res {
@@ -369,7 +359,7 @@ where
DiscoveryOut::ValueNotFound(e.into_key())
}
};
return Async::Ready(NetworkBehaviourAction::GenerateEvent(ev));
return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev));
}
KademliaEvent::PutRecordResult(res) => {
let ev = match res {
@@ -378,7 +368,7 @@ where
DiscoveryOut::ValuePutFailed(e.into_key())
}
};
return Async::Ready(NetworkBehaviourAction::GenerateEvent(ev));
return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev));
}
KademliaEvent::RepublishRecordResult(res) => {
match res {
@@ -398,46 +388,45 @@ where
warn!(target: "sub-libp2p", "Libp2p => Unhandled Kademlia event: {:?}", e)
}
},
Async::Ready(NetworkBehaviourAction::DialAddress { address }) =>
return Async::Ready(NetworkBehaviourAction::DialAddress { address }),
Async::Ready(NetworkBehaviourAction::DialPeer { peer_id }) =>
return Async::Ready(NetworkBehaviourAction::DialPeer { peer_id }),
Async::Ready(NetworkBehaviourAction::SendEvent { peer_id, event }) =>
return Async::Ready(NetworkBehaviourAction::SendEvent { peer_id, event }),
Async::Ready(NetworkBehaviourAction::ReportObservedAddr { address }) =>
return Async::Ready(NetworkBehaviourAction::ReportObservedAddr { address }),
NetworkBehaviourAction::DialAddress { address } =>
return Poll::Ready(NetworkBehaviourAction::DialAddress { address }),
NetworkBehaviourAction::DialPeer { peer_id } =>
return Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id }),
NetworkBehaviourAction::SendEvent { peer_id, event } =>
return Poll::Ready(NetworkBehaviourAction::SendEvent { peer_id, event }),
NetworkBehaviourAction::ReportObservedAddr { address } =>
return Poll::Ready(NetworkBehaviourAction::ReportObservedAddr { address }),
}
}
// Poll mDNS.
#[cfg(not(target_os = "unknown"))]
loop {
match self.mdns.poll(params) {
Async::NotReady => break,
Async::Ready(NetworkBehaviourAction::GenerateEvent(event)) => {
while let Poll::Ready(ev) = self.mdns.poll(cx, params) {
match ev {
NetworkBehaviourAction::GenerateEvent(event) => {
match event {
MdnsEvent::Discovered(list) => {
self.discoveries.extend(list.into_iter().map(|(peer_id, _)| peer_id));
if let Some(peer_id) = self.discoveries.pop_front() {
let ev = DiscoveryOut::Discovered(peer_id);
return Async::Ready(NetworkBehaviourAction::GenerateEvent(ev));
return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev));
}
},
MdnsEvent::Expired(_) => {}
}
},
Async::Ready(NetworkBehaviourAction::DialAddress { address }) =>
return Async::Ready(NetworkBehaviourAction::DialAddress { address }),
Async::Ready(NetworkBehaviourAction::DialPeer { peer_id }) =>
return Async::Ready(NetworkBehaviourAction::DialPeer { peer_id }),
Async::Ready(NetworkBehaviourAction::SendEvent { event, .. }) =>
NetworkBehaviourAction::DialAddress { address } =>
return Poll::Ready(NetworkBehaviourAction::DialAddress { address }),
NetworkBehaviourAction::DialPeer { peer_id } =>
return Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id }),
NetworkBehaviourAction::SendEvent { event, .. } =>
match event {}, // `event` is an enum with no variant
Async::Ready(NetworkBehaviourAction::ReportObservedAddr { address }) =>
return Async::Ready(NetworkBehaviourAction::ReportObservedAddr { address }),
NetworkBehaviourAction::ReportObservedAddr { address } =>
return Poll::Ready(NetworkBehaviourAction::ReportObservedAddr { address }),
}
}
Async::NotReady
Poll::Pending
}
}
@@ -450,7 +439,7 @@ mod tests {
use libp2p::core::transport::{Transport, MemoryTransport};
use libp2p::core::upgrade::{InboundUpgradeExt, OutboundUpgradeExt};
use libp2p::swarm::Swarm;
use std::collections::HashSet;
use std::{collections::HashSet, task::Poll};
use super::{DiscoveryBehaviour, DiscoveryOut};
#[test]
@@ -469,7 +458,7 @@ mod tests {
out,
secio,
endpoint,
libp2p::core::upgrade::Version::V1
upgrade::Version::V1
)
})
.and_then(move |(peer_id, stream), endpoint| {
@@ -477,10 +466,16 @@ mod tests {
let upgrade = libp2p::yamux::Config::default()
.map_inbound(move |muxer| (peer_id, muxer))
.map_outbound(move |muxer| (peer_id2, muxer));
upgrade::apply(stream, upgrade, endpoint, libp2p::core::upgrade::Version::V1)
upgrade::apply(stream, upgrade, endpoint, upgrade::Version::V1)
});
let behaviour = DiscoveryBehaviour::new(keypair.public(), user_defined.clone(), false, true);
let behaviour = futures::executor::block_on({
let user_defined = user_defined.clone();
let keypair_public = keypair.public();
async move {
DiscoveryBehaviour::new(keypair_public, user_defined, false, true).await
}
});
let mut swarm = Swarm::new(transport, behaviour, keypair.public().into_peer_id());
let listen_addr: Multiaddr = format!("/memory/{}", rand::random::<u64>()).parse().unwrap();
@@ -499,11 +494,11 @@ mod tests {
.collect::<HashSet<_>>()
}).collect::<Vec<_>>();
let fut = futures::future::poll_fn::<_, (), _>(move || {
let fut = futures::future::poll_fn(move |cx| {
'polling: loop {
for swarm_n in 0..swarms.len() {
match swarms[swarm_n].0.poll().unwrap() {
Async::Ready(Some(e)) => {
match swarms[swarm_n].0.poll_next_unpin(cx) {
Poll::Ready(Some(e)) => {
match e {
DiscoveryOut::UnroutablePeer(other) => {
// Call `add_self_reported_address` to simulate identify happening.
@@ -530,12 +525,12 @@ mod tests {
}
if to_discover.iter().all(|l| l.is_empty()) {
Ok(Async::Ready(()))
Poll::Ready(())
} else {
Ok(Async::NotReady)
Poll::Pending
}
});
tokio::runtime::Runtime::new().unwrap().block_on(fut).unwrap();
futures::executor::block_on(fut);
}
}