2016-12-11 19:30:54 +01:00
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
2016-07-14 12:07:33 +02:00
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std ::sync ::Arc ;
2016-11-16 13:37:21 +01:00
use std ::collections ::{ HashMap , BTreeMap } ;
2016-10-25 15:55:53 +02:00
use std ::io ;
2016-10-18 18:16:00 +02:00
use util ::Bytes ;
2016-10-24 16:24:35 +02:00
use network ::{ NetworkProtocolHandler , NetworkService , NetworkContext , PeerId , ProtocolId ,
2016-10-24 18:25:27 +02:00
NetworkConfiguration as BasicNetworkConfiguration , NonReservedPeerMode , NetworkError ,
AllowIP as NetworkAllowIP } ;
2016-11-16 13:37:21 +01:00
use util ::{ U256 , H256 , H512 } ;
2016-08-05 10:32:04 +02:00
use io ::{ TimerToken } ;
2016-07-16 19:09:14 +02:00
use ethcore ::client ::{ BlockChainClient , ChainNotify } ;
2016-09-06 15:31:13 +02:00
use ethcore ::snapshot ::SnapshotService ;
2016-07-27 21:38:22 +02:00
use ethcore ::header ::BlockNumber ;
2016-08-05 10:32:04 +02:00
use sync_io ::NetSyncIo ;
2016-07-14 12:07:33 +02:00
use chain ::{ ChainSync , SyncStatus } ;
use std ::net ::{ SocketAddr , AddrParseError } ;
use ipc ::{ BinaryConvertable , BinaryConvertError , IpcConfig } ;
2016-08-05 10:32:04 +02:00
use std ::str ::FromStr ;
2016-07-14 12:07:33 +02:00
use parking_lot ::RwLock ;
2016-10-24 16:24:35 +02:00
use chain ::{ ETH_PACKET_COUNT , SNAPSHOT_SYNC_PACKET_COUNT } ;
2016-12-16 17:38:16 +01:00
use light ::client ::LightChainClient ;
use light ::Provider ;
2016-12-08 23:21:47 +01:00
use light ::net ::{ LightProtocol , Params as LightParams , Capabilities , Handler as LightHandler , EventContext } ;
2016-10-24 16:24:35 +02:00
2016-11-29 16:54:30 +01:00
/// Parity sync protocol
2016-10-27 13:49:44 +02:00
pub const WARP_SYNC_PROTOCOL_ID : ProtocolId = * b " par " ;
2016-07-14 12:07:33 +02:00
/// Ethereum sync protocol
2016-11-29 16:54:30 +01:00
pub const ETH_PROTOCOL : ProtocolId = * b " eth " ;
2016-12-10 11:01:23 +01:00
/// Ethereum light protocol
pub const LES_PROTOCOL : ProtocolId = * b " les " ;
2016-07-14 12:07:33 +02:00
/// Sync configuration
2016-09-01 12:23:31 +02:00
#[ derive(Debug, Clone, Copy) ]
2016-07-14 12:07:33 +02:00
pub struct SyncConfig {
/// Max blocks to download ahead
pub max_download_ahead_blocks : usize ,
2016-11-22 18:03:35 +01:00
/// Enable ancient block download.
pub download_old_blocks : bool ,
2016-07-14 12:07:33 +02:00
/// Network ID
2016-12-05 15:54:31 +01:00
pub network_id : u64 ,
2016-09-28 14:21:59 +02:00
/// Main "eth" subprotocol name.
pub subprotocol_name : [ u8 ; 3 ] ,
2016-12-08 23:21:47 +01:00
/// Light "les" subprotocol name.
pub light_subprotocol_name : [ u8 ; 3 ] ,
2016-07-27 21:38:22 +02:00
/// Fork block to check
pub fork_block : Option < ( BlockNumber , H256 ) > ,
2016-10-18 18:16:00 +02:00
/// Enable snapshot sync
pub warp_sync : bool ,
2016-12-08 23:21:47 +01:00
/// Enable light client server.
pub serve_light : bool ,
2016-07-14 12:07:33 +02:00
}
impl Default for SyncConfig {
fn default ( ) -> SyncConfig {
SyncConfig {
max_download_ahead_blocks : 20000 ,
2016-11-22 18:03:35 +01:00
download_old_blocks : true ,
2016-11-03 22:22:25 +01:00
network_id : 1 ,
2016-09-30 13:44:52 +02:00
subprotocol_name : ETH_PROTOCOL ,
2016-12-10 11:01:23 +01:00
light_subprotocol_name : LES_PROTOCOL ,
2016-07-27 21:38:22 +02:00
fork_block : None ,
2016-10-29 13:07:06 +02:00
warp_sync : false ,
2016-12-08 23:21:47 +01:00
serve_light : false ,
2016-07-14 12:07:33 +02:00
}
}
}
binary_fixed_size! ( SyncConfig ) ;
binary_fixed_size! ( SyncStatus ) ;
/// Current sync status
pub trait SyncProvider : Send + Sync {
/// Get sync status
fn status ( & self ) -> SyncStatus ;
2016-10-12 20:18:59 +02:00
/// Get peers information
fn peers ( & self ) -> Vec < PeerInfo > ;
2016-11-13 13:52:53 +01:00
2016-11-02 19:43:21 +01:00
/// Get the enode if available.
fn enode ( & self ) -> Option < String > ;
2016-11-16 13:37:21 +01:00
/// Returns propagation count for pending transactions.
fn transactions_stats ( & self ) -> BTreeMap < H256 , TransactionStats > ;
}
/// Transaction stats
2016-12-08 19:52:48 +01:00
#[ derive(Debug) ]
#[ cfg_attr(feature = " ipc " , derive(Binary)) ]
2016-11-16 13:37:21 +01:00
pub struct TransactionStats {
2016-12-08 19:52:48 +01:00
/// Block number where this TX was first seen.
2016-11-16 13:37:21 +01:00
pub first_seen : u64 ,
2016-12-08 19:52:48 +01:00
/// Peers it was propagated to.
2016-11-16 13:37:21 +01:00
pub propagated_to : BTreeMap < H512 , usize > ,
2016-10-12 20:18:59 +02:00
}
/// Peer connection information
2016-12-08 19:52:48 +01:00
#[ derive(Debug) ]
#[ cfg_attr(feature = " ipc " , derive(Binary)) ]
2016-10-12 20:18:59 +02:00
pub struct PeerInfo {
/// Public node id
pub id : Option < String > ,
/// Node client ID
pub client_version : String ,
/// Capabilities
2016-10-24 16:24:35 +02:00
pub capabilities : Vec < String > ,
2016-10-12 20:18:59 +02:00
/// Remote endpoint address
pub remote_address : String ,
/// Local endpoint address
pub local_address : String ,
/// Ethereum protocol version
pub eth_version : u32 ,
/// SHA3 of peer best block hash
pub eth_head : H256 ,
/// Peer total difficulty if known
pub eth_difficulty : Option < U256 > ,
2016-07-14 12:07:33 +02:00
}
2016-12-08 23:21:47 +01:00
/// EthSync initialization parameters.
#[ cfg_attr(feature = " ipc " , derive(Binary)) ]
pub struct Params {
/// Configuration.
pub config : SyncConfig ,
/// Blockchain client.
pub chain : Arc < BlockChainClient > ,
/// Snapshot service.
pub snapshot_service : Arc < SnapshotService > ,
/// Light data provider.
pub provider : Arc < ::light ::Provider > ,
/// Network layer configuration.
pub network_config : NetworkConfiguration ,
}
2016-07-14 12:07:33 +02:00
/// Ethereum network protocol handler
pub struct EthSync {
/// Network service
network : NetworkService ,
2016-12-08 23:21:47 +01:00
/// Main (eth/par) protocol handler
2016-08-15 14:25:57 +02:00
eth_handler : Arc < SyncProtocolHandler > ,
2016-12-10 14:56:41 +01:00
/// Light (les) protocol handler
2016-12-08 23:21:47 +01:00
light_proto : Option < Arc < LightProtocol > > ,
2016-09-28 14:21:59 +02:00
/// The main subprotocol name
subprotocol_name : [ u8 ; 3 ] ,
2016-12-08 23:21:47 +01:00
/// Light subprotocol name.
light_subprotocol_name : [ u8 ; 3 ] ,
2016-07-14 12:07:33 +02:00
}
impl EthSync {
/// Creates and register protocol with the network service
2016-12-08 23:21:47 +01:00
pub fn new ( params : Params ) -> Result < Arc < EthSync > , NetworkError > {
2016-12-10 14:56:41 +01:00
let pruning_info = params . chain . pruning_info ( ) ;
2016-12-08 23:21:47 +01:00
let light_proto = match params . config . serve_light {
false = > None ,
true = > Some ( {
let light_params = LightParams {
network_id : params . config . network_id ,
flow_params : Default ::default ( ) ,
capabilities : Capabilities {
serve_headers : true ,
serve_chain_since : Some ( pruning_info . earliest_chain ) ,
serve_state_since : Some ( pruning_info . earliest_state ) ,
tx_relay : true ,
} ,
} ;
let mut light_proto = LightProtocol ::new ( params . provider , light_params ) ;
light_proto . add_handler ( Box ::new ( TxRelay ( params . chain . clone ( ) ) ) ) ;
Arc ::new ( light_proto )
} )
} ;
let chain_sync = ChainSync ::new ( params . config , & * params . chain ) ;
2016-12-27 12:53:56 +01:00
let service = NetworkService ::new ( params . network_config . clone ( ) . into_basic ( ) ? ) ? ;
2016-12-08 23:21:47 +01:00
let sync = Arc ::new ( EthSync {
2016-07-14 12:07:33 +02:00
network : service ,
2016-11-07 12:34:45 +01:00
eth_handler : Arc ::new ( SyncProtocolHandler {
2016-10-18 18:16:00 +02:00
sync : RwLock ::new ( chain_sync ) ,
2016-12-08 23:21:47 +01:00
chain : params . chain ,
snapshot_service : params . snapshot_service ,
2016-11-07 12:34:45 +01:00
overlay : RwLock ::new ( HashMap ::new ( ) ) ,
} ) ,
2016-12-08 23:21:47 +01:00
light_proto : light_proto ,
subprotocol_name : params . config . subprotocol_name ,
light_subprotocol_name : params . config . light_subprotocol_name ,
2016-07-14 12:07:33 +02:00
} ) ;
Ok ( sync )
}
}
2016-12-08 19:52:48 +01:00
#[ cfg_attr(feature = " ipc " , ipc(client_ident= " SyncClient " )) ]
2016-07-14 12:07:33 +02:00
impl SyncProvider for EthSync {
/// Get sync status
fn status ( & self ) -> SyncStatus {
2016-08-15 14:25:57 +02:00
self . eth_handler . sync . write ( ) . status ( )
2016-07-14 12:07:33 +02:00
}
2016-10-12 20:18:59 +02:00
/// Get sync peers
fn peers ( & self ) -> Vec < PeerInfo > {
2016-12-08 23:21:47 +01:00
// TODO: [rob] LES peers/peer info
2016-10-12 20:18:59 +02:00
self . network . with_context_eval ( self . subprotocol_name , | context | {
2016-11-07 12:34:45 +01:00
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 )
2016-10-12 20:18:59 +02:00
} ) . unwrap_or ( Vec ::new ( ) )
}
2016-11-02 19:43:21 +01:00
fn enode ( & self ) -> Option < String > {
self . network . external_url ( )
}
2016-11-16 13:37:21 +01:00
fn transactions_stats ( & self ) -> BTreeMap < H256 , TransactionStats > {
2016-11-25 12:36:25 +01:00
let sync = self . eth_handler . sync . read ( ) ;
2016-11-16 13:37:21 +01:00
sync . transactions_stats ( )
. iter ( )
. map ( | ( hash , stats ) | ( * hash , stats . into ( ) ) )
. collect ( )
}
2016-07-14 12:07:33 +02:00
}
struct SyncProtocolHandler {
2016-08-15 14:25:57 +02:00
/// Shared blockchain client.
2016-07-15 15:32:29 +02:00
chain : Arc < BlockChainClient > ,
2016-09-06 15:31:13 +02:00
/// Shared snapshot service.
snapshot_service : Arc < SnapshotService > ,
2016-07-14 12:07:33 +02:00
/// Sync strategy
sync : RwLock < ChainSync > ,
2016-10-18 18:16:00 +02:00
/// Chain overlay used to cache data such as fork block.
overlay : RwLock < HashMap < BlockNumber , Bytes > > ,
2016-07-14 12:07:33 +02:00
}
impl NetworkProtocolHandler for SyncProtocolHandler {
fn initialize ( & self , io : & NetworkContext ) {
2016-10-24 16:24:35 +02:00
if io . subprotocol_name ( ) ! = WARP_SYNC_PROTOCOL_ID {
io . register_timer ( 0 , 1000 ) . expect ( " Error registering sync timer " ) ;
}
2016-07-14 12:07:33 +02:00
}
fn read ( & self , io : & NetworkContext , peer : & PeerId , packet_id : u8 , data : & [ u8 ] ) {
2016-10-18 18:16:00 +02:00
ChainSync ::dispatch_packet ( & self . sync , & mut NetSyncIo ::new ( io , & * self . chain , & * self . snapshot_service , & self . overlay ) , * peer , packet_id , data ) ;
2016-07-14 12:07:33 +02:00
}
fn connected ( & self , io : & NetworkContext , peer : & PeerId ) {
2016-10-24 16:24:35 +02:00
// If warp protocol is supported only allow warp handshake
let warp_protocol = io . protocol_version ( WARP_SYNC_PROTOCOL_ID , * peer ) . unwrap_or ( 0 ) ! = 0 ;
let warp_context = io . subprotocol_name ( ) = = WARP_SYNC_PROTOCOL_ID ;
if warp_protocol = = warp_context {
self . sync . write ( ) . on_peer_connected ( & mut NetSyncIo ::new ( io , & * self . chain , & * self . snapshot_service , & self . overlay ) , * peer ) ;
}
2016-07-14 12:07:33 +02:00
}
fn disconnected ( & self , io : & NetworkContext , peer : & PeerId ) {
2016-10-24 16:24:35 +02:00
if io . subprotocol_name ( ) ! = WARP_SYNC_PROTOCOL_ID {
self . sync . write ( ) . on_peer_aborting ( & mut NetSyncIo ::new ( io , & * self . chain , & * self . snapshot_service , & self . overlay ) , * peer ) ;
}
2016-07-14 12:07:33 +02:00
}
fn timeout ( & self , io : & NetworkContext , _timer : TimerToken ) {
2016-10-18 18:16:00 +02:00
self . sync . write ( ) . maintain_peers ( & mut NetSyncIo ::new ( io , & * self . chain , & * self . snapshot_service , & self . overlay ) ) ;
self . sync . write ( ) . maintain_sync ( & mut NetSyncIo ::new ( io , & * self . chain , & * self . snapshot_service , & self . overlay ) ) ;
self . sync . write ( ) . propagate_new_transactions ( & mut NetSyncIo ::new ( io , & * self . chain , & * self . snapshot_service , & self . overlay ) ) ;
2016-07-14 12:07:33 +02:00
}
}
impl ChainNotify for EthSync {
fn new_blocks ( & self ,
imported : Vec < H256 > ,
invalid : Vec < H256 > ,
enacted : Vec < H256 > ,
retracted : Vec < H256 > ,
2016-07-20 12:36:20 +02:00
sealed : Vec < H256 > ,
2016-12-08 12:03:34 +01:00
proposed : Vec < Bytes > ,
2016-07-20 12:36:20 +02:00
_duration : u64 )
2016-07-14 12:07:33 +02:00
{
2016-12-08 23:57:09 +01:00
use light ::net ::Announcement ;
2016-09-28 14:21:59 +02:00
self . network . with_context ( self . subprotocol_name , | context | {
2016-11-07 12:34:45 +01:00
let mut sync_io = NetSyncIo ::new ( context , & * self . eth_handler . chain , & * self . eth_handler . snapshot_service , & self . eth_handler . overlay ) ;
2016-08-15 14:25:57 +02:00
self . eth_handler . sync . write ( ) . chain_new_blocks (
2016-07-14 12:07:33 +02:00
& mut sync_io ,
& imported ,
& invalid ,
& enacted ,
& retracted ,
2016-12-08 12:03:34 +01:00
& sealed ,
& proposed ) ;
2016-07-14 12:07:33 +02:00
} ) ;
2016-12-08 23:57:09 +01:00
self . network . with_context ( self . light_subprotocol_name , | context | {
let light_proto = match self . light_proto . as_ref ( ) {
Some ( lp ) = > lp ,
None = > return ,
} ;
2016-12-16 17:38:16 +01:00
2016-12-10 11:01:23 +01:00
let chain_info = self . eth_handler . chain . chain_info ( ) ;
2016-12-08 23:57:09 +01:00
light_proto . make_announcement ( context , Announcement {
head_hash : chain_info . best_block_hash ,
head_num : chain_info . best_block_number ,
head_td : chain_info . total_difficulty ,
reorg_depth : 0 , // recalculated on a per-peer basis.
serve_headers : false , // these fields consist of _changes_ in capability.
serve_state_since : None ,
serve_chain_since : None ,
tx_relay : false ,
} )
} )
2016-07-14 12:07:33 +02:00
}
fn start ( & self ) {
2016-10-25 15:55:53 +02:00
match self . network . start ( ) {
Err ( NetworkError ::StdIo ( ref e ) ) if e . kind ( ) = = io ::ErrorKind ::AddrInUse = > warn! ( " Network port {:?} is already in use, make sure that another instance of an Ethereum client is not running or change the port using the --port option. " , self . network . config ( ) . listen_address . expect ( " Listen address is not set. " ) ) ,
Err ( err ) = > warn! ( " Error starting network: {} " , err ) ,
_ = > { } ,
}
2016-11-07 12:34:45 +01:00
self . network . register_protocol ( self . eth_handler . clone ( ) , self . subprotocol_name , ETH_PACKET_COUNT , & [ 62 u8 , 63 u8 ] )
2016-07-14 12:07:33 +02:00
. unwrap_or_else ( | e | warn! ( " Error registering ethereum protocol: {:?} " , e ) ) ;
2016-10-24 16:24:35 +02:00
// register the warp sync subprotocol
2016-11-30 16:47:20 +01:00
self . network . register_protocol ( self . eth_handler . clone ( ) , WARP_SYNC_PROTOCOL_ID , SNAPSHOT_SYNC_PACKET_COUNT , & [ 1 u8 , 2 u8 ] )
2016-10-24 16:24:35 +02:00
. unwrap_or_else ( | e | warn! ( " Error registering snapshot sync protocol: {:?} " , e ) ) ;
2016-12-10 14:56:41 +01:00
2016-12-08 23:21:47 +01:00
// register the light protocol.
if let Some ( light_proto ) = self . light_proto . as_ref ( ) . map ( | x | x . clone ( ) ) {
self . network . register_protocol ( light_proto , self . light_subprotocol_name , ::light ::net ::PACKET_COUNT , ::light ::net ::PROTOCOL_VERSIONS )
. unwrap_or_else ( | e | warn! ( " Error registering light client protocol: {:?} " , e ) ) ;
}
2016-07-14 12:07:33 +02:00
}
fn stop ( & self ) {
2016-11-16 14:13:21 +01:00
self . eth_handler . snapshot_service . abort_restore ( ) ;
2016-07-14 12:07:33 +02:00
self . network . stop ( ) . unwrap_or_else ( | e | warn! ( " Error stopping network: {:?} " , e ) ) ;
}
2016-08-15 14:25:57 +02:00
2016-08-26 13:16:56 +02:00
fn broadcast ( & self , message : Vec < u8 > ) {
2016-12-01 15:48:56 +01:00
self . network . with_context ( WARP_SYNC_PROTOCOL_ID , | context | {
2016-11-07 12:34:45 +01:00
let mut sync_io = NetSyncIo ::new ( context , & * self . eth_handler . chain , & * self . eth_handler . snapshot_service , & self . eth_handler . overlay ) ;
2016-11-29 16:54:30 +01:00
self . eth_handler . sync . write ( ) . propagate_consensus_packet ( & mut sync_io , message . clone ( ) ) ;
2016-08-15 14:25:57 +02:00
} ) ;
}
2016-12-12 21:28:46 +01:00
2016-12-10 21:22:19 +01:00
fn transactions_received ( & self , hashes : Vec < H256 > , peer_id : PeerId ) {
2016-12-12 21:28:46 +01:00
let mut sync = self . eth_handler . sync . write ( ) ;
2016-12-10 21:22:19 +01:00
sync . transactions_received ( hashes , peer_id ) ;
2016-12-10 14:56:41 +01:00
}
2016-07-14 12:07:33 +02:00
}
2016-12-08 23:21:47 +01:00
/// LES event handler.
/// Simply queues transactions from light client peers.
struct TxRelay ( Arc < BlockChainClient > ) ;
impl LightHandler for TxRelay {
fn on_transactions ( & self , ctx : & EventContext , relay : & [ ::ethcore ::transaction ::SignedTransaction ] ) {
trace! ( target : " les " , " Relaying {} transactions from peer {} " , relay . len ( ) , ctx . peer ( ) ) ;
2016-12-10 21:22:19 +01:00
self . 0. queue_transactions ( relay . iter ( ) . map ( | tx | ::rlp ::encode ( tx ) . to_vec ( ) ) . collect ( ) , ctx . peer ( ) )
2016-12-08 23:21:47 +01:00
}
}
2016-07-16 19:24:45 +02:00
impl IpcConfig for ManageNetwork { }
impl IpcConfig for SyncProvider { }
2016-07-14 12:07:33 +02:00
/// Trait for managing network
pub trait ManageNetwork : Send + Sync {
/// Set to allow unreserved peers to connect
fn accept_unreserved_peers ( & self ) ;
/// Set to deny unreserved peers to connect
fn deny_unreserved_peers ( & self ) ;
/// Remove reservation for the peer
fn remove_reserved_peer ( & self , peer : String ) -> Result < ( ) , String > ;
/// Add reserved peer
fn add_reserved_peer ( & self , peer : String ) -> Result < ( ) , String > ;
/// Start network
fn start_network ( & self ) ;
/// Stop network
fn stop_network ( & self ) ;
/// Query the current configuration of the network
fn network_config ( & self ) -> NetworkConfiguration ;
}
2016-12-08 19:52:48 +01:00
#[ cfg_attr(feature = " ipc " , ipc(client_ident= " NetworkManagerClient " )) ]
2016-07-14 12:07:33 +02:00
impl ManageNetwork for EthSync {
fn accept_unreserved_peers ( & self ) {
self . network . set_non_reserved_mode ( NonReservedPeerMode ::Accept ) ;
}
fn deny_unreserved_peers ( & self ) {
self . network . set_non_reserved_mode ( NonReservedPeerMode ::Deny ) ;
}
fn remove_reserved_peer ( & self , peer : String ) -> Result < ( ) , String > {
self . network . remove_reserved_peer ( & peer ) . map_err ( | e | format! ( " {:?} " , e ) )
}
fn add_reserved_peer ( & self , peer : String ) -> Result < ( ) , String > {
self . network . add_reserved_peer ( & peer ) . map_err ( | e | format! ( " {:?} " , e ) )
}
fn start_network ( & self ) {
self . start ( ) ;
}
fn stop_network ( & self ) {
2016-09-28 14:21:59 +02:00
self . network . with_context ( self . subprotocol_name , | context | {
2016-11-07 12:34:45 +01:00
let mut sync_io = NetSyncIo ::new ( context , & * self . eth_handler . chain , & * self . eth_handler . snapshot_service , & self . eth_handler . overlay ) ;
2016-08-15 14:25:57 +02:00
self . eth_handler . sync . write ( ) . abort ( & mut sync_io ) ;
2016-07-14 12:07:33 +02:00
} ) ;
2016-12-08 23:21:47 +01:00
if let Some ( light_proto ) = self . light_proto . as_ref ( ) {
light_proto . abort ( ) ;
}
2016-07-14 12:07:33 +02:00
self . stop ( ) ;
}
fn network_config ( & self ) -> NetworkConfiguration {
NetworkConfiguration ::from ( self . network . config ( ) . clone ( ) )
}
}
2016-10-24 18:25:27 +02:00
/// IP fiter
2016-12-08 19:52:48 +01:00
#[ derive(Clone, Debug, PartialEq, Eq) ]
2016-12-21 15:09:35 +01:00
#[ cfg_attr(feature = " ipc " , binary) ]
2016-10-24 18:25:27 +02:00
pub enum AllowIP {
/// Connect to any address
All ,
/// Connect to private network only
Private ,
/// Connect to public network only
Public ,
}
impl AllowIP {
/// Attempt to parse the peer mode from a string.
pub fn parse ( s : & str ) -> Option < Self > {
match s {
" all " = > Some ( AllowIP ::All ) ,
" private " = > Some ( AllowIP ::Private ) ,
" public " = > Some ( AllowIP ::Public ) ,
_ = > None ,
}
}
}
2016-12-08 19:52:48 +01:00
#[ derive(Debug, Clone, PartialEq, Eq) ]
2016-12-21 15:09:35 +01:00
#[ cfg_attr(feature = " ipc " , binary) ]
2016-07-14 12:07:33 +02:00
/// Network service configuration
pub struct NetworkConfiguration {
2016-08-21 11:23:47 +02:00
/// Directory path to store general network configuration. None means nothing will be saved
2016-07-14 12:07:33 +02:00
pub config_path : Option < String > ,
2016-08-21 11:23:47 +02:00
/// Directory path to store network-specific configuration. None means nothing will be saved
pub net_config_path : Option < String > ,
2016-07-14 12:07:33 +02:00
/// IP address to listen for incoming connections. Listen to all connections by default
pub listen_address : Option < String > ,
/// IP address to advertise. Detected automatically if none.
pub public_address : Option < String > ,
/// Port for UDP connections, same as TCP by default
pub udp_port : Option < u16 > ,
/// Enable NAT configuration
pub nat_enabled : bool ,
/// Enable discovery
pub discovery_enabled : bool ,
/// List of initial node addresses
pub boot_nodes : Vec < String > ,
/// Use provided node key instead of default
2016-08-24 18:35:21 +02:00
pub use_secret : Option < H256 > ,
2016-07-29 17:30:02 +02:00
/// Max number of connected peers to maintain
pub max_peers : u32 ,
/// Min number of connected peers to maintain
pub min_peers : u32 ,
2016-10-24 18:25:27 +02:00
/// Max pending peers.
pub max_pending_peers : u32 ,
/// Reserved snapshot sync peers.
pub snapshot_peers : u32 ,
2016-07-14 12:07:33 +02:00
/// List of reserved node addresses.
pub reserved_nodes : Vec < String > ,
/// The non-reserved peer mode.
pub allow_non_reserved : bool ,
2016-10-24 18:25:27 +02:00
/// IP Filtering
pub allow_ips : AllowIP ,
2016-07-14 12:07:33 +02:00
}
impl NetworkConfiguration {
2016-12-08 19:52:48 +01:00
/// Create a new default config.
2016-08-05 10:32:04 +02:00
pub fn new ( ) -> Self {
From ::from ( BasicNetworkConfiguration ::new ( ) )
}
2016-12-08 19:52:48 +01:00
/// Create a new local config.
2016-08-05 10:32:04 +02:00
pub fn new_local ( ) -> Self {
From ::from ( BasicNetworkConfiguration ::new_local ( ) )
}
2016-12-08 19:52:48 +01:00
/// Attempt to convert this config into a BasicNetworkConfiguration.
2016-07-14 12:07:33 +02:00
pub fn into_basic ( self ) -> Result < BasicNetworkConfiguration , AddrParseError > {
Ok ( BasicNetworkConfiguration {
config_path : self . config_path ,
2016-08-21 11:23:47 +02:00
net_config_path : self . net_config_path ,
2016-12-27 12:53:56 +01:00
listen_address : match self . listen_address { None = > None , Some ( addr ) = > Some ( SocketAddr ::from_str ( & addr ) ? ) } ,
public_address : match self . public_address { None = > None , Some ( addr ) = > Some ( SocketAddr ::from_str ( & addr ) ? ) } ,
2016-07-14 12:07:33 +02:00
udp_port : self . udp_port ,
nat_enabled : self . nat_enabled ,
discovery_enabled : self . discovery_enabled ,
boot_nodes : self . boot_nodes ,
use_secret : self . use_secret ,
2016-07-29 17:30:02 +02:00
max_peers : self . max_peers ,
min_peers : self . min_peers ,
2016-10-24 18:25:27 +02:00
max_handshakes : self . max_pending_peers ,
reserved_protocols : hash_map ! [ WARP_SYNC_PROTOCOL_ID = > self . snapshot_peers ] ,
2016-07-14 12:07:33 +02:00
reserved_nodes : self . reserved_nodes ,
2016-10-24 18:25:27 +02:00
allow_ips : match self . allow_ips {
AllowIP ::All = > NetworkAllowIP ::All ,
AllowIP ::Private = > NetworkAllowIP ::Private ,
AllowIP ::Public = > NetworkAllowIP ::Public ,
} ,
2016-07-14 12:07:33 +02:00
non_reserved_mode : if self . allow_non_reserved { NonReservedPeerMode ::Accept } else { NonReservedPeerMode ::Deny } ,
} )
}
}
impl From < BasicNetworkConfiguration > for NetworkConfiguration {
fn from ( other : BasicNetworkConfiguration ) -> Self {
NetworkConfiguration {
config_path : other . config_path ,
2016-08-21 11:23:47 +02:00
net_config_path : other . net_config_path ,
2016-07-14 12:07:33 +02:00
listen_address : other . listen_address . and_then ( | addr | Some ( format! ( " {} " , addr ) ) ) ,
public_address : other . public_address . and_then ( | addr | Some ( format! ( " {} " , addr ) ) ) ,
udp_port : other . udp_port ,
nat_enabled : other . nat_enabled ,
discovery_enabled : other . discovery_enabled ,
boot_nodes : other . boot_nodes ,
use_secret : other . use_secret ,
2016-07-29 17:30:02 +02:00
max_peers : other . max_peers ,
min_peers : other . min_peers ,
2016-10-24 18:25:27 +02:00
max_pending_peers : other . max_handshakes ,
snapshot_peers : * other . reserved_protocols . get ( & WARP_SYNC_PROTOCOL_ID ) . unwrap_or ( & 0 ) ,
2016-07-14 12:07:33 +02:00
reserved_nodes : other . reserved_nodes ,
2016-10-24 18:25:27 +02:00
allow_ips : match other . allow_ips {
NetworkAllowIP ::All = > AllowIP ::All ,
NetworkAllowIP ::Private = > AllowIP ::Private ,
NetworkAllowIP ::Public = > AllowIP ::Public ,
} ,
2016-07-14 12:07:33 +02:00
allow_non_reserved : match other . non_reserved_mode { NonReservedPeerMode ::Accept = > true , _ = > false } ,
}
}
}
2016-07-20 18:13:56 +02:00
2016-12-08 19:52:48 +01:00
/// Configuration for IPC service.
#[ derive(Debug, Clone) ]
2016-12-21 15:09:35 +01:00
#[ cfg_attr(feature = " ipc " , binary) ]
2016-07-20 18:13:56 +02:00
pub struct ServiceConfiguration {
2016-12-08 19:52:48 +01:00
/// Sync config.
2016-07-20 18:13:56 +02:00
pub sync : SyncConfig ,
2016-12-08 19:52:48 +01:00
/// Network configuration.
2016-07-20 18:13:56 +02:00
pub net : NetworkConfiguration ,
2016-12-08 19:52:48 +01:00
/// IPC path.
2016-08-22 18:41:58 +02:00
pub io_path : String ,
2016-07-20 18:13:56 +02:00
}
2016-12-16 17:38:16 +01:00
/// Configuration for the light sync.
pub struct LightSyncParams < L > {
/// Network configuration.
pub network_config : BasicNetworkConfiguration ,
/// Light client to sync to.
pub client : Arc < L > ,
/// Network ID.
pub network_id : u64 ,
/// Subprotocol name.
pub subprotocol_name : [ u8 ; 3 ] ,
}
/// Service for light synchronization.
pub struct LightSync {
proto : Arc < LightProtocol > ,
network : NetworkService ,
subprotocol_name : [ u8 ; 3 ] ,
}
impl LightSync {
/// Create a new light sync service.
pub fn new < L > ( params : LightSyncParams < L > ) -> Result < Self , NetworkError >
where L : LightChainClient + Provider + 'static
{
use light_sync ::LightSync as SyncHandler ;
// initialize light protocol handler and attach sync module.
let light_proto = {
let light_params = LightParams {
network_id : params . network_id ,
flow_params : Default ::default ( ) , // or `None`?
capabilities : Capabilities {
serve_headers : false ,
serve_chain_since : None ,
serve_state_since : None ,
tx_relay : false ,
} ,
} ;
let mut light_proto = LightProtocol ::new ( params . client . clone ( ) , light_params ) ;
let sync_handler = try ! ( SyncHandler ::new ( params . client . clone ( ) ) ) ;
light_proto . add_handler ( Box ::new ( sync_handler ) ) ;
Arc ::new ( light_proto )
} ;
let service = try ! ( NetworkService ::new ( params . network_config ) ) ;
Ok ( LightSync {
proto : light_proto ,
network : service ,
subprotocol_name : params . subprotocol_name ,
} )
}
}
impl ManageNetwork for LightSync {
fn accept_unreserved_peers ( & self ) {
self . network . set_non_reserved_mode ( NonReservedPeerMode ::Accept ) ;
}
fn deny_unreserved_peers ( & self ) {
self . network . set_non_reserved_mode ( NonReservedPeerMode ::Deny ) ;
}
fn remove_reserved_peer ( & self , peer : String ) -> Result < ( ) , String > {
self . network . remove_reserved_peer ( & peer ) . map_err ( | e | format! ( " {:?} " , e ) )
}
fn add_reserved_peer ( & self , peer : String ) -> Result < ( ) , String > {
self . network . add_reserved_peer ( & peer ) . map_err ( | e | format! ( " {:?} " , e ) )
}
fn start_network ( & self ) {
match self . network . start ( ) {
Err ( NetworkError ::StdIo ( ref e ) ) if e . kind ( ) = = io ::ErrorKind ::AddrInUse = > warn! ( " Network port {:?} is already in use, make sure that another instance of an Ethereum client is not running or change the port using the --port option. " , self . network . config ( ) . listen_address . expect ( " Listen address is not set. " ) ) ,
Err ( err ) = > warn! ( " Error starting network: {} " , err ) ,
_ = > { } ,
}
let light_proto = self . proto . clone ( ) ;
self . network . register_protocol ( light_proto , self . subprotocol_name , ::light ::net ::PACKET_COUNT , ::light ::net ::PROTOCOL_VERSIONS )
. unwrap_or_else ( | e | warn! ( " Error registering light client protocol: {:?} " , e ) ) ;
}
fn stop_network ( & self ) {
self . proto . abort ( ) ;
if let Err ( e ) = self . network . stop ( ) {
warn! ( " Error stopping network: {} " , e ) ;
}
}
fn network_config ( & self ) -> NetworkConfiguration {
NetworkConfiguration ::from ( self . network . config ( ) . clone ( ) )
}
}