From edf17d00c43a3ac38d33aadf91fd8ea5b4adc0af Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Fri, 4 Nov 2016 18:40:31 +0100 Subject: [PATCH] revise light implementation strategy --- ethcore/src/light/client.rs | 12 +++++----- ethcore/src/light/provider.rs | 8 +++++-- sync/src/light/mod.rs | 41 ++++++++++++++++++++++++++++++----- 3 files changed, 48 insertions(+), 13 deletions(-) diff --git a/ethcore/src/light/client.rs b/ethcore/src/light/client.rs index ae882b1a8..9f1b00e71 100644 --- a/ethcore/src/light/client.rs +++ b/ethcore/src/light/client.rs @@ -69,16 +69,16 @@ impl Client { pub fn queue_info(&self) -> QueueInfo { self.header_queue.queue_info() } - - /// Get the chain info. - pub fn chain_info(&self) -> BlockChainInfo { - unimplemented!() - } } // dummy implementation -- may draw from canonical cache further on. impl Provider for Client { - fn block_headers(&self, block: H256, skip: usize, max: usize, reverse: bool) -> Vec { + /// Get the chain info. + fn chain_info(&self) -> BlockChainInfo { + unimplemented!() + } + + fn block_headers(&self, block: (u64, H256), skip: usize, max: usize, reverse: bool) -> Vec { Vec::new() } diff --git a/ethcore/src/light/provider.rs b/ethcore/src/light/provider.rs index 05859c78b..10d3eed88 100644 --- a/ethcore/src/light/provider.rs +++ b/ethcore/src/light/provider.rs @@ -20,6 +20,7 @@ pub use proof_request::{CHTProofRequest, ProofRequest}; use transaction::SignedTransaction; +use blockchain_info::BlockChainInfo; use util::Bytes; use util::hash::H256; @@ -30,13 +31,16 @@ use util::hash::H256; /// Requests which can't be fulfilled should return an empty RLP list. /// /// [1]: https://github.com/ethcore/parity/wiki/Light-Ethereum-Subprotocol-(LES) -pub trait Provider { +pub trait Provider: Sync { + /// Provide current blockchain info. + fn chain_info(&self) -> BlockChainInfo; + /// Provide a list of headers starting at the requested block, /// possibly in reverse and skipping `skip` at a time. /// /// The returned vector may have any length in the range [0, `max`], but the /// results within must adhere to the `skip` and `reverse` parameters. - fn block_headers(&self, block: H256, skip: usize, max: usize, reverse: bool) -> Vec; + fn block_headers(&self, block: (u64, H256), skip: usize, max: usize, reverse: bool) -> Vec; /// Provide as many as possible of the requested blocks (minus the headers) encoded /// in RLP format. diff --git a/sync/src/light/mod.rs b/sync/src/light/mod.rs index a4aa0dcf7..19dac8561 100644 --- a/sync/src/light/mod.rs +++ b/sync/src/light/mod.rs @@ -91,6 +91,22 @@ mod packet { pub const TRANSACTION_PROOFS: u8 = 0x13; } +// helper macro for disconnecting peer on error while returning +// the value if ok. +// requires that error types are debug. +macro_rules! try_dc { + ($io: expr, $peer: expr, $e: expr) => { + match $e { + Ok(x) => x, + Err(e) => { + debug!(target: "les", "disconnecting peer {} due to error {:?}", $peer, e); + $io.disconnect_peer($peer); + return; + } + } + } +} + struct Requested { timestamp: usize, req: Request, @@ -102,9 +118,14 @@ struct Peer { current_asking: HashSet, // pending request ids. } -/// This handles synchronization of the header chain for a light client. -pub struct Chain { - client: Client, +/// This is an implementation of the light ethereum network protocol, abstracted +/// over a `Provider` of data and a p2p network. +/// +/// This is simply designed for request-response purposes. Higher level uses +/// of the protocol, such as synchronization, will function as wrappers around +/// this system. +pub struct LightProtocol { + provider: Box, genesis_hash: H256, mainnet: bool, peers: RwLock>, @@ -112,7 +133,7 @@ pub struct Chain { req_id: AtomicUsize, } -impl Chain { +impl LightProtocol { // make a request to a given peer. fn request_from(&self, peer: &PeerId, req: Request) { unimplemented!() @@ -189,6 +210,14 @@ impl Chain { fn get_block_headers(&self, peer: &PeerId, io: &NetworkContext, data: UntrustedRlp) { const MAX_HEADERS: usize = 512; + let req_id: u64 = try_dc!(io, peer, data.val_at(0)); + let block = try_dc!(io, peer, data.at(1).and_then(|block_list| { + (try!(block_list.val_at(0)), try!(block_list.val_at(1)) + })); + let max = ::std::cmp::min(MAX_HEADERS, try_dc!(io, peer, data.val_at(2))); + let reverse = try_dc!(io, peer, data.val_at(3)); + + let headers = self.provider.block_headers() unimplemented!() } @@ -199,6 +228,8 @@ impl Chain { // Handle a request for block bodies. fn get_block_bodies(&self, peer: &PeerId, io: &NetworkContext, data: UntrustedRlp) { + const MAX_BODIES: usize = 512; + unimplemented!() } @@ -278,7 +309,7 @@ impl Chain { } } -impl NetworkProtocolHandler for Chain { +impl NetworkProtocolHandler for LightProtocol { fn initialize(&self, io: &NetworkContext) { io.register_timer(TIMEOUT, TIMEOUT_INTERVAL_MS).expect("Error registering sync timer."); }