initial request definitions

This commit is contained in:
Robert Habermeier 2017-03-03 19:25:29 +01:00
parent af235e564e
commit bbb50caa89
4 changed files with 709 additions and 230 deletions

View File

@ -57,7 +57,7 @@ mod types;
pub use self::provider::Provider;
pub use self::transaction_queue::TransactionQueue;
pub use types::les_request as request;
pub use types::request as request;
#[macro_use]
extern crate log;

View File

@ -1,228 +0,0 @@
// Copyright 2015-2017 Parity Technologies (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 ethcore::transaction::Action;
use util::{Address, H256, U256, Uint};
/// Either a hash or a number.
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", binary)]
pub enum HashOrNumber {
/// Block hash variant.
Hash(H256),
/// Block number variant.
Number(u64),
}
impl From<H256> for HashOrNumber {
fn from(hash: H256) -> Self {
HashOrNumber::Hash(hash)
}
}
impl From<u64> for HashOrNumber {
fn from(num: u64) -> Self {
HashOrNumber::Number(num)
}
}
/// A request for block headers.
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", binary)]
pub struct Headers {
/// Starting block number or hash.
pub start: HashOrNumber,
/// 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)]
#[cfg_attr(feature = "ipc", 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)]
#[cfg_attr(feature = "ipc", 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)]
#[cfg_attr(feature = "ipc", 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)]
#[cfg_attr(feature = "ipc", binary)]
pub struct StateProofs {
/// All the proof requests.
pub requests: Vec<StateProof>,
}
/// A request for contract code.
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", 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)]
#[cfg_attr(feature = "ipc", 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)]
#[cfg_attr(feature = "ipc", binary)]
pub struct HeaderProof {
/// Number of the CHT.
pub cht_number: u64,
/// Block number requested. May not be 0: genesis isn't included in any CHT.
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)]
#[cfg_attr(feature = "ipc", binary)]
pub struct HeaderProofs {
/// All the proof requests.
pub requests: Vec<HeaderProof>,
}
/// A request for proof of (simulated) transaction execution.
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", binary)]
pub struct TransactionProof {
/// Block hash to request for.
pub at: H256,
/// Address to treat as the caller.
pub from: Address,
/// Action to take: either a call or a create.
pub action: Action,
/// Amount of gas to request proof-of-execution for.
pub gas: U256,
/// Price for each gas.
pub gas_price: U256,
/// Value to simulate sending.
pub value: U256,
/// Transaction data.
pub data: Vec<u8>,
}
/// Kinds of requests.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", 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,
/// Requesting proof of transaction execution.
TransactionProof,
}
/// Encompasses all possible types of requests in a single structure.
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", 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),
/// Requesting proof of transaction execution.
TransactionProof(TransactionProof),
}
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::TransactionProof(_) => Kind::TransactionProof,
}
}
/// Get the amount of requests being made.
/// In the case of `TransactionProof`, this is the amount of gas being requested.
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(),
Request::TransactionProof(ref req) => match req.gas > usize::max_value().into() {
true => usize::max_value(),
false => req.gas.low_u64() as usize,
}
}
}
}

View File

@ -14,4 +14,4 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
pub mod les_request;
pub mod request;

View File

@ -0,0 +1,707 @@
// Copyright 2015-2017 Parity Technologies (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/>.
//! Light protocol request types.
use std::collections::HashMap;
use ethcore::transaction::Action;
use util::{Address, H256, U256, Uint};
// re-exports of request types.
pub use self::header::{
Complete as CompleteHeadersRequest,
Incomplete as IncompleteHeadersRequest,
Response as HeadersResponse
};
pub use self::header_proof::{
Complete as CompleteHeaderProofRequest,
Incomplete as IncompleteHeaderProofRequest,
Response as HeaderProofResponse
};
pub use self::block_body::{
Complete as CompleteBodyRequest,
Incomplete as IncompleteBodyRequest,
Response as BodyResponse
};
pub use self::receipts::{
Complete as CompleteReceiptsRequest,
Incomplete as IncompleteReceiptsRequest
Response as ReceiptsResponse
};
pub use self::account::{
Complete as CompleteAccountRequest,
Incomplete as IncompleteAccountRequest,
Response as AccountResponse,
};
pub use self::storage::{
Complete as CompleteStorageRequest,
Incomplete as IncompleteStorageRequest,
Response as StorageResponse
};
pub use self::contract_code::{
Complete as CompleteCodeRequest,
Incomplete as IncompleteCodeRequest,
Response as CodeResponse,
};
/// Error indicating a reference to a non-existent or wrongly-typed output.
pub struct NoSuchOutput;
/// An input to a request.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Field<T> {
/// A pre-specified input.
Scalar(T),
/// An input which can be resolved later on.
/// (Request index, output index)
BackReference(usize, usize),
}
impl From<T> for Field<T> {
fn from(val: T) -> Self {
Field::Scalar(val)
}
}
/// Request outputs which can be reused as inputs.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Output {
/// A 32-byte hash output.
Hash(H256),
/// An unsigned-integer output.
Number(u64),
}
/// Response output kinds which can be used as back-references.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum OutputKind {
/// A 32-byte hash output.
Hash,
/// An unsigned-integer output.
Number,
}
/// Either a hash or a number.
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", binary)]
pub enum HashOrNumber {
/// Block hash variant.
Hash(H256),
/// Block number variant.
Number(u64),
}
impl From<H256> for HashOrNumber {
fn from(hash: H256) -> Self {
HashOrNumber::Hash(hash)
}
}
impl From<u64> for HashOrNumber {
fn from(num: u64) -> Self {
HashOrNumber::Number(num)
}
}
/// A potentially incomplete request.
pub trait IncompleteRequest: Sized {
type Complete;
/// Check prior outputs against the needed inputs.
///
/// This is called to ensure consistency of this request with
/// others in the same packet.
fn check_outputs<F>(&self, f: F) -> Result<(), NoSuchOutput>
where F: FnMut(usize, usize, OutputKind) -> Result<(), NoSuchOutput>;
/// Note that this request will produce the following outputs.
fn note_outputs<F>(&self, f: F) where F: FnMut(usize, OutputKind);
/// Fill the request.
///
/// This function is provided an "output oracle" which allows fetching of
/// prior request outputs.
/// Only outputs previously checked with `check_outputs` will be available.
fn fill<F>(self, oracle: F) -> Result<Self::Complete, NoSuchOutput>
where F: Fn(usize, usize) -> Result<Output, NoSuchOutput>;
}
/// Header request.
pub mod header {
use super::{Field, HashOrNumber, NoSuchOutput, OutputKind, Output};
use ethcore::encoded;
use util::U256;
/// Potentially incomplete headers request.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Incomplete {
/// Start block.
pub start: Field<HashOrNumber>,
/// Skip between.
pub skip: U256,
/// Maximum to return.
pub max: U256,
/// Whether to reverse from start.
pub reverse: bool,
}
impl super::IncompleteRequest for Incomplete {
type Complete = Complete;
fn check_outputs<F>(&self, mut f: F) -> Result<(), NoSuchOutput>
where F: FnMut(usize, usize, OutputKind) -> Result<(), NoSuchOutput>
{
match self.start {
Field::Scalar(_) => Ok(()),
Field::BackReference(req, idx) =>
f(req, idx, OutputKind::Hash).or_else(|| f(req, idx, OutputKind::Number))
}
}
fn note_outputs<F>(&self, _: F) where F: FnMut(usize, OutputKind) { }
fn fill<F>(self, oracle: F) -> Result<Self::Complete, NoSuchOutput>
where F: Fn(usize, usize) -> Result<Output, NoSuchOutput>
{
let start = match self.start {
Field::Scalar(start) => start,
Field::BackReference(req, idx) => match oracle(req, idx)? {
Output::Hash(hash) => hash.into(),
Output::Number(num) => num.into(),
}
};
Ok(Complete {
start: start,
skip: self.skip,
max: self.max,
reverse: self.reverse,
})
}
}
/// A complete header request.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Complete {
/// Start block.
pub start: HashOrNumber,
/// Skip between.
pub skip: U256,
/// Maximum to return.
pub max: U256,
/// Whether to reverse from start.
pub reverse: bool,
}
/// The output of a request for headers.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Response {
header: Vec<encoded::Header>,
}
impl Response {
/// Fill reusable outputs by writing them into the function.
pub fn fill_outputs<F>(&self, _: F) where F: FnMut(usize, Output) { }
}
}
/// Request and response for header proofs.
pub mod header_proof {
use super::{Field, NoSuchOutput, OutputKind, Output};
use util::{Bytes, U256, H256};
/// Potentially incomplete header proof request.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Incomplete {
/// Block number.
pub num: Field<u64>,
}
impl super::IncompleteRequest for Incomplete {
type Complete = Complete;
fn check_outputs<F>(&self, mut f: F) -> Result<(), NoSuchOutput>
where F: FnMut(usize, usize, OutputKind) -> Result<(), NoSuchOutput>
{
match self.num {
Field::Scalar(_) => Ok(()),
Field::BackReference(req, idx) => f(req, idx, OutputKind::Number),
}
}
fn note_outputs<F>(&self, mut note: F) where F: FnMut(usize, OutputKind) {
note(1, OutputKind::Hash);
}
fn fill<F>(self, oracle: F) -> Result<Self::Complete, NoSuchOutput>
where F: Fn(usize, usize) -> Result<Output, NoSuchOutput>
{
let num = match self.num {
Field::Scalar(num) => num,
Field::BackReference(req, idx) => match oracle(req, idx)? {
Output::Number(num) => num,
_ => return Err(NoSuchOutput),
}
};
Ok(Complete {
num: num,
})
}
}
/// A complete header proof request.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Complete {
/// The number to get a header proof for.
pub num: u64,
}
/// The output of a request for a header proof.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Response {
/// Inclusion proof of the header and total difficulty in the CHT.
pub proof: Vec<Bytes>,
/// The proved header's hash.
pub hash: H256,
/// The proved header's total difficulty.
pub td: U256,
}
impl Response {
/// Fill reusable outputs by providing them to the function.
pub fn fill_outputs<F>(&self, mut f: F) where F: FnMut(usize, Output) {
f(1, Output::Hash(self.hash));
}
}
}
/// Request and response for block receipts
pub mod block_receipts {
use super::{Field, NoSuchOutput, OutputKind, Output};
use util::{Bytes, U256, H256};
/// Potentially incomplete block receipts request.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Incomplete {
/// Block hash to get receipts for.
pub hash: Field<H256>,
}
impl super::IncompleteRequest for Incomplete {
type Complete = Complete;
fn check_outputs<F>(&self, mut f: F) -> Result<(), NoSuchOutput>
where F: FnMut(usize, usize, OutputKind) -> Result<(), NoSuchOutput>
{
match self.num {
Field::Scalar(_) => Ok(()),
Field::BackReference(req, idx) => f(req, idx, OutputKind::Hash),
}
}
fn note_outputs<F>(&self, _: F) where F: FnMut(usize, OutputKind) {}
fn fill<F>(self, oracle: F) -> Result<Self::Complete, NoSuchOutput>
where F: Fn(usize, usize) -> Result<Output, NoSuchOutput>
{
let hash = match self.hash {
Field::Scalar(hash) => hash,
Field::BackReference(req, idx) => match oracle(req, idx)? {
Output::Hash(hash) => hash,
_ => return Err(NoSuchOutput),
}
};
Ok(Complete {
hash: hash,
})
}
}
/// A complete block receipts request.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Complete {
/// The number to get block receipts for.
pub hash: H256,
}
/// The output of a request for block receipts.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Response {
/// The block receipts.
pub receipts: Vec<Receipt>
}
impl Response {
/// Fill reusable outputs by providing them to the function.
pub fn fill_outputs<F>(&self, _: F) where F: FnMut(usize, Output) {}
}
}
/// Request and response for a block body
pub mod block_body {
use super::{Field, NoSuchOutput, OutputKind, Output};
use ethcore::encoded;
use util::{Bytes, U256, H256};
/// Potentially incomplete block body request.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Incomplete {
/// Block hash to get receipts for.
pub hash: Field<H256>,
}
impl super::IncompleteRequest for Incomplete {
type Complete = Complete;
fn check_outputs<F>(&self, mut f: F) -> Result<(), NoSuchOutput>
where F: FnMut(usize, usize, OutputKind) -> Result<(), NoSuchOutput>
{
match self.num {
Field::Scalar(_) => Ok(()),
Field::BackReference(req, idx) => f(req, idx, OutputKind::Hash),
}
}
fn note_outputs<F>(&self, _: F) where F: FnMut(usize, OutputKind) {}
fn fill<F>(self, oracle: F) -> Result<Self::Complete, NoSuchOutput>
where F: Fn(usize, usize) -> Result<Output, NoSuchOutput>
{
let hash = match self.hash {
Field::Scalar(hash) => hash,
Field::BackReference(req, idx) => match oracle(req, idx)? {
Output::Hash(hash) => hash,
_ => return Err(NoSuchOutput),
}
};
Ok(Complete {
hash: hash,
})
}
}
/// A complete block body request.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Complete {
/// The hash to get a block body for.
pub hash: H256,
}
/// The output of a request for block body.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Response {
/// The block body.
pub body: encoded::Body,
}
impl Response {
/// Fill reusable outputs by providing them to the function.
pub fn fill_outputs<F>(&self, _: F) where F: FnMut(usize, Output) {}
}
}
/// A request for an account proof.
pub mod account {
use super::{Field, NoSuchOutput, OutputKind, Output};
use ethcore::encoded;
use util::{Bytes, U256, H256};
/// Potentially incomplete request for an account proof.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Incomplete {
/// Block hash to request state proof for.
pub block_hash: Field<H256>,
/// Hash of the account's address.
pub address_hash: Field<H256>,
}
impl super::IncompleteRequest for Incomplete {
type Complete = Complete;
fn check_outputs<F>(&self, mut f: F) -> Result<(), NoSuchOutput>
where F: FnMut(usize, usize, OutputKind) -> Result<(), NoSuchOutput>
{
if let Field::BackReference(req, idx) = self.block_hash {
f(req, idx, OutputKind::Hash)?
}
if let Field::BackReference(req, idx) = self.address_hash {
f(req, idx, OutputKind::Hash)?
}
Ok(())
}
fn note_outputs<F>(&self, mut f: F) where F: FnMut(usize, OutputKind) {
f(0, OutputKind::Hash);
f(1, OutputKind::Hash);
}
fn fill<F>(self, oracle: F) -> Result<Self::Complete, NoSuchOutput>
where F: Fn(usize, usize) -> Result<Output, NoSuchOutput>
{
let block_hash = match self.block_hash {
Field::Scalar(hash) => hash,
Field::BackReference(req, idx) => match oracle(req, idx)? {
Output::Hash(hash) => hash,
_ => return Err(NoSuchOutput)?,
}
};
let address_hash = match self.address_hash {
Field::Scalar(hash) => hash,
Field::BackReference(req, idx) => match oracle(req, idx)? {
Output::Hash(hash) => hash,
_ => return Err(NoSuchOutput)?,
}
};
Ok(Complete {
block_hash: block_hash,
address_hash: address_hash,
})
}
}
/// A complete request for an account.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Complete {
/// Block hash to request state proof for.
pub block_hash: H256,
/// Hash of the account's address.
pub address_hash: H256,
}
/// The output of a request for an account state proof.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Response {
/// Inclusion/exclusion proof
pub proof: Vec<Bytes>,
/// Account nonce.
pub nonce: U256,
/// Account balance.
pub balance: U256,
/// Account's code hash.
pub code_hash: H256,
/// Account's storage trie root.
pub storage_root: H256,
}
impl Response {
/// Fill reusable outputs by providing them to the function.
pub fn fill_outputs<F>(&self, mut f: F) where F: FnMut(usize, Output) {
f(0, Output::Hash(self.code_hash));
f(1, Output::Hash(self.storage_root));
}
}
}
/// A request for a storage proof.
pub mod storage {
use super::{Field, NoSuchOutput, OutputKind, Output};
use ethcore::encoded;
use util::{Bytes, U256, H256};
/// Potentially incomplete request for an storage proof.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Incomplete {
/// Block hash to request state proof for.
pub block_hash: Field<H256>,
/// Hash of the account's address.
pub address_hash: Field<H256>,
/// Hash of the storage key.
pub key_hash: Field<H256>,
}
impl super::IncompleteRequest for Incomplete {
type Complete = Complete;
fn check_outputs<F>(&self, mut f: F) -> Result<(), NoSuchOutput>
where F: FnMut(usize, usize, OutputKind) -> Result<(), NoSuchOutput>
{
if let Field::BackReference(req, idx) = self.block_hash {
f(req, idx, OutputKind::Hash)?
}
if let Field::BackReference(req, idx) = self.address_hash {
f(req, idx, OutputKind::Hash)?
}
if let Field::BackReference(req, idx) = self.key_hash {
f(req, idx, OutputKind::Hash)?
}
Ok(())
}
fn note_outputs<F>(&self, mut f: F) where F: FnMut(usize, OutputKind) {
f(0, OutputKind::Hash);
}
fn fill<F>(self, oracle: F) -> Result<Self::Complete, NoSuchOutput>
where F: Fn(usize, usize) -> Result<Output, NoSuchOutput>
{
let block_hash = match self.block_hash {
Field::Scalar(hash) => hash,
Field::BackReference(req, idx) => match oracle(req, idx)? {
Output::Hash(hash) => hash,
_ => return Err(NoSuchOutput)?,
}
};
let address_hash = match self.address_hash {
Field::Scalar(hash) => hash,
Field::BackReference(req, idx) => match oracle(req, idx)? {
Output::Hash(hash) => hash,
_ => return Err(NoSuchOutput)?,
}
};
let key_hash = match self.key_hash {
Field::Scalar(hash) => hash,
Field::BackReference(req, idx) => match oracle(req, idx)? {
Output::Hash(hash) => hash,
_ => return Err(NoSuchOutput)?,
}
};
Ok(Complete {
block_hash: block_hash,
address_hash: address_hash,
key_hash: key_hash
})
}
}
/// A complete request for a storage proof.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Complete {
/// Block hash to request state proof for.
pub block_hash: H256,
/// Hash of the account's address.
pub address_hash: H256,
/// Storage key hash.
pub key_hash: H256,
}
/// The output of a request for an account state proof.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Response {
/// Inclusion/exclusion proof
pub proof: Vec<Bytes>,
/// Storage value.
pub value: H256,
}
impl Response {
/// Fill reusable outputs by providing them to the function.
pub fn fill_outputs<F>(&self, mut f: F) where F: FnMut(usize, Output) {
f(0, Output::Hash(self.value));
}
}
}
/// A request for contract code.
pub mod contract_code {
use super::{Field, NoSuchOutput, OutputKind, Output};
use ethcore::encoded;
use util::{Bytes, U256, H256};
/// Potentially incomplete _ request.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Incomplete {
/// The block hash to request the state for.
pub block_hash: Field<H256>,
/// The code hash.
pub code_hash: Field<H256>,
}
impl super::IncompleteRequest for Incomplete {
type Complete = Complete;
fn check_outputs<F>(&self, mut f: F) -> Result<(), NoSuchOutput>
where F: FnMut(usize, usize, OutputKind) -> Result<(), NoSuchOutput>
{
if let Field::BackReference(req, idx) = self.block_hash {
f(req, idx, OutputKind::Hash)?;
}
if let Field::BackReference(req, idx) = self.code_hash {
f(req, idx, OutputKind::Hash)?;
}
Ok(())
}
fn note_outputs<F>(&self, _: F) where F: FnMut(usize, OutputKind) {}
fn fill<F>(self, oracle: F) -> Result<Self::Complete, NoSuchOutput>
where F: Fn(usize, usize) -> Result<Output, NoSuchOutput>
{
let block_hash = match self.block_hash {
Field::Scalar(hash) => hash,
Field::BackReference(req, idx) => match oracle(req, idx)? {
Output::Hash(hash) => hash,
_ => return Err(NoSuchOutput)?,
}
};
let code_hash = match self.code_hash {
Field::Scalar(hash) => hash,
Field::BackReference(req, idx) => match oracle(req, idx)? {
Output::Hash(hash) => hash,
_ => return Err(NoSuchOutput)?,
}
};
Ok(Complete {
block_hash: block_hash,
code_hash: code_hash,
})
}
}
/// A complete request.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Complete {
/// The block hash to request the state for.
pub block_hash: H256,
/// The code hash.
pub code_hash: H256,
}
/// The output of a request for
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Response {
/// The requested code.
pub code: Bytes,
}
impl Response {
/// Fill reusable outputs by providing them to the function.
pub fn fill_outputs<F>(&self, _: F) where F: FnMut(usize, Output) {}
}
}