revise light implementation strategy

This commit is contained in:
Robert Habermeier 2016-11-04 18:40:31 +01:00
parent 90a2c37977
commit edf17d00c4
3 changed files with 48 additions and 13 deletions

View File

@ -69,16 +69,16 @@ impl Client {
pub fn queue_info(&self) -> QueueInfo { pub fn queue_info(&self) -> QueueInfo {
self.header_queue.queue_info() 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. // dummy implementation -- may draw from canonical cache further on.
impl Provider for Client { impl Provider for Client {
fn block_headers(&self, block: H256, skip: usize, max: usize, reverse: bool) -> Vec<Bytes> { /// Get the chain info.
fn chain_info(&self) -> BlockChainInfo {
unimplemented!()
}
fn block_headers(&self, block: (u64, H256), skip: usize, max: usize, reverse: bool) -> Vec<Bytes> {
Vec::new() Vec::new()
} }

View File

@ -20,6 +20,7 @@
pub use proof_request::{CHTProofRequest, ProofRequest}; pub use proof_request::{CHTProofRequest, ProofRequest};
use transaction::SignedTransaction; use transaction::SignedTransaction;
use blockchain_info::BlockChainInfo;
use util::Bytes; use util::Bytes;
use util::hash::H256; use util::hash::H256;
@ -30,13 +31,16 @@ use util::hash::H256;
/// Requests which can't be fulfilled should return an empty RLP list. /// Requests which can't be fulfilled should return an empty RLP list.
/// ///
/// [1]: https://github.com/ethcore/parity/wiki/Light-Ethereum-Subprotocol-(LES) /// [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, /// Provide a list of headers starting at the requested block,
/// possibly in reverse and skipping `skip` at a time. /// possibly in reverse and skipping `skip` at a time.
/// ///
/// The returned vector may have any length in the range [0, `max`], but the /// The returned vector may have any length in the range [0, `max`], but the
/// results within must adhere to the `skip` and `reverse` parameters. /// results within must adhere to the `skip` and `reverse` parameters.
fn block_headers(&self, block: H256, skip: usize, max: usize, reverse: bool) -> Vec<Bytes>; fn block_headers(&self, block: (u64, H256), skip: usize, max: usize, reverse: bool) -> Vec<Bytes>;
/// Provide as many as possible of the requested blocks (minus the headers) encoded /// Provide as many as possible of the requested blocks (minus the headers) encoded
/// in RLP format. /// in RLP format.

View File

@ -91,6 +91,22 @@ mod packet {
pub const TRANSACTION_PROOFS: u8 = 0x13; 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 { struct Requested {
timestamp: usize, timestamp: usize,
req: Request, req: Request,
@ -102,9 +118,14 @@ struct Peer {
current_asking: HashSet<usize>, // pending request ids. current_asking: HashSet<usize>, // pending request ids.
} }
/// This handles synchronization of the header chain for a light client. /// This is an implementation of the light ethereum network protocol, abstracted
pub struct Chain { /// over a `Provider` of data and a p2p network.
client: Client, ///
/// 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<Provider>,
genesis_hash: H256, genesis_hash: H256,
mainnet: bool, mainnet: bool,
peers: RwLock<HashMap<PeerId, Peer>>, peers: RwLock<HashMap<PeerId, Peer>>,
@ -112,7 +133,7 @@ pub struct Chain {
req_id: AtomicUsize, req_id: AtomicUsize,
} }
impl Chain { impl LightProtocol {
// make a request to a given peer. // make a request to a given peer.
fn request_from(&self, peer: &PeerId, req: Request) { fn request_from(&self, peer: &PeerId, req: Request) {
unimplemented!() unimplemented!()
@ -189,6 +210,14 @@ impl Chain {
fn get_block_headers(&self, peer: &PeerId, io: &NetworkContext, data: UntrustedRlp) { fn get_block_headers(&self, peer: &PeerId, io: &NetworkContext, data: UntrustedRlp) {
const MAX_HEADERS: usize = 512; 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!() unimplemented!()
} }
@ -199,6 +228,8 @@ impl Chain {
// Handle a request for block bodies. // Handle a request for block bodies.
fn get_block_bodies(&self, peer: &PeerId, io: &NetworkContext, data: UntrustedRlp) { fn get_block_bodies(&self, peer: &PeerId, io: &NetworkContext, data: UntrustedRlp) {
const MAX_BODIES: usize = 512;
unimplemented!() unimplemented!()
} }
@ -278,7 +309,7 @@ impl Chain {
} }
} }
impl NetworkProtocolHandler for Chain { impl NetworkProtocolHandler for LightProtocol {
fn initialize(&self, io: &NetworkContext) { fn initialize(&self, io: &NetworkContext) {
io.register_timer(TIMEOUT, TIMEOUT_INTERVAL_MS).expect("Error registering sync timer."); io.register_timer(TIMEOUT, TIMEOUT_INTERVAL_MS).expect("Error registering sync timer.");
} }