2019-01-07 11:33:07 +01:00
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
// This file is part of Parity Ethereum.
2016-07-14 12:07:33 +02:00
2019-01-07 11:33:07 +01:00
// Parity Ethereum is free software: you can redistribute it and/or modify
2016-07-14 12:07:33 +02:00
// 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.
2019-01-07 11:33:07 +01:00
// Parity Ethereum is distributed in the hope that it will be useful,
2016-07-14 12:07:33 +02:00
// 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
2019-01-07 11:33:07 +01:00
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
2016-07-14 12:07:33 +02:00
2018-11-28 11:30:05 +01:00
use std ::sync ::{ Arc , mpsc , atomic } ;
2016-11-16 13:37:21 +01:00
use std ::collections ::{ HashMap , BTreeMap } ;
2016-10-25 15:55:53 +02:00
use std ::io ;
2019-01-22 09:51:40 +01:00
use std ::ops ::RangeInclusive ;
2018-04-14 21:35:58 +02:00
use std ::time ::Duration ;
2017-09-06 20:47:45 +02:00
use bytes ::Bytes ;
2018-05-22 06:34:01 +02:00
use devp2p ::NetworkService ;
2018-06-02 11:05:11 +02:00
use network ::{ NetworkProtocolHandler , NetworkContext , PeerId , ProtocolId ,
2019-06-17 08:44:59 +02:00
NetworkConfiguration as BasicNetworkConfiguration , NonReservedPeerMode , Error ,
2018-05-22 06:34:01 +02:00
ConnectionFilter } ;
2019-02-07 15:27:09 +01:00
use network ::client_version ::ClientVersion ;
2018-08-13 17:53:19 +02:00
use types ::pruning_info ::PruningInfo ;
2018-01-10 13:35:18 +01:00
use ethereum_types ::{ H256 , H512 , U256 } ;
2019-04-02 17:13:55 +02:00
use futures ::sync ::mpsc as futures_mpsc ;
use futures ::Stream ;
2016-08-05 10:32:04 +02:00
use io ::{ TimerToken } ;
2019-02-07 14:34:24 +01:00
use ethkey ::Secret ;
2019-08-15 17:59:22 +02:00
use ethcore ::client ::{ ChainNotify , NewBlocks , ChainMessageType } ;
use client_traits ::BlockChainClient ;
2016-09-06 15:31:13 +02:00
use ethcore ::snapshot ::SnapshotService ;
2019-08-16 14:45:52 +02:00
use ethcore_private_tx ::PrivateStateDB ;
2019-01-04 14:05:46 +01:00
use types ::BlockNumber ;
2016-08-05 10:32:04 +02:00
use sync_io ::NetSyncIo ;
2018-11-28 11:30:05 +01:00
use chain ::{ ChainSyncApi , SyncStatus as EthSyncStatus } ;
2016-07-14 12:07:33 +02:00
use std ::net ::{ SocketAddr , AddrParseError } ;
2016-08-05 10:32:04 +02:00
use std ::str ::FromStr ;
2018-11-28 11:30:05 +01:00
use parking_lot ::{ RwLock , Mutex } ;
2018-05-14 10:09:05 +02:00
use chain ::{ ETH_PROTOCOL_VERSION_63 , ETH_PROTOCOL_VERSION_62 ,
2019-08-16 14:45:52 +02:00
PAR_PROTOCOL_VERSION_1 , PAR_PROTOCOL_VERSION_2 , PAR_PROTOCOL_VERSION_3 , PAR_PROTOCOL_VERSION_4 , SyncState } ;
2019-02-13 09:20:33 +01:00
use chain ::sync_packet ::SyncPacket ::{ PrivateTransactionPacket , SignedPrivateTransactionPacket } ;
2017-02-09 18:42:18 +01:00
use light ::client ::AsLightClient ;
2016-12-16 17:38:16 +01:00
use light ::Provider ;
2018-08-13 17:53:19 +02:00
use light ::net ::{
self as light_net , LightProtocol , Params as LightParams ,
Capabilities , Handler as LightHandler , EventContext , SampleStore ,
} ;
2019-04-02 17:13:55 +02:00
use parity_runtime ::Executor ;
use std ::sync ::atomic ::{ AtomicBool , Ordering } ;
2017-07-28 19:06:39 +02:00
use network ::IpFilter ;
2018-04-09 16:14:33 +02:00
use private_tx ::PrivateTxHandler ;
2019-01-04 14:05:46 +01:00
use types ::transaction ::UnverifiedTransaction ;
2016-10-24 16:24:35 +02:00
2019-02-11 11:33:16 +01:00
use super ::light_sync ::SyncInfo ;
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
2017-03-22 18:32:04 +01:00
pub const LIGHT_PROTOCOL : ProtocolId = * b " pip " ;
2016-07-14 12:07:33 +02:00
2018-03-29 11:20:27 +02:00
/// Determine warp sync status.
2019-06-19 13:54:05 +02:00
#[ derive(Debug, Clone, Copy, PartialEq, Eq, MallocSizeOf) ]
2018-03-29 11:20:27 +02:00
pub enum WarpSync {
/// Warp sync is enabled.
Enabled ,
/// Warp sync is disabled.
Disabled ,
/// Only warp sync is allowed (no regular sync) and only after given block number.
OnlyAndAfter ( BlockNumber ) ,
}
impl WarpSync {
/// Returns true if warp sync is enabled.
pub fn is_enabled ( & self ) -> bool {
match * self {
WarpSync ::Enabled = > true ,
WarpSync ::OnlyAndAfter ( _ ) = > true ,
WarpSync ::Disabled = > false ,
}
}
/// Returns `true` if we are in warp-only mode.
///
/// i.e. we will never fall back to regular sync
/// until given block number is reached by
/// successfuly finding and restoring from a snapshot.
pub fn is_warp_only ( & self ) -> bool {
if let WarpSync ::OnlyAndAfter ( _ ) = * self {
true
} else {
false
}
}
}
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 ] ,
2017-02-02 15:22:38 +01:00
/// Light subprotocol name.
2016-12-08 23:21:47 +01:00
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
2018-03-29 11:20:27 +02:00
pub warp_sync : WarpSync ,
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 ,
2017-02-02 15:22:38 +01:00
light_subprotocol_name : LIGHT_PROTOCOL ,
2016-07-27 21:38:22 +02:00
fork_block : None ,
2018-03-29 11:20:27 +02:00
warp_sync : WarpSync ::Disabled ,
2016-12-08 23:21:47 +01:00
serve_light : false ,
2016-07-14 12:07:33 +02:00
}
}
}
2019-04-02 17:13:55 +02:00
/// receiving end of a futures::mpsc channel
pub type Notification < T > = futures_mpsc ::UnboundedReceiver < T > ;
2016-07-14 12:07:33 +02:00
/// Current sync status
pub trait SyncProvider : Send + Sync {
/// Get sync status
2017-02-17 21:38:43 +01:00
fn status ( & self ) -> EthSyncStatus ;
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
2019-04-02 17:13:55 +02:00
/// gets sync status notifications
fn sync_notification ( & self ) -> Notification < SyncState > ;
2016-11-16 13:37:21 +01:00
/// Returns propagation count for pending transactions.
fn transactions_stats ( & self ) -> BTreeMap < H256 , TransactionStats > ;
2019-04-02 17:13:55 +02:00
/// are we in the middle of a major sync?
fn is_major_syncing ( & self ) -> bool ;
2016-11-16 13:37:21 +01:00
}
/// Transaction stats
2016-12-08 19:52:48 +01:00
#[ derive(Debug) ]
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) ]
2016-10-12 20:18:59 +02:00
pub struct PeerInfo {
/// Public node id
pub id : Option < String > ,
/// Node client ID
2019-02-07 15:27:09 +01:00
pub client_version : ClientVersion ,
2016-10-12 20:18:59 +02:00
/// 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 ,
2017-01-20 12:41:49 +01:00
/// Eth protocol info.
pub eth_info : Option < EthProtocolInfo > ,
/// Light protocol info.
2017-03-22 16:45:50 +01:00
pub pip_info : Option < PipProtocolInfo > ,
2017-01-20 12:41:49 +01:00
}
/// Ethereum protocol info.
#[ derive(Debug) ]
pub struct EthProtocolInfo {
/// Protocol version
pub version : u32 ,
2016-10-12 20:18:59 +02:00
/// SHA3 of peer best block hash
2017-01-20 12:41:49 +01:00
pub head : H256 ,
2016-10-12 20:18:59 +02:00
/// Peer total difficulty if known
2017-01-20 12:41:49 +01:00
pub difficulty : Option < U256 > ,
}
2017-03-22 16:45:50 +01:00
/// PIP protocol info.
2017-01-20 12:41:49 +01:00
#[ derive(Debug) ]
2017-03-22 16:45:50 +01:00
pub struct PipProtocolInfo {
2017-01-20 12:41:49 +01:00
/// Protocol version
pub version : u32 ,
/// SHA3 of peer best block hash
pub head : H256 ,
/// Peer total difficulty if known
pub difficulty : U256 ,
}
2017-03-22 16:45:50 +01:00
impl From < light_net ::Status > for PipProtocolInfo {
2017-01-20 12:41:49 +01:00
fn from ( status : light_net ::Status ) -> Self {
2017-03-22 16:45:50 +01:00
PipProtocolInfo {
2017-01-20 12:41:49 +01:00
version : status . protocol_version ,
head : status . head_hash ,
difficulty : status . head_td ,
}
}
2016-07-14 12:07:33 +02:00
}
2018-11-28 11:30:05 +01:00
/// A prioritized tasks run in a specialised timer.
/// Every task should be completed within a hard deadline,
/// if it's not it's either cancelled or split into multiple tasks.
/// NOTE These tasks might not complete at all, so anything
/// that happens here should work even if the task is cancelled.
#[ derive(Debug) ]
pub enum PriorityTask {
/// Propagate given block
PropagateBlock {
/// When the task was initiated
started : ::std ::time ::Instant ,
/// Raw block RLP to propagate
block : Bytes ,
/// Block hash
hash : H256 ,
/// Blocks difficulty
difficulty : U256 ,
} ,
/// Propagate a list of transactions
PropagateTransactions ( ::std ::time ::Instant , Arc < atomic ::AtomicBool > ) ,
}
impl PriorityTask {
/// Mark the task as being processed, right after it's retrieved from the queue.
pub fn starting ( & self ) {
match * self {
PriorityTask ::PropagateTransactions ( _ , ref is_ready ) = > is_ready . store ( true , atomic ::Ordering ::SeqCst ) ,
_ = > { } ,
}
}
}
2016-12-08 23:21:47 +01:00
/// EthSync initialization parameters.
pub struct Params {
/// Configuration.
pub config : SyncConfig ,
2019-04-02 17:13:55 +02:00
/// Runtime executor
pub executor : Executor ,
2016-12-08 23:21:47 +01:00
/// Blockchain client.
2019-07-09 10:04:20 +02:00
pub chain : Arc < dyn BlockChainClient > ,
2016-12-08 23:21:47 +01:00
/// Snapshot service.
2019-07-09 10:04:20 +02:00
pub snapshot_service : Arc < dyn SnapshotService > ,
2018-04-09 16:14:33 +02:00
/// Private tx service.
2019-07-09 10:04:20 +02:00
pub private_tx_handler : Option < Arc < dyn PrivateTxHandler > > ,
2019-08-16 14:45:52 +02:00
/// Private state wrapper
pub private_state : Option < Arc < PrivateStateDB > > ,
2016-12-08 23:21:47 +01:00
/// Light data provider.
2019-07-09 10:04:20 +02:00
pub provider : Arc < dyn ( ::light ::Provider ) > ,
2016-12-08 23:21:47 +01:00
/// 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 > ,
2017-03-22 16:45:50 +01:00
/// Light (pip) 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 ] ,
2018-11-28 11:30:05 +01:00
/// Priority tasks notification channel
priority_tasks : Mutex < mpsc ::Sender < PriorityTask > > ,
2019-04-02 17:13:55 +02:00
/// for state tracking
is_major_syncing : Arc < AtomicBool >
2016-07-14 12:07:33 +02:00
}
2018-08-13 17:53:19 +02:00
fn light_params (
network_id : u64 ,
2018-11-21 20:11:01 +01:00
median_peers : f64 ,
2018-08-13 17:53:19 +02:00
pruning_info : PruningInfo ,
2019-07-09 10:04:20 +02:00
sample_store : Option < Box < dyn SampleStore > > ,
2018-08-13 17:53:19 +02:00
) -> LightParams {
let mut light_params = LightParams {
network_id : network_id ,
config : 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 ,
} ,
sample_store : sample_store ,
} ;
2018-11-21 20:11:01 +01:00
light_params . config . median_peers = median_peers ;
2018-08-13 17:53:19 +02:00
light_params
}
2016-07-14 12:07:33 +02:00
impl EthSync {
/// Creates and register protocol with the network service
2019-07-09 10:04:20 +02:00
pub fn new ( params : Params , connection_filter : Option < Arc < dyn ConnectionFilter > > ) -> Result < Arc < EthSync > , Error > {
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 ( {
2017-05-23 12:31:09 +02:00
let sample_store = params . network_config . net_config_path
. clone ( )
. map ( ::std ::path ::PathBuf ::from )
. map ( | mut p | { p . push ( " request_timings " ) ; light_net ::FileStore ( p ) } )
. map ( | store | Box ::new ( store ) as Box < _ > ) ;
2018-11-21 20:11:01 +01:00
let median_peers = ( params . network_config . min_peers + params . network_config . max_peers ) as f64 / 2.0 ;
2018-08-13 17:53:19 +02:00
let light_params = light_params (
params . config . network_id ,
2018-11-21 20:11:01 +01:00
median_peers ,
2018-08-13 17:53:19 +02:00
pruning_info ,
sample_store ,
) ;
2017-05-23 12:31:09 +02:00
2016-12-08 23:21:47 +01:00
let mut light_proto = LightProtocol ::new ( params . provider , light_params ) ;
2017-01-11 14:39:03 +01:00
light_proto . add_handler ( Arc ::new ( TxRelay ( params . chain . clone ( ) ) ) ) ;
2016-12-08 23:21:47 +01:00
Arc ::new ( light_proto )
} )
} ;
2018-11-28 11:30:05 +01:00
let ( priority_tasks_tx , priority_tasks_rx ) = mpsc ::channel ( ) ;
let sync = ChainSyncApi ::new (
params . config ,
& * params . chain ,
2019-01-04 19:57:01 +01:00
params . private_tx_handler . as_ref ( ) . cloned ( ) ,
2018-11-28 11:30:05 +01:00
priority_tasks_rx ,
) ;
2019-04-02 17:13:55 +02:00
let is_major_syncing = Arc ::new ( AtomicBool ::new ( false ) ) ;
{
// spawn task that constantly updates EthSync.is_major_sync
let notifications = sync . write ( ) . sync_notifications ( ) ;
let moved_client = Arc ::downgrade ( & params . chain ) ;
let moved_is_major_syncing = is_major_syncing . clone ( ) ;
params . executor . spawn ( notifications . for_each ( move | sync_status | {
if let Some ( queue_info ) = moved_client . upgrade ( ) . map ( | client | client . queue_info ( ) ) {
let is_syncing_state = match sync_status {
SyncState ::Idle | SyncState ::NewBlocks = > false ,
_ = > true
} ;
let is_verifying = queue_info . unverified_queue_size + queue_info . verified_queue_size > 3 ;
moved_is_major_syncing . store ( is_verifying | | is_syncing_state , Ordering ::SeqCst ) ;
return Ok ( ( ) )
}
// client has been dropped
return Err ( ( ) )
} ) ) ;
}
2017-08-29 14:38:01 +02:00
let service = NetworkService ::new ( params . network_config . clone ( ) . into_basic ( ) ? , connection_filter ) ? ;
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 {
2018-11-28 11:30:05 +01:00
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 ( ) ) ,
2019-08-16 14:45:52 +02:00
private_state : params . private_state ,
2016-11-07 12:34:45 +01:00
} ) ,
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 ,
2018-11-28 11:30:05 +01:00
priority_tasks : Mutex ::new ( priority_tasks_tx ) ,
2019-04-02 17:13:55 +02:00
is_major_syncing
2016-07-14 12:07:33 +02:00
} ) ;
Ok ( sync )
}
2018-11-28 11:30:05 +01:00
/// Priority tasks producer
pub fn priority_tasks ( & self ) -> mpsc ::Sender < PriorityTask > {
self . priority_tasks . lock ( ) . clone ( )
}
2016-07-14 12:07:33 +02:00
}
impl SyncProvider for EthSync {
/// Get sync status
2017-02-17 21:38:43 +01:00
fn status ( & self ) -> EthSyncStatus {
2018-11-28 11:30:05 +01:00
self . eth_handler . sync . 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 > {
2017-01-20 12:41:49 +01:00
self . network . with_context_eval ( self . subprotocol_name , | ctx | {
let peer_ids = self . network . connected_peers ( ) ;
let light_proto = self . light_proto . as_ref ( ) ;
2018-11-28 11:30:05 +01:00
let peer_info = self . eth_handler . sync . peer_info ( & peer_ids ) ;
peer_ids . into_iter ( ) . zip ( peer_info ) . filter_map ( | ( peer_id , peer_info ) | {
2017-01-20 12:41:49 +01:00
let session_info = match ctx . session_info ( peer_id ) {
None = > return None ,
Some ( info ) = > info ,
} ;
Some ( PeerInfo {
2018-02-09 09:32:06 +01:00
id : session_info . id . map ( | id | format! ( " {:x} " , id ) ) ,
2017-01-20 12:41:49 +01:00
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 ,
2018-11-28 11:30:05 +01:00
eth_info : peer_info ,
2018-09-06 15:44:40 +02:00
pip_info : light_proto . as_ref ( ) . and_then ( | lp | lp . peer_status ( peer_id ) ) . map ( Into ::into ) ,
2017-01-20 12:41:49 +01:00
} )
} ) . collect ( )
} ) . unwrap_or_else ( Vec ::new )
2016-10-12 20:18:59 +02:00
}
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 > {
2018-11-28 11:30:05 +01:00
self . eth_handler . sync . transactions_stats ( )
2016-11-16 13:37:21 +01:00
}
2019-04-02 17:13:55 +02:00
fn sync_notification ( & self ) -> Notification < SyncState > {
self . eth_handler . sync . write ( ) . sync_notifications ( )
}
fn is_major_syncing ( & self ) -> bool {
self . is_major_syncing . load ( Ordering ::SeqCst )
}
2016-07-14 12:07:33 +02:00
}
2018-06-12 08:22:54 +02:00
const PEERS_TIMER : TimerToken = 0 ;
2018-11-28 12:19:35 +01:00
const MAINTAIN_SYNC_TIMER : TimerToken = 1 ;
const CONTINUE_SYNC_TIMER : TimerToken = 2 ;
const TX_TIMER : TimerToken = 3 ;
const PRIORITY_TIMER : TimerToken = 4 ;
2018-11-28 11:30:05 +01:00
pub ( crate ) const PRIORITY_TIMER_INTERVAL : Duration = Duration ::from_millis ( 250 ) ;
2018-06-12 08:22:54 +02:00
2016-07-14 12:07:33 +02:00
struct SyncProtocolHandler {
2016-08-15 14:25:57 +02:00
/// Shared blockchain client.
2019-07-09 10:04:20 +02:00
chain : Arc < dyn BlockChainClient > ,
2016-09-06 15:31:13 +02:00
/// Shared snapshot service.
2019-07-09 10:04:20 +02:00
snapshot_service : Arc < dyn SnapshotService > ,
2016-07-14 12:07:33 +02:00
/// Sync strategy
2018-11-28 11:30:05 +01:00
sync : ChainSyncApi ,
2016-10-18 18:16:00 +02:00
/// Chain overlay used to cache data such as fork block.
overlay : RwLock < HashMap < BlockNumber , Bytes > > ,
2019-08-16 14:45:52 +02:00
/// Private state db
private_state : Option < Arc < PrivateStateDB > > ,
2016-07-14 12:07:33 +02:00
}
impl NetworkProtocolHandler for SyncProtocolHandler {
2019-07-09 10:04:20 +02:00
fn initialize ( & self , io : & dyn NetworkContext ) {
2016-10-24 16:24:35 +02:00
if io . subprotocol_name ( ) ! = WARP_SYNC_PROTOCOL_ID {
2018-06-12 08:22:54 +02:00
io . register_timer ( PEERS_TIMER , Duration ::from_millis ( 700 ) ) . expect ( " Error registering peers timer " ) ;
2018-11-28 12:19:35 +01:00
io . register_timer ( MAINTAIN_SYNC_TIMER , Duration ::from_millis ( 1100 ) ) . expect ( " Error registering sync timer " ) ;
io . register_timer ( CONTINUE_SYNC_TIMER , Duration ::from_millis ( 2500 ) ) . expect ( " Error registering sync timer " ) ;
2018-06-12 08:22:54 +02:00
io . register_timer ( TX_TIMER , Duration ::from_millis ( 1300 ) ) . expect ( " Error registering transactions timer " ) ;
2018-11-28 11:30:05 +01:00
io . register_timer ( PRIORITY_TIMER , PRIORITY_TIMER_INTERVAL ) . expect ( " Error registering peers timer " ) ;
2016-10-24 16:24:35 +02:00
}
2016-07-14 12:07:33 +02:00
}
2019-07-09 10:04:20 +02:00
fn read ( & self , io : & dyn NetworkContext , peer : & PeerId , packet_id : u8 , data : & [ u8 ] ) {
2019-08-16 14:45:52 +02:00
self . sync . dispatch_packet ( & mut NetSyncIo ::new ( io ,
& * self . chain ,
& * self . snapshot_service ,
& self . overlay ,
self . private_state . clone ( ) ) ,
* peer , packet_id , data ) ;
2016-07-14 12:07:33 +02:00
}
2019-07-09 10:04:20 +02:00
fn connected ( & self , io : & dyn NetworkContext , peer : & PeerId ) {
2018-05-09 08:49:34 +02:00
trace_time! ( " sync::connected " ) ;
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 {
2019-08-16 14:45:52 +02:00
self . sync . write ( ) . on_peer_connected ( & mut NetSyncIo ::new ( io ,
& * self . chain ,
& * self . snapshot_service ,
& self . overlay ,
self . private_state . clone ( ) ) ,
* peer ) ;
2016-10-24 16:24:35 +02:00
}
2016-07-14 12:07:33 +02:00
}
2019-07-09 10:04:20 +02:00
fn disconnected ( & self , io : & dyn NetworkContext , peer : & PeerId ) {
2018-05-09 08:49:34 +02:00
trace_time! ( " sync::disconnected " ) ;
2016-10-24 16:24:35 +02:00
if io . subprotocol_name ( ) ! = WARP_SYNC_PROTOCOL_ID {
2019-08-16 14:45:52 +02:00
self . sync . write ( ) . on_peer_aborting ( & mut NetSyncIo ::new ( io ,
& * self . chain ,
& * self . snapshot_service ,
& self . overlay ,
self . private_state . clone ( ) ) ,
* peer ) ;
2016-10-24 16:24:35 +02:00
}
2016-07-14 12:07:33 +02:00
}
2019-07-09 10:04:20 +02:00
fn timeout ( & self , io : & dyn NetworkContext , timer : TimerToken ) {
2018-05-09 08:49:34 +02:00
trace_time! ( " sync::timeout " ) ;
2019-08-16 14:45:52 +02:00
let mut io = NetSyncIo ::new ( io , & * self . chain , & * self . snapshot_service , & self . overlay , self . private_state . clone ( ) ) ;
2018-06-12 08:22:54 +02:00
match timer {
PEERS_TIMER = > self . sync . write ( ) . maintain_peers ( & mut io ) ,
2018-11-28 12:19:35 +01:00
MAINTAIN_SYNC_TIMER = > self . sync . write ( ) . maintain_sync ( & mut io ) ,
CONTINUE_SYNC_TIMER = > self . sync . write ( ) . continue_sync ( & mut io ) ,
2018-11-28 11:30:05 +01:00
TX_TIMER = > self . sync . write ( ) . propagate_new_transactions ( & mut io ) ,
PRIORITY_TIMER = > self . sync . process_priority_queue ( & mut io ) ,
2018-06-12 08:22:54 +02:00
_ = > warn! ( " Unknown timer {} triggered. " , timer ) ,
}
2016-07-14 12:07:33 +02:00
}
}
impl ChainNotify for EthSync {
2018-11-28 11:30:05 +01:00
fn block_pre_import ( & self , bytes : & Bytes , hash : & H256 , difficulty : & U256 ) {
let task = PriorityTask ::PropagateBlock {
started : ::std ::time ::Instant ::now ( ) ,
block : bytes . clone ( ) ,
hash : * hash ,
difficulty : * difficulty ,
} ;
if let Err ( e ) = self . priority_tasks . lock ( ) . send ( task ) {
warn! ( target : " sync " , " Unexpected error during priority block propagation: {:?} " , e ) ;
}
}
2018-12-19 10:24:14 +01:00
fn new_blocks ( & self , new_blocks : NewBlocks )
2016-07-14 12:07:33 +02:00
{
2018-12-19 10:24:14 +01:00
if new_blocks . has_more_blocks_to_import { return }
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 | {
2019-08-16 14:45:52 +02:00
let mut sync_io = NetSyncIo ::new ( context ,
& * self . eth_handler . chain ,
& * self . eth_handler . snapshot_service ,
& self . eth_handler . overlay ,
self . eth_handler . private_state . clone ( ) ) ;
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 ,
2018-12-19 10:24:14 +01:00
& new_blocks . imported ,
& new_blocks . invalid ,
new_blocks . route . enacted ( ) ,
new_blocks . route . retracted ( ) ,
& new_blocks . sealed ,
& new_blocks . 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 ( ) ;
2018-03-05 11:56:35 +01:00
light_proto . make_announcement ( & context , Announcement {
2016-12-08 23:57:09 +01:00
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 ) {
2018-06-01 09:49:46 +02:00
match self . network . start ( ) {
Err ( ( err , listen_address ) ) = > {
match err . into ( ) {
2019-06-17 08:44:59 +02:00
Error ::Io ( ref e ) if e . kind ( ) = = io ::ErrorKind ::AddrInUse = > {
2018-06-01 09:49:46 +02:00
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. " , listen_address . expect ( " Listen address is not set. " ) )
} ,
err = > warn! ( " Error starting network: {} " , err ) ,
}
} ,
2016-10-25 15:55:53 +02:00
_ = > { } ,
}
2018-06-01 09:49:46 +02:00
2018-05-14 10:09:05 +02:00
self . network . register_protocol ( self . eth_handler . clone ( ) , self . subprotocol_name , & [ ETH_PROTOCOL_VERSION_62 , ETH_PROTOCOL_VERSION_63 ] )
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
2019-08-16 14:45:52 +02:00
self . network . register_protocol ( self . eth_handler . clone ( ) , WARP_SYNC_PROTOCOL_ID , & [ PAR_PROTOCOL_VERSION_1 , PAR_PROTOCOL_VERSION_2 , PAR_PROTOCOL_VERSION_3 , PAR_PROTOCOL_VERSION_4 ] )
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 ( ) ) {
2018-05-14 10:09:05 +02:00
self . network . register_protocol ( light_proto , self . light_subprotocol_name , ::light ::net ::PROTOCOL_VERSIONS )
2016-12-08 23:21:47 +01:00
. 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 ( ) ;
2018-05-22 06:35:13 +02:00
self . network . stop ( ) ;
2016-07-14 12:07:33 +02:00
}
2016-08-15 14:25:57 +02:00
2018-04-09 16:14:33 +02:00
fn broadcast ( & self , message_type : ChainMessageType ) {
2016-12-01 15:48:56 +01:00
self . network . with_context ( WARP_SYNC_PROTOCOL_ID , | context | {
2019-08-16 14:45:52 +02:00
let mut sync_io = NetSyncIo ::new ( context ,
& * self . eth_handler . chain ,
& * self . eth_handler . snapshot_service ,
& self . eth_handler . overlay ,
self . eth_handler . private_state . clone ( ) ) ;
2018-04-09 16:14:33 +02:00
match message_type {
ChainMessageType ::Consensus ( message ) = > self . eth_handler . sync . write ( ) . propagate_consensus_packet ( & mut sync_io , message ) ,
2018-08-29 14:31:04 +02:00
ChainMessageType ::PrivateTransaction ( transaction_hash , message ) = >
2019-02-13 09:20:33 +01:00
self . eth_handler . sync . write ( ) . propagate_private_transaction ( & mut sync_io , transaction_hash , PrivateTransactionPacket , message ) ,
2018-08-29 14:31:04 +02:00
ChainMessageType ::SignedPrivateTransaction ( transaction_hash , message ) = >
2019-02-13 09:20:33 +01:00
self . eth_handler . sync . write ( ) . propagate_private_transaction ( & mut sync_io , transaction_hash , SignedPrivateTransactionPacket , message ) ,
2019-08-16 14:45:52 +02:00
ChainMessageType ::PrivateStateRequest ( hash ) = >
self . eth_handler . sync . write ( ) . request_private_state ( & mut sync_io , & hash ) ,
2018-04-09 16:14:33 +02:00
}
2016-08-15 14:25:57 +02:00
} ) ;
}
2016-12-12 21:28:46 +01:00
2018-04-13 17:34:27 +02:00
fn transactions_received ( & self , txs : & [ UnverifiedTransaction ] , peer_id : PeerId ) {
2016-12-12 21:28:46 +01:00
let mut sync = self . eth_handler . sync . write ( ) ;
2018-04-13 17:34:27 +02:00
sync . transactions_received ( txs , peer_id ) ;
2016-12-10 14:56:41 +01:00
}
2016-07-14 12:07:33 +02:00
}
2017-03-22 16:45:50 +01:00
/// PIP event handler.
2016-12-08 23:21:47 +01:00
/// Simply queues transactions from light client peers.
2019-07-09 10:04:20 +02:00
struct TxRelay ( Arc < dyn BlockChainClient > ) ;
2016-12-08 23:21:47 +01:00
impl LightHandler for TxRelay {
2019-07-09 10:04:20 +02:00
fn on_transactions ( & self , ctx : & dyn EventContext , relay : & [ ::types ::transaction ::UnverifiedTransaction ] ) {
2017-03-23 20:02:46 +01:00
trace! ( target : " pip " , " Relaying {} transactions from peer {} " , relay . len ( ) , ctx . peer ( ) ) ;
2018-10-09 22:07:25 +02:00
self . 0. queue_transactions ( relay . iter ( ) . map ( | tx | ::rlp ::encode ( tx ) ) . collect ( ) , ctx . peer ( ) )
2016-12-08 23:21:47 +01:00
}
}
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 ) ;
2018-06-01 09:49:46 +02:00
/// Returns the minimum and maximum peers.
2019-01-22 09:51:40 +01:00
fn num_peers_range ( & self ) -> RangeInclusive < u32 > ;
2017-09-10 18:02:14 +02:00
/// Get network context for protocol.
2019-07-09 10:04:20 +02:00
fn with_proto_context ( & self , proto : ProtocolId , f : & mut dyn FnMut ( & dyn NetworkContext ) ) ;
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 | {
2019-08-16 14:45:52 +02:00
let mut sync_io = NetSyncIo ::new ( context ,
& * self . eth_handler . chain ,
& * self . eth_handler . snapshot_service ,
& self . eth_handler . overlay ,
self . eth_handler . private_state . clone ( ) ) ;
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 ( ) ;
}
2019-01-22 09:51:40 +01:00
fn num_peers_range ( & self ) -> RangeInclusive < u32 > {
2018-06-01 09:49:46 +02:00
self . network . num_peers_range ( )
2016-07-14 12:07:33 +02:00
}
2017-09-10 18:02:14 +02:00
2019-07-09 10:04:20 +02:00
fn with_proto_context ( & self , proto : ProtocolId , f : & mut dyn FnMut ( & dyn NetworkContext ) ) {
2017-09-10 18:02:14 +02:00
self . network . with_context_eval ( proto , f ) ;
}
2016-07-14 12:07:33 +02:00
}
2016-12-08 19:52:48 +01:00
#[ derive(Debug, Clone, PartialEq, Eq) ]
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
2017-01-11 12:16:47 +01:00
pub use_secret : Option < Secret > ,
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
2017-07-28 19:06:39 +02:00
pub ip_filter : IpFilter ,
2017-12-02 10:08:04 +01:00
/// Client version string
pub client_version : String ,
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 ) ? ) } ,
2018-04-27 15:04:27 +02:00
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 ,
2017-07-28 19:06:39 +02:00
ip_filter : self . ip_filter ,
2016-07-14 12:07:33 +02:00
non_reserved_mode : if self . allow_non_reserved { NonReservedPeerMode ::Accept } else { NonReservedPeerMode ::Deny } ,
2017-12-02 10:08:04 +01:00
client_version : self . client_version ,
2016-07-14 12:07:33 +02:00
} )
}
}
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 ,
2017-07-28 19:06:39 +02:00
ip_filter : other . ip_filter ,
2016-07-14 12:07:33 +02:00
allow_non_reserved : match other . non_reserved_mode { NonReservedPeerMode ::Accept = > true , _ = > false } ,
2017-12-02 10:08:04 +01:00
client_version : other . client_version ,
2016-07-14 12:07:33 +02:00
}
}
}
2016-07-20 18:13:56 +02:00
2016-12-08 19:52:48 +01:00
/// Configuration for IPC service.
#[ derive(Debug, Clone) ]
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
2017-02-17 21:38:43 +01:00
/// Numbers of peers (max, min, active).
#[ derive(Debug, Clone) ]
pub struct PeerNumbers {
/// Number of connected peers.
pub connected : usize ,
/// Number of active peers.
pub active : usize ,
/// Max peers.
pub max : usize ,
/// Min peers.
pub min : usize ,
}
/// Light synchronization.
pub trait LightSyncProvider {
/// Get peer numbers.
fn peer_numbers ( & self ) -> PeerNumbers ;
/// Get peers information
fn peers ( & self ) -> Vec < PeerInfo > ;
2017-03-22 21:09:43 +01:00
/// Get network id.
fn network_id ( & self ) -> u64 ;
2017-02-17 21:38:43 +01:00
/// Get the enode if available.
fn enode ( & self ) -> Option < String > ;
/// Returns propagation count for pending transactions.
fn transactions_stats ( & self ) -> BTreeMap < H256 , TransactionStats > ;
}
2019-02-11 11:33:16 +01:00
/// Wrapper around `light_sync::SyncInfo` to expose those methods without the concrete type `LightSync`
pub trait LightSyncInfo : Send + Sync {
/// Get the highest block advertised on the network.
fn highest_block ( & self ) -> Option < u64 > ;
/// Get the block number at the time of sync start.
fn start_block ( & self ) -> u64 ;
/// Whether major sync is underway.
fn is_major_importing ( & self ) -> bool ;
}
/// Execute a closure with a protocol context.
pub trait LightNetworkDispatcher {
/// Execute a closure with a protocol context.
2019-07-09 10:04:20 +02:00
fn with_context < F , T > ( & self , f : F ) -> Option < T > where F : FnOnce ( & dyn ( ::light ::net ::BasicContext ) ) -> T ;
2019-02-11 11:33:16 +01: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 ] ,
2017-03-22 22:00:52 +01:00
/// Other handlers to attach.
2019-07-09 10:04:20 +02:00
pub handlers : Vec < Arc < dyn LightHandler > > ,
2016-12-16 17:38:16 +01:00
}
/// Service for light synchronization.
pub struct LightSync {
proto : Arc < LightProtocol > ,
2019-07-09 10:04:20 +02:00
sync : Arc < dyn SyncInfo + Sync + Send > ,
2016-12-16 17:38:16 +01:00
network : NetworkService ,
subprotocol_name : [ u8 ; 3 ] ,
2017-03-22 21:09:43 +01:00
network_id : u64 ,
2016-12-16 17:38:16 +01:00
}
impl LightSync {
/// Create a new light sync service.
2017-11-13 14:37:08 +01:00
pub fn new < L > ( params : LightSyncParams < L > ) -> Result < Self , Error >
2017-02-09 18:42:18 +01:00
where L : AsLightClient + Provider + Sync + Send + 'static
2016-12-16 17:38:16 +01:00
{
use light_sync ::LightSync as SyncHandler ;
// initialize light protocol handler and attach sync module.
2017-03-23 03:23:53 +01:00
let ( sync , light_proto ) = {
2016-12-16 17:38:16 +01:00
let light_params = LightParams {
network_id : params . network_id ,
2017-05-23 12:31:09 +02:00
config : Default ::default ( ) ,
2016-12-16 17:38:16 +01:00
capabilities : Capabilities {
serve_headers : false ,
serve_chain_since : None ,
serve_state_since : None ,
tx_relay : false ,
} ,
2017-05-23 12:31:09 +02:00
sample_store : None ,
2016-12-16 17:38:16 +01:00
} ;
let mut light_proto = LightProtocol ::new ( params . client . clone ( ) , light_params ) ;
2017-06-18 16:15:44 +02:00
let sync_handler = Arc ::new ( SyncHandler ::new ( params . client . clone ( ) ) ? ) ;
2017-03-23 03:23:53 +01:00
light_proto . add_handler ( sync_handler . clone ( ) ) ;
2016-12-16 17:38:16 +01:00
2017-03-22 22:00:52 +01:00
for handler in params . handlers {
light_proto . add_handler ( handler ) ;
}
2017-03-23 03:23:53 +01:00
( sync_handler , Arc ::new ( light_proto ) )
2016-12-16 17:38:16 +01:00
} ;
2017-08-29 14:38:01 +02:00
let service = NetworkService ::new ( params . network_config , None ) ? ;
2016-12-16 17:38:16 +01:00
Ok ( LightSync {
proto : light_proto ,
2017-03-23 03:23:53 +01:00
sync : sync ,
2016-12-16 17:38:16 +01:00
network : service ,
subprotocol_name : params . subprotocol_name ,
2017-03-22 21:09:43 +01:00
network_id : params . network_id ,
2016-12-16 17:38:16 +01:00
} )
}
2017-02-02 17:02:46 +01:00
2016-12-16 17:38:16 +01:00
}
2017-03-23 03:23:53 +01:00
impl ::std ::ops ::Deref for LightSync {
2019-07-09 10:04:20 +02:00
type Target = dyn ( ::light_sync ::SyncInfo ) ;
2017-03-23 03:23:53 +01:00
fn deref ( & self ) -> & Self ::Target { & * self . sync }
}
2019-02-11 11:33:16 +01:00
impl LightNetworkDispatcher for LightSync {
2019-07-09 10:04:20 +02:00
fn with_context < F , T > ( & self , f : F ) -> Option < T > where F : FnOnce ( & dyn ( ::light ::net ::BasicContext ) ) -> T {
2019-02-11 11:33:16 +01:00
self . network . with_context_eval (
self . subprotocol_name ,
move | ctx | self . proto . with_context ( & ctx , f ) ,
)
}
}
2016-12-16 17:38:16 +01:00
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 ) {
2018-06-01 09:49:46 +02:00
match self . network . start ( ) {
Err ( ( err , listen_address ) ) = > {
match err . into ( ) {
2019-06-17 08:44:59 +02:00
Error ::Io ( ref e ) if e . kind ( ) = = io ::ErrorKind ::AddrInUse = > {
2018-06-01 09:49:46 +02:00
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. " , listen_address . expect ( " Listen address is not set. " ) )
} ,
err = > warn! ( " Error starting network: {} " , err ) ,
}
} ,
2016-12-16 17:38:16 +01:00
_ = > { } ,
}
let light_proto = self . proto . clone ( ) ;
2018-05-14 10:09:05 +02:00
self . network . register_protocol ( light_proto , self . subprotocol_name , ::light ::net ::PROTOCOL_VERSIONS )
2016-12-16 17:38:16 +01:00
. unwrap_or_else ( | e | warn! ( " Error registering light client protocol: {:?} " , e ) ) ;
}
fn stop_network ( & self ) {
self . proto . abort ( ) ;
2018-05-22 06:35:13 +02:00
self . network . stop ( ) ;
2016-12-16 17:38:16 +01:00
}
2019-01-22 09:51:40 +01:00
fn num_peers_range ( & self ) -> RangeInclusive < u32 > {
2018-06-01 09:49:46 +02:00
self . network . num_peers_range ( )
2016-12-16 17:38:16 +01:00
}
2017-09-10 18:02:14 +02:00
2019-07-09 10:04:20 +02:00
fn with_proto_context ( & self , proto : ProtocolId , f : & mut dyn FnMut ( & dyn NetworkContext ) ) {
2017-09-10 18:02:14 +02:00
self . network . with_context_eval ( proto , f ) ;
}
2016-12-16 17:38:16 +01:00
}
2017-01-11 12:16:47 +01:00
2017-02-17 21:38:43 +01:00
impl LightSyncProvider for LightSync {
fn peer_numbers ( & self ) -> PeerNumbers {
let ( connected , active ) = self . proto . peer_count ( ) ;
2018-06-01 09:49:46 +02:00
let peers_range = self . num_peers_range ( ) ;
2019-01-22 09:51:40 +01:00
debug_assert! ( peers_range . end ( ) > = peers_range . start ( ) ) ;
2017-02-17 21:38:43 +01:00
PeerNumbers {
connected : connected ,
active : active ,
2019-01-22 09:51:40 +01:00
max : * peers_range . end ( ) as usize ,
min : * peers_range . start ( ) as usize ,
2017-02-17 21:38:43 +01:00
}
}
fn peers ( & self ) -> Vec < PeerInfo > {
self . network . with_context_eval ( self . subprotocol_name , | ctx | {
let peer_ids = self . network . connected_peers ( ) ;
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 {
2018-02-09 09:32:06 +01:00
id : session_info . id . map ( | id | format! ( " {:x} " , id ) ) ,
2017-02-17 21:38:43 +01:00
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 : None ,
2018-09-06 15:44:40 +02:00
pip_info : self . proto . peer_status ( peer_id ) . map ( Into ::into ) ,
2017-02-17 21:38:43 +01:00
} )
} ) . collect ( )
} ) . unwrap_or_else ( Vec ::new )
}
fn enode ( & self ) -> Option < String > {
self . network . external_url ( )
}
2017-03-22 21:09:43 +01:00
fn network_id ( & self ) -> u64 {
self . network_id
}
2017-02-17 21:38:43 +01:00
fn transactions_stats ( & self ) -> BTreeMap < H256 , TransactionStats > {
Default ::default ( ) // TODO
}
}
2019-02-11 11:33:16 +01:00
impl LightSyncInfo for LightSync {
fn highest_block ( & self ) -> Option < u64 > {
( * self . sync ) . highest_block ( )
}
fn start_block ( & self ) -> u64 {
( * self . sync ) . start_block ( )
}
fn is_major_importing ( & self ) -> bool {
( * self . sync ) . is_major_importing ( )
}
}