@@ -356,6 +356,10 @@ impl ChainSync {
|
||||
};
|
||||
|
||||
trace!(target: "sync", "New peer {} (protocol: {}, network: {:?}, difficulty: {:?}, latest:{}, genesis:{})", peer_id, peer.protocol_version, peer.network_id, peer.difficulty, peer.latest_hash, peer.genesis);
|
||||
if io.is_expired() {
|
||||
trace!("Status packet from expired session {}:{}", peer_id, io.peer_info(peer_id));
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if self.peers.contains_key(&peer_id) {
|
||||
warn!("Unexpected status packet from {}:{}", peer_id, io.peer_info(peer_id));
|
||||
|
||||
@@ -41,6 +41,8 @@ pub trait SyncIo {
|
||||
fn is_chain_queue_empty(&self) -> bool {
|
||||
self.chain().queue_info().is_empty()
|
||||
}
|
||||
/// Check if the session is expired
|
||||
fn is_expired(&self) -> bool;
|
||||
}
|
||||
|
||||
/// Wraps `NetworkContext` and the blockchain client
|
||||
@@ -83,6 +85,10 @@ impl<'s, 'h> SyncIo for NetSyncIo<'s, 'h> {
|
||||
fn peer_info(&self, peer_id: PeerId) -> String {
|
||||
self.network.peer_info(peer_id)
|
||||
}
|
||||
|
||||
fn is_expired(&self) -> bool {
|
||||
self.network.is_expired()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -41,11 +41,13 @@
|
||||
//! use ethcore::miner::Miner;
|
||||
//!
|
||||
//! fn main() {
|
||||
//! let mut service = NetworkService::start(NetworkConfiguration::new()).unwrap();
|
||||
//! let mut service = NetworkService::new(NetworkConfiguration::new()).unwrap();
|
||||
//! service.start().unwrap();
|
||||
//! let dir = env::temp_dir();
|
||||
//! let client = Client::new(ClientConfig::default(), ethereum::new_frontier(), &dir, Arc::new(Miner::default()), service.io().channel()).unwrap();
|
||||
//! let miner = Miner::new(false, ethereum::new_frontier());
|
||||
//! EthSync::register(&mut service, SyncConfig::default(), client);
|
||||
//! let sync = EthSync::new(SyncConfig::default(), client);
|
||||
//! EthSync::register(&mut service, sync);
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
@@ -66,8 +68,10 @@ use util::network::{NetworkProtocolHandler, NetworkService, NetworkContext, Peer
|
||||
use util::TimerToken;
|
||||
use util::{U256, ONE_U256};
|
||||
use ethcore::client::Client;
|
||||
use ethcore::service::SyncMessage;
|
||||
use ethcore::service::{SyncMessage, NetSyncMessage};
|
||||
use io::NetSyncIo;
|
||||
use util::io::IoChannel;
|
||||
use util::{NetworkIoMessage, NetworkError};
|
||||
use chain::ChainSync;
|
||||
|
||||
mod chain;
|
||||
@@ -98,6 +102,10 @@ impl Default for SyncConfig {
|
||||
pub trait SyncProvider: Send + Sync {
|
||||
/// Get sync status
|
||||
fn status(&self) -> SyncStatus;
|
||||
/// Start the network
|
||||
fn start_network(&self);
|
||||
/// Stop the network
|
||||
fn stop_network(&self);
|
||||
}
|
||||
|
||||
/// Ethereum network protocol handler
|
||||
@@ -105,23 +113,30 @@ pub struct EthSync {
|
||||
/// Shared blockchain client. TODO: this should evetually become an IPC endpoint
|
||||
chain: Arc<Client>,
|
||||
/// Sync strategy
|
||||
sync: RwLock<ChainSync>
|
||||
sync: RwLock<ChainSync>,
|
||||
/// IO communication chnnel.
|
||||
io_channel: RwLock<IoChannel<NetSyncMessage>>,
|
||||
}
|
||||
|
||||
pub use self::chain::{SyncStatus, SyncState};
|
||||
|
||||
impl EthSync {
|
||||
/// Creates and register protocol with the network service
|
||||
pub fn register(service: &mut NetworkService<SyncMessage>, config: SyncConfig, chain: Arc<Client>) -> Arc<EthSync> {
|
||||
pub fn new(config: SyncConfig, chain: Arc<Client>) -> Arc<EthSync> {
|
||||
let sync = ChainSync::new(config, chain.deref());
|
||||
let sync = Arc::new(EthSync {
|
||||
chain: chain,
|
||||
sync: RwLock::new(sync),
|
||||
io_channel: RwLock::new(IoChannel::disconnected()),
|
||||
});
|
||||
service.register_protocol(sync.clone(), "eth", &[62u8, 63u8]).expect("Error registering eth protocol handler");
|
||||
sync
|
||||
}
|
||||
|
||||
/// Register protocol with the network service
|
||||
pub fn register(service: &NetworkService<SyncMessage>, sync: Arc<EthSync>) -> Result<(), NetworkError> {
|
||||
service.register_protocol(sync.clone(), "eth", &[62u8, 63u8])
|
||||
}
|
||||
|
||||
/// Stop sync
|
||||
pub fn stop(&mut self, io: &mut NetworkContext<SyncMessage>) {
|
||||
self.sync.write().unwrap().abort(&mut NetSyncIo::new(io, self.chain.deref()));
|
||||
@@ -138,11 +153,20 @@ impl SyncProvider for EthSync {
|
||||
fn status(&self) -> SyncStatus {
|
||||
self.sync.read().unwrap().status()
|
||||
}
|
||||
|
||||
fn start_network(&self) {
|
||||
self.io_channel.read().unwrap().send(NetworkIoMessage::User(SyncMessage::StartNetwork)).expect("Error sending IO notification");
|
||||
}
|
||||
|
||||
fn stop_network(&self) {
|
||||
self.io_channel.read().unwrap().send(NetworkIoMessage::User(SyncMessage::StopNetwork)).expect("Error sending IO notification");
|
||||
}
|
||||
}
|
||||
|
||||
impl NetworkProtocolHandler<SyncMessage> for EthSync {
|
||||
fn initialize(&self, io: &NetworkContext<SyncMessage>) {
|
||||
io.register_timer(0, 1000).expect("Error registering sync timer");
|
||||
*self.io_channel.write().unwrap() = io.io_channel();
|
||||
}
|
||||
|
||||
fn read(&self, io: &NetworkContext<SyncMessage>, peer: &PeerId, packet_id: u8, data: &[u8]) {
|
||||
|
||||
@@ -192,3 +192,13 @@ fn restart_on_broken_chain() {
|
||||
|
||||
assert_eq!(net.peer(0).chain.chain_info().best_block_number, 5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn high_td_attach() {
|
||||
let mut net = TestNet::new(2);
|
||||
net.peer_mut(1).chain.add_blocks(10, EachBlockWith::Uncle);
|
||||
net.peer_mut(1).chain.corrupt_block_parent(6);
|
||||
net.sync_steps(20);
|
||||
|
||||
assert_eq!(net.peer(0).chain.chain_info().best_block_number, 5);
|
||||
}
|
||||
|
||||
@@ -43,6 +43,10 @@ impl<'p> SyncIo for TestIo<'p> {
|
||||
fn disconnect_peer(&mut self, _peer_id: PeerId) {
|
||||
}
|
||||
|
||||
fn is_expired(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn respond(&mut self, packet_id: PacketId, data: Vec<u8>) -> Result<(), UtilError> {
|
||||
self.queue.push_back(TestPacket {
|
||||
data: data,
|
||||
|
||||
Reference in New Issue
Block a user