request definitions
This commit is contained in:
parent
1bc124f980
commit
eef9a355af
@ -27,18 +27,19 @@ use block_import_error::BlockImportError;
|
|||||||
use block_status::BlockStatus;
|
use block_status::BlockStatus;
|
||||||
use verification::queue::{Config as QueueConfig, HeaderQueue, QueueInfo, Status};
|
use verification::queue::{Config as QueueConfig, HeaderQueue, QueueInfo, Status};
|
||||||
use transaction::SignedTransaction;
|
use transaction::SignedTransaction;
|
||||||
|
use types::blockchain_info::BlockChainInfo;
|
||||||
|
|
||||||
use super::provider::{CHTProofRequest, Provider, ProofRequest};
|
use super::provider::{CHTProofRequest, Provider, ProofRequest};
|
||||||
|
|
||||||
use io::IoChannel;
|
use io::IoChannel;
|
||||||
use util::hash::H256;
|
use util::hash::H256;
|
||||||
use util::Bytes;
|
use util::{Bytes, Mutex};
|
||||||
|
|
||||||
/// Light client implementation.
|
/// Light client implementation.
|
||||||
pub struct Client {
|
pub struct Client {
|
||||||
engine: Arc<Engine>,
|
engine: Arc<Engine>,
|
||||||
header_queue: HeaderQueue,
|
header_queue: HeaderQueue,
|
||||||
message_channel: IoChannel<ClientIoMessage>,
|
message_channel: Mutex<IoChannel<ClientIoMessage>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Client {
|
impl Client {
|
||||||
@ -70,11 +71,12 @@ impl Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the chain info.
|
/// 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 {
|
impl Provider for Client {
|
||||||
fn block_headers(&self, block: H256, skip: usize, max: usize, reverse: bool) -> Vec<Bytes> {
|
fn block_headers(&self, block: H256, skip: usize, max: usize, reverse: bool) -> Vec<Bytes> {
|
||||||
Vec::new()
|
Vec::new()
|
||||||
|
@ -29,6 +29,10 @@ use parking_lot::{Mutex, RwLock};
|
|||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
|
|
||||||
|
use self::request::Request;
|
||||||
|
|
||||||
|
mod request;
|
||||||
|
|
||||||
const TIMEOUT: TimerToken = 0;
|
const TIMEOUT: TimerToken = 0;
|
||||||
const TIMEOUT_INTERVAL_MS: u64 = 1000;
|
const TIMEOUT_INTERVAL_MS: u64 = 1000;
|
||||||
|
|
||||||
@ -87,11 +91,9 @@ mod packet {
|
|||||||
pub const TRANSACTION_PROOFS: u8 = 0x13;
|
pub const TRANSACTION_PROOFS: u8 = 0x13;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Request;
|
|
||||||
|
|
||||||
struct Requested {
|
struct Requested {
|
||||||
timestamp: usize,
|
timestamp: usize,
|
||||||
total: Request,
|
req: Request,
|
||||||
}
|
}
|
||||||
|
|
||||||
// data about each peer.
|
// data about each peer.
|
||||||
@ -172,7 +174,7 @@ impl Chain {
|
|||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn status(&self, peer: &PeerId, io: &NetworkContext) {
|
fn status(&self, peer: &PeerId, io: &NetworkContext, data: UntrustedRlp) {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,6 +207,16 @@ impl Chain {
|
|||||||
unimplemented!()
|
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.
|
// Handle a request for proofs.
|
||||||
fn get_proofs(&self, peer: &PeerId, io: &NetworkContext, data: UntrustedRlp) {
|
fn get_proofs(&self, peer: &PeerId, io: &NetworkContext, data: UntrustedRlp) {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
@ -284,7 +296,7 @@ impl NetworkProtocolHandler for Chain {
|
|||||||
packet::BLOCK_BODIES => self.block_bodies(peer, io, rlp),
|
packet::BLOCK_BODIES => self.block_bodies(peer, io, rlp),
|
||||||
|
|
||||||
packet::GET_RECEIPTS => self.get_receipts(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::GET_PROOFS => self.get_proofs(peer, io, rlp),
|
||||||
packet::PROOFS => self.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) {
|
fn disconnected(&self, io: &NetworkContext, peer: &PeerId) {
|
||||||
self.on_disconnect(peer, io);
|
self.on_disconnect(*peer, io);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn timeout(&self, io: &NetworkContext, timer: TimerToken) {
|
fn timeout(&self, io: &NetworkContext, timer: TimerToken) {
|
||||||
|
@ -14,125 +14,152 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
//! LES request types.
|
/// LES request types.
|
||||||
|
|
||||||
use util::bigint::prelude::*;
|
use ethcore::transaction::Transaction;
|
||||||
use rlp::*;
|
use util::{Address, H256};
|
||||||
|
|
||||||
/// An LES request. This defines its data format, and the format of its response type.
|
/// A request for block headers.
|
||||||
pub trait Request: Sized {
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
/// The response type of this request.
|
pub struct Headers {
|
||||||
type Response: Response;
|
/// Block information for the request being made.
|
||||||
|
pub block: (u64, H256),
|
||||||
/// The error type when decoding a response.
|
/// The maximum amount of headers which can be returned.
|
||||||
type Error;
|
pub max: u64,
|
||||||
|
/// The amount of headers to skip between each response entry.
|
||||||
/// Whether this request is empty.
|
pub skip: u64,
|
||||||
fn is_empty(&self) -> bool;
|
/// Whether the headers should proceed in falling number from the initial block.
|
||||||
|
pub reverse: 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>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Request responses. These must have a combination operation used to fill the gaps
|
/// A request for specific block bodies.
|
||||||
/// in one response with data from another.
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub trait Response: Sized {
|
pub struct Bodies {
|
||||||
/// Combine the two responses into one. This can only be relied on to behave correctly
|
/// Hashes which bodies are being requested for.
|
||||||
/// if `other` is a response to a sub-request of the request this response was
|
pub block_hashes: Vec<H256>
|
||||||
/// produced from.
|
|
||||||
fn combine(&mut self, other: Self);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A request for block bodies.
|
/// A request for transaction receipts.
|
||||||
pub struct BlockBodies {
|
///
|
||||||
hashes: Vec<H256>,
|
/// 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.
|
/// A request for state proofs.
|
||||||
pub struct BlockBodiesResponse {
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
bodies: Vec<(H256, Vec<u8>)>,
|
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 {
|
/// A request for contract code.
|
||||||
type Response = BlockBodiesResponse;
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
type Error = ::rlp::DecoderError;
|
pub struct ContractCodes {
|
||||||
|
/// Block hash and account key (== sha3(address)) pairs to fetch code for.
|
||||||
fn is_empty(&self) -> bool { self.hashes.is_empty() }
|
pub code_requests: Vec<(H256, H256)>,
|
||||||
|
|
||||||
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,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Response for BlockBodiesResponse {
|
/// A request for header proofs from the Canonical Hash Trie.
|
||||||
fn identity() -> Self {
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
BlockBodiesResponse {
|
pub struct HeaderProofs {
|
||||||
bodies: Vec::new(),
|
/// 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) {
|
/// A request for block deltas -- merkle proofs of all changed trie nodes and code.
|
||||||
let other_iter = other.bodies.into_iter();
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct BlockDeltas {
|
||||||
|
/// Block hashes deltas are being requested for.
|
||||||
|
pub block_hashes: Vec<H256>,
|
||||||
|
}
|
||||||
|
|
||||||
'a:
|
/// A request for a single transaction merkle proof.
|
||||||
for &mut (ref my_hash, ref mut my_body) in self.bodies.iter_mut() {
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
loop {
|
pub struct TransactionProof {
|
||||||
match other_iter.next() {
|
/// The block hash to use the initial state from.
|
||||||
Some((hash, body)) if hash == my_hash && !body.is_empty() => {
|
pub block_hash: H256,
|
||||||
*my_body = body.to_owned();
|
/// The address to treat as the sender of the transaction.
|
||||||
break
|
pub sender: Address,
|
||||||
}
|
/// The raw transaction request itself.
|
||||||
Some(_) => continue,
|
pub transaction: Transaction,
|
||||||
None => break 'a,
|
}
|
||||||
}
|
|
||||||
}
|
/// 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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user