[devp2p] Update to 2018 edition (#10716)

* Run cargo fix

* Optimize imports

* compiles

* cleanup

* Use Secret to store mac-key
Truncate payload properly

* cleanup

* Reorg imports

* brwchk hand waving

* Fix a bunch of imports

* Fixup imports

* Sort

* indentation

* WIP

* Revert "WIP"

This reverts commit 85f7e74f4bd1990db865cf6acfa8d494798eeeaa.

* inclusive range pattern syntax is changing

* remove usless todo
This commit is contained in:
David
2019-06-19 12:20:50 +02:00
committed by GitHub
parent d2120ded56
commit 859a41308c
12 changed files with 131 additions and 168 deletions

View File

@@ -21,21 +21,23 @@ use std::sync::atomic::{AtomicBool, Ordering as AtomicOrdering};
use std::time::Duration;
use bytes::{Buf, BufMut};
use crypto::aes::{AesCtr256, AesEcb256};
use ethereum_types::{H128, H256, H512};
use hash::{keccak, write_keccak};
use keccak_hash::{keccak, write_keccak};
use log::{debug, trace, warn};
use mio::{PollOpt, Ready, Token};
use mio::deprecated::{EventLoop, Handler, TryRead, TryWrite};
use mio::tcp::*;
use parity_bytes::*;
use crypto::aes::{AesCtr256, AesEcb256};
use mio::tcp::TcpStream;
use parity_bytes::Bytes;
use rlp::{Rlp, RlpStream};
use tiny_keccak::Keccak;
use ethkey::{crypto, Secret};
use handshake::Handshake;
use io::{IoContext, StreamToken};
use ethcore_io::{IoContext, StreamToken};
use ethkey::{crypto as ethcrypto, Secret};
use network::Error;
use crate::handshake::Handshake;
const ENCRYPTED_HEADER_LEN: usize = 32;
const RECEIVE_PAYLOAD: Duration = Duration::from_secs(30);
pub const MAX_PAYLOAD_SIZE: usize = (1 << 24) - 1;
@@ -297,7 +299,7 @@ const NULL_IV : [u8; 16] = [0;16];
impl EncryptedConnection {
/// Create an encrypted connection out of the handshake.
pub fn new(handshake: &mut Handshake) -> Result<EncryptedConnection, Error> {
let shared = crypto::ecdh::agree(handshake.ecdhe.secret(), &handshake.remote_ephemeral)?;
let shared = ethcrypto::ecdh::agree(handshake.ecdhe.secret(), &handshake.remote_ephemeral)?;
let mut nonce_material = H512::default();
if handshake.originated {
(&mut nonce_material[0..32]).copy_from_slice(handshake.remote_nonce.as_bytes());
@@ -391,13 +393,11 @@ impl EncryptedConnection {
return Err(Error::Auth);
}
EncryptedConnection::update_mac(&mut self.ingress_mac, &self.mac_encoder_key, &header[0..16])?;
{
let mac = &header[16..];
let mut expected = H256::zero();
self.ingress_mac.clone().finalize(expected.as_bytes_mut());
if mac != &expected[0..16] {
return Err(Error::Auth);
}
let mac = &header[16..];
let mut expected = H256::zero();
self.ingress_mac.clone().finalize(expected.as_bytes_mut());
if mac != &expected[0..16] {
return Err(Error::Auth);
}
self.decoder.decrypt(&mut header[..16])?;
@@ -426,13 +426,11 @@ impl EncryptedConnection {
self.ingress_mac.update(&payload[0..payload.len() - 16]);
EncryptedConnection::update_mac(&mut self.ingress_mac, &self.mac_encoder_key, &[0u8; 0])?;
{
let mac = &payload[(payload.len() - 16)..];
let mut expected = H128::default();
self.ingress_mac.clone().finalize(expected.as_bytes_mut());
if mac != &expected[..] {
return Err(Error::Auth);
}
let mac = &payload[(payload.len() - 16)..];
let mut expected = H128::default();
self.ingress_mac.clone().finalize(expected.as_bytes_mut());
if mac != &expected[..] {
return Err(Error::Auth);
}
self.decoder.decrypt(&mut payload[..self.payload_len + padding])?;
payload.truncate(self.payload_len);
@@ -496,7 +494,7 @@ mod tests {
use mio::Ready;
use parity_bytes::Bytes;
use io::*;
use ethcore_io::*;
use super::*;

View File

@@ -21,7 +21,8 @@ use std::net::SocketAddr;
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
use ethereum_types::{H256, H520};
use hash::keccak;
use keccak_hash::keccak;
use log::{debug, trace, warn};
use lru_cache::LruCache;
use parity_bytes::Bytes;
use rlp::{Rlp, RlpStream};
@@ -29,8 +30,9 @@ use rlp::{Rlp, RlpStream};
use ethkey::{KeyPair, recover, Secret, sign};
use network::Error;
use network::IpFilter;
use node_table::*;
use PROTOCOL_VERSION;
use crate::node_table::*;
use crate::PROTOCOL_VERSION;
const ADDRESS_BYTES_SIZE: usize = 32; // Size of address type in bytes.
const ADDRESS_BITS: usize = 8 * ADDRESS_BYTES_SIZE; // Denoted by n in [Kademlia].
@@ -900,7 +902,8 @@ mod tests {
use rustc_hex::FromHex;
use ethkey::{Generator, Random};
use node_table::{Node, NodeEndpoint, NodeId};
use crate::node_table::{Node, NodeEndpoint, NodeId};
use super::*;

View File

@@ -17,19 +17,21 @@
use std::time::Duration;
use ethereum_types::{H256, H520};
use hash::write_keccak;
use keccak_hash::write_keccak;
use log::{debug, trace};
use mio::tcp::*;
use parity_bytes::Bytes;
use rand::random;
use rlp::{Rlp, RlpStream};
use connection::Connection;
use ethcore_io::{IoContext, StreamToken};
use ethkey::{Generator, KeyPair, Public, Random, recover, Secret, sign};
use ethkey::crypto::{ecdh, ecies};
use host::HostInfo;
use io::{IoContext, StreamToken};
use network::Error;
use node_table::NodeId;
use crate::connection::Connection;
use crate::host::HostInfo;
use crate::node_table::NodeId;
#[derive(PartialEq, Eq, Debug)]
enum HandshakeState {
@@ -320,18 +322,18 @@ impl Handshake {
#[cfg(test)]
mod test {
use std::str::FromStr;
use std::str::FromStr;
use ethereum_types::{H256, H512};
use mio::tcp::TcpStream;
use rustc_hex::FromHex;
use ethereum_types::{H256, H512};
use mio::tcp::TcpStream;
use rustc_hex::FromHex;
use ethkey::Public;
use io::*;
use ethcore_io::*;
use ethkey::Public;
use super::*;
use super::*;
fn check_auth(h: &Handshake, version: u64) {
fn check_auth(h: &Handshake, version: u64) {
assert_eq!(
h.id,
H512::from_str("fda1cff674c90c9a197539fe3dfb53086ace64f83ed7c6eabec741f7f381cc803e52ab2cd55d5569bce4347107a310dfd5f88a010cd2ffd1005ca406f1842877").unwrap(),

View File

@@ -27,29 +27,34 @@ use std::sync::atomic::{AtomicBool, Ordering as AtomicOrdering};
use std::time::Duration;
use ethereum_types::H256;
use hash::keccak;
use mio::*;
use mio::deprecated::EventLoop;
use mio::tcp::*;
use mio::udp::*;
use keccak_hash::keccak;
use log::{debug, info, trace, warn};
use mio::{
deprecated::EventLoop, PollOpt, Ready, tcp::{TcpListener, TcpStream},
Token,
udp::UdpSocket
};
use parity_path::restrict_permissions_owner;
use parking_lot::{Mutex, RwLock};
use rlp::{Encodable, RlpStream};
use rustc_hex::ToHex;
use connection::PAYLOAD_SOFT_LIMIT;
use discovery::{Discovery, MAX_DATAGRAM_SIZE, NodeEntry, TableUpdates};
use ethcore_io::{IoContext, IoHandler, IoManager, StreamToken, TimerToken};
use ethkey::{Generator, KeyPair, Random, Secret};
use io::*;
use ip_utils::{map_external_address, select_public_address};
use network::{NetworkConfiguration, NetworkIoMessage, PacketId, PeerId, ProtocolId};
use network::{NetworkContext as NetworkContextTrait, NonReservedPeerMode};
use network::{DisconnectReason, Error, NetworkProtocolHandler, SessionInfo};
use network::{ConnectionDirection, ConnectionFilter};
use network::client_version::ClientVersion;
use node_table::*;
use PROTOCOL_VERSION;
use session::{Session, SessionData};
use network::{
client_version::ClientVersion, ConnectionDirection, ConnectionFilter, DisconnectReason, Error,
NetworkConfiguration, NetworkContext as NetworkContextTrait, NetworkIoMessage, NetworkProtocolHandler,
NonReservedPeerMode, PacketId, PeerId, ProtocolId, SessionInfo
};
use crate::{
connection::PAYLOAD_SOFT_LIMIT,
discovery::{Discovery, MAX_DATAGRAM_SIZE, NodeEntry, TableUpdates},
ip_utils::{map_external_address, select_public_address},
node_table::*,
PROTOCOL_VERSION,
session::{Session, SessionData}
};
type Slab<T> = ::slab::Slab<T, usize>;
@@ -263,17 +268,17 @@ pub struct Host {
sessions: Arc<RwLock<Slab<SharedSession>>>,
discovery: Mutex<Option<Discovery<'static>>>,
nodes: RwLock<NodeTable>,
handlers: RwLock<HashMap<ProtocolId, Arc<NetworkProtocolHandler + Sync>>>,
handlers: RwLock<HashMap<ProtocolId, Arc<dyn NetworkProtocolHandler + Sync>>>,
timers: RwLock<HashMap<TimerToken, ProtocolTimer>>,
timer_counter: RwLock<usize>,
reserved_nodes: RwLock<HashSet<NodeId>>,
stopping: AtomicBool,
filter: Option<Arc<ConnectionFilter>>,
filter: Option<Arc<dyn ConnectionFilter>>,
}
impl Host {
/// Create a new instance
pub fn new(mut config: NetworkConfiguration, filter: Option<Arc<ConnectionFilter>>) -> Result<Host, Error> {
pub fn new(mut config: NetworkConfiguration, filter: Option<Arc<dyn ConnectionFilter>>) -> Result<Host, Error> {
let mut listen_address = match config.listen_address {
None => SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), DEFAULT_PORT)),
Some(addr) => addr,
@@ -924,7 +929,7 @@ impl Host {
let mut failure_id = None;
let mut deregister = false;
let mut expired_session = None;
if let FIRST_SESSION ... LAST_SESSION = token {
if let FIRST_SESSION ..= LAST_SESSION = token {
let sessions = self.sessions.read();
if let Some(session) = sessions.get(token).cloned() {
expired_session = Some(session.clone());
@@ -978,14 +983,14 @@ impl Host {
self.nodes.write().update(node_changes, &*self.reserved_nodes.read());
}
pub fn with_context<F>(&self, protocol: ProtocolId, io: &IoContext<NetworkIoMessage>, action: F) where F: FnOnce(&NetworkContextTrait) {
pub fn with_context<F>(&self, protocol: ProtocolId, io: &IoContext<NetworkIoMessage>, action: F) where F: FnOnce(&dyn NetworkContextTrait) {
let reserved = { self.reserved_nodes.read() };
let context = NetworkContext::new(io, protocol, None, self.sessions.clone(), &reserved);
action(&context);
}
pub fn with_context_eval<F, T>(&self, protocol: ProtocolId, io: &IoContext<NetworkIoMessage>, action: F) -> T where F: FnOnce(&NetworkContextTrait) -> T {
pub fn with_context_eval<F, T>(&self, protocol: ProtocolId, io: &IoContext<NetworkIoMessage>, action: F) -> T where F: FnOnce(&dyn NetworkContextTrait) -> T {
let reserved = { self.reserved_nodes.read() };
let context = NetworkContext::new(io, protocol, None, self.sessions.clone(), &reserved);
@@ -1004,7 +1009,7 @@ impl IoHandler<NetworkIoMessage> for Host {
fn stream_hup(&self, io: &IoContext<NetworkIoMessage>, stream: StreamToken) {
trace!(target: "network", "Hup: {}", stream);
match stream {
FIRST_SESSION ... LAST_SESSION => self.connection_closed(stream, io),
FIRST_SESSION ..= LAST_SESSION => self.connection_closed(stream, io),
_ => warn!(target: "network", "Unexpected hup"),
};
}
@@ -1014,7 +1019,7 @@ impl IoHandler<NetworkIoMessage> for Host {
return;
}
match stream {
FIRST_SESSION ... LAST_SESSION => self.session_readable(stream, io),
FIRST_SESSION ..= LAST_SESSION => self.session_readable(stream, io),
DISCOVERY => self.discovery_readable(io),
TCP_ACCEPT => self.accept(io),
_ => panic!("Received unknown readable token"),
@@ -1026,7 +1031,7 @@ impl IoHandler<NetworkIoMessage> for Host {
return;
}
match stream {
FIRST_SESSION ... LAST_SESSION => self.session_writable(stream, io),
FIRST_SESSION ..= LAST_SESSION => self.session_writable(stream, io),
DISCOVERY => self.discovery_writable(io),
_ => panic!("Received unknown writable token"),
}
@@ -1038,7 +1043,7 @@ impl IoHandler<NetworkIoMessage> for Host {
}
match token {
IDLE => self.maintain_network(io),
FIRST_SESSION ... LAST_SESSION => self.connection_timeout(token, io),
FIRST_SESSION ..= LAST_SESSION => self.connection_timeout(token, io),
DISCOVERY_REFRESH => {
// Run the _slow_ discovery if enough peers are connected
if !self.has_enough_peers() {
@@ -1146,7 +1151,7 @@ impl IoHandler<NetworkIoMessage> for Host {
fn register_stream(&self, stream: StreamToken, reg: Token, event_loop: &mut EventLoop<IoManager<NetworkIoMessage>>) {
match stream {
FIRST_SESSION ... LAST_SESSION => {
FIRST_SESSION ..= LAST_SESSION => {
let session = { self.sessions.read().get(stream).cloned() };
if let Some(session) = session {
session.lock().register_socket(reg, event_loop).expect("Error registering socket");
@@ -1166,7 +1171,7 @@ impl IoHandler<NetworkIoMessage> for Host {
fn deregister_stream(&self, stream: StreamToken, event_loop: &mut EventLoop<IoManager<NetworkIoMessage>>) {
match stream {
FIRST_SESSION ... LAST_SESSION => {
FIRST_SESSION ..= LAST_SESSION => {
let mut connections = self.sessions.write();
if let Some(connection) = connections.get(stream).cloned() {
let c = connection.lock();
@@ -1183,7 +1188,7 @@ impl IoHandler<NetworkIoMessage> for Host {
fn update_stream(&self, stream: StreamToken, reg: Token, event_loop: &mut EventLoop<IoManager<NetworkIoMessage>>) {
match stream {
FIRST_SESSION ... LAST_SESSION => {
FIRST_SESSION ..= LAST_SESSION => {
let connection = { self.sessions.read().get(stream).cloned() };
if let Some(connection) = connection {
connection.lock().update_socket(reg, event_loop).expect("Error updating socket");

View File

@@ -22,8 +22,9 @@ use std::time::Duration;
use igd::{PortMappingProtocol, search_gateway_from_timeout};
use ipnetwork::IpNetwork;
use log::debug;
use node_table::NodeEndpoint;
use crate::node_table::NodeEndpoint;
/// Socket address extension for rustc beta. To be replaces with now unstable API
pub trait SocketAddrExt {
@@ -214,13 +215,13 @@ impl SocketAddrExt for IpAddr {
#[cfg(not(any(windows, target_os = "android")))]
mod getinterfaces {
use std::{io, mem};
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use std::{io, mem};
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use libc::{AF_INET, AF_INET6};
use libc::{freeifaddrs, getifaddrs, ifaddrs, sockaddr, sockaddr_in, sockaddr_in6};
use libc::{AF_INET, AF_INET6};
use libc::{freeifaddrs, getifaddrs, ifaddrs, sockaddr, sockaddr_in, sockaddr_in6};
fn convert_sockaddr(sa: *mut sockaddr) -> Option<IpAddr> {
fn convert_sockaddr(sa: *mut sockaddr) -> Option<IpAddr> {
if sa.is_null() { return None; }
let (addr, _) = match i32::from(unsafe { *sa }.sa_family) {

View File

@@ -19,7 +19,7 @@
//! Example usage for creating a network service and adding an IO handler:
//!
//! ```rust
//! extern crate ethcore_network as net;
//! extern crate network as net;
//! extern crate ethcore_network_devp2p as devp2p;
//! use net::*;
//! use devp2p::NetworkService;
@@ -60,44 +60,8 @@
//TODO: use Poll from mio
#![allow(deprecated)]
//TODO: remove this
extern crate ansi_term;
#[cfg(test)] #[macro_use]
extern crate assert_matches;
extern crate bytes;
#[cfg(test)]
extern crate env_logger;
extern crate ethcore_io as io;
extern crate ethcore_network as network;
extern crate ethereum_types;
extern crate ethkey;
extern crate igd;
extern crate ipnetwork;
extern crate keccak_hash as hash;
extern crate libc;
#[macro_use]
extern crate log;
extern crate lru_cache;
extern crate mio;
extern crate parity_bytes;
extern crate parity_crypto as crypto;
extern crate parity_path;
extern crate parity_snappy as snappy;
extern crate parking_lot;
extern crate rand;
extern crate rlp;
extern crate rustc_hex;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate slab;
#[cfg(test)]
extern crate tempdir;
extern crate tiny_keccak;
pub use ethcore_io::TimerToken;
pub use host::NetworkContext;
pub use io::TimerToken;
pub use node_table::{MAX_NODES_IN_TABLE, NodeId, validate_node_url};
pub use service::NetworkService;

View File

@@ -25,14 +25,19 @@ use std::str::FromStr;
use std::time::{self, Duration, SystemTime};
use ethereum_types::H512;
use log::{debug, warn};
use rand::{self, Rng};
use rlp::{DecoderError, Rlp, RlpStream};
use serde::{Deserialize, Serialize};
use serde_json;
use discovery::{NodeEntry, TableUpdates};
use ip_utils::*;
use network::{AllowIP, Error, IpFilter};
use crate::{
discovery::{NodeEntry, TableUpdates},
ip_utils::*,
};
/// Node public key
pub type NodeId = H512;
@@ -612,6 +617,8 @@ mod tests {
use ipnetwork::IpNetwork;
use tempdir::TempDir;
use assert_matches::assert_matches;
use super::*;
#[test]

View File

@@ -19,13 +19,17 @@ use std::ops::RangeInclusive;
use std::sync::Arc;
use ansi_term::Colour;
use log::info;
use parking_lot::RwLock;
use host::Host;
use io::*;
use network::{Error, NetworkConfiguration, NetworkProtocolHandler, NonReservedPeerMode};
use network::{NetworkContext, NetworkIoMessage, PeerId, ProtocolId};
use network::ConnectionFilter;
use ethcore_io::{IoContext, IoHandler, IoService};
use network::{
ConnectionFilter, Error, NetworkConfiguration, NetworkContext,
NetworkIoMessage, NetworkProtocolHandler, NonReservedPeerMode, PeerId, ProtocolId,
};
use crate::host::Host;
struct HostHandler {
public_url: RwLock<Option<String>>

View File

@@ -20,20 +20,24 @@ use std::net::SocketAddr;
use std::time::{Duration, Instant};
use ethereum_types::H256;
use log::{debug, trace, warn};
use mio::*;
use mio::deprecated::{EventLoop, Handler};
use mio::tcp::*;
use parity_snappy as snappy;
use rlp::{EMPTY_LIST_RLP, Rlp, RlpStream};
use snappy;
use connection::{Connection, EncryptedConnection, MAX_PAYLOAD_SIZE, Packet};
use handshake::Handshake;
use host::*;
use io::{IoContext, StreamToken};
use ethcore_io::{IoContext, StreamToken};
use network::{DisconnectReason, Error, PeerCapabilityInfo, ProtocolId, SessionInfo};
use network::client_version::ClientVersion;
use network::SessionCapabilityInfo;
use node_table::NodeId;
use crate::{
connection::{Connection, EncryptedConnection, MAX_PAYLOAD_SIZE, Packet},
handshake::Handshake,
host::HostInfo,
node_table::NodeId,
};
// Timeout must be less than (interval - 1).
const PING_TIMEOUT: Duration = Duration::from_secs(60);
@@ -372,7 +376,7 @@ impl Session {
},
PACKET_GET_PEERS => Ok(SessionData::None), //TODO;
PACKET_PEERS => Ok(SessionData::None),
PACKET_USER ... PACKET_LAST => {
PACKET_USER ..= PACKET_LAST => {
let mut i = 0usize;
while packet_id >= self.info.capabilities[i].id_offset + self.info.capabilities[i].packet_count {
i += 1;