Update libp2p to v0.3 (#1634)

* Update libp2p

* Some more diagnostics

* 30 seconds back to 5 seconds

* Bump libp2p-core and improve test

* Fix runtime Cargo.lock

* More work

* Finish upgrade to libp2p 0.3

* Add a maximum of 60 seconds for the rounds

* Remove env_logger

* Update Cargo.lock

* Update Cargo.lock in test-runtime

* Fix test compilation

* Make the test pass

* Add identify addresses to Kademlia

* Don't connect to nodes we're already connected to

* Add warning for non-Substrate nodes

* Fix external address not added

* Start in Enabled mode
This commit is contained in:
Pierre Krieger
2019-02-06 16:39:22 +01:00
committed by Arkadiy Paronyan
parent 7d8ae2df5c
commit b6fd967dfb
18 changed files with 599 additions and 411 deletions
+1 -1
View File
@@ -6,7 +6,7 @@ edition = "2018"
[dependencies]
substrate-primitives = { path = "../primitives" }
crypto = { package = "parity-crypto", version = "0.2", default-features = false }
crypto = { package = "parity-crypto", version = "0.3", default-features = false }
error-chain = "0.12"
hex = "0.3"
rand = "0.6"
+20 -7
View File
@@ -24,6 +24,7 @@ use std::collections::HashMap;
use std::path::PathBuf;
use std::fs::{self, File};
use std::io::{self, Write};
use std::num::NonZeroU32;
use serde_derive::{Serialize, Deserialize};
use error_chain::{error_chain, error_chain_processing, impl_error_chain_processed,
@@ -60,11 +61,11 @@ struct EncryptedKey {
salt: [u8; 32],
ciphertext: Vec<u8>, // FIXME: switch to fixed-size when serde supports
iv: [u8; 16],
iterations: u32,
iterations: NonZeroU32,
}
impl EncryptedKey {
fn encrypt(plain: &[u8; PKCS_LEN], password: &str, iterations: u32) -> Self {
fn encrypt(plain: &[u8; PKCS_LEN], password: &str, iterations: NonZeroU32) -> Self {
use rand::{Rng, rngs::OsRng};
let mut rng = OsRng::new().expect("OS Randomness available on all supported platforms; qed");
@@ -149,7 +150,11 @@ impl Store {
/// Generate a new key, placing it into the store.
pub fn generate(&self, password: &str) -> Result<Pair> {
let (pair, pkcs_bytes) = Pair::generate_with_pkcs8();
let key_file = EncryptedKey::encrypt(&pkcs_bytes, password, KEY_ITERATIONS as u32);
let key_file = EncryptedKey::encrypt(
&pkcs_bytes,
password,
NonZeroU32::new(KEY_ITERATIONS as u32).expect("KEY_ITERATIONS is not zero; QED")
);
let mut file = File::create(self.key_file_path(&pair.public()))?;
::serde_json::to_writer(&file, &key_file)?;
@@ -225,7 +230,7 @@ mod tests {
#[test]
fn encrypt_and_decrypt() {
let plain = [1; PKCS_LEN];
let encrypted_key = EncryptedKey::encrypt(&plain, "thepassword", KEY_ITERATIONS as u32);
let encrypted_key = EncryptedKey::encrypt(&plain, "thepassword", NonZeroU32::new(KEY_ITERATIONS as u32).expect("KEY_ITERATIONS is not zero; QED"));
let decrypted_key = encrypted_key.decrypt("thepassword").unwrap();
@@ -235,7 +240,11 @@ mod tests {
#[test]
fn decrypt_wrong_password_fails() {
let plain = [1; PKCS_LEN];
let encrypted_key = EncryptedKey::encrypt(&plain, "thepassword", KEY_ITERATIONS as u32);
let encrypted_key = EncryptedKey::encrypt(
&plain,
"thepassword",
NonZeroU32::new(KEY_ITERATIONS as u32).expect("KEY_ITERATIONS is not zero; QED")
);
assert!(encrypted_key.decrypt("thepassword2").is_err());
}
@@ -243,9 +252,13 @@ mod tests {
#[test]
fn decrypt_wrong_iterations_fails() {
let plain = [1; PKCS_LEN];
let mut encrypted_key = EncryptedKey::encrypt(&plain, "thepassword", KEY_ITERATIONS as u32);
let mut encrypted_key = EncryptedKey::encrypt(
&plain,
"thepassword",
NonZeroU32::new(KEY_ITERATIONS as u32).expect("KEY_ITERATIONS is not zero; QED")
);
encrypted_key.iterations -= 64;
encrypted_key.iterations = NonZeroU32::new(encrypted_key.iterations.get() - 64).unwrap();
assert!(encrypted_key.decrypt("thepassword").is_err());
}
+1 -1
View File
@@ -12,7 +12,7 @@ bytes = "0.4"
error-chain = { version = "0.12", default-features = false }
fnv = "1.0"
futures = "0.1"
libp2p = { version = "0.2", default-features = false, features = ["secio-rsa", "secio-secp256k1", "libp2p-websocket"] }
libp2p = { version = "0.3.1", default-features = false, features = ["secio-secp256k1", "libp2p-websocket"] }
parking_lot = "0.7.1"
lazy_static = "1.2"
log = "0.4"
+64 -20
View File
@@ -19,11 +19,11 @@ use crate::{NetworkConfiguration, ProtocolId};
use bytes::Bytes;
use futures::prelude::*;
use libp2p::NetworkBehaviour;
use libp2p::core::{PeerId, ProtocolsHandler};
use libp2p::core::{Multiaddr, PeerId, ProtocolsHandler, PublicKey};
use libp2p::core::swarm::{ConnectedPoint, NetworkBehaviour, NetworkBehaviourAction};
use libp2p::core::swarm::{NetworkBehaviourEventProcess, PollParameters};
use libp2p::identify::{Identify, IdentifyEvent, protocol::IdentifyInfo};
use libp2p::kad::{Kademlia, KademliaOut, KademliaTopology};
use libp2p::kad::{Kademlia, KademliaOut, KadConnectionType};
use libp2p::ping::{Ping, PingEvent};
use log::{debug, trace, warn};
use std::{cmp, io, time::Duration, time::Instant};
@@ -51,17 +51,20 @@ pub struct Behaviour<TSubstream> {
impl<TSubstream> Behaviour<TSubstream> {
/// Builds a new `Behaviour`.
// TODO: redundancy between config and local_peer_id (https://github.com/libp2p/rust-libp2p/issues/745)
pub fn new(config: &NetworkConfiguration, local_peer_id: PeerId, protocols: RegisteredProtocols) -> Self {
// TODO: redundancy between config and local_public_key (https://github.com/libp2p/rust-libp2p/issues/745)
pub fn new(config: &NetworkConfiguration, local_public_key: PublicKey, protocols: RegisteredProtocols) -> Self {
let identify = {
let proto_version = "/substrate/1.0".to_string();
let user_agent = format!("{} ({})", config.client_version, config.node_name);
Identify::new(proto_version, user_agent)
Identify::new(proto_version, user_agent, local_public_key.clone())
};
let local_peer_id = local_public_key.into_peer_id();
let custom_protocols = CustomProtos::new(config, &local_peer_id, protocols);
Behaviour {
ping: Ping::new(),
custom_protocols: CustomProtos::new(config, protocols),
custom_protocols,
discovery: DiscoveryBehaviour::new(local_peer_id),
identify,
events: Vec::new(),
@@ -79,9 +82,26 @@ impl<TSubstream> Behaviour<TSubstream> {
self.custom_protocols.send_packet(target, protocol_id, data)
}
/// Returns the number of peers in the topology.
pub fn num_topology_peers(&self) -> usize {
self.custom_protocols.num_topology_peers()
}
/// Flushes the topology to the disk.
pub fn flush_topology(&mut self) -> Result<(), io::Error> {
self.custom_protocols.flush_topology()
}
/// Perform a cleanup pass, removing all obsolete addresses and peers.
///
/// This should be done from time to time.
pub fn cleanup(&mut self) {
self.custom_protocols.cleanup();
}
/// Try to add a reserved peer.
pub fn add_reserved_peer(&mut self, peer_id: PeerId) {
self.custom_protocols.add_reserved_peer(peer_id)
pub fn add_reserved_peer(&mut self, peer_id: PeerId, addr: Multiaddr) {
self.custom_protocols.add_reserved_peer(peer_id, addr)
}
/// Try to remove a reserved peer.
@@ -218,6 +238,20 @@ impl<TSubstream> NetworkBehaviourEventProcess<IdentifyEvent> for Behaviour<TSubs
// TODO: ideally we would delay the first identification to when we open the custom
// protocol, so that we only report id info to the service about the nodes we
// care about (https://github.com/libp2p/rust-libp2p/issues/876)
if !info.protocol_version.contains("substrate") {
warn!(target: "sub-libp2p", "Connected to a non-Substrate node: {:?}", info);
}
if info.listen_addrs.is_empty() {
warn!(target: "sub-libp2p", "Received identify response with empty list of \
addresses");
}
for addr in &info.listen_addrs {
self.discovery.kademlia.add_address(&peer_id, addr.clone());
}
self.custom_protocols.add_discovered_addrs(
&peer_id,
info.listen_addrs.iter().map(|addr| (addr.clone(), true))
);
self.events.push(BehaviourOut::Identified { peer_id, info });
}
IdentifyEvent::Error { .. } => {}
@@ -227,10 +261,13 @@ impl<TSubstream> NetworkBehaviourEventProcess<IdentifyEvent> for Behaviour<TSubs
impl<TSubstream> NetworkBehaviourEventProcess<KademliaOut> for Behaviour<TSubstream> {
fn inject_event(&mut self, out: KademliaOut) {
// We only ever use Kademlia for discovering nodes, and nodes discovered by Kademlia are
// automatically added to the topology. Therefore we don't need to perform any further
// action.
match out {
KademliaOut::Discovered { peer_id, addresses, ty } => {
self.custom_protocols.add_discovered_addrs(
&peer_id,
addresses.into_iter().map(|addr| (addr, ty == KadConnectionType::Connected))
);
}
KademliaOut::FindNodeResult { key, closer_peers } => {
trace!(target: "sub-libp2p", "Kademlia query for {:?} yielded {:?} results",
key, closer_peers.len());
@@ -284,24 +321,31 @@ impl<TSubstream> DiscoveryBehaviour<TSubstream> {
}
}
impl<TSubstream, TTopology> NetworkBehaviour<TTopology> for DiscoveryBehaviour<TSubstream>
impl<TSubstream> NetworkBehaviour for DiscoveryBehaviour<TSubstream>
where
TSubstream: AsyncRead + AsyncWrite,
TTopology: KademliaTopology,
{
type ProtocolsHandler = <Kademlia<TSubstream> as NetworkBehaviour<TTopology>>::ProtocolsHandler;
type OutEvent = <Kademlia<TSubstream> as NetworkBehaviour<TTopology>>::OutEvent;
type ProtocolsHandler = <Kademlia<TSubstream> as NetworkBehaviour>::ProtocolsHandler;
type OutEvent = <Kademlia<TSubstream> as NetworkBehaviour>::OutEvent;
fn new_handler(&mut self) -> Self::ProtocolsHandler {
NetworkBehaviour::<TTopology>::new_handler(&mut self.kademlia)
NetworkBehaviour::new_handler(&mut self.kademlia)
}
fn addresses_of_peer(&mut self, peer_id: &PeerId) -> Vec<Multiaddr> {
self.kademlia.addresses_of_peer(peer_id)
}
fn inject_connected(&mut self, peer_id: PeerId, endpoint: ConnectedPoint) {
NetworkBehaviour::<TTopology>::inject_connected(&mut self.kademlia, peer_id, endpoint)
NetworkBehaviour::inject_connected(&mut self.kademlia, peer_id, endpoint)
}
fn inject_disconnected(&mut self, peer_id: &PeerId, endpoint: ConnectedPoint) {
NetworkBehaviour::<TTopology>::inject_disconnected(&mut self.kademlia, peer_id, endpoint)
NetworkBehaviour::inject_disconnected(&mut self.kademlia, peer_id, endpoint)
}
fn inject_replaced(&mut self, peer_id: PeerId, closed: ConnectedPoint, opened: ConnectedPoint) {
NetworkBehaviour::inject_replaced(&mut self.kademlia, peer_id, closed, opened)
}
fn inject_node_event(
@@ -309,12 +353,12 @@ where
peer_id: PeerId,
event: <Self::ProtocolsHandler as ProtocolsHandler>::OutEvent,
) {
NetworkBehaviour::<TTopology>::inject_node_event(&mut self.kademlia, peer_id, event)
NetworkBehaviour::inject_node_event(&mut self.kademlia, peer_id, event)
}
fn poll(
&mut self,
params: &mut PollParameters<TTopology>,
params: &mut PollParameters,
) -> Async<
NetworkBehaviourAction<
<Self::ProtocolsHandler as ProtocolsHandler>::InEvent,
@@ -15,19 +15,23 @@
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
use crate::custom_proto::handler::{CustomProtosHandler, CustomProtosHandlerOut, CustomProtosHandlerIn};
use crate::custom_proto::topology::NetTopology;
use crate::custom_proto::upgrade::RegisteredProtocols;
use crate::{NetworkConfiguration, NonReservedPeerMode, ProtocolId, topology::NetTopology};
use crate::{NetworkConfiguration, NonReservedPeerMode, ProtocolId};
use crate::parse_str_addr;
use bytes::Bytes;
use fnv::{FnvHashMap, FnvHashSet};
use futures::prelude::*;
use libp2p::core::swarm::{ConnectedPoint, NetworkBehaviour, NetworkBehaviourAction, PollParameters};
use libp2p::core::{protocols_handler::ProtocolsHandler, PeerId};
use libp2p::core::{protocols_handler::ProtocolsHandler, Multiaddr, PeerId};
use log::{debug, trace, warn};
use smallvec::SmallVec;
use std::{io, marker::PhantomData, time::Duration, time::Instant};
use std::{cmp, error, io, marker::PhantomData, path::Path, time::Duration, time::Instant};
use tokio_io::{AsyncRead, AsyncWrite};
use tokio_timer::Delay;
// File where the network topology is stored.
const NODES_FILE: &str = "nodes.json";
// Duration during which a peer is disabled.
const PEER_DISABLE_DURATION: Duration = Duration::from_secs(5 * 60);
@@ -36,6 +40,9 @@ pub struct CustomProtos<TSubstream> {
/// List of protocols to open with peers. Never modified.
registered_protocols: RegisteredProtocols,
/// Topology of the network.
topology: NetTopology,
/// List of custom protocols that we have open with remotes.
open_protocols: Vec<(PeerId, ProtocolId)>,
@@ -56,6 +63,9 @@ pub struct CustomProtos<TSubstream> {
/// If true, only reserved peers can connect.
reserved_only: bool,
/// List of the IDs of the peers we are connected to.
connected_peers: FnvHashSet<PeerId>,
/// List of the IDs of the reserved peers. We always try to maintain a connection these peers.
reserved_peers: FnvHashSet<PeerId>,
@@ -122,7 +132,24 @@ pub enum CustomProtosOut {
impl<TSubstream> CustomProtos<TSubstream> {
/// Creates a `CustomProtos`.
pub fn new(config: &NetworkConfiguration, registered_protocols: RegisteredProtocols) -> Self {
pub fn new(config: &NetworkConfiguration, local_peer_id: &PeerId, registered_protocols: RegisteredProtocols) -> Self {
// Initialize the topology of the network.
let mut topology = if let Some(ref path) = config.net_config_path {
let path = Path::new(path).join(NODES_FILE);
debug!(target: "sub-libp2p", "Initializing peer store for JSON file {:?}", path);
NetTopology::from_file(local_peer_id.clone(), path)
} else {
debug!(target: "sub-libp2p", "No peers file configured ; peers won't be saved");
NetTopology::memory(local_peer_id.clone())
};
// Add the bootstrap nodes to the topology.
for bootnode in config.boot_nodes.iter() {
if let Ok((peer_id, addr)) = parse_str_addr(bootnode) {
topology.add_bootstrap_addr(&peer_id, addr.clone());
}
}
let max_incoming_connections = config.in_peers as usize;
let max_outgoing_connections = config.out_peers as usize;
@@ -136,9 +163,11 @@ impl<TSubstream> CustomProtos<TSubstream> {
CustomProtos {
registered_protocols,
topology,
max_incoming_connections,
max_outgoing_connections,
reserved_only: config.non_reserved_mode == NonReservedPeerMode::Deny,
connected_peers: Default::default(),
reserved_peers: Default::default(),
banned_peers: Vec::new(),
open_protocols: Vec::with_capacity(open_protos_cap),
@@ -150,7 +179,8 @@ impl<TSubstream> CustomProtos<TSubstream> {
}
/// Adds a reserved peer.
pub fn add_reserved_peer(&mut self, peer_id: PeerId) {
pub fn add_reserved_peer(&mut self, peer_id: PeerId, addr: Multiaddr) {
self.topology.add_bootstrap_addr(&peer_id, addr);
self.reserved_peers.insert(peer_id);
// Trigger a `connect_to_nodes` round.
@@ -240,11 +270,40 @@ impl<TSubstream> CustomProtos<TSubstream> {
});
}
/// Indicates to the topology that we have discovered new addresses for a given node.
pub fn add_discovered_addrs<I>(
&mut self,
peer_id: &PeerId,
addrs: I,
) where I: Iterator<Item = (Multiaddr, bool)> {
if self.topology.add_discovered_addrs(peer_id, addrs) {
// Trigger a `connect_to_nodes` round.
self.next_connect_to_nodes = Delay::new(Instant::now());
}
}
/// Returns the number of peers in the topology.
pub fn num_topology_peers(&self) -> usize {
self.topology.num_peers()
}
/// Flushes the topology to the disk.
pub fn flush_topology(&mut self) -> Result<(), io::Error> {
self.topology.flush_to_disk()
}
/// Perform a cleanup pass, removing all obsolete addresses and peers.
///
/// This should be done from time to time.
pub fn cleanup(&mut self) {
self.topology.cleanup();
}
/// Updates the attempted connections to nodes.
///
/// Also updates `next_connect_to_nodes` with the earliest known moment when we need to
/// update connections again.
fn connect_to_nodes(&mut self, params: &mut PollParameters<NetTopology>) {
fn connect_to_nodes(&mut self, params: &mut PollParameters) {
// Make sure we are connected or connecting to all the reserved nodes.
for reserved in self.reserved_peers.iter() {
// TODO: don't generate an event if we're already in a pending connection (https://github.com/libp2p/rust-libp2p/issues/697)
@@ -272,7 +331,7 @@ impl<TSubstream> CustomProtos<TSubstream> {
num_to_open);
let local_peer_id = params.local_peer_id().clone();
let (to_try, will_change) = params.topology().addrs_to_attempt();
let (to_try, will_change) = self.topology.addrs_to_attempt();
for (peer_id, _) in to_try {
if num_to_open == 0 {
break
@@ -282,6 +341,10 @@ impl<TSubstream> CustomProtos<TSubstream> {
continue
}
if self.connected_peers.contains(&peer_id) {
continue
}
if let Some((_, ban_end)) = self.banned_peers.iter().find(|(p, _)| p == peer_id) {
if *ban_end > Instant::now() {
continue
@@ -293,11 +356,11 @@ impl<TSubstream> CustomProtos<TSubstream> {
}
// Next round is when we expect the topology will change.
self.next_connect_to_nodes.reset(will_change);
self.next_connect_to_nodes.reset(cmp::min(will_change, Instant::now() + Duration::from_secs(60)));
}
}
impl<TSubstream> NetworkBehaviour<NetTopology> for CustomProtos<TSubstream>
impl<TSubstream> NetworkBehaviour for CustomProtos<TSubstream>
where
TSubstream: AsyncRead + AsyncWrite,
{
@@ -308,13 +371,23 @@ where
CustomProtosHandler::new(self.registered_protocols.clone())
}
fn addresses_of_peer(&mut self, peer_id: &PeerId) -> Vec<Multiaddr> {
self.topology.addresses_of_peer(peer_id)
}
fn inject_connected(&mut self, peer_id: PeerId, endpoint: ConnectedPoint) {
// When a peer connects, its handler is initially in the disabled state. We make sure that
// the peer is allowed, and if so we put it in the enabled state.
self.connected_peers.insert(peer_id.clone());
let is_reserved = self.reserved_peers.contains(&peer_id);
if self.reserved_only && !is_reserved {
debug!(target: "sub-libp2p", "Ignoring {:?} because we're in reserved mode", peer_id);
self.events.push(NetworkBehaviourAction::SendEvent {
peer_id: peer_id.clone(),
event: CustomProtosHandlerIn::Disable,
});
return
}
@@ -323,6 +396,10 @@ where
if let Some((_, expire)) = self.banned_peers.iter().find(|(p, _)| p == &peer_id) {
if *expire >= Instant::now() {
debug!(target: "sub-libp2p", "Ignoring banned peer {:?}", peer_id);
self.events.push(NetworkBehaviourAction::SendEvent {
peer_id: peer_id.clone(),
event: CustomProtosHandlerIn::Disable,
});
return
}
}
@@ -338,6 +415,10 @@ where
debug_assert!(num_outgoing <= self.max_outgoing_connections);
if num_outgoing == self.max_outgoing_connections {
self.events.push(NetworkBehaviourAction::SendEvent {
peer_id: peer_id.clone(),
event: CustomProtosHandlerIn::Disable,
});
return
}
}
@@ -351,6 +432,10 @@ where
if num_ingoing == self.max_incoming_connections {
debug!(target: "sub-libp2p", "Ignoring incoming connection from {:?} because \
we're full", peer_id);
self.events.push(NetworkBehaviourAction::SendEvent {
peer_id: peer_id.clone(),
event: CustomProtosHandlerIn::Disable,
});
return
}
}
@@ -374,10 +459,16 @@ where
});
}
self.topology.set_connected(&peer_id, &endpoint);
self.enabled_peers.insert(peer_id, endpoint);
}
fn inject_disconnected(&mut self, peer_id: &PeerId, _: ConnectedPoint) {
fn inject_disconnected(&mut self, peer_id: &PeerId, endpoint: ConnectedPoint) {
let was_connected = self.connected_peers.remove(&peer_id);
debug_assert!(was_connected);
self.topology.set_disconnected(peer_id, &endpoint);
while let Some(pos) = self.open_protocols.iter().position(|(p, _)| p == peer_id) {
let (_, protocol_id) = self.open_protocols.remove(pos);
@@ -388,12 +479,24 @@ where
};
self.events.push(NetworkBehaviourAction::GenerateEvent(event));
}
// Trigger a `connect_to_nodes` round.
self.next_connect_to_nodes = Delay::new(Instant::now());
self.enabled_peers.remove(peer_id);
}
fn inject_dial_failure(&mut self, peer_id: Option<&PeerId>, addr: &Multiaddr, error: &dyn error::Error) {
if let Some(peer_id) = peer_id.as_ref() {
debug!(target: "sub-libp2p", "Failed to reach peer {:?} through {} => {:?}", peer_id, addr, error);
if self.connected_peers.contains(peer_id) {
self.topology.set_unreachable(addr);
}
// Trigger a `connect_to_nodes` round.
self.next_connect_to_nodes = Delay::new(Instant::now());
}
self.enabled_peers.remove(peer_id);
}
fn inject_node_event(
@@ -461,7 +564,7 @@ where
fn poll(
&mut self,
params: &mut PollParameters<NetTopology>,
params: &mut PollParameters,
) -> Async<
NetworkBehaviourAction<
<Self::ProtocolsHandler as ProtocolsHandler>::InEvent,
@@ -19,13 +19,14 @@ use crate::custom_proto::upgrade::{RegisteredProtocol, RegisteredProtocols, Regi
use bytes::Bytes;
use futures::prelude::*;
use libp2p::core::{
Endpoint, ProtocolsHandler, ProtocolsHandlerEvent,
ProtocolsHandler, ProtocolsHandlerEvent,
protocols_handler::KeepAlive,
protocols_handler::ProtocolsHandlerUpgrErr,
upgrade::{InboundUpgrade, OutboundUpgrade}
};
use log::{trace, warn};
use smallvec::SmallVec;
use std::{fmt, io};
use std::{fmt, io, time::Duration, time::Instant};
use tokio_io::{AsyncRead, AsyncWrite};
use void::Void;
@@ -42,6 +43,9 @@ pub struct CustomProtosHandler<TSubstream> {
/// See the documentation of `State`.
state: State,
/// Value to be returned by `connection_keep_alive()`.
keep_alive: KeepAlive,
/// The active substreams. There should always ever be only one substream per protocol.
substreams: SmallVec<[RegisteredProtocolSubstream<TSubstream>; 6]>,
@@ -130,7 +134,9 @@ where
pub fn new(protocols: RegisteredProtocols) -> Self {
CustomProtosHandler {
protocols,
state: State::Disabled,
// We keep the connection alive for at least 5 seconds, waiting for what happens.
keep_alive: KeepAlive::Until(Instant::now() + Duration::from_secs(5)),
state: State::Normal,
substreams: SmallVec::new(),
events_queue: SmallVec::new(),
}
@@ -140,9 +146,10 @@ where
fn inject_fully_negotiated(
&mut self,
proto: RegisteredProtocolSubstream<TSubstream>,
_: Endpoint,
) {
match self.state {
// TODO: we should shut down refused substreams gracefully; this should be fixed
// at the same time as https://github.com/paritytech/substrate/issues/1517
State::Disabled | State::ShuttingDown => return,
State::Normal => ()
}
@@ -183,7 +190,7 @@ where
&mut self,
proto: <Self::InboundProtocol as InboundUpgrade<TSubstream>>::Output
) {
self.inject_fully_negotiated(proto, Endpoint::Listener);
self.inject_fully_negotiated(proto);
}
#[inline]
@@ -192,7 +199,7 @@ where
proto: <Self::OutboundProtocol as OutboundUpgrade<TSubstream>>::Output,
_: Self::OutboundOpenInfo
) {
self.inject_fully_negotiated(proto, Endpoint::Dialer);
self.inject_fully_negotiated(proto);
}
fn inject_event(&mut self, message: CustomProtosHandlerIn) {
@@ -203,6 +210,7 @@ where
State::Disabled | State::ShuttingDown => (),
}
self.keep_alive = KeepAlive::Now;
for substream in self.substreams.iter_mut() {
substream.shutdown();
}
@@ -213,6 +221,8 @@ where
State::Normal | State::ShuttingDown => (),
}
self.keep_alive = KeepAlive::Forever;
// Try open one substream for each registered protocol.
if let CustomProtosHandlerIn::EnableActive = message {
for protocol in self.protocols.0.iter() {
@@ -253,14 +263,16 @@ where
#[inline]
fn inject_dial_upgrade_error(&mut self, _: Self::OutboundOpenInfo, err: ProtocolsHandlerUpgrErr<io::Error>) {
warn!(target: "sub-libp2p", "Error while opening custom protocol: {:?}", err);
}
#[inline]
fn connection_keep_alive(&self) -> bool {
// Right now if the remote doesn't support one of the custom protocols, we shut down the
// entire connection. This is a hack-ish solution to the problem where we connect to nodes
// that support libp2p but not the testnet that we want.
self.substreams.len() == self.protocols.len()
self.shutdown();
}
#[inline]
fn connection_keep_alive(&self) -> KeepAlive {
self.keep_alive
}
fn shutdown(&mut self) {
@@ -19,4 +19,5 @@ pub use self::upgrade::{RegisteredProtocol, RegisteredProtocols};
mod behaviour;
mod handler;
mod topology;
mod upgrade;
@@ -15,12 +15,10 @@
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.?
use fnv::FnvHashMap;
use libp2p::{Multiaddr, PeerId, identify::IdentifyTopology, multihash::Multihash};
use libp2p::core::{PublicKey, swarm::ConnectedPoint, topology::DisconnectReason, topology::Topology};
use libp2p::kad::{KBucketsPeerId, KadConnectionType, KademliaTopology};
use libp2p::{core::swarm::ConnectedPoint, Multiaddr, PeerId};
use log::{debug, info, trace, warn};
use serde_derive::{Serialize, Deserialize};
use std::{cmp, fs, iter, vec};
use std::{cmp, fs};
use std::io::{Read, Cursor, Error as IoError, ErrorKind as IoErrorKind, Write, BufReader, BufWriter};
use std::path::{Path, PathBuf};
use std::time::{Duration, Instant, SystemTime};
@@ -58,8 +56,6 @@ const FAIL_BACKOFF_MULTIPLIER: u32 = 2;
/// We need a maximum value for the backoff, overwise we risk an overflow.
const MAX_BACKOFF: Duration = Duration::from_secs(30 * 60);
// TODO: should be merged with the Kademlia k-buckets
/// Stores information about the topology of the network.
#[derive(Debug)]
pub struct NetTopology {
@@ -67,12 +63,8 @@ pub struct NetTopology {
store: FnvHashMap<PeerId, PeerInfo>,
/// Optional path to the file that caches the serialized version of `store`.
cache_path: Option<PathBuf>,
/// Public key of the local node.
local_public_key: PublicKey,
/// PeerId of the local node. Derived from `local_public_key`.
/// PeerId of the local node.
local_peer_id: PeerId,
/// Known addresses for the local node to report to the network.
external_addresses: Vec<Multiaddr>,
}
impl NetTopology {
@@ -80,14 +72,11 @@ impl NetTopology {
///
/// `flush_to_disk()` will be a no-op.
#[inline]
pub fn memory(local_public_key: PublicKey) -> NetTopology {
let local_peer_id = local_public_key.clone().into_peer_id();
pub fn memory(local_peer_id: PeerId) -> NetTopology {
NetTopology {
store: Default::default(),
cache_path: None,
local_peer_id,
local_public_key,
external_addresses: Vec::new(),
}
}
@@ -97,17 +86,14 @@ impl NetTopology {
/// or contains garbage data, the execution still continues.
///
/// Calling `flush_to_disk()` in the future writes to the given path.
pub fn from_file<P: AsRef<Path>>(local_public_key: PublicKey, path: P) -> NetTopology {
pub fn from_file<P: AsRef<Path>>(local_peer_id: PeerId, path: P) -> NetTopology {
let path = path.as_ref();
let local_peer_id = local_public_key.clone().into_peer_id();
debug!(target: "sub-libp2p", "Initializing peer store for JSON file {:?}", path);
let store = try_load(path, &local_peer_id);
NetTopology {
store,
cache_path: Some(path.to_owned()),
local_peer_id,
local_public_key,
external_addresses: Vec::new(),
}
}
@@ -146,12 +132,6 @@ impl NetTopology {
});
}
/// Add the external addresses that are known for the local node.
pub fn add_external_addrs<TIter>(&mut self, addrs: TIter)
where TIter: Iterator<Item = Multiaddr> {
self.external_addresses.extend(addrs);
}
/// Returns a list of all the known addresses of peers, ordered by the
/// order in which we should attempt to connect to them.
///
@@ -200,6 +180,10 @@ impl NetTopology {
///
/// We assume that the address is valid, so its score starts very high.
pub fn add_bootstrap_addr(&mut self, peer: &PeerId, addr: Multiaddr) {
if *peer == self.local_peer_id {
return
}
let now_systime = SystemTime::now();
let now = Instant::now();
@@ -235,16 +219,22 @@ impl NetTopology {
}
}
/// Inner implementaiton of the `add_*_discovered_addrs` methods.
/// Indicates the topology that we have discovered new addresses for a given node.
///
/// Returns `true` if the topology has changed in some way. Returns `false` if calling this
/// method was a no-op.
fn add_discovered_addrs<I>(
pub fn add_discovered_addrs<I>(
&mut self,
peer_id: &PeerId,
addrs: I,
) -> bool
where I: Iterator<Item = (Multiaddr, bool)> {
if *peer_id == self.local_peer_id {
return false
}
let mut addrs: Vec<_> = addrs.collect();
let now_systime = SystemTime::now();
let now = Instant::now();
@@ -252,14 +242,14 @@ impl NetTopology {
let new_addrs = peer.addrs
.drain(..)
.filter_map(|a| {
.filter(|a| {
if a.expires < now_systime && !a.is_connected() {
return None
return false
}
if let Some(pos) = addrs.iter().position(|&(ref addr, _)| addr == &a.addr) {
while let Some(pos) = addrs.iter().position(|&(ref addr, _)| addr == &a.addr) {
addrs.remove(pos);
}
Some(a)
true
})
.collect();
peer.addrs = new_addrs;
@@ -267,6 +257,7 @@ impl NetTopology {
let mut anything_changed = false;
if !addrs.is_empty() {
anything_changed = true;
trace!(
target: "sub-libp2p",
"Peer store: adding addresses {:?} for {:?}",
@@ -292,7 +283,11 @@ impl NetTopology {
}
}
anything_changed = true;
// `addrs` can contain duplicates, therefore we would insert the same address twice.
if peer.addrs.iter().any(|a| a.addr == addr) {
continue;
}
peer.addrs.push(Addr {
addr,
expires: now_systime + KADEMLIA_DISCOVERY_EXPIRATION,
@@ -308,58 +303,10 @@ impl NetTopology {
anything_changed
}
}
impl KademliaTopology for NetTopology {
type ClosestPeersIter = vec::IntoIter<PeerId>;
type GetProvidersIter = iter::Empty<PeerId>;
fn add_kad_discovered_address(&mut self, peer: PeerId, addr: Multiaddr, ty: KadConnectionType) {
self.add_discovered_addrs(&peer, iter::once((addr, ty == KadConnectionType::Connected)));
}
fn closest_peers(&mut self, target: &Multihash, _max: usize) -> Self::ClosestPeersIter {
// TODO: very inefficient
let mut peers = self.store.keys().cloned().collect::<Vec<_>>();
peers.push(self.local_peer_id.clone());
peers.sort_by(|a, b| {
b.as_ref().distance_with(target).cmp(&a.as_ref().distance_with(target))
});
peers.into_iter()
}
fn add_provider(&mut self, _: Multihash, _: PeerId) {
// We don't implement ADD_PROVIDER/GET_PROVIDERS
}
fn get_providers(&mut self, _: &Multihash) -> Self::GetProvidersIter {
// We don't implement ADD_PROVIDER/GET_PROVIDERS
iter::empty()
}
}
impl IdentifyTopology for NetTopology {
/// Returns the addresses stored for a specific peer.
#[inline]
fn add_identify_discovered_addrs<TIter>(&mut self, peer: &PeerId, addrs: TIter)
where
TIter: Iterator<Item = Multiaddr>
{
// These are addresses that peers indicate for themselves.
// The typical use case is:
// - A peer connects to one of our listening points.
// - We send an identify request to it, and it answers with a list of addresses.
// - If later it disconnects, we can try to dial it back through one of these addresses.
self.add_discovered_addrs(peer, addrs.map(move |a| (a, true)));
}
}
impl Topology for NetTopology {
#[inline]
fn addresses_of_peer(&mut self, peer: &PeerId) -> Vec<Multiaddr> {
if peer == &self.local_peer_id {
return self.external_addresses.clone()
}
pub fn addresses_of_peer(&mut self, peer: &PeerId) -> Vec<Multiaddr> {
let peer = if let Some(peer) = self.store.get_mut(peer) {
peer
} else {
@@ -382,20 +329,12 @@ impl Topology for NetTopology {
list.into_iter().map(|(_, addr)| addr.clone()).collect::<Vec<_>>()
}
fn add_local_external_addrs<TIter>(&mut self, addrs: TIter)
where TIter: Iterator<Item = Multiaddr> {
self.add_external_addrs(addrs)
}
/// Marks the given peer as connected through the given endpoint.
pub fn set_connected(&mut self, peer: &PeerId, endpoint: &ConnectedPoint) {
if *peer == self.local_peer_id {
return
}
fn local_peer_id(&self) -> &PeerId {
&self.local_peer_id
}
fn local_public_key(&self) -> &PublicKey {
&self.local_public_key
}
fn set_connected(&mut self, peer: &PeerId, endpoint: &ConnectedPoint) {
let addr = match endpoint {
ConnectedPoint::Dialer { address } => address,
ConnectedPoint::Listener { .. } => return
@@ -438,17 +377,16 @@ impl Topology for NetTopology {
}
}
fn set_disconnected(&mut self, _: &PeerId, endpoint: &ConnectedPoint, reason: DisconnectReason) {
/// Marks the given peer as disconnected. The endpoint is the one we were connected to.
pub fn set_disconnected(&mut self, _: &PeerId, endpoint: &ConnectedPoint) {
let addr = match endpoint {
ConnectedPoint::Dialer { address } => address,
ConnectedPoint::Listener { .. } => return
};
let score_diff = match reason {
DisconnectReason::Replaced => -3,
DisconnectReason::Graceful => -1,
DisconnectReason::Error => -5,
};
// Note that we used to have different score values here in the past, but there really
// isn't much point in doing so in practice.
let score_diff = -3;
for info in self.store.values_mut() {
for a in info.addrs.iter_mut() {
@@ -466,13 +404,15 @@ impl Topology for NetTopology {
}
}
fn set_unreachable(&mut self, addr: &Multiaddr) {
/// Indicates to the topology that we failed to reach a node when dialing the given address.
pub fn set_unreachable(&mut self, addr: &Multiaddr) {
for info in self.store.values_mut() {
for a in info.addrs.iter_mut() {
if &a.addr != addr {
continue
}
debug_assert!(!a.is_connected());
a.adjust_score(SCORE_DIFF_ON_FAILED_TO_CONNECT);
trace!(target: "sub-libp2p", "Back off for {} = {:?}", addr, a.next_back_off);
a.back_off_until = Instant::now() + a.next_back_off;
-1
View File
@@ -21,7 +21,6 @@ mod custom_proto;
mod error;
mod secret;
mod service_task;
mod topology;
mod traits;
mod transport;
@@ -19,7 +19,6 @@ use crate::{
transport
};
use crate::custom_proto::{RegisteredProtocol, RegisteredProtocols};
use crate::topology::NetTopology;
use crate::{Error, NetworkConfiguration, NodeIndex, ProtocolId, parse_str_addr};
use bytes::Bytes;
use fnv::FnvHashMap;
@@ -37,9 +36,6 @@ use std::sync::Arc;
use std::time::Duration;
use tokio_timer::Interval;
// File where the network topology is stored.
const NODES_FILE: &str = "nodes.json";
/// Starts the substrate libp2p service.
///
/// Returns a stream that must be polled regularly in order for the networking to function.
@@ -58,25 +54,12 @@ where TProtos: IntoIterator<Item = RegisteredProtocol> {
let local_public_key = local_private_key.to_public_key();
let local_peer_id = local_public_key.clone().into_peer_id();
// Initialize the topology of the network.
let mut topology = if let Some(ref path) = config.net_config_path {
let path = Path::new(path).join(NODES_FILE);
debug!(target: "sub-libp2p", "Initializing peer store for JSON file {:?}", path);
NetTopology::from_file(local_public_key, path)
} else {
debug!(target: "sub-libp2p", "No peers file configured ; peers won't be saved");
NetTopology::memory(local_public_key)
};
// Register the external addresses provided by the user as our own.
topology.add_external_addrs(config.public_addresses.clone().into_iter());
// Build the swarm.
let (mut swarm, bandwidth) = {
let registered_custom = RegisteredProtocols(registered_custom.into_iter().collect());
let behaviour = Behaviour::new(&config, local_peer_id.clone(), registered_custom);
let behaviour = Behaviour::new(&config, local_public_key.clone(), registered_custom);
let (transport, bandwidth) = transport::build_transport(local_private_key);
(Swarm::new(transport, behaviour, topology), bandwidth)
(Swarm::new(transport, behaviour, local_peer_id.clone()), bandwidth)
};
// Listen on multiaddresses.
@@ -90,11 +73,15 @@ where TProtos: IntoIterator<Item = RegisteredProtocol> {
}
}
// Add the bootstrap nodes to the topology and connect to them.
// Add external addresses.
for addr in &config.public_addresses {
Swarm::add_external_address(&mut swarm, addr.clone());
}
// Connect to the bootnodes.
for bootnode in config.boot_nodes.iter() {
match parse_str_addr(bootnode) {
Ok((peer_id, addr)) => {
Swarm::topology_mut(&mut swarm).add_bootstrap_addr(&peer_id, addr.clone());
Ok((peer_id, _)) => {
Swarm::dial(&mut swarm, peer_id);
},
Err(_) => {
@@ -121,8 +108,7 @@ where TProtos: IntoIterator<Item = RegisteredProtocol> {
// Initialize the reserved peers.
for reserved in config.reserved_nodes.iter() {
if let Ok((peer_id, addr)) = parse_str_addr(reserved) {
Swarm::topology_mut(&mut swarm).add_bootstrap_addr(&peer_id, addr);
swarm.add_reserved_peer(peer_id.clone());
swarm.add_reserved_peer(peer_id.clone(), addr);
Swarm::dial(&mut swarm, peer_id);
} else {
warn!(target: "sub-libp2p", "Not a valid reserved node address: {}", reserved);
@@ -130,7 +116,7 @@ where TProtos: IntoIterator<Item = RegisteredProtocol> {
}
debug!(target: "sub-libp2p", "Topology started with {} entries",
Swarm::topology_mut(&mut swarm).num_peers());
swarm.num_topology_peers());
Ok(Service {
swarm,
@@ -204,7 +190,7 @@ pub enum ServiceEvent {
/// Network service. Must be polled regularly in order for the networking to work.
pub struct Service {
/// Stream of events of the swarm.
swarm: Swarm<Boxed<(PeerId, StreamMuxerBox), IoError>, Behaviour<Substream<StreamMuxerBox>>, NetTopology>,
swarm: Swarm<Boxed<(PeerId, StreamMuxerBox), IoError>, Behaviour<Substream<StreamMuxerBox>>>,
/// Bandwidth logging system. Can be queried to know the average bandwidth consumed.
bandwidth: Arc<transport::BandwidthSinks>,
@@ -270,8 +256,7 @@ impl Service {
/// Try to add a reserved peer.
pub fn add_reserved_peer(&mut self, peer_id: PeerId, addr: Multiaddr) {
Swarm::topology_mut(&mut self.swarm).add_bootstrap_addr(&peer_id, addr);
self.swarm.add_reserved_peer(peer_id);
self.swarm.add_reserved_peer(peer_id, addr);
}
/// Try to remove a reserved peer.
@@ -452,13 +437,13 @@ impl Service {
Ok(Async::NotReady) => return Ok(Async::NotReady),
Ok(Async::Ready(Some(_))) => {
debug!(target: "sub-libp2p", "Cleaning and flushing topology");
Swarm::topology_mut(&mut self.swarm).cleanup();
if let Err(err) = Swarm::topology_mut(&mut self.swarm).flush_to_disk() {
self.swarm.cleanup();
if let Err(err) = self.swarm.flush_topology() {
warn!(target: "sub-libp2p", "Failed to flush topology: {:?}", err);
}
debug!(target: "sub-libp2p", "Topology now contains {} nodes",
Swarm::topology_mut(&mut self.swarm).num_peers());
},
self.swarm.num_topology_peers());
}
Ok(Async::Ready(None)) => {
warn!(target: "sub-libp2p", "Topology flush stream ended unexpectedly");
return Ok(Async::Ready(None))
@@ -474,7 +459,7 @@ impl Service {
impl Drop for Service {
fn drop(&mut self) {
if let Err(err) = Swarm::topology_mut(&mut self.swarm).flush_to_disk() {
if let Err(err) = self.swarm.flush_topology() {
warn!(target: "sub-libp2p", "Failed to flush topology: {:?}", err);
}
}
+8 -5
View File
@@ -124,7 +124,7 @@ fn two_nodes_transfer_lots_of_packets() {
});
let combined = fut1.select(fut2).map_err(|(err, _)| err);
tokio::runtime::Runtime::new().unwrap().block_on_all(combined).unwrap();
tokio::runtime::Runtime::new().unwrap().block_on(combined).unwrap();
}
#[test]
@@ -148,10 +148,13 @@ fn many_nodes_connectivity() {
return Ok(Async::Ready(Some(())))
}
}
// TODO: we sometimes receive a closed connection event; maybe this is
// benign, but it would be nice to figure out why
// (https://github.com/libp2p/rust-libp2p/issues/844)
Some(ServiceEvent::ClosedCustomProtocol { .. }) => {}
Some(ServiceEvent::ClosedCustomProtocol { .. }) => {
// Only remove 1 if we haven't returned success yet, otherwise we
// will succeed the test multiple times.
if num_connecs < NUM_NODES - 1 {
num_connecs -= 1;
}
}
_ => panic!(),
}
}
+1 -1
View File
@@ -17,7 +17,7 @@ impl-serde = { version = "0.1", optional = true }
wasmi = { version = "0.4.3", optional = true }
hash-db = { version = "0.11", default-features = false }
hash256-std-hasher = { version = "0.11", default-features = false }
ring = { version = "0.13", optional = true }
ring = { version = "0.14", optional = true }
untrusted = { version = "0.6", optional = true }
hex-literal = { version = "0.1", optional = true }
base58 = { version = "0.1", optional = true }
+7 -5
View File
@@ -20,7 +20,7 @@
use untrusted;
use blake2_rfc;
use ring::{rand, signature};
use ring::{rand, signature, signature::KeyPair};
use {hash::H512, Ed25519AuthorityId};
use base58::{ToBase58, FromBase58};
@@ -199,9 +199,11 @@ impl Pair {
pub fn generate_with_pkcs8() -> (Self, [u8; PKCS_LEN]) {
let rng = rand::SystemRandom::new();
let pkcs8_bytes = signature::Ed25519KeyPair::generate_pkcs8(&rng).expect("system randomness is available; qed");
let pair = Self::from_pkcs8(&pkcs8_bytes).expect("just-generated pkcs#8 data is valid; qed");
let pair = Self::from_pkcs8(&pkcs8_bytes.as_ref()).expect("just-generated pkcs#8 data is valid; qed");
(pair, pkcs8_bytes)
let mut out = [0; PKCS_LEN];
out.copy_from_slice(pkcs8_bytes.as_ref());
(pair, out)
}
/// Generate new secure (random) key pair.
@@ -211,7 +213,7 @@ impl Pair {
}
/// Generate from pkcs#8 bytes.
pub fn from_pkcs8(pkcs8_bytes: &[u8]) -> Result<Self, ::ring::error::Unspecified> {
pub fn from_pkcs8(pkcs8_bytes: &[u8]) -> Result<Self, ::ring::error::KeyRejected> {
signature::Ed25519KeyPair::from_pkcs8(untrusted::Input::from(&pkcs8_bytes)).map(Pair)
}
@@ -234,7 +236,7 @@ impl Pair {
/// Get the public key.
pub fn public(&self) -> Public {
let mut r = [0u8; 32];
let pk = self.0.public_key_bytes();
let pk = self.0.public_key().as_ref();
r.copy_from_slice(pk);
Public(r)
}
+35 -28
View File
@@ -20,7 +20,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -30,8 +30,8 @@ name = "backtrace-sys"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -83,7 +83,7 @@ dependencies = [
[[package]]
name = "cc"
version = "1.0.25"
version = "1.0.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -209,7 +209,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -361,7 +361,7 @@ name = "iovec"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -405,7 +405,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.44"
version = "0.2.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -490,7 +490,7 @@ dependencies = [
"iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -515,7 +515,7 @@ version = "0.6.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -536,7 +536,7 @@ version = "0.2.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -563,7 +563,7 @@ name = "num_cpus"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -580,7 +580,7 @@ dependencies = [
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -589,8 +589,8 @@ name = "openssl-sys"
version = "0.9.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -658,7 +658,7 @@ name = "parking_lot_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -670,7 +670,7 @@ name = "parking_lot_core"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -763,7 +763,7 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -774,7 +774,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -786,7 +786,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -859,12 +859,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ring"
version = "0.13.5"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
"spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1000,6 +1001,11 @@ dependencies = [
"unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "spin"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "sr-api-macros"
version = "0.1.0"
@@ -1260,7 +1266,7 @@ dependencies = [
"parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)",
"ring 0.14.5 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1378,7 +1384,7 @@ name = "time"
version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1537,7 +1543,7 @@ dependencies = [
"bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
"mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1718,7 +1724,7 @@ dependencies = [
"checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40"
"checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d"
"checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa"
"checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16"
"checksum cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "4390a3b5f4f6bce9c1d0c00128379df433e53777fdd30e92f16a529332baec4e"
"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4"
"checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878"
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
@@ -1762,7 +1768,7 @@ dependencies = [
"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1"
"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
"checksum libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)" = "10923947f84a519a45c8fefb7dd1b3e8c08747993381adee176d7a82b4195311"
"checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047"
"checksum libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "688e8d65e495567c2c35ea0001b26b9debf0b4ea11f8cccc954233b75fc3428a"
"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c"
"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
@@ -1814,7 +1820,7 @@ dependencies = [
"checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05"
"checksum rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effa3fcaa47e18db002bdde6060944b6d2f9cfd8db471c30e873448ad9187be3"
"checksum redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "679da7508e9a6390aeaf7fbd02a800fdc64b73fe2204dd2c8ae66d22d9d5ad5d"
"checksum ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2c4db68a2e35f3497146b7e4563df7d4773a2433230c5e4b448328e31740458a"
"checksum ring 0.14.5 (registry+https://github.com/rust-lang/crates.io-index)" = "148fc853f6d85f53f5f315d46701eaacc565cdfb3cb1959730c96e81e7e49999"
"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395"
"checksum rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "403bb3a286107a04825a5f82e1270acc1e14028d3d554d7a1e08914549575ab8"
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
@@ -1833,6 +1839,7 @@ dependencies = [
"checksum slog-json 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddc0d2aff1f8f325ef660d9a0eb6e6dcd20b30b3f581a5897f58bf42d061c37a"
"checksum slog-scope 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "053344c94c0e2b22da6305efddb698d7c485809427cf40555dc936085f67a9df"
"checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db"
"checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55"
"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
"checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5"
"checksum syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)" = "ae8b29eb5210bc5cf63ed6149cbf9adfc82ac0be023d8735c176ee74a2db4da7"