2020-09-22 14:53:52 +02:00
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
2016-07-14 12:07:33 +02:00
2020-09-22 14:53:52 +02:00
// OpenEthereum 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.
2020-09-22 14:53:52 +02:00
// OpenEthereum 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
2020-09-22 14:53:52 +02:00
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
2016-07-14 12:07:33 +02:00
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 ::{
client_version ::ClientVersion , ConnectionFilter , Error , ErrorKind ,
2018-05-22 06:34:01 +02:00
NetworkConfiguration as BasicNetworkConfiguration , NetworkContext , NetworkProtocolHandler ,
NonReservedPeerMode , PeerId , ProtocolId ,
} ;
2016-11-16 13:37:21 +01:00
use std ::{
2020-09-21 14:48:14 +02:00
collections ::{ BTreeMap , BTreeSet , HashMap } ,
2019-02-07 15:27:09 +01:00
io ,
ops ::RangeInclusive ,
2018-11-28 11:30:05 +01:00
sync ::{ atomic , mpsc , Arc } ,
2019-02-07 15:27:09 +01:00
time ::Duration ,
} ;
2018-08-13 17:53:19 +02:00
use chain ::{
2020-09-21 14:48:14 +02:00
fork_filter ::ForkFilterApi , ChainSyncApi , SyncState , SyncStatus as EthSyncStatus ,
ETH_PROTOCOL_VERSION_63 , ETH_PROTOCOL_VERSION_64 , PAR_PROTOCOL_VERSION_1 ,
PAR_PROTOCOL_VERSION_2 ,
2018-08-13 17:53:19 +02:00
} ;
2018-12-19 10:24:14 +01:00
use ethcore ::{
2018-08-13 17:53:19 +02:00
client ::{ BlockChainClient , ChainMessageType , ChainNotify , NewBlocks } ,
2016-09-06 15:31:13 +02:00
snapshot ::SnapshotService ,
2020-08-05 06:08:03 +02:00
} ;
2018-01-10 13:35:18 +01:00
use ethereum_types ::{ H256 , H512 , U256 } ;
2019-02-07 14:34:24 +01:00
use ethkey ::Secret ;
2018-12-19 10:24:14 +01:00
use io ::TimerToken ;
2017-07-28 19:06:39 +02:00
use network ::IpFilter ;
2018-11-28 11:30:05 +01:00
use parking_lot ::{ Mutex , RwLock } ;
2020-09-14 16:08:57 +02:00
use stats ::{ prometheus , prometheus_counter , prometheus_gauge , PrometheusMetrics } ;
2016-07-14 12:07:33 +02:00
use std ::{
net ::{ AddrParseError , SocketAddr } ,
2016-08-05 10:32:04 +02:00
str ::FromStr ,
2020-08-05 06:08:03 +02:00
} ;
2016-08-05 10:32:04 +02:00
use sync_io ::NetSyncIo ;
2020-09-14 16:08:57 +02:00
use types ::{
creation_status ::CreationStatus , restoration_status ::RestorationStatus ,
transaction ::UnverifiedTransaction , BlockNumber ,
} ;
2019-02-11 11:33:16 +01:00
2020-09-22 14:53:52 +02:00
/// OpenEthereum sync protocol
2020-08-13 13:52:54 +02:00
pub const PAR_PROTOCOL : 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-07-14 12:07:33 +02:00
2018-03-29 11:20:27 +02:00
/// Determine warp sync status.
#[ derive(Debug, Clone, Copy, PartialEq, Eq) ]
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 ,
}
}
2020-08-05 06:08:03 +02:00
2018-03-29 11:20:27 +02:00
/// 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 ] ,
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-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-07-27 21:38:22 +02:00
fork_block : None ,
2018-03-29 11:20:27 +02:00
warp_sync : WarpSync ::Disabled ,
2016-07-14 12:07:33 +02:00
}
}
}
/// Current sync status
2020-09-14 16:08:57 +02:00
pub trait SyncProvider : Send + Sync + PrometheusMetrics {
2016-07-14 12:07:33 +02:00
/// 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
/// 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) ]
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 > ,
}
/// 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 > ,
}
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 )
2020-08-05 06:08:03 +02:00
}
2018-11-28 11:30:05 +01:00
_ = > { }
}
}
}
2016-12-08 23:21:47 +01:00
/// EthSync initialization parameters.
pub struct Params {
/// Configuration.
pub config : SyncConfig ,
/// Blockchain client.
2020-07-29 10:36:15 +02:00
pub chain : Arc < dyn BlockChainClient > ,
2020-09-21 14:48:14 +02:00
/// Forks.
pub forks : BTreeSet < BlockNumber > ,
2016-12-08 23:21:47 +01:00
/// Snapshot service.
2020-07-29 10:36:15 +02:00
pub snapshot_service : Arc < dyn SnapshotService > ,
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 > ,
2016-09-28 14:21:59 +02:00
/// The main subprotocol name
subprotocol_name : [ u8 ; 3 ] ,
2018-11-28 11:30:05 +01:00
/// Priority tasks notification channel
priority_tasks : Mutex < mpsc ::Sender < PriorityTask > > ,
2016-07-14 12:07:33 +02:00
}
impl EthSync {
/// Creates and register protocol with the network service
2017-11-13 14:37:08 +01:00
pub fn new (
params : Params ,
2020-07-29 10:36:15 +02:00
connection_filter : Option < Arc < dyn ConnectionFilter > > ,
2017-11-13 14:37:08 +01:00
) -> Result < Arc < EthSync > , Error > {
2018-11-28 11:30:05 +01:00
let ( priority_tasks_tx , priority_tasks_rx ) = mpsc ::channel ( ) ;
2020-09-21 14:48:14 +02:00
let fork_filter = ForkFilterApi ::new ( & * params . chain , params . forks ) ;
let sync = ChainSyncApi ::new (
params . config ,
& * params . chain ,
fork_filter ,
priority_tasks_rx ,
) ;
2017-08-29 14:38:01 +02:00
let service = NetworkService ::new (
params . network_config . clone ( ) . into_basic ( ) ? ,
connection_filter ,
) ? ;
2020-08-05 06:08:03 +02:00
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 ( ) ) ,
} ) ,
2016-12-08 23:21:47 +01:00
subprotocol_name : params . config . subprotocol_name ,
2018-11-28 11:30:05 +01:00
priority_tasks : Mutex ::new ( priority_tasks_tx ) ,
2016-07-14 12:07:33 +02:00
} ) ;
2020-08-05 06:08:03 +02:00
2016-07-14 12:07:33 +02:00
Ok ( sync )
}
2020-08-05 06:08:03 +02:00
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
}
2020-08-05 06:08:03 +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 ( ) ;
2020-08-05 06:08:03 +02:00
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 ) | {
2021-01-21 18:27:35 +01:00
let session_info = ctx . session_info ( peer_id ) ? ;
2020-08-05 06:08:03 +02:00
2017-01-20 12:41:49 +01:00
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 ,
2017-01-20 12:41:49 +01:00
} )
} )
. collect ( )
} )
. unwrap_or_else ( Vec ::new )
2016-10-12 20:18:59 +02:00
}
2020-08-05 06:08:03 +02:00
2016-11-02 19:43:21 +01:00
fn enode ( & self ) -> Option < String > {
self . network . external_url ( )
}
2020-08-05 06:08:03 +02:00
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
}
2016-07-14 12:07:33 +02:00
}
2020-09-14 16:08:57 +02:00
impl PrometheusMetrics for EthSync {
fn prometheus_metrics ( & self , r : & mut prometheus ::Registry ) {
let scalar = | b | if b { 1 i64 } else { 0 i64 } ;
let sync_status = self . status ( ) ;
prometheus_gauge ( r ,
" sync_status " ,
" WaitingPeers(0), SnapshotManifest(1), SnapshotData(2), SnapshotWaiting(3), Blocks(4), Idle(5), Waiting(6), NewBlocks(7) " ,
match self . eth_handler . sync . status ( ) . state {
SyncState ::WaitingPeers = > 0 ,
SyncState ::SnapshotManifest = > 1 ,
SyncState ::SnapshotData = > 2 ,
SyncState ::SnapshotWaiting = > 3 ,
SyncState ::Blocks = > 4 ,
SyncState ::Idle = > 5 ,
SyncState ::Waiting = > 6 ,
SyncState ::NewBlocks = > 7 ,
} ) ;
for ( key , value ) in sync_status . item_sizes . iter ( ) {
prometheus_gauge (
r ,
& key ,
format! ( " Total item number of {} " , key ) . as_str ( ) ,
* value as i64 ,
) ;
}
prometheus_gauge (
r ,
" net_peers " ,
" Total number of connected peers " ,
sync_status . num_peers as i64 ,
) ;
prometheus_gauge (
r ,
" net_active_peers " ,
" Total number of active peers " ,
sync_status . num_active_peers as i64 ,
) ;
prometheus_counter (
r ,
" sync_blocks_recieved " ,
" Number of blocks downloaded so far " ,
sync_status . blocks_received as i64 ,
) ;
prometheus_counter (
r ,
" sync_blocks_total " ,
" Total number of blocks for the sync process " ,
sync_status . blocks_total as i64 ,
) ;
prometheus_gauge (
r ,
" sync_blocks_highest " ,
" Highest block number in the download queue " ,
sync_status . highest_block_number . unwrap_or ( 0 ) as i64 ,
) ;
prometheus_gauge (
r ,
" snapshot_download_active " ,
" 1 if downloading snapshots " ,
scalar ( sync_status . is_snapshot_syncing ( ) ) ,
) ;
prometheus_gauge (
r ,
" snapshot_download_chunks " ,
" Snapshot chunks " ,
sync_status . num_snapshot_chunks as i64 ,
) ;
prometheus_gauge (
r ,
" snapshot_download_chunks_done " ,
" Snapshot chunks downloaded " ,
sync_status . snapshot_chunks_done as i64 ,
) ;
let restoration = self . eth_handler . snapshot_service . restoration_status ( ) ;
let creation = self . eth_handler . snapshot_service . creation_status ( ) ;
2021-01-21 17:23:15 +01:00
let ( manifest_block_num , _ ) = self
. eth_handler
. snapshot_service
. manifest_block ( )
. unwrap_or ( ( 0 , H256 ::zero ( ) ) ) ;
2020-09-14 16:08:57 +02:00
prometheus_gauge (
r ,
" snapshot_create_block " ,
" First block of the current snapshot creation " ,
if let CreationStatus ::Ongoing { block_number } = creation {
block_number as i64
} else {
0
} ,
) ;
prometheus_gauge (
r ,
" snapshot_restore_block " ,
" First block of the current snapshot restoration " ,
if let RestorationStatus ::Ongoing { block_number , .. } = restoration {
block_number as i64
} else {
0
} ,
) ;
2021-01-21 17:23:15 +01:00
prometheus_gauge (
r ,
" snapshot_manifest_block " ,
" First block number of the present snapshot " ,
manifest_block_num as i64 ,
) ;
2020-09-14 16:08:57 +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 ;
2020-09-05 19:45:31 +02:00
const DELAYED_PROCESSING_TIMER : TimerToken = 5 ;
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.
2020-07-29 10:36:15 +02:00
chain : Arc < dyn BlockChainClient > ,
2016-09-06 15:31:13 +02:00
/// Shared snapshot service.
2020-07-29 10:36:15 +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 > > ,
2016-07-14 12:07:33 +02:00
}
impl NetworkProtocolHandler for SyncProtocolHandler {
2020-07-29 10:36:15 +02:00
fn initialize ( & self , io : & dyn NetworkContext ) {
2020-08-13 13:52:54 +02:00
if io . subprotocol_name ( ) ! = PAR_PROTOCOL {
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 " ) ;
2020-09-05 19:45:31 +02:00
io . register_timer ( DELAYED_PROCESSING_TIMER , Duration ::from_millis ( 2100 ) )
. expect ( " Error registering delayed processing timer " ) ;
2020-08-05 06:08:03 +02:00
2018-11-28 11:30:05 +01:00
io . register_timer ( PRIORITY_TIMER , PRIORITY_TIMER_INTERVAL )
. expect ( " Error registering peers timer " ) ;
2016-07-14 12:07:33 +02:00
}
2020-08-05 06:08:03 +02:00
}
2020-07-29 10:36:15 +02:00
fn read ( & self , io : & dyn NetworkContext , peer : & PeerId , packet_id : u8 , data : & [ u8 ] ) {
2018-11-28 11:30:05 +01:00
self . sync . dispatch_packet (
& mut NetSyncIo ::new ( io , & * self . chain , & * self . snapshot_service , & self . overlay ) ,
* peer ,
packet_id ,
data ,
) ;
2016-07-14 12:07:33 +02:00
}
2020-08-05 06:08:03 +02:00
2020-07-29 10:36:15 +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
2020-08-13 13:52:54 +02:00
let warp_protocol = io . protocol_version ( PAR_PROTOCOL , * peer ) . unwrap_or ( 0 ) ! = 0 ;
let warp_context = io . subprotocol_name ( ) = = PAR_PROTOCOL ;
2016-10-24 16:24:35 +02:00
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
}
2020-08-05 06:08:03 +02:00
}
2020-07-29 10:36:15 +02:00
fn disconnected ( & self , io : & dyn NetworkContext , peer : & PeerId ) {
2018-05-09 08:49:34 +02:00
trace_time! ( " sync::disconnected " ) ;
2020-08-13 13:52:54 +02:00
if io . subprotocol_name ( ) ! = PAR_PROTOCOL {
2016-10-24 16:24:35 +02:00
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
}
2020-08-05 06:08:03 +02:00
}
2020-07-29 10:36:15 +02:00
fn timeout ( & self , io : & dyn NetworkContext , timer : TimerToken ) {
2018-05-09 08:49:34 +02:00
trace_time! ( " sync::timeout " ) ;
2018-04-09 16:14:33 +02:00
let mut io = NetSyncIo ::new ( io , & * self . chain , & * self . snapshot_service , & self . overlay ) ;
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 ) ,
2020-09-05 19:45:31 +02:00
DELAYED_PROCESSING_TIMER = > self . sync . process_delayed_requests ( & 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 ) ;
2020-08-05 06:08:03 +02:00
}
2018-11-28 11:30:05 +01:00
}
2020-08-05 06:08:03 +02:00
2020-12-02 11:31:11 +01:00
// t_nb 11.4
2018-12-19 10:24:14 +01:00
fn new_blocks ( & self , new_blocks : NewBlocks ) {
if new_blocks . has_more_blocks_to_import {
return ;
}
2016-09-28 14:21:59 +02:00
self . network . with_context ( self . subprotocol_name , | context | {
2018-04-09 16:14:33 +02: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 ,
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
} ) ;
}
2020-08-05 06:08:03 +02:00
2016-07-14 12:07:33 +02:00
fn start ( & self ) {
2018-06-01 09:49:46 +02:00
match self . network . start ( ) {
2020-11-25 18:28:17 +01:00
Err ( ( err , listen_address ) ) = > match err . into ( ) {
ErrorKind ::Io ( 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. " , listen_address . expect ( " Listen address is not set. " ) )
}
err = > warn! ( " Error starting network: {} " , err ) ,
} ,
_ = > { }
}
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 ,
2020-09-21 14:48:14 +02:00
& [ ETH_PROTOCOL_VERSION_63 , ETH_PROTOCOL_VERSION_64 ] ,
2018-05-14 10:09:05 +02:00
)
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
2018-05-14 10:09:05 +02:00
self . network
. register_protocol (
self . eth_handler . clone ( ) ,
2020-08-13 13:52:54 +02:00
PAR_PROTOCOL ,
2020-09-02 17:43:14 +02:00
& [ PAR_PROTOCOL_VERSION_1 , PAR_PROTOCOL_VERSION_2 ] ,
2018-05-14 10:09:05 +02:00
)
2016-10-24 16:24:35 +02:00
. unwrap_or_else ( | e | warn! ( " Error registering snapshot sync protocol: {:?} " , e ) ) ;
2020-08-05 06:08:03 +02:00
}
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
}
2020-08-05 06:08:03 +02:00
2018-04-09 16:14:33 +02:00
fn broadcast ( & self , message_type : ChainMessageType ) {
2020-08-13 13:52:54 +02:00
self . network . with_context ( PAR_PROTOCOL , | 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 ,
) ;
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 ) ,
2020-08-05 06:08:03 +02:00
}
2016-08-15 14:25:57 +02:00
} ) ;
}
2020-08-05 06:08:03 +02: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
}
/// 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.
2020-07-29 10:36:15 +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 ) ;
}
2020-08-05 06:08:03 +02:00
2016-07-14 12:07:33 +02:00
fn deny_unreserved_peers ( & self ) {
self . network
. set_non_reserved_mode ( NonReservedPeerMode ::Deny ) ;
}
2020-08-05 06:08:03 +02:00
2016-07-14 12:07:33 +02:00
fn remove_reserved_peer ( & self , peer : String ) -> Result < ( ) , String > {
self . network
. remove_reserved_peer ( & peer )
. map_err ( | e | format! ( " {:?} " , e ) )
}
2020-08-05 06:08:03 +02:00
2016-07-14 12:07:33 +02:00
fn add_reserved_peer ( & self , peer : String ) -> Result < ( ) , String > {
self . network
. add_reserved_peer ( & peer )
. map_err ( | e | format! ( " {:?} " , e ) )
}
2020-08-05 06:08:03 +02:00
2016-07-14 12:07:33 +02:00
fn start_network ( & self ) {
self . start ( ) ;
}
2020-08-05 06:08:03 +02:00
2016-07-14 12:07:33 +02:00
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
} ) ;
2020-08-05 06:08:03 +02:00
2016-07-14 12:07:33 +02:00
self . stop ( ) ;
}
2020-08-05 06:08:03 +02: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-07-14 12:07:33 +02:00
}
2020-08-05 06:08:03 +02:00
2020-07-29 10:36:15 +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 ( ) )
}
2020-08-05 06:08:03 +02:00
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 ( ) )
}
2020-08-05 06:08:03 +02:00
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 ,
2021-01-21 18:27:35 +01:00
listen_address : self
. listen_address
. map ( | addr | SocketAddr ::from_str ( & addr ) )
. transpose ( ) ? ,
public_address : self
. public_address
. map ( | addr | SocketAddr ::from_str ( & addr ) )
. transpose ( ) ? ,
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 ,
2020-08-13 13:52:54 +02:00
reserved_protocols : hash_map ! [ PAR_PROTOCOL = > 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 ,
2020-08-13 13:52:54 +02:00
snapshot_peers : * other . reserved_protocols . get ( & PAR_PROTOCOL ) . 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 ,
}