eth_syncing RPC for light client

This commit is contained in:
Robert Habermeier 2017-03-23 03:23:53 +01:00
parent a55001ad1d
commit b96eb45877
3 changed files with 65 additions and 5 deletions

View File

@ -245,7 +245,22 @@ impl Eth for EthClient {
}
fn syncing(&self) -> Result<SyncStatus, Error> {
rpc_unimplemented!()
if self.sync.is_major_importing() {
let chain_info = self.client.chain_info();
let current_block = U256::from(chain_info.best_block_number);
let highest_block = self.sync.highest_block().map(U256::from)
.unwrap_or_else(|| current_block.clone());
Ok(SyncStatus::Info(SyncInfo {
starting_block: U256::from(self.sync.start_block()).into(),
current_block: current_block.into(),
highest_block: highest_block.into(),
warp_chunks_amount: None,
warp_chunks_processed: None,
}))
} else {
Ok(SyncStatus::None)
}
}
fn author(&self, _meta: Self::Metadata) -> BoxFuture<RpcH160, Error> {

View File

@ -669,6 +669,7 @@ pub struct LightSyncParams<L> {
/// Service for light synchronization.
pub struct LightSync {
proto: Arc<LightProtocol>,
sync: Arc<::light_sync::SyncInfo + Sync + Send>,
network: NetworkService,
subprotocol_name: [u8; 3],
network_id: u64,
@ -682,7 +683,7 @@ impl LightSync {
use light_sync::LightSync as SyncHandler;
// initialize light protocol handler and attach sync module.
let light_proto = {
let (sync, light_proto) = {
let light_params = LightParams {
network_id: params.network_id,
flow_params: Default::default(), // or `None`?
@ -695,20 +696,21 @@ impl LightSync {
};
let mut light_proto = LightProtocol::new(params.client.clone(), light_params);
let sync_handler = try!(SyncHandler::new(params.client.clone()));
light_proto.add_handler(Arc::new(sync_handler));
let sync_handler = Arc::new(try!(SyncHandler::new(params.client.clone())));
light_proto.add_handler(sync_handler.clone());
for handler in params.handlers {
light_proto.add_handler(handler);
}
Arc::new(light_proto)
(sync_handler, Arc::new(light_proto))
};
let service = try!(NetworkService::new(params.network_config));
Ok(LightSync {
proto: light_proto,
sync: sync,
network: service,
subprotocol_name: params.subprotocol_name,
network_id: params.network_id,
@ -726,6 +728,12 @@ impl LightSync {
}
}
impl ::std::ops::Deref for LightSync {
type Target = ::light_sync::SyncInfo;
fn deref(&self) -> &Self::Target { &*self.sync }
}
impl ManageNetwork for LightSync {
fn accept_unreserved_peers(&self) {
self.network.set_non_reserved_mode(NonReservedPeerMode::Accept);

View File

@ -206,6 +206,7 @@ impl<'a> ResponseContext for ResponseCtx<'a> {
/// Light client synchronization manager. See module docs for more details.
pub struct LightSync<L: AsLightClient> {
start_block_number: u64,
best_seen: Mutex<Option<ChainInfo>>, // best seen block on the network.
peers: RwLock<HashMap<PeerId, Mutex<Peer>>>, // peers which are relevant to synchronization.
client: Arc<L>,
@ -525,6 +526,7 @@ impl<L: AsLightClient> LightSync<L> {
/// so it can act on events.
pub fn new(client: Arc<L>) -> Result<Self, ::std::io::Error> {
Ok(LightSync {
start_block_number: client.as_light_client().chain_info().best_block_number,
best_seen: Mutex::new(None),
peers: RwLock::new(HashMap::new()),
client: client,
@ -533,3 +535,38 @@ impl<L: AsLightClient> LightSync<L> {
})
}
}
/// Trait for erasing the type of a light sync object and exposing read-only methods.
pub trait SyncInfo {
/// 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;
}
impl<L: AsLightClient> SyncInfo for LightSync<L> {
fn highest_block(&self) -> Option<u64> {
self.best_seen.lock().as_ref().map(|x| x.head_num)
}
fn start_block(&self) -> u64 {
self.start_block_number
}
fn is_major_importing(&self) -> bool {
const EMPTY_QUEUE: usize = 3;
if self.client.as_light_client().queue_info().unverified_queue_size > EMPTY_QUEUE {
return true;
}
match *self.state.lock() {
SyncState::Idle => false,
_ => true,
}
}
}