request definitions

This commit is contained in:
Robert Habermeier 2016-11-04 17:19:01 +01:00
parent 1bc124f980
commit eef9a355af
3 changed files with 156 additions and 115 deletions

View File

@ -27,18 +27,19 @@ use block_import_error::BlockImportError;
use block_status::BlockStatus;
use verification::queue::{Config as QueueConfig, HeaderQueue, QueueInfo, Status};
use transaction::SignedTransaction;
use types::blockchain_info::BlockChainInfo;
use super::provider::{CHTProofRequest, Provider, ProofRequest};
use io::IoChannel;
use util::hash::H256;
use util::Bytes;
use util::{Bytes, Mutex};
/// Light client implementation.
pub struct Client {
engine: Arc<Engine>,
header_queue: HeaderQueue,
message_channel: IoChannel<ClientIoMessage>,
message_channel: Mutex<IoChannel<ClientIoMessage>>,
}
impl Client {
@ -70,11 +71,12 @@ impl Client {
}
/// Get the chain info.
pub fn chain_info(&self) -> ChainInfo {
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<Bytes> {
Vec::new()

View File

@ -29,6 +29,10 @@ use parking_lot::{Mutex, RwLock};
use std::collections::{HashMap, HashSet};
use std::sync::atomic::{AtomicUsize, Ordering};
use self::request::Request;
mod request;
const TIMEOUT: TimerToken = 0;
const TIMEOUT_INTERVAL_MS: u64 = 1000;
@ -87,11 +91,9 @@ mod packet {
pub const TRANSACTION_PROOFS: u8 = 0x13;
}
struct Request;
struct Requested {
timestamp: usize,
total: Request,
req: Request,
}
// data about each peer.
@ -172,7 +174,7 @@ impl Chain {
unimplemented!()
}
fn status(&self, peer: &PeerId, io: &NetworkContext) {
fn status(&self, peer: &PeerId, io: &NetworkContext, data: UntrustedRlp) {
unimplemented!()
}
@ -205,6 +207,16 @@ impl Chain {
unimplemented!()
}
// Handle a request for receipts.
fn get_receipts(&self, peer: &PeerId, io: &NetworkContext, data: UntrustedRlp) {
unimplemented!()
}
// Receive a response for receipts.
fn receipts(&self, peer: &PeerId, io: &NetworkContext, data: UntrustedRlp) {
unimplemented!()
}
// Handle a request for proofs.
fn get_proofs(&self, peer: &PeerId, io: &NetworkContext, data: UntrustedRlp) {
unimplemented!()
@ -284,7 +296,7 @@ impl NetworkProtocolHandler for Chain {
packet::BLOCK_BODIES => self.block_bodies(peer, io, rlp),
packet::GET_RECEIPTS => self.get_receipts(peer, io, rlp),
packet::RECEIPTS => self.receipt(peer, io, rlp),
packet::RECEIPTS => self.receipts(peer, io, rlp),
packet::GET_PROOFS => self.get_proofs(peer, io, rlp),
packet::PROOFS => self.proofs(peer, io, rlp),
@ -311,7 +323,7 @@ impl NetworkProtocolHandler for Chain {
}
fn disconnected(&self, io: &NetworkContext, peer: &PeerId) {
self.on_disconnect(peer, io);
self.on_disconnect(*peer, io);
}
fn timeout(&self, io: &NetworkContext, timer: TimerToken) {

View File

@ -14,125 +14,152 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! LES request types.
/// LES request types.
use util::bigint::prelude::*;
use rlp::*;
use ethcore::transaction::Transaction;
use util::{Address, H256};
/// An LES request. This defines its data format, and the format of its response type.
pub trait Request: Sized {
/// The response type of this request.
type Response: Response;
/// The error type when decoding a response.
type Error;
/// Whether this request is empty.
fn is_empty(&self) -> bool;
/// The remainder of this request unfulfilled by the response. Required to return
/// an equivalent request when provided with an empty response.
fn remainder(&self, res: &Self::Response) -> Self;
/// Attempt to parse raw data into a response object
/// or an error. Behavior undefined if the raw data didn't originate from
/// this request.
fn parse_response(&self, raw: &[u8]) -> Result<Self::Response, Self::Error>;
/// A request for block headers.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Headers {
/// Block information for the request being made.
pub block: (u64, H256),
/// The maximum amount of headers which can be returned.
pub max: u64,
/// The amount of headers to skip between each response entry.
pub skip: u64,
/// Whether the headers should proceed in falling number from the initial block.
pub reverse: bool,
}
/// Request responses. These must have a combination operation used to fill the gaps
/// in one response with data from another.
pub trait Response: Sized {
/// Combine the two responses into one. This can only be relied on to behave correctly
/// if `other` is a response to a sub-request of the request this response was
/// produced from.
fn combine(&mut self, other: Self);
/// A request for specific block bodies.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Bodies {
/// Hashes which bodies are being requested for.
pub block_hashes: Vec<H256>
}
/// A request for block bodies.
pub struct BlockBodies {
hashes: Vec<H256>,
/// A request for transaction receipts.
///
/// This request is answered with a list of transaction receipts for each block
/// requested.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Receipts {
/// Block hashes to return receipts for.
pub block_hashes: Vec<H256>,
}
/// A response for block bodies.
pub struct BlockBodiesResponse {
bodies: Vec<(H256, Vec<u8>)>,
/// A request for state proofs.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct StateProofs {
/// Block hash to query state from.
pub block: H256,
/// Key of the state trie -- corresponds to account hash.
pub key1: H256,
/// Key in that account's storage trie; if empty, then the account RLP should be
/// returned.
pub key2: Option<H256>,
/// if greater than zero, trie nodes beyond this level may be omitted.
pub from_level: u32, // could even safely be u8; trie w/ 32-byte key can be at most 64-levels deep.
}
impl Request for BlockBodies {
type Response = BlockBodiesResponse;
type Error = ::rlp::DecoderError;
fn is_empty(&self) -> bool { self.hashes.is_empty() }
fn remainder(&self, res: &Self::Response) -> Self {
let mut remaining = Vec::new();
let bodies = res.bodies.iter().map(|&(_, ref b) b).chain(::std::iter::repeat(&Vec::new()));
for (hash, body) in self.hashes.iter().zip(bodies) {
if body.is_empty() {
remaining.push(hash);
}
}
BlockBodies {
hashes: remaining,
}
}
fn parse_response(&self, raw: &[u8]) -> Result<Self::Response, Self::Error> {
use ethcore::transaction::SignedTransaction;
use ethcore::header::Header;
let rlp = UntrustedRlp::new(raw);
let mut bodies = Vec::with_capacity(self.hashes.len());
let items = rlp.iter();
for hash in self.hashes.iter().cloned() {
let res_bytes = match items.next() {
Some(rlp) => {
// perform basic block verification.
// TODO: custom error type?
try!(rlp.val_at::<Vec<SignedTransaction>>(0)
.and_then(|_| rlp.val_at::<Vec<Header>>(1)));
try!(rlp.data()).to_owned()
}
None => Vec::new(),
};
bodies.push((hash, res_bytes));
}
Ok(BlockBodiesResponse {
bodies: bodies,
})
}
/// A request for contract code.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ContractCodes {
/// Block hash and account key (== sha3(address)) pairs to fetch code for.
pub code_requests: Vec<(H256, H256)>,
}
impl Response for BlockBodiesResponse {
fn identity() -> Self {
BlockBodiesResponse {
bodies: Vec::new(),
}
}
/// A request for header proofs from the Canonical Hash Trie.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct HeaderProofs {
/// Number of the CHT.
pub cht_number: u64,
/// Block number requested.
pub block_number: u64,
/// If greater than zero, trie nodes beyond this level may be omitted.
pub from_level: u32,
}
fn combine(&mut self, other: Self) {
let other_iter = other.bodies.into_iter();
/// A request for block deltas -- merkle proofs of all changed trie nodes and code.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BlockDeltas {
/// Block hashes deltas are being requested for.
pub block_hashes: Vec<H256>,
}
'a:
for &mut (ref my_hash, ref mut my_body) in self.bodies.iter_mut() {
loop {
match other_iter.next() {
Some((hash, body)) if hash == my_hash && !body.is_empty() => {
*my_body = body.to_owned();
break
}
Some(_) => continue,
None => break 'a,
}
}
/// A request for a single transaction merkle proof.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TransactionProof {
/// The block hash to use the initial state from.
pub block_hash: H256,
/// The address to treat as the sender of the transaction.
pub sender: Address,
/// The raw transaction request itself.
pub transaction: Transaction,
}
/// A request for transaction merkle proofs.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TransactionProofs {
/// Transaction proof requests.
pub tx_reqs: Vec<TransactionProof>,
}
/// Kinds of requests.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Kind {
/// Requesting headers.
Headers,
/// Requesting block bodies.
Bodies,
/// Requesting transaction receipts.
Receipts,
/// Requesting proofs of state trie nodes.
StateProofs,
/// Requesting contract code by hash.
Codes,
/// Requesting header proofs (from the CHT).
HeaderProofs,
/// Requesting block deltas.
Deltas,
/// Requesting merkle proofs for transactions.
TransactionProofs,
}
/// Encompasses all possible types of requests in a single structure.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Request {
/// Requesting headers.
Headers(Headers),
/// Requesting block bodies.
Bodies(Bodies),
/// Requesting transaction receipts.
Receipts(Receipts),
/// Requesting state proofs.
StateProofs(StateProofs),
/// Requesting contract codes.
Codes(ContractCodes),
/// Requesting header proofs.
HeaderProofs(HeaderProofs),
/// Requesting block deltas.
Deltas(BlockDeltas),
/// Requesting transaction proofs.
TransactionProofs(TransactionProofs),
}
impl Request {
/// Get the kind of request this is.
pub fn kind(&self) -> Kind {
match *self {
Request::Headers(_) => Kind::Headers,
Request::Bodies(_) => Kind::Bodies,
Request::Receipts(_) => Kind::Receipts,
Request::StateProofs(_) => Kind::StateProofs,
Request::Codes(_) => Kind::Codes,
Request::HeaderProofs(_) => Kind::HeaderProofs,
Request::Deltas(_) => Kind::Deltas,
Request::TransactionProofs(_) => Kind::TransactionProofs,
}
}
}