move light to its own crate again

This commit is contained in:
Robert Habermeier
2016-12-05 16:55:33 +01:00
parent 6e1a1f9dec
commit 61c3358447
14 changed files with 247 additions and 362 deletions

View File

@@ -52,7 +52,7 @@ use blockchain::{BlockChain, BlockProvider, TreeRoute, ImportRoute};
use client::{
BlockID, TransactionID, UncleID, TraceId, ClientConfig, BlockChainClient,
MiningBlockChainClient, TraceFilter, CallAnalytics, BlockImportError, Mode,
ChainNotify, PruningInfo,
ChainNotify, PruningInfo, ProvingBlockChainClient,
};
use client::Error as ClientError;
use env_info::EnvInfo;
@@ -68,7 +68,6 @@ use factory::Factories;
use rlp::{decode, View, UntrustedRlp};
use state_db::StateDB;
use rand::OsRng;
use light::{self, request};
// re-export
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 light::Provider for Client {
fn chain_info(&self) -> BlockChainInfo {
BlockChainClient::chain_info(self)
impl ProvingBlockChainClient for Client {
fn prove_storage(&self, key1: H256, key2: H256, from_level: u32, id: BlockID) -> Vec<Bytes> {
self.state_at(id)
.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> {
self.tree_route(a, b).map(|route| route.index as u64)
fn prove_account(&self, key1: H256, from_level: u32, id: BlockID) -> Vec<Bytes> {
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> {
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)
fn code_by_hash(&self, account_key: H256, id: BlockID) -> Bytes {
self.state_at(id)
.and_then(move |state| state.code_by_address_hash(account_key).ok())
.and_then(|x| x)
.unwrap_or_else(Vec::new)
}
}

View File

@@ -27,7 +27,7 @@ pub use self::config::{Mode, ClientConfig, DatabaseCompactionProfile, BlockChain
pub use self::error::Error;
pub use self::test_client::{TestBlockChainClient, EachBlockWith};
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::trace_filter::Filter as TraceFilter;

View File

@@ -256,8 +256,10 @@ pub trait BlockChainClient : Sync + Send {
fn pruning_info(&self) -> PruningInfo;
}
impl IpcConfig for BlockChainClient { }
/// Extended client interface used for mining
pub trait MiningBlockChainClient : BlockChainClient {
pub trait MiningBlockChainClient: BlockChainClient {
/// Returns OpenBlock prepared for closing.
fn prepare_open_block(&self,
author: Address,
@@ -275,4 +277,23 @@ pub trait MiningBlockChainClient : BlockChainClient {
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;
}