light IPC feature and mock state proofs

This commit is contained in:
Robert Habermeier 2016-12-08 13:44:17 +01:00
parent 8d16f73795
commit 3e8ee9d423
7 changed files with 206 additions and 20 deletions

2
Cargo.lock generated
View File

@ -462,8 +462,6 @@ version = "1.5.0"
dependencies = [
"ethcore 1.5.0",
"ethcore-io 1.5.0",
"ethcore-ipc 1.4.0",
"ethcore-ipc-codegen 1.4.0",
"ethcore-network 1.5.0",
"ethcore-util 1.5.0",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",

View File

@ -8,7 +8,7 @@ authors = ["Ethcore <admin@ethcore.io>"]
build = "build.rs"
[build-dependencies]
"ethcore-ipc-codegen" = { path = "../../ipc/codegen" }
"ethcore-ipc-codegen" = { path = "../../ipc/codegen", optional = true }
[dependencies]
log = "0.3"
@ -16,6 +16,9 @@ ethcore = { path = "..", features = ["light"] }
ethcore-util = { path = "../../util" }
ethcore-network = { path = "../../util/network" }
ethcore-io = { path = "../../util/io" }
ethcore-ipc = { path = "../../ipc/rpc" }
ethcore-ipc = { path = "../../ipc/rpc", optional = true }
rlp = { path = "../../util/rlp" }
time = "0.1"
time = "0.1"
[features]
ipc = ["ethcore/ipc", "ethcore-ipc", "ethcore-ipc-codegen"]

View File

@ -14,8 +14,13 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
#[cfg(feature = "ipc")]
extern crate ethcore_ipc_codegen;
#[cfg(feature = "ipc")]
fn main() {
ethcore_ipc_codegen::derive_binary("src/types/mod.rs.in").unwrap();
}
#[cfg(not(feature = "ipc"))]
fn main() { }

View File

@ -47,6 +47,8 @@ extern crate ethcore;
extern crate ethcore_util as util;
extern crate ethcore_network as network;
extern crate ethcore_io as io;
extern crate ethcore_ipc as ipc;
extern crate rlp;
extern crate time;
extern crate time;
#[cfg(feature = "ipc")]
extern crate ethcore_ipc as ipc;

View File

@ -123,7 +123,19 @@ impl Provider for TestProvider {
}
fn proofs(&self, req: request::StateProofs) -> Vec<Bytes> {
req.requests.into_iter().map(|_| ::rlp::EMPTY_LIST_RLP.to_vec()).collect()
req.requests.into_iter()
.map(|req| {
match req.key2 {
Some(key2) => ::util::sha3::SHA3_NULL_RLP.to_owned(),
None => {
// sort of a leaf node
let mut stream = RlpStream::new_list(2);
stream.append(&req.key1).append_empty_data();
stream.out()
}
}
})
.collect()
}
fn contract_code(&self, req: request::ContractCodes) -> Vec<Bytes> {
@ -240,6 +252,9 @@ fn buffer_overflow() {
proto.handle_packet(&Expect::Punish(1), &1, packet::GET_BLOCK_HEADERS, &request);
}
// test the basic request types -- these just make sure that requests are parsed
// and sent to the provider correctly as well as testing response formatting.
#[test]
fn get_block_headers() {
let flow_params = FlowParams::new(5_000_000.into(), Default::default(), 0.into());
@ -288,4 +303,151 @@ fn get_block_headers() {
let expected = Expect::Respond(packet::BLOCK_HEADERS, response);
proto.handle_packet(&expected, &1, packet::GET_BLOCK_HEADERS, &request_body);
}
#[test]
fn get_block_bodies() {
let flow_params = FlowParams::new(5_000_000.into(), Default::default(), 0.into());
let capabilities = capabilities();
let (provider, proto) = setup(flow_params.clone(), capabilities.clone());
let cur_status = status(provider.client.chain_info());
let my_status = write_handshake(&cur_status, &capabilities, &flow_params);
provider.client.add_blocks(100, EachBlockWith::Nothing);
let cur_status = status(provider.client.chain_info());
{
let packet_body = write_handshake(&cur_status, &capabilities, &flow_params);
proto.on_connect(&1, &Expect::Send(1, packet::STATUS, packet_body));
proto.handle_packet(&Expect::Nothing, &1, packet::STATUS, &my_status);
}
let request = request::Bodies {
block_hashes: (0..10).map(|i| provider.client.block_hash(BlockID::Number(i)).unwrap()).collect(),
};
let req_id = 111;
let request_body = encode_request(&Request::Bodies(request.clone()), req_id);
let response = {
let bodies: Vec<_> = (0..10).map(|i| provider.client.block_body(BlockID::Number(i + 1)).unwrap()).collect();
assert_eq!(bodies.len(), 10);
let new_buf = *flow_params.limit() - flow_params.compute_cost(request::Kind::Bodies, 10);
let mut response_stream = RlpStream::new_list(12);
response_stream.append(&req_id).append(&new_buf);
for body in bodies {
response_stream.append_raw(&body, 1);
}
response_stream.out()
};
let expected = Expect::Respond(packet::BLOCK_BODIES, response);
proto.handle_packet(&expected, &1, packet::GET_BLOCK_BODIES, &request_body);
}
#[test]
fn get_block_receipts() {
let flow_params = FlowParams::new(5_000_000.into(), Default::default(), 0.into());
let capabilities = capabilities();
let (provider, proto) = setup(flow_params.clone(), capabilities.clone());
let cur_status = status(provider.client.chain_info());
let my_status = write_handshake(&cur_status, &capabilities, &flow_params);
provider.client.add_blocks(1000, EachBlockWith::Nothing);
let cur_status = status(provider.client.chain_info());
{
let packet_body = write_handshake(&cur_status, &capabilities, &flow_params);
proto.on_connect(&1, &Expect::Send(1, packet::STATUS, packet_body));
proto.handle_packet(&Expect::Nothing, &1, packet::STATUS, &my_status);
}
// find the first 10 block hashes starting with `f` because receipts are only provided
// by the test client in that case.
let block_hashes: Vec<_> = (0..1000).map(|i| provider.client.block_hash(BlockID::Number(i)).unwrap())
.filter(|hash| format!("{}", hash).starts_with("f")).take(10).collect();
let request = request::Receipts {
block_hashes: block_hashes.clone(),
};
let req_id = 111;
let request_body = encode_request(&Request::Receipts(request.clone()), req_id);
let response = {
let receipts: Vec<_> = block_hashes.iter()
.map(|hash| provider.client.block_receipts(hash).unwrap())
.collect();
let new_buf = *flow_params.limit() - flow_params.compute_cost(request::Kind::Receipts, receipts.len());
let mut response_stream = RlpStream::new_list(2 + receipts.len());
response_stream.append(&req_id).append(&new_buf);
for block_receipts in receipts {
response_stream.append_raw(&block_receipts, 1);
}
response_stream.out()
};
let expected = Expect::Respond(packet::RECEIPTS, response);
proto.handle_packet(&expected, &1, packet::GET_RECEIPTS, &request_body);
}
#[test]
fn get_block_bodies() {
let flow_params = FlowParams::new(5_000_000.into(), Default::default(), 0.into());
let capabilities = capabilities();
let (provider, proto) = setup(flow_params.clone(), capabilities.clone());
let cur_status = status(provider.client.chain_info());
let my_status = write_handshake(&cur_status, &capabilities, &flow_params);
provider.client.add_blocks(100, EachBlockWith::Nothing);
let cur_status = status(provider.client.chain_info());
{
let packet_body = write_handshake(&cur_status, &capabilities, &flow_params);
proto.on_connect(&1, &Expect::Send(1, packet::STATUS, packet_body));
proto.handle_packet(&Expect::Nothing, &1, packet::STATUS, &my_status);
}
let request = request::Bodies {
block_hashes: (0..10).map(|i| provider.client.block_hash(BlockID::Number(i)).unwrap()).collect(),
};
let req_id = 111;
let request_body = encode_request(&Request::Bodies(request.clone()), req_id);
let response = {
let bodies: Vec<_> = (0..10).map(|i| provider.client.block_body(BlockID::Number(i + 1)).unwrap()).collect();
assert_eq!(bodies.len(), 10);
let new_buf = *flow_params.limit() - flow_params.compute_cost(request::Kind::Bodies, 10);
let mut response_stream = RlpStream::new_list(12);
response_stream.append(&req_id).append(&new_buf);
for body in bodies {
response_stream.append_raw(&body, 1);
}
response_stream.out()
};
let expected = Expect::Respond(packet::BLOCK_BODIES, response);
proto.handle_packet(&expected, &1, packet::GET_BLOCK_BODIES, &request_body);
}

View File

@ -19,7 +19,8 @@
use util::H256;
/// A request for block headers.
#[derive(Debug, Clone, PartialEq, Eq, Binary)]
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", derive(Binary))]
pub struct Headers {
/// Starting block number
pub block_num: u64,
@ -35,7 +36,8 @@ pub struct Headers {
}
/// A request for specific block bodies.
#[derive(Debug, Clone, PartialEq, Eq, Binary)]
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", derive(Binary))]
pub struct Bodies {
/// Hashes which bodies are being requested for.
pub block_hashes: Vec<H256>
@ -45,14 +47,16 @@ pub struct Bodies {
///
/// This request is answered with a list of transaction receipts for each block
/// requested.
#[derive(Debug, Clone, PartialEq, Eq, Binary)]
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", derive(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)]
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", derive(Binary))]
pub struct StateProof {
/// Block hash to query state from.
pub block: H256,
@ -66,14 +70,16 @@ pub struct StateProof {
}
/// A request for state proofs.
#[derive(Debug, Clone, PartialEq, Eq, Binary)]
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", derive(Binary))]
pub struct StateProofs {
/// All the proof requests.
pub requests: Vec<StateProof>,
}
/// A request for contract code.
#[derive(Debug, Clone, PartialEq, Eq, Binary)]
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", derive(Binary))]
pub struct ContractCode {
/// Block hash
pub block_hash: H256,
@ -82,14 +88,16 @@ pub struct ContractCode {
}
/// A request for contract code.
#[derive(Debug, Clone, PartialEq, Eq, Binary)]
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", derive(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)]
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", derive(Binary))]
pub struct HeaderProof {
/// Number of the CHT.
pub cht_number: u64,
@ -100,14 +108,16 @@ pub struct HeaderProof {
}
/// A request for header proofs from the CHT.
#[derive(Debug, Clone, PartialEq, Eq, Binary)]
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", derive(Binary))]
pub struct HeaderProofs {
/// All the proof requests.
pub requests: Vec<HeaderProof>,
}
/// Kinds of requests.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Binary)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", derive(Binary))]
pub enum Kind {
/// Requesting headers.
Headers,
@ -124,7 +134,8 @@ pub enum Kind {
}
/// Encompasses all possible types of requests in a single structure.
#[derive(Debug, Clone, PartialEq, Eq, Binary)]
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", derive(Binary))]
pub enum Request {
/// Requesting headers.
Headers(Headers),

View File

@ -15,6 +15,11 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Types used in the public (IPC) api which require custom code generation.
#![cfg_attr(feature = "ipc", allow(dead_code, unused_assignments, unused_variables))] // codegen issues
#![allow(dead_code, unused_assignments, unused_variables)] // codegen issues
#[cfg(feature = "ipc")]
include!(concat!(env!("OUT_DIR"), "/mod.rs.in"));
#[cfg(not(feature = "ipc"))]
include!("mod.rs.in");