LES Peer Info (#4195)
* connected peers function for network service * get LES peer info in sync API * new peer info in RPC
This commit is contained in:
parent
35666f718b
commit
3ff9324ec0
@ -77,7 +77,7 @@ impl<'a> IoContext for NetworkContext<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Basic context for a the protocol.
|
||||
/// Basic context for the protocol.
|
||||
pub trait BasicContext {
|
||||
/// Returns the relevant's peer persistent Id (aka NodeId).
|
||||
fn persistent_peer_id(&self, peer: PeerId) -> Option<NodeId>;
|
||||
|
@ -316,6 +316,12 @@ impl LightProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
/// Attempt to get peer status.
|
||||
pub fn peer_status(&self, peer: &PeerId) -> Option<Status> {
|
||||
self.peers.read().get(&peer)
|
||||
.map(|peer| peer.lock().status.clone())
|
||||
}
|
||||
|
||||
/// Check the maximum amount of requests of a specific type
|
||||
/// which a peer would be able to serve. Returns zero if the
|
||||
/// peer is unknown or has no buffer flow parameters.
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use util::{H256, RwLock};
|
||||
use ethsync::{SyncProvider, SyncStatus, SyncState, PeerInfo, TransactionStats};
|
||||
use ethsync::{SyncProvider, EthProtocolInfo, SyncStatus, SyncState, PeerInfo, TransactionStats};
|
||||
|
||||
/// TestSyncProvider config.
|
||||
pub struct Config {
|
||||
@ -78,9 +78,12 @@ impl SyncProvider for TestSyncProvider {
|
||||
capabilities: vec!["eth/62".to_owned(), "eth/63".to_owned()],
|
||||
remote_address: "127.0.0.1:7777".to_owned(),
|
||||
local_address: "127.0.0.1:8888".to_owned(),
|
||||
eth_version: 62,
|
||||
eth_difficulty: Some(40.into()),
|
||||
eth_head: 50.into()
|
||||
eth_info: Some(EthProtocolInfo {
|
||||
version: 62,
|
||||
difficulty: Some(40.into()),
|
||||
head: 50.into(),
|
||||
}),
|
||||
les_info: None,
|
||||
},
|
||||
PeerInfo {
|
||||
id: None,
|
||||
@ -88,9 +91,12 @@ impl SyncProvider for TestSyncProvider {
|
||||
capabilities: vec!["eth/63".to_owned(), "eth/64".to_owned()],
|
||||
remote_address: "Handshake".to_owned(),
|
||||
local_address: "127.0.0.1:3333".to_owned(),
|
||||
eth_version: 64,
|
||||
eth_difficulty: None,
|
||||
eth_head: 60.into()
|
||||
eth_info: Some(EthProtocolInfo {
|
||||
version: 64,
|
||||
difficulty: None,
|
||||
head: 60.into()
|
||||
}),
|
||||
les_info: None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -265,7 +265,7 @@ fn rpc_parity_net_peers() {
|
||||
let io = deps.default_client();
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_netPeers", "params":[], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":{"active":0,"connected":120,"max":50,"peers":[{"caps":["eth/62","eth/63"],"id":"node1","name":"Parity/1","network":{"localAddress":"127.0.0.1:8888","remoteAddress":"127.0.0.1:7777"},"protocols":{"eth":{"difficulty":"0x28","head":"0000000000000000000000000000000000000000000000000000000000000032","version":62}}},{"caps":["eth/63","eth/64"],"id":null,"name":"Parity/2","network":{"localAddress":"127.0.0.1:3333","remoteAddress":"Handshake"},"protocols":{"eth":{"difficulty":null,"head":"000000000000000000000000000000000000000000000000000000000000003c","version":64}}}]},"id":1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":{"active":0,"connected":120,"max":50,"peers":[{"caps":["eth/62","eth/63"],"id":"node1","name":"Parity/1","network":{"localAddress":"127.0.0.1:8888","remoteAddress":"127.0.0.1:7777"},"protocols":{"eth":{"difficulty":"0x28","head":"0000000000000000000000000000000000000000000000000000000000000032","version":62},"les":null}},{"caps":["eth/63","eth/64"],"id":null,"name":"Parity/2","network":{"localAddress":"127.0.0.1:3333","remoteAddress":"Handshake"},"protocols":{"eth":{"difficulty":null,"head":"000000000000000000000000000000000000000000000000000000000000003c","version":64},"les":null}}]},"id":1}"#;
|
||||
|
||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||
}
|
||||
|
@ -50,8 +50,8 @@ pub use self::hash::{H64, H160, H256, H512, H520, H2048};
|
||||
pub use self::index::Index;
|
||||
pub use self::log::Log;
|
||||
pub use self::sync::{
|
||||
SyncStatus, SyncInfo, Peers, PeerInfo, PeerNetworkInfo, PeerProtocolsInfo, PeerEthereumProtocolInfo,
|
||||
TransactionStats, ChainStatus
|
||||
SyncStatus, SyncInfo, Peers, PeerInfo, PeerNetworkInfo, PeerProtocolsInfo,
|
||||
TransactionStats, ChainStatus, EthProtocolInfo, LesProtocolInfo,
|
||||
};
|
||||
pub use self::transaction::{Transaction, RichRawTransaction, LocalTransactionStatus};
|
||||
pub use self::transaction_request::TransactionRequest;
|
||||
|
@ -15,7 +15,7 @@
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use ethsync::{PeerInfo as SyncPeerInfo, TransactionStats as SyncTransactionStats};
|
||||
use ethsync::{self, PeerInfo as SyncPeerInfo, TransactionStats as SyncTransactionStats};
|
||||
use serde::{Serialize, Serializer};
|
||||
use v1::types::{U256, H512};
|
||||
|
||||
@ -82,12 +82,14 @@ pub struct PeerNetworkInfo {
|
||||
#[derive(Default, Debug, Serialize)]
|
||||
pub struct PeerProtocolsInfo {
|
||||
/// Ethereum protocol information
|
||||
pub eth: Option<PeerEthereumProtocolInfo>,
|
||||
pub eth: Option<EthProtocolInfo>,
|
||||
/// LES protocol information.
|
||||
pub les: Option<LesProtocolInfo>,
|
||||
}
|
||||
|
||||
/// Peer Ethereum protocol information
|
||||
#[derive(Default, Debug, Serialize)]
|
||||
pub struct PeerEthereumProtocolInfo {
|
||||
pub struct EthProtocolInfo {
|
||||
/// Negotiated ethereum protocol version
|
||||
pub version: u32,
|
||||
/// Peer total difficulty if known
|
||||
@ -96,6 +98,37 @@ pub struct PeerEthereumProtocolInfo {
|
||||
pub head: String,
|
||||
}
|
||||
|
||||
impl From<ethsync::EthProtocolInfo> for EthProtocolInfo {
|
||||
fn from(info: ethsync::EthProtocolInfo) -> Self {
|
||||
EthProtocolInfo {
|
||||
version: info.version,
|
||||
difficulty: info.difficulty.map(Into::into),
|
||||
head: info.head.hex(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Peer LES protocol information
|
||||
#[derive(Default, Debug, Serialize)]
|
||||
pub struct LesProtocolInfo {
|
||||
/// Negotiated LES protocol version
|
||||
pub version: u32,
|
||||
/// Peer total difficulty
|
||||
pub difficulty: U256,
|
||||
/// SHA3 of peer best block hash
|
||||
pub head: String,
|
||||
}
|
||||
|
||||
impl From<ethsync::LesProtocolInfo> for LesProtocolInfo {
|
||||
fn from(info: ethsync::LesProtocolInfo) -> Self {
|
||||
LesProtocolInfo {
|
||||
version: info.version,
|
||||
difficulty: info.difficulty.into(),
|
||||
head: info.head.hex(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Sync status
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum SyncStatus {
|
||||
@ -137,11 +170,8 @@ impl From<SyncPeerInfo> for PeerInfo {
|
||||
local_address: p.local_address,
|
||||
},
|
||||
protocols: PeerProtocolsInfo {
|
||||
eth: Some(PeerEthereumProtocolInfo {
|
||||
version: p.eth_version,
|
||||
difficulty: p.eth_difficulty.map(|d| d.into()),
|
||||
head: p.eth_head.hex(),
|
||||
})
|
||||
eth: p.eth_info.map(Into::into),
|
||||
les: p.les_info.map(Into::into),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ use parking_lot::RwLock;
|
||||
use chain::{ETH_PACKET_COUNT, SNAPSHOT_SYNC_PACKET_COUNT};
|
||||
use light::client::LightChainClient;
|
||||
use light::Provider;
|
||||
use light::net::{LightProtocol, Params as LightParams, Capabilities, Handler as LightHandler, EventContext};
|
||||
use light::net::{self as light_net, LightProtocol, Params as LightParams, Capabilities, Handler as LightHandler, EventContext};
|
||||
|
||||
/// Parity sync protocol
|
||||
pub const WARP_SYNC_PROTOCOL_ID: ProtocolId = *b"par";
|
||||
@ -123,12 +123,44 @@ pub struct PeerInfo {
|
||||
pub remote_address: String,
|
||||
/// Local endpoint address
|
||||
pub local_address: String,
|
||||
/// Ethereum protocol version
|
||||
pub eth_version: u32,
|
||||
/// Eth protocol info.
|
||||
pub eth_info: Option<EthProtocolInfo>,
|
||||
/// Light protocol info.
|
||||
pub les_info: Option<LesProtocolInfo>,
|
||||
}
|
||||
|
||||
/// Ethereum protocol info.
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "ipc", derive(Binary))]
|
||||
pub struct EthProtocolInfo {
|
||||
/// Protocol version
|
||||
pub version: u32,
|
||||
/// SHA3 of peer best block hash
|
||||
pub eth_head: H256,
|
||||
pub head: H256,
|
||||
/// Peer total difficulty if known
|
||||
pub eth_difficulty: Option<U256>,
|
||||
pub difficulty: Option<U256>,
|
||||
}
|
||||
|
||||
/// LES protocol info.
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "ipc", derive(Binary))]
|
||||
pub struct LesProtocolInfo {
|
||||
/// Protocol version
|
||||
pub version: u32,
|
||||
/// SHA3 of peer best block hash
|
||||
pub head: H256,
|
||||
/// Peer total difficulty if known
|
||||
pub difficulty: U256,
|
||||
}
|
||||
|
||||
impl From<light_net::Status> for LesProtocolInfo {
|
||||
fn from(status: light_net::Status) -> Self {
|
||||
LesProtocolInfo {
|
||||
version: status.protocol_version,
|
||||
head: status.head_hash,
|
||||
difficulty: status.head_td,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// EthSync initialization parameters.
|
||||
@ -214,11 +246,28 @@ impl SyncProvider for EthSync {
|
||||
|
||||
/// Get sync peers
|
||||
fn peers(&self) -> Vec<PeerInfo> {
|
||||
// TODO: [rob] LES peers/peer info
|
||||
self.network.with_context_eval(self.subprotocol_name, |context| {
|
||||
let sync_io = NetSyncIo::new(context, &*self.eth_handler.chain, &*self.eth_handler.snapshot_service, &self.eth_handler.overlay);
|
||||
self.eth_handler.sync.write().peers(&sync_io)
|
||||
}).unwrap_or(Vec::new())
|
||||
self.network.with_context_eval(self.subprotocol_name, |ctx| {
|
||||
let peer_ids = self.network.connected_peers();
|
||||
let eth_sync = self.eth_handler.sync.read();
|
||||
let light_proto = self.light_proto.as_ref();
|
||||
|
||||
peer_ids.into_iter().filter_map(|peer_id| {
|
||||
let session_info = match ctx.session_info(peer_id) {
|
||||
None => return None,
|
||||
Some(info) => info,
|
||||
};
|
||||
|
||||
Some(PeerInfo {
|
||||
id: session_info.id.map(|id| id.hex()),
|
||||
client_version: session_info.client_version,
|
||||
capabilities: session_info.peer_capabilities.into_iter().map(|c| c.to_string()).collect(),
|
||||
remote_address: session_info.remote_address,
|
||||
local_address: session_info.local_address,
|
||||
eth_info: eth_sync.peer_info(&peer_id),
|
||||
les_info: light_proto.as_ref().and_then(|lp| lp.peer_status(&peer_id)).map(Into::into),
|
||||
})
|
||||
}).collect()
|
||||
}).unwrap_or_else(Vec::new)
|
||||
}
|
||||
|
||||
fn enode(&self) -> Option<String> {
|
||||
|
@ -102,7 +102,7 @@ use super::SyncConfig;
|
||||
use block_sync::{BlockDownloader, BlockRequest, BlockDownloaderImportError as DownloaderImportError, DownloadAction};
|
||||
use rand::Rng;
|
||||
use snapshot::{Snapshot, ChunkType};
|
||||
use api::{PeerInfo as PeerInfoDigest, WARP_SYNC_PROTOCOL_ID};
|
||||
use api::{EthProtocolInfo as PeerInfoDigest, WARP_SYNC_PROTOCOL_ID};
|
||||
use transactions_stats::{TransactionsStats, Stats as TransactionStats};
|
||||
|
||||
known_heap_size!(0, PeerInfo);
|
||||
@ -431,22 +431,14 @@ impl ChainSync {
|
||||
}
|
||||
|
||||
/// Returns information on peers connections
|
||||
pub fn peers(&self, io: &SyncIo) -> Vec<PeerInfoDigest> {
|
||||
self.peers.iter()
|
||||
.filter_map(|(&peer_id, peer_data)|
|
||||
io.peer_session_info(peer_id).map(|session_info|
|
||||
PeerInfoDigest {
|
||||
id: session_info.id.map(|id| id.hex()),
|
||||
client_version: session_info.client_version,
|
||||
capabilities: session_info.peer_capabilities.into_iter().map(|c| c.to_string()).collect(),
|
||||
remote_address: session_info.remote_address,
|
||||
local_address: session_info.local_address,
|
||||
eth_version: peer_data.protocol_version as u32,
|
||||
eth_difficulty: peer_data.difficulty,
|
||||
eth_head: peer_data.latest_hash,
|
||||
})
|
||||
)
|
||||
.collect()
|
||||
pub fn peer_info(&self, peer_id: &PeerId) -> Option<PeerInfoDigest> {
|
||||
self.peers.get(peer_id).map(|peer_data| {
|
||||
PeerInfoDigest {
|
||||
version: peer_data.protocol_version as u32,
|
||||
difficulty: peer_data.difficulty,
|
||||
head: peer_data.latest_hash,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns transactions propagation statistics
|
||||
|
@ -75,7 +75,7 @@ mod api;
|
||||
pub use api::{
|
||||
EthSync, Params, SyncProvider, ManageNetwork, SyncConfig,
|
||||
ServiceConfiguration, NetworkConfiguration, PeerInfo, AllowIP, TransactionStats,
|
||||
LightSync, LightSyncParams,
|
||||
LightSync, LightSyncParams, LesProtocolInfo, EthProtocolInfo,
|
||||
};
|
||||
pub use chain::{SyncStatus, SyncState};
|
||||
pub use network::{is_valid_node_url, NonReservedPeerMode, NetworkError};
|
||||
|
@ -542,6 +542,20 @@ impl Host {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get all connected peers.
|
||||
pub fn connected_peers(&self) -> Vec<PeerId> {
|
||||
let sessions = self.sessions.read();
|
||||
let sessions = &*sessions;
|
||||
|
||||
let mut peers = Vec::with_capacity(sessions.count());
|
||||
for i in (0..MAX_SESSIONS).map(|x| x + FIRST_SESSION) {
|
||||
if sessions.get(i).is_some() {
|
||||
peers.push(i);
|
||||
}
|
||||
}
|
||||
peers
|
||||
}
|
||||
|
||||
fn init_public_interface(&self, io: &IoContext<NetworkIoMessage>) -> Result<(), NetworkError> {
|
||||
if self.info.read().public_endpoint.is_some() {
|
||||
return Ok(());
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
use {NetworkProtocolHandler, NetworkConfiguration, NonReservedPeerMode};
|
||||
use error::NetworkError;
|
||||
use host::{Host, NetworkContext, NetworkIoMessage, ProtocolId};
|
||||
use host::{Host, NetworkContext, NetworkIoMessage, PeerId, ProtocolId};
|
||||
use stats::NetworkStats;
|
||||
use io::*;
|
||||
use parking_lot::RwLock;
|
||||
@ -142,6 +142,11 @@ impl NetworkService {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get a list of all connected peers by id.
|
||||
pub fn connected_peers(&self) -> Vec<PeerId> {
|
||||
self.host.read().as_ref().map(|h| h.connected_peers()).unwrap_or_else(Vec::new)
|
||||
}
|
||||
|
||||
/// Try to add a reserved peer.
|
||||
pub fn add_reserved_peer(&self, peer: &str) -> Result<(), NetworkError> {
|
||||
let host = self.host.read();
|
||||
|
Loading…
Reference in New Issue
Block a user