mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 01:11:10 +00:00
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:
committed by
Gavin Wood
parent
6e572a9477
commit
ca997cf1e4
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user