move light to its own crate again
This commit is contained in:
parent
6e1a1f9dec
commit
61c3358447
@ -35,5 +35,17 @@ pub mod client;
|
|||||||
pub mod net;
|
pub mod net;
|
||||||
pub mod provider;
|
pub mod provider;
|
||||||
|
|
||||||
|
mod types;
|
||||||
|
|
||||||
pub use self::provider::Provider;
|
pub use self::provider::Provider;
|
||||||
pub use types::les_request as request;
|
pub use types::les_request as request;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate log;
|
||||||
|
|
||||||
|
extern crate ethcore;
|
||||||
|
extern crate ethcore_util as util;
|
||||||
|
extern crate ethcore_network as network;
|
||||||
|
extern crate ethcore_io as io;
|
||||||
|
extern crate rlp;
|
||||||
|
extern crate time;
|
194
ethcore/light/src/provider.rs
Normal file
194
ethcore/light/src/provider.rs
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
// Copyright 2015, 2016 Ethcore (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
//! A provider for the LES protocol. This is typically a full node, who can
|
||||||
|
//! give as much data as necessary to its peers.
|
||||||
|
|
||||||
|
use ethcore::blockchain_info::BlockChainInfo;
|
||||||
|
use ethcore::client::{BlockChainClient, ProvingBlockChainClient};
|
||||||
|
use ethcore::transaction::SignedTransaction;
|
||||||
|
|
||||||
|
use util::{Bytes, H256};
|
||||||
|
|
||||||
|
use light::request;
|
||||||
|
|
||||||
|
/// Defines the operations that a provider for `LES` must fulfill.
|
||||||
|
///
|
||||||
|
/// These are defined at [1], but may be subject to change.
|
||||||
|
/// Requests which can't be fulfilled should return either an empty RLP list
|
||||||
|
/// or empty vector where appropriate.
|
||||||
|
///
|
||||||
|
/// [1]: https://github.com/ethcore/parity/wiki/Light-Ethereum-Subprotocol-(LES)
|
||||||
|
pub trait Provider: Send + Sync {
|
||||||
|
/// Provide current blockchain info.
|
||||||
|
fn chain_info(&self) -> BlockChainInfo;
|
||||||
|
|
||||||
|
/// Find the depth of a common ancestor between two blocks.
|
||||||
|
/// If either block is unknown or an ancestor can't be found
|
||||||
|
/// then return `None`.
|
||||||
|
fn reorg_depth(&self, a: &H256, b: &H256) -> Option<u64>;
|
||||||
|
|
||||||
|
/// Earliest block where state queries are available.
|
||||||
|
/// If `None`, no state queries are servable.
|
||||||
|
fn earliest_state(&self) -> Option<u64>;
|
||||||
|
|
||||||
|
/// 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, req: request::Headers) -> Vec<Bytes>;
|
||||||
|
|
||||||
|
/// Provide as many as possible of the requested blocks (minus the headers) encoded
|
||||||
|
/// in RLP format.
|
||||||
|
fn block_bodies(&self, req: request::Bodies) -> Vec<Bytes>;
|
||||||
|
|
||||||
|
/// Provide the receipts as many as possible of the requested blocks.
|
||||||
|
/// Returns a vector of RLP-encoded lists of receipts.
|
||||||
|
fn receipts(&self, req: request::Receipts) -> Vec<Bytes>;
|
||||||
|
|
||||||
|
/// Provide a set of merkle proofs, as requested. Each request is a
|
||||||
|
/// block hash and request parameters.
|
||||||
|
///
|
||||||
|
/// Returns a vector of RLP-encoded lists satisfying the requests.
|
||||||
|
fn proofs(&self, req: request::StateProofs) -> Vec<Bytes>;
|
||||||
|
|
||||||
|
/// Provide contract code for the specified (block_hash, account_hash) pairs.
|
||||||
|
/// Each item in the resulting vector is either the raw bytecode or empty.
|
||||||
|
fn contract_code(&self, req: request::ContractCodes) -> Vec<Bytes>;
|
||||||
|
|
||||||
|
/// Provide header proofs from the Canonical Hash Tries.
|
||||||
|
fn header_proofs(&self, req: request::HeaderProofs) -> Vec<Bytes>;
|
||||||
|
|
||||||
|
/// Provide pending transactions.
|
||||||
|
fn pending_transactions(&self) -> Vec<SignedTransaction>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implementation of a light client data provider for a client.
|
||||||
|
impl<T: ProvingBlockChainClient + ?Sized> light::Provider for T {
|
||||||
|
fn chain_info(&self) -> BlockChainInfo {
|
||||||
|
BlockChainClient::chain_info(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reorg_depth(&self, a: &H256, b: &H256) -> Option<u64> {
|
||||||
|
self.tree_route(a, b).map(|route| route.index as u64)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn earliest_state(&self) -> Option<u64> {
|
||||||
|
Some(self.pruning_info().earliest_state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn block_headers(&self, req: request::Headers) -> Vec<Bytes> {
|
||||||
|
let best_num = self.chain.read().best_block_number();
|
||||||
|
let start_num = req.block_num;
|
||||||
|
|
||||||
|
match self.block_hash(BlockID::Number(req.block_num)) {
|
||||||
|
Some(hash) if hash == req.block_hash => {}
|
||||||
|
_=> {
|
||||||
|
trace!(target: "les_provider", "unknown/non-canonical start block in header request: {:?}", (req.block_num, req.block_hash));
|
||||||
|
return vec![]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(0u64..req.max as u64)
|
||||||
|
.map(|x: u64| x.saturating_mul(req.skip))
|
||||||
|
.take_while(|x| if req.reverse { x < &start_num } else { best_num - start_num < *x })
|
||||||
|
.map(|x| if req.reverse { start_num - x } else { start_num + x })
|
||||||
|
.map(|x| self.block_header(BlockID::Number(x)))
|
||||||
|
.take_while(|x| x.is_some())
|
||||||
|
.flat_map(|x| x)
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn block_bodies(&self, req: request::Bodies) -> Vec<Bytes> {
|
||||||
|
use ids::BlockID;
|
||||||
|
|
||||||
|
req.block_hashes.into_iter()
|
||||||
|
.map(|hash| self.block_body(BlockID::Hash(hash)))
|
||||||
|
.map(|body| body.unwrap_or_else(|| ::rlp::EMPTY_LIST_RLP.to_vec()))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn receipts(&self, req: request::Receipts) -> Vec<Bytes> {
|
||||||
|
req.block_hashes.into_iter()
|
||||||
|
.map(|hash| self.block_receipts(&hash))
|
||||||
|
.map(|receipts| receipts.unwrap_or_else(|| ::rlp::EMPTY_LIST_RLP.to_vec()))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn proofs(&self, req: request::StateProofs) -> Vec<Bytes> {
|
||||||
|
use rlp::{EMPTY_LIST_RLP, RlpStream, Stream};
|
||||||
|
|
||||||
|
let mut results = Vec::with_capacity(req.requests.len());
|
||||||
|
|
||||||
|
for request in req.requests {
|
||||||
|
let state = match self.state_at(BlockID::Hash(request.block)) {
|
||||||
|
Some(state) => state,
|
||||||
|
None => {
|
||||||
|
trace!(target: "light_provider", "state for {} not available", request.block);
|
||||||
|
results.push(EMPTY_LIST_RLP.to_vec());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let res = match request.key2 {
|
||||||
|
Some(storage_key) => state.prove_storage(request.key1, storage_key, request.from_level),
|
||||||
|
None => state.prove_account(request.key1, request.from_level),
|
||||||
|
};
|
||||||
|
|
||||||
|
match res {
|
||||||
|
Ok(records) => {
|
||||||
|
let mut stream = RlpStream::new_list(records.len());
|
||||||
|
for record in records {
|
||||||
|
stream.append_raw(&record, 1);
|
||||||
|
}
|
||||||
|
results.push(stream.out())
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
debug!(target: "light_provider", "encountered error {} while forming proof of state at {}", e, request.block);
|
||||||
|
results.push(EMPTY_LIST_RLP.to_vec());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
results
|
||||||
|
}
|
||||||
|
|
||||||
|
fn contract_code(&self, req: request::ContractCodes) -> Vec<Bytes> {
|
||||||
|
req.code_requests.into_iter()
|
||||||
|
.map(|req| {
|
||||||
|
self.state_at(BlockID::Hash(req.block_hash))
|
||||||
|
.map(|state| {
|
||||||
|
match state.code_by_address_hash(req.account_key) {
|
||||||
|
Ok(code) => code.unwrap_or_else(Vec::new),
|
||||||
|
Err(e) => {
|
||||||
|
debug!(target: "light_provider", "encountered error {} while fetching code.", e);
|
||||||
|
Vec::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).unwrap_or_else(Vec::new)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn header_proofs(&self, req: request::HeaderProofs) -> Vec<Bytes> {
|
||||||
|
req.requests.into_iter().map(|_| ::rlp::EMPTY_LIST_RLP.to_vec()).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pending_transactions(&self) -> Vec<SignedTransaction> {
|
||||||
|
BlockChainClient::pending_transactions(self)
|
||||||
|
}
|
||||||
|
}
|
@ -52,7 +52,7 @@ use blockchain::{BlockChain, BlockProvider, TreeRoute, ImportRoute};
|
|||||||
use client::{
|
use client::{
|
||||||
BlockID, TransactionID, UncleID, TraceId, ClientConfig, BlockChainClient,
|
BlockID, TransactionID, UncleID, TraceId, ClientConfig, BlockChainClient,
|
||||||
MiningBlockChainClient, TraceFilter, CallAnalytics, BlockImportError, Mode,
|
MiningBlockChainClient, TraceFilter, CallAnalytics, BlockImportError, Mode,
|
||||||
ChainNotify, PruningInfo,
|
ChainNotify, PruningInfo, ProvingBlockChainClient,
|
||||||
};
|
};
|
||||||
use client::Error as ClientError;
|
use client::Error as ClientError;
|
||||||
use env_info::EnvInfo;
|
use env_info::EnvInfo;
|
||||||
@ -68,7 +68,6 @@ use factory::Factories;
|
|||||||
use rlp::{decode, View, UntrustedRlp};
|
use rlp::{decode, View, UntrustedRlp};
|
||||||
use state_db::StateDB;
|
use state_db::StateDB;
|
||||||
use rand::OsRng;
|
use rand::OsRng;
|
||||||
use light::{self, request};
|
|
||||||
|
|
||||||
// re-export
|
// re-export
|
||||||
pub use types::blockchain_info::BlockChainInfo;
|
pub use types::blockchain_info::BlockChainInfo;
|
||||||
@ -1378,119 +1377,24 @@ impl MayPanic for Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implementation of a light client data provider for a client.
|
impl ProvingBlockChainClient for Client {
|
||||||
impl light::Provider for Client {
|
fn prove_storage(&self, key1: H256, key2: H256, from_level: u32, id: BlockID) -> Vec<Bytes> {
|
||||||
fn chain_info(&self) -> BlockChainInfo {
|
self.state_at(id)
|
||||||
BlockChainClient::chain_info(self)
|
.and_then(move |state| state.prove_storage(key1, key2, from_level).ok())
|
||||||
|
.unwrap_or_else(Vec::new)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reorg_depth(&self, a: &H256, b: &H256) -> Option<u64> {
|
fn prove_account(&self, key1: H256, from_level: u32, id: BlockID) -> Vec<Bytes> {
|
||||||
self.tree_route(a, b).map(|route| route.index as u64)
|
self.state_at(id)
|
||||||
|
.and_then(move |state| state.prove_account(key1, from_level).ok())
|
||||||
|
.unwrap_or_else(Vec::new)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn earliest_state(&self) -> Option<u64> {
|
fn code_by_hash(&self, account_key: H256, id: BlockID) -> Bytes {
|
||||||
Some(self.pruning_info().earliest_state)
|
self.state_at(id)
|
||||||
}
|
.and_then(move |state| state.code_by_address_hash(account_key).ok())
|
||||||
|
.and_then(|x| x)
|
||||||
fn block_headers(&self, req: request::Headers) -> Vec<Bytes> {
|
.unwrap_or_else(Vec::new)
|
||||||
let best_num = self.chain.read().best_block_number();
|
|
||||||
let start_num = req.block_num;
|
|
||||||
|
|
||||||
match self.block_hash(BlockID::Number(req.block_num)) {
|
|
||||||
Some(hash) if hash == req.block_hash => {}
|
|
||||||
_=> {
|
|
||||||
trace!(target: "les_provider", "unknown/non-canonical start block in header request: {:?}", (req.block_num, req.block_hash));
|
|
||||||
return vec![]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(0u64..req.max as u64)
|
|
||||||
.map(|x: u64| x.saturating_mul(req.skip))
|
|
||||||
.take_while(|x| if req.reverse { x < &start_num } else { best_num - start_num < *x })
|
|
||||||
.map(|x| if req.reverse { start_num - x } else { start_num + x })
|
|
||||||
.map(|x| self.block_header(BlockID::Number(x)))
|
|
||||||
.take_while(|x| x.is_some())
|
|
||||||
.flat_map(|x| x)
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn block_bodies(&self, req: request::Bodies) -> Vec<Bytes> {
|
|
||||||
use ids::BlockID;
|
|
||||||
|
|
||||||
req.block_hashes.into_iter()
|
|
||||||
.map(|hash| self.block_body(BlockID::Hash(hash)))
|
|
||||||
.map(|body| body.unwrap_or_else(|| ::rlp::EMPTY_LIST_RLP.to_vec()))
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn receipts(&self, req: request::Receipts) -> Vec<Bytes> {
|
|
||||||
req.block_hashes.into_iter()
|
|
||||||
.map(|hash| self.block_receipts(&hash))
|
|
||||||
.map(|receipts| receipts.unwrap_or_else(|| ::rlp::EMPTY_LIST_RLP.to_vec()))
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn proofs(&self, req: request::StateProofs) -> Vec<Bytes> {
|
|
||||||
use rlp::{EMPTY_LIST_RLP, RlpStream, Stream};
|
|
||||||
|
|
||||||
let mut results = Vec::with_capacity(req.requests.len());
|
|
||||||
|
|
||||||
for request in req.requests {
|
|
||||||
let state = match self.state_at(BlockID::Hash(request.block)) {
|
|
||||||
Some(state) => state,
|
|
||||||
None => {
|
|
||||||
trace!(target: "light_provider", "state for {} not available", request.block);
|
|
||||||
results.push(EMPTY_LIST_RLP.to_vec());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let res = match request.key2 {
|
|
||||||
Some(storage_key) => state.prove_storage(request.key1, storage_key, request.from_level),
|
|
||||||
None => state.prove_account(request.key1, request.from_level),
|
|
||||||
};
|
|
||||||
|
|
||||||
match res {
|
|
||||||
Ok(records) => {
|
|
||||||
let mut stream = RlpStream::new_list(records.len());
|
|
||||||
for record in records {
|
|
||||||
stream.append_raw(&record, 1);
|
|
||||||
}
|
|
||||||
results.push(stream.out())
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
debug!(target: "light_provider", "encountered error {} while forming proof of state at {}", e, request.block);
|
|
||||||
results.push(EMPTY_LIST_RLP.to_vec());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
results
|
|
||||||
}
|
|
||||||
|
|
||||||
fn contract_code(&self, req: request::ContractCodes) -> Vec<Bytes> {
|
|
||||||
req.code_requests.into_iter()
|
|
||||||
.map(|req| {
|
|
||||||
self.state_at(BlockID::Hash(req.block_hash))
|
|
||||||
.map(|state| {
|
|
||||||
match state.code_by_address_hash(req.account_key) {
|
|
||||||
Ok(code) => code.unwrap_or_else(Vec::new),
|
|
||||||
Err(e) => {
|
|
||||||
debug!(target: "light_provider", "encountered error {} while fetching code.", e);
|
|
||||||
Vec::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).unwrap_or_else(Vec::new)
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn header_proofs(&self, req: request::HeaderProofs) -> Vec<Bytes> {
|
|
||||||
req.requests.into_iter().map(|_| ::rlp::EMPTY_LIST_RLP.to_vec()).collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn pending_transactions(&self) -> Vec<SignedTransaction> {
|
|
||||||
BlockChainClient::pending_transactions(self)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ pub use self::config::{Mode, ClientConfig, DatabaseCompactionProfile, BlockChain
|
|||||||
pub use self::error::Error;
|
pub use self::error::Error;
|
||||||
pub use self::test_client::{TestBlockChainClient, EachBlockWith};
|
pub use self::test_client::{TestBlockChainClient, EachBlockWith};
|
||||||
pub use self::chain_notify::ChainNotify;
|
pub use self::chain_notify::ChainNotify;
|
||||||
pub use self::traits::{BlockChainClient, MiningBlockChainClient};
|
pub use self::traits::{BlockChainClient, MiningBlockChainClient, ProvingBlockChainClient};
|
||||||
|
|
||||||
pub use types::ids::*;
|
pub use types::ids::*;
|
||||||
pub use types::trace_filter::Filter as TraceFilter;
|
pub use types::trace_filter::Filter as TraceFilter;
|
||||||
|
@ -256,8 +256,10 @@ pub trait BlockChainClient : Sync + Send {
|
|||||||
fn pruning_info(&self) -> PruningInfo;
|
fn pruning_info(&self) -> PruningInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl IpcConfig for BlockChainClient { }
|
||||||
|
|
||||||
/// Extended client interface used for mining
|
/// Extended client interface used for mining
|
||||||
pub trait MiningBlockChainClient : BlockChainClient {
|
pub trait MiningBlockChainClient: BlockChainClient {
|
||||||
/// Returns OpenBlock prepared for closing.
|
/// Returns OpenBlock prepared for closing.
|
||||||
fn prepare_open_block(&self,
|
fn prepare_open_block(&self,
|
||||||
author: Address,
|
author: Address,
|
||||||
@ -275,4 +277,23 @@ pub trait MiningBlockChainClient : BlockChainClient {
|
|||||||
fn latest_schedule(&self) -> Schedule;
|
fn latest_schedule(&self) -> Schedule;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IpcConfig for BlockChainClient { }
|
/// Extended client interface for providing proofs of the state.
|
||||||
|
pub trait ProvingBlockChainClient: BlockChainClient {
|
||||||
|
/// Prove account storage at a specific block id.
|
||||||
|
///
|
||||||
|
/// Both provided keys assume a secure trie.
|
||||||
|
/// Returns a vector of raw trie nodes (in order from the root) proving the storage query.
|
||||||
|
/// Nodes after `from_level` may be omitted.
|
||||||
|
/// An empty vector indicates unservable query.
|
||||||
|
fn prove_storage(&self, key1: H256, key2: H256, from_level: u32, id: BlockID) -> Vec<Bytes>;
|
||||||
|
|
||||||
|
/// Prove account existence at a specific block id.
|
||||||
|
/// The key is the keccak hash of the account's address.
|
||||||
|
/// Returns a vector of raw trie nodes (in order from the root) proving the query.
|
||||||
|
/// Nodes after `from_level` may be omitted.
|
||||||
|
/// An empty vector indicates unservable query.
|
||||||
|
fn prove_account(&self, key1: H256, from_level: u32, id: BlockID) -> Vec<Bytes>;
|
||||||
|
|
||||||
|
/// Get code by address hash.
|
||||||
|
fn code_by_hash(&self, account_key: H256, id: BlockID) -> Bytes;
|
||||||
|
}
|
@ -140,7 +140,6 @@ pub mod snapshot;
|
|||||||
pub mod action_params;
|
pub mod action_params;
|
||||||
pub mod db;
|
pub mod db;
|
||||||
pub mod verification;
|
pub mod verification;
|
||||||
pub mod light;
|
|
||||||
#[macro_use] pub mod evm;
|
#[macro_use] pub mod evm;
|
||||||
|
|
||||||
mod cache_manager;
|
mod cache_manager;
|
||||||
|
@ -1,77 +0,0 @@
|
|||||||
// Copyright 2015, 2016 Ethcore (UK) Ltd.
|
|
||||||
// This file is part of Parity.
|
|
||||||
|
|
||||||
// Parity is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
|
|
||||||
// Parity is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
//! A provider for the LES protocol. This is typically a full node, who can
|
|
||||||
//! give as much data as necessary to its peers.
|
|
||||||
|
|
||||||
use transaction::SignedTransaction;
|
|
||||||
use blockchain_info::BlockChainInfo;
|
|
||||||
|
|
||||||
use util::{Bytes, H256};
|
|
||||||
|
|
||||||
use light::request;
|
|
||||||
|
|
||||||
/// Defines the operations that a provider for `LES` must fulfill.
|
|
||||||
///
|
|
||||||
/// These are defined at [1], but may be subject to change.
|
|
||||||
/// Requests which can't be fulfilled should return either an empty RLP list
|
|
||||||
/// or empty vector where appropriate.
|
|
||||||
///
|
|
||||||
/// [1]: https://github.com/ethcore/parity/wiki/Light-Ethereum-Subprotocol-(LES)
|
|
||||||
pub trait Provider: Send + Sync {
|
|
||||||
/// Provide current blockchain info.
|
|
||||||
fn chain_info(&self) -> BlockChainInfo;
|
|
||||||
|
|
||||||
/// Find the depth of a common ancestor between two blocks.
|
|
||||||
/// If either block is unknown or an ancestor can't be found
|
|
||||||
/// then return `None`.
|
|
||||||
fn reorg_depth(&self, a: &H256, b: &H256) -> Option<u64>;
|
|
||||||
|
|
||||||
/// Earliest block where state queries are available.
|
|
||||||
/// If `None`, no state queries are servable.
|
|
||||||
fn earliest_state(&self) -> Option<u64>;
|
|
||||||
|
|
||||||
/// 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, req: request::Headers) -> Vec<Bytes>;
|
|
||||||
|
|
||||||
/// Provide as many as possible of the requested blocks (minus the headers) encoded
|
|
||||||
/// in RLP format.
|
|
||||||
fn block_bodies(&self, req: request::Bodies) -> Vec<Bytes>;
|
|
||||||
|
|
||||||
/// Provide the receipts as many as possible of the requested blocks.
|
|
||||||
/// Returns a vector of RLP-encoded lists of receipts.
|
|
||||||
fn receipts(&self, req: request::Receipts) -> Vec<Bytes>;
|
|
||||||
|
|
||||||
/// Provide a set of merkle proofs, as requested. Each request is a
|
|
||||||
/// block hash and request parameters.
|
|
||||||
///
|
|
||||||
/// Returns a vector of RLP-encoded lists satisfying the requests.
|
|
||||||
fn proofs(&self, req: request::StateProofs) -> Vec<Bytes>;
|
|
||||||
|
|
||||||
/// Provide contract code for the specified (block_hash, account_hash) pairs.
|
|
||||||
/// Each item in the resulting vector is either the raw bytecode or empty.
|
|
||||||
fn contract_code(&self, req: request::ContractCodes) -> Vec<Bytes>;
|
|
||||||
|
|
||||||
/// Provide header proofs from the Canonical Hash Tries.
|
|
||||||
fn header_proofs(&self, req: request::HeaderProofs) -> Vec<Bytes>;
|
|
||||||
|
|
||||||
/// Provide pending transactions.
|
|
||||||
fn pending_transactions(&self) -> Vec<SignedTransaction>;
|
|
||||||
}
|
|
@ -1,167 +0,0 @@
|
|||||||
// Copyright 2015, 2016 Ethcore (UK) Ltd.
|
|
||||||
// This file is part of Parity.
|
|
||||||
|
|
||||||
// Parity is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
|
|
||||||
// Parity is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
use util::H256;
|
|
||||||
|
|
||||||
/// A request for block headers.
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Binary)]
|
|
||||||
pub struct Headers {
|
|
||||||
/// Starting block number
|
|
||||||
pub block_num: u64,
|
|
||||||
/// Starting block hash. This and number could be combined but IPC codegen is
|
|
||||||
/// not robust enough to support it.
|
|
||||||
pub block_hash: H256,
|
|
||||||
/// The maximum amount of headers which can be returned.
|
|
||||||
pub max: usize,
|
|
||||||
/// 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,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A request for specific block bodies.
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Binary)]
|
|
||||||
pub struct Bodies {
|
|
||||||
/// Hashes which bodies are being requested for.
|
|
||||||
pub block_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, Binary)]
|
|
||||||
pub struct Receipts {
|
|
||||||
/// Block hashes to return receipts for.
|
|
||||||
pub block_hashes: Vec<H256>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A request for a state proof
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Binary)]
|
|
||||||
pub struct StateProof {
|
|
||||||
/// 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.
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A request for state proofs.
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Binary)]
|
|
||||||
pub struct StateProofs {
|
|
||||||
/// All the proof requests.
|
|
||||||
pub requests: Vec<StateProof>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A request for contract code.
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Binary)]
|
|
||||||
pub struct ContractCode {
|
|
||||||
/// Block hash
|
|
||||||
pub block_hash: H256,
|
|
||||||
/// Account key (== sha3(address))
|
|
||||||
pub account_key: H256,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A request for contract code.
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Binary)]
|
|
||||||
pub struct ContractCodes {
|
|
||||||
/// Block hash and account key (== sha3(address)) pairs to fetch code for.
|
|
||||||
pub code_requests: Vec<ContractCode>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A request for a header proof from the Canonical Hash Trie.
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Binary)]
|
|
||||||
pub struct HeaderProof {
|
|
||||||
/// 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,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A request for header proofs from the CHT.
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Binary)]
|
|
||||||
pub struct HeaderProofs {
|
|
||||||
/// All the proof requests.
|
|
||||||
pub requests: Vec<HeaderProof>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Kinds of requests.
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Binary)]
|
|
||||||
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,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Encompasses all possible types of requests in a single structure.
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Binary)]
|
|
||||||
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),
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the amount of requests being made.
|
|
||||||
pub fn amount(&self) -> usize {
|
|
||||||
match *self {
|
|
||||||
Request::Headers(ref req) => req.max,
|
|
||||||
Request::Bodies(ref req) => req.block_hashes.len(),
|
|
||||||
Request::Receipts(ref req) => req.block_hashes.len(),
|
|
||||||
Request::StateProofs(ref req) => req.requests.len(),
|
|
||||||
Request::Codes(ref req) => req.code_requests.len(),
|
|
||||||
Request::HeaderProofs(ref req) => req.requests.len(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -35,4 +35,3 @@ pub mod restoration_status;
|
|||||||
pub mod snapshot_manifest;
|
pub mod snapshot_manifest;
|
||||||
pub mod mode;
|
pub mod mode;
|
||||||
pub mod pruning_info;
|
pub mod pruning_info;
|
||||||
pub mod les_request;
|
|
||||||
|
Loading…
Reference in New Issue
Block a user