encode and decode responses
This commit is contained in:
parent
87f3d53607
commit
b396b56e34
@ -30,16 +30,9 @@ use cht::{self, BlockInfo};
|
|||||||
use client::{LightChainClient, AsLightClient};
|
use client::{LightChainClient, AsLightClient};
|
||||||
use transaction_queue::TransactionQueue;
|
use transaction_queue::TransactionQueue;
|
||||||
|
|
||||||
|
|
||||||
use request;
|
use request;
|
||||||
|
|
||||||
/// Defines the operations that a provider for `LES` must fulfill.
|
/// Defines the operations that a provider for the light subprotocol 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)
|
|
||||||
#[cfg_attr(feature = "ipc", ipc(client_ident="LightProviderClient"))]
|
#[cfg_attr(feature = "ipc", ipc(client_ident="LightProviderClient"))]
|
||||||
pub trait Provider: Send + Sync {
|
pub trait Provider: Send + Sync {
|
||||||
/// Provide current blockchain info.
|
/// Provide current blockchain info.
|
||||||
@ -149,12 +142,12 @@ impl<T: ProvingBlockChainClient + ?Sized> Provider for T {
|
|||||||
BlockChainClient::block_header(self, id)
|
BlockChainClient::block_header(self, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn block_body(&self, req: request::CompleteBodyRequest) -> Option<request::BodyResponse>;
|
fn block_body(&self, req: request::CompleteBodyRequest) -> Option<request::BodyResponse> {
|
||||||
BlockChainClient::block_body(self, id)
|
BlockChainClient::block_body(self, id)
|
||||||
.map(|body| ::request::BodyResponse { body: body })
|
.map(|body| ::request::BodyResponse { body: body })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn block_receipts(&self, req: request::CompleteReceiptsRequest) -> Option<request::ReceiptsResponse>;
|
fn block_receipts(&self, req: request::CompleteReceiptsRequest) -> Option<request::ReceiptsResponse> {
|
||||||
BlockChainClient::block_receipts(self, hash)
|
BlockChainClient::block_receipts(self, hash)
|
||||||
.map(|x| ::request::ReceiptsResponse { receipts: ::rlp::decode(&x) })
|
.map(|x| ::request::ReceiptsResponse { receipts: ::rlp::decode(&x) })
|
||||||
}
|
}
|
||||||
@ -168,7 +161,7 @@ impl<T: ProvingBlockChainClient + ?Sized> Provider for T {
|
|||||||
code_hash: acc.code_hash,
|
code_hash: acc.code_hash,
|
||||||
storage_root: acc.storage_root,
|
storage_root: acc.storage_root,
|
||||||
}
|
}
|
||||||
}))
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn storage_proof(&self, req: request::CompleteStorageRequest) -> Option<request::StorageResponse> {
|
fn storage_proof(&self, req: request::CompleteStorageRequest) -> Option<request::StorageResponse> {
|
||||||
@ -177,7 +170,7 @@ impl<T: ProvingBlockChainClient + ?Sized> Provider for T {
|
|||||||
proof: proof,
|
proof: proof,
|
||||||
value: item,
|
value: item,
|
||||||
}
|
}
|
||||||
}))
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn contract_code(&self, req: request::ContractCode) -> Option<request::CodeResponse> {
|
fn contract_code(&self, req: request::ContractCode) -> Option<request::CodeResponse> {
|
||||||
@ -185,7 +178,7 @@ impl<T: ProvingBlockChainClient + ?Sized> Provider for T {
|
|||||||
.map(|code| ::request::CodeResponse { code: code })
|
.map(|code| ::request::CodeResponse { code: code })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn header_proof(&self, req: request::CompleteHeaderProofRequest) -> Option<request::HeaderProofResponse>;
|
fn header_proof(&self, req: request::CompleteHeaderProofRequest) -> Option<request::HeaderProofResponse> {
|
||||||
let cht_number = match cht::block_to_cht_number(req.num) {
|
let cht_number = match cht::block_to_cht_number(req.num) {
|
||||||
Some(cht_num) => cht_num,
|
Some(cht_num) => cht_num,
|
||||||
None => {
|
None => {
|
||||||
@ -243,7 +236,7 @@ impl<T: ProvingBlockChainClient + ?Sized> Provider for T {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transaction_proof(&self, req: request::TransactionProof) -> Option<Vec<DBValue>> {
|
fn transaction_proof(&self, req: request::CompleteExecutionRequest) -> Option<request::ExecutionResponse> {
|
||||||
use ethcore::transaction::Transaction;
|
use ethcore::transaction::Transaction;
|
||||||
|
|
||||||
let id = BlockId::Hash(req.at);
|
let id = BlockId::Hash(req.at);
|
||||||
@ -261,6 +254,7 @@ impl<T: ProvingBlockChainClient + ?Sized> Provider for T {
|
|||||||
}.fake_sign(req.from);
|
}.fake_sign(req.from);
|
||||||
|
|
||||||
self.prove_transaction(transaction, id)
|
self.prove_transaction(transaction, id)
|
||||||
|
.map(|proof| ::request::ExecutionResponse { items: proof })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ready_transactions(&self) -> Vec<PendingTransaction> {
|
fn ready_transactions(&self) -> Vec<PendingTransaction> {
|
||||||
|
@ -38,9 +38,9 @@ pub use self::block_body::{
|
|||||||
Incomplete as IncompleteBodyRequest,
|
Incomplete as IncompleteBodyRequest,
|
||||||
Response as BodyResponse
|
Response as BodyResponse
|
||||||
};
|
};
|
||||||
pub use self::receipts::{
|
pub use self::block_receipts::{
|
||||||
Complete as CompleteReceiptsRequest,
|
Complete as CompleteReceiptsRequest,
|
||||||
Incomplete as IncompleteReceiptsRequest
|
Incomplete as IncompleteReceiptsRequest,
|
||||||
Response as ReceiptsResponse
|
Response as ReceiptsResponse
|
||||||
};
|
};
|
||||||
pub use self::account::{
|
pub use self::account::{
|
||||||
@ -58,6 +58,11 @@ pub use self::contract_code::{
|
|||||||
Incomplete as IncompleteCodeRequest,
|
Incomplete as IncompleteCodeRequest,
|
||||||
Response as CodeResponse,
|
Response as CodeResponse,
|
||||||
};
|
};
|
||||||
|
pub use self::execution::{
|
||||||
|
Complete as CompleteExecutionRequest,
|
||||||
|
Incomplete as IncompleteExecutionRequest,
|
||||||
|
Response as ExecutionResponse,
|
||||||
|
};
|
||||||
|
|
||||||
/// Error indicating a reference to a non-existent or wrongly-typed output.
|
/// Error indicating a reference to a non-existent or wrongly-typed output.
|
||||||
pub struct NoSuchOutput;
|
pub struct NoSuchOutput;
|
||||||
@ -87,7 +92,7 @@ impl<T: Decodable> Decodable for Field<T> {
|
|||||||
1 => Ok({
|
1 => Ok({
|
||||||
let inner_rlp = rlp.at(1)?;
|
let inner_rlp = rlp.at(1)?;
|
||||||
Field::BackReference(inner_rlp.val_at(0)?, inner_rlp.val_at(1)?)
|
Field::BackReference(inner_rlp.val_at(0)?, inner_rlp.val_at(1)?)
|
||||||
})
|
}),
|
||||||
_ => Err(DecoderError::Custom("Unknown discriminant for PIP field.")),
|
_ => Err(DecoderError::Custom("Unknown discriminant for PIP field.")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -171,7 +176,8 @@ pub enum Request {
|
|||||||
Storage(IncompleteStorageRequest),
|
Storage(IncompleteStorageRequest),
|
||||||
/// A request for contract code.
|
/// A request for contract code.
|
||||||
Code(IncompleteCodeRequest),
|
Code(IncompleteCodeRequest),
|
||||||
// Transaction proof.
|
/// A request for proof of execution,
|
||||||
|
Execution(IncompleteExecutionRequest),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// All request types, as they're sent over the network.
|
/// All request types, as they're sent over the network.
|
||||||
@ -192,19 +198,21 @@ pub enum CompleteRequest {
|
|||||||
Storage(CompleteStorageRequest),
|
Storage(CompleteStorageRequest),
|
||||||
/// A request for contract code.
|
/// A request for contract code.
|
||||||
Code(CompleteCodeRequest),
|
Code(CompleteCodeRequest),
|
||||||
// Transaction proof.
|
/// A request for proof of execution,
|
||||||
|
Execution(CompleteExecutionRequest),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Request {
|
impl Request {
|
||||||
fn kind(&self) -> RequestKind {
|
fn kind(&self) -> Kind {
|
||||||
match *self {
|
match *self {
|
||||||
Request::Headers(_) => RequestKind::Headers,
|
Request::Headers(_) => Kind::Headers,
|
||||||
Request::HeaderProof(_) => RequestKind::HeaderProof,
|
Request::HeaderProof(_) => Kind::HeaderProof,
|
||||||
Request::Receipts(_) => RequestKind::Receipts,
|
Request::Receipts(_) => Kind::Receipts,
|
||||||
Request::Body(_) => RequestKind::Body,
|
Request::Body(_) => Kind::Body,
|
||||||
Request::Account(_) => RequestKind::Account,
|
Request::Account(_) => Kind::Account,
|
||||||
Request::Storage(_) => RequestKind::Storage,
|
Request::Storage(_) => Kind::Storage,
|
||||||
Request::Code(_) => RequestKind::Code,
|
Request::Code(_) => Kind::Code,
|
||||||
|
Request::Execution(_) => Kind::Execution,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -213,14 +221,15 @@ impl Decodable for Request {
|
|||||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||||
let rlp = decoder.as_rlp();
|
let rlp = decoder.as_rlp();
|
||||||
|
|
||||||
match rlp.val_at::<RequestKind>(0)? {
|
match rlp.val_at::<Kind>(0)? {
|
||||||
RequestKind::Headers => Ok(Request::Headers(rlp.val_at(1)?)),
|
Kind::Headers => Ok(Request::Headers(rlp.val_at(1)?)),
|
||||||
RequestKind::HeaderProof => Ok(Request::HeaderProof(rlp.val_at(1)?)),
|
Kind::HeaderProof => Ok(Request::HeaderProof(rlp.val_at(1)?)),
|
||||||
RequestKind::Receipts => Ok(Request::Receipts(rlp.val_at(1)?)),
|
Kind::Receipts => Ok(Request::Receipts(rlp.val_at(1)?)),
|
||||||
RequestKind::Body => Ok(Request::Body(rlp.val_at(1)?)),
|
Kind::Body => Ok(Request::Body(rlp.val_at(1)?)),
|
||||||
RequestKind::Account => Ok(Request::Account(rlp.val_at(1)?)),
|
Kind::Account => Ok(Request::Account(rlp.val_at(1)?)),
|
||||||
RequestKind::Storage => Ok(Request::Storage(rlp.val_at(1)?)),
|
Kind::Storage => Ok(Request::Storage(rlp.val_at(1)?)),
|
||||||
RequestKind::Code => Ok(Request::Code(rlp.val_at(1)?)),
|
Kind::Code => Ok(Request::Code(rlp.val_at(1)?)),
|
||||||
|
Kind::Execution => Ok(Request::Execution(rlp.val_at(1)?)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -237,6 +246,7 @@ impl Encodable for Request {
|
|||||||
Request::Account(ref req) => s.append(req),
|
Request::Account(ref req) => s.append(req),
|
||||||
Request::Storage(ref req) => s.append(req),
|
Request::Storage(ref req) => s.append(req),
|
||||||
Request::Code(ref req) => s.append(req),
|
Request::Code(ref req) => s.append(req),
|
||||||
|
Request::Execution(ref req) => s.append(req),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -255,6 +265,7 @@ impl IncompleteRequest for Request {
|
|||||||
Request::Account(ref req) => req.check_outputs(f),
|
Request::Account(ref req) => req.check_outputs(f),
|
||||||
Request::Storage(ref req) => req.check_outputs(f),
|
Request::Storage(ref req) => req.check_outputs(f),
|
||||||
Request::Code(ref req) => req.check_outputs(f),
|
Request::Code(ref req) => req.check_outputs(f),
|
||||||
|
Request::Execution(ref req) => req.check_outputs(f),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,29 +278,31 @@ impl IncompleteRequest for Request {
|
|||||||
Request::Account(ref req) => req.note_outputs(f),
|
Request::Account(ref req) => req.note_outputs(f),
|
||||||
Request::Storage(ref req) => req.note_outputs(f),
|
Request::Storage(ref req) => req.note_outputs(f),
|
||||||
Request::Code(ref req) => req.note_outputs(f),
|
Request::Code(ref req) => req.note_outputs(f),
|
||||||
|
Request::Execution(ref req) => req.note_outputs(f),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fill<F>(self, oracle: F) -> Result<Self::Complete, NoSuchOutput>
|
fn fill<F>(self, oracle: F) -> Result<Self::Complete, NoSuchOutput>
|
||||||
where F: Fn(usize, usize) -> Result<Output, NoSuchOutput>
|
where F: Fn(usize, usize) -> Result<Output, NoSuchOutput>
|
||||||
{
|
{
|
||||||
match self {
|
Ok(match self {
|
||||||
Request::Headers(req) => CompleteRequest::Headers(req.fill(oracle)),
|
Request::Headers(req) => CompleteRequest::Headers(req.fill(oracle)?),
|
||||||
Request::HeaderProof(req) => CompleteRequest::HeaderProof(req.fill(oracle)),
|
Request::HeaderProof(req) => CompleteRequest::HeaderProof(req.fill(oracle)?),
|
||||||
Request::Receipts(req) => CompleteRequest::Receipts(req.fill(oracle)),
|
Request::Receipts(req) => CompleteRequest::Receipts(req.fill(oracle)?),
|
||||||
Request::Body(req) => CompleteRequest::Body(req.fill(oracle)),
|
Request::Body(req) => CompleteRequest::Body(req.fill(oracle)?),
|
||||||
Request::Account(req) => CompleteRequest::Account(req.fill(oracle)),
|
Request::Account(req) => CompleteRequest::Account(req.fill(oracle)?),
|
||||||
Request::Storage(req) => CompleteRequest::Storage(req.fill(oracle)),
|
Request::Storage(req) => CompleteRequest::Storage(req.fill(oracle)?),
|
||||||
Request::Code(req) => CompleteRequest::Code(req.fill(oracle)),
|
Request::Code(req) => CompleteRequest::Code(req.fill(oracle)?),
|
||||||
}
|
Request::Execution(req) => CompleteRequest::Execution(req.fill(oracle)?),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Kinds of requests.
|
/// Kinds of requests.
|
||||||
/// Doubles as the "ID" field of the request.
|
/// Doubles as the "ID" field of the request.
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum RequestKind {
|
pub enum Kind {
|
||||||
/// A request for headers.
|
/// A request for headers.
|
||||||
Headers = 0,
|
Headers = 0,
|
||||||
HeaderProof = 1,
|
HeaderProof = 1,
|
||||||
@ -299,29 +312,29 @@ pub enum RequestKind {
|
|||||||
Account = 5,
|
Account = 5,
|
||||||
Storage = 6,
|
Storage = 6,
|
||||||
Code = 7,
|
Code = 7,
|
||||||
// TransactionProof = 8,
|
Execution = 8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decodable for RequestKind {
|
impl Decodable for Kind {
|
||||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||||
let rlp = decoder.as_rlp();
|
let rlp = decoder.as_rlp();
|
||||||
|
|
||||||
match rlp.as_val::<u8>()? {
|
match rlp.as_val::<u8>()? {
|
||||||
0 => Ok(RequestKind::Headers),
|
0 => Ok(Kind::Headers),
|
||||||
1 => Ok(RequestKind::HeaderProof),
|
1 => Ok(Kind::HeaderProof),
|
||||||
// 2 => Ok(RequestKind::TransactionIndex,
|
// 2 => Ok(Kind::TransactionIndex,
|
||||||
3 => Ok(RequestKind::Receipts),
|
3 => Ok(Kind::Receipts),
|
||||||
4 => Ok(RequestKind::Body),
|
4 => Ok(Kind::Body),
|
||||||
5 => Ok(RequestKind::Account),
|
5 => Ok(Kind::Account),
|
||||||
6 => Ok(RequestKind::Storage),
|
6 => Ok(Kind::Storage),
|
||||||
7 => Ok(RequestKind::Code),
|
7 => Ok(Kind::Code),
|
||||||
// 8 => Ok(RequestKind::TransactionProof),
|
8 => Ok(Kind::Execution),
|
||||||
_ => Err(DecoderError::Custom("Unknown PIP request ID.")),
|
_ => Err(DecoderError::Custom("Unknown PIP request ID.")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Encodable for RequestKind {
|
impl Encodable for Kind {
|
||||||
fn rlp_append(&self, s: &mut RlpStream) {
|
fn rlp_append(&self, s: &mut RlpStream) {
|
||||||
s.append(self as &u8);
|
s.append(self as &u8);
|
||||||
}
|
}
|
||||||
@ -345,22 +358,71 @@ pub enum Response {
|
|||||||
Storage(StorageResponse),
|
Storage(StorageResponse),
|
||||||
/// A response for contract code.
|
/// A response for contract code.
|
||||||
Code(CodeResponse),
|
Code(CodeResponse),
|
||||||
// Transaction proof.
|
/// A response for proof of execution,
|
||||||
|
Execution(ExecutionResponse),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Response {
|
impl Response {
|
||||||
/// Fill reusable outputs by writing them into the function.
|
/// Fill reusable outputs by writing them into the function.
|
||||||
pub fn fill_outputs<F>(&self, mut f: F) where F: FnMut(usize, Output) {
|
pub fn fill_outputs<F>(&self, mut f: F) where F: FnMut(usize, Output) {
|
||||||
match *self {
|
match *self {
|
||||||
Response::Headers(res) => res.fill_outputs(f)
|
Response::Headers(res) => res.fill_outputs(f),
|
||||||
Response::HeaderProof(res) => res.fill_outputs(f)
|
Response::HeaderProof(res) => res.fill_outputs(f),
|
||||||
Response::Receipts(res) => res.fill_outputs(f)
|
Response::Receipts(res) => res.fill_outputs(f),
|
||||||
Response::Body(res) => res.fill_outputs(f)
|
Response::Body(res) => res.fill_outputs(f),
|
||||||
Response::Account(res) => res.fill_outputs(f)
|
Response::Account(res) => res.fill_outputs(f),
|
||||||
Response::Storage(res) => res.fill_outputs(f)
|
Response::Storage(res) => res.fill_outputs(f),
|
||||||
Response::Code(res) => res.fill_outputs(f)
|
Response::Code(res) => res.fill_outputs(f),
|
||||||
|
Response::Execution(res) => res.fill_outputs(f),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn kind(&self) -> Kind {
|
||||||
|
match *self {
|
||||||
|
Response::Headers(_) => Kind::Headers,
|
||||||
|
Response::HeaderProof(_) => Kind::HeaderProof,
|
||||||
|
Response::Receipts(_) => Kind::Receipts,
|
||||||
|
Response::Body(_) => Kind::Body,
|
||||||
|
Response::Account(_) => Kind::Account,
|
||||||
|
Response::Storage(_) => Kind::Storage,
|
||||||
|
Response::Code(_) => Kind::Code,
|
||||||
|
Respnse::Execution(_) => Kind::Execution,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Decodable for Response {
|
||||||
|
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||||
|
let rlp = decoder.as_rlp();
|
||||||
|
|
||||||
|
match rlp.val_at::<Kind>(0)? {
|
||||||
|
Kind::Headers => Ok(Response::Headers(rlp.val_at(1)?)),
|
||||||
|
Kind::HeaderProof => Ok(Response::HeaderProof(rlp.val_at(1)?)),
|
||||||
|
Kind::Receipts => Ok(Response::Receipts(rlp.val_at(1)?)),
|
||||||
|
Kind::Body => Ok(Response::Body(rlp.val_at(1)?)),
|
||||||
|
Kind::Account => Ok(Response::Account(rlp.val_at(1)?)),
|
||||||
|
Kind::Storage => Ok(Response::Storage(rlp.val_at(1)?)),
|
||||||
|
Kind::Code => Ok(Response::Code(rlp.val_at(1)?)),
|
||||||
|
Kind::Execution=> Ok(Response::Execution(rlp.val_at(1)?)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Encodable for Response {
|
||||||
|
fn rlp_append(&self, s: &mut RlpStream) {
|
||||||
|
s.begin_list(2).append(&self.kind());
|
||||||
|
|
||||||
|
match *self {
|
||||||
|
Response::Headers(ref res) => s.append(res),
|
||||||
|
Response::HeaderProof(ref res) => s.append(res),
|
||||||
|
Response::Receipts(ref res) => s.append(res),
|
||||||
|
Response::Body(ref res) => s.append(res),
|
||||||
|
Response::Account(ref res) => s.append(res),
|
||||||
|
Response::Storage(ref res) => s.append(res),
|
||||||
|
Response::Code(ref res) => s.append(res),
|
||||||
|
Response::Execution(ref res) => s.append(res),
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A potentially incomplete request.
|
/// A potentially incomplete request.
|
||||||
@ -390,7 +452,7 @@ pub trait IncompleteRequest: Sized {
|
|||||||
pub mod header {
|
pub mod header {
|
||||||
use super::{Field, HashOrNumber, NoSuchOutput, OutputKind, Output};
|
use super::{Field, HashOrNumber, NoSuchOutput, OutputKind, Output};
|
||||||
use ethcore::encoded;
|
use ethcore::encoded;
|
||||||
use rlp::{Encodable, Decodable, Decoder, DecoderError, RlpStream, Stream};
|
use rlp::{Encodable, Decodable, Decoder, DecoderError, RlpStream, Stream, View};
|
||||||
use util::U256;
|
use util::U256;
|
||||||
|
|
||||||
/// Potentially incomplete headers request.
|
/// Potentially incomplete headers request.
|
||||||
@ -488,12 +550,41 @@ pub mod header {
|
|||||||
/// Fill reusable outputs by writing them into the function.
|
/// Fill reusable outputs by writing them into the function.
|
||||||
pub fn fill_outputs<F>(&self, _: F) where F: FnMut(usize, Output) { }
|
pub fn fill_outputs<F>(&self, _: F) where F: FnMut(usize, Output) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Decodable for Response {
|
||||||
|
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||||
|
use ethcore::header::Header as FullHeader;
|
||||||
|
let rlp = decoder.as_rlp();
|
||||||
|
|
||||||
|
let mut headers = Vec::new();
|
||||||
|
|
||||||
|
for item in rlp.at(0)?.iter() {
|
||||||
|
// check that it's a valid encoding.
|
||||||
|
// TODO: just return full headers here?
|
||||||
|
let _: FullHeader = item.as_val()?;
|
||||||
|
headers.push(encoded::Header::new(item.as_raw().to_owned()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Response {
|
||||||
|
headers: headers,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Encodable for Response {
|
||||||
|
fn rlp_append(&self, s: &mut RlpStream) {
|
||||||
|
s.begin_list(self.headers.len());
|
||||||
|
for header in &self.headers {
|
||||||
|
s.append_raw(header.rlp().as_raw(), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Request and response for header proofs.
|
/// Request and response for header proofs.
|
||||||
pub mod header_proof {
|
pub mod header_proof {
|
||||||
use super::{Field, NoSuchOutput, OutputKind, Output};
|
use super::{Field, NoSuchOutput, OutputKind, Output};
|
||||||
use rlp::{Encodable, Decodable, Decoder, DecoderError, RlpStream, Stream};
|
use rlp::{Encodable, Decodable, Decoder, DecoderError, RlpStream, Stream, View};
|
||||||
use util::{Bytes, U256, H256};
|
use util::{Bytes, U256, H256};
|
||||||
|
|
||||||
/// Potentially incomplete header proof request.
|
/// Potentially incomplete header proof request.
|
||||||
@ -576,12 +667,34 @@ pub mod header_proof {
|
|||||||
f(1, Output::Hash(self.hash));
|
f(1, Output::Hash(self.hash));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Decodable for Response {
|
||||||
|
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||||
|
let rlp = decoder.as_rlp();
|
||||||
|
|
||||||
|
Ok(Response {
|
||||||
|
proof: rlp.val_at(0)?,
|
||||||
|
hash: rlp.val_at(1)?,
|
||||||
|
td: rlp.val_at(2)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Encodable for Response {
|
||||||
|
fn rlp_append(&self, s: &mut RlpStream) {
|
||||||
|
s.begin_list(3)
|
||||||
|
.append(&self.proof)
|
||||||
|
.append(&self.hash)
|
||||||
|
.append(&self.td);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Request and response for block receipts
|
/// Request and response for block receipts
|
||||||
pub mod block_receipts {
|
pub mod block_receipts {
|
||||||
use super::{Field, NoSuchOutput, OutputKind, Output};
|
use super::{Field, NoSuchOutput, OutputKind, Output};
|
||||||
use rlp::{Encodable, Decodable, Decoder, DecoderError, RlpStream, Stream};
|
use ethcore::receipt::Receipt;
|
||||||
|
use rlp::{Encodable, Decodable, Decoder, DecoderError, RlpStream, Stream, View};
|
||||||
use util::{Bytes, U256, H256};
|
use util::{Bytes, U256, H256};
|
||||||
|
|
||||||
/// Potentially incomplete block receipts request.
|
/// Potentially incomplete block receipts request.
|
||||||
@ -655,13 +768,29 @@ pub mod block_receipts {
|
|||||||
/// Fill reusable outputs by providing them to the function.
|
/// Fill reusable outputs by providing them to the function.
|
||||||
pub fn fill_outputs<F>(&self, _: F) where F: FnMut(usize, Output) {}
|
pub fn fill_outputs<F>(&self, _: F) where F: FnMut(usize, Output) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Decodable for Response {
|
||||||
|
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||||
|
let rlp = decoder.as_rlp();
|
||||||
|
|
||||||
|
Ok(Response {
|
||||||
|
receipts: rlp.val_at(0)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Encodable for Response {
|
||||||
|
fn rlp_append(&self, s: &mut RlpStream) {
|
||||||
|
s.append(&self.receipts);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Request and response for a block body
|
/// Request and response for a block body
|
||||||
pub mod block_body {
|
pub mod block_body {
|
||||||
use super::{Field, NoSuchOutput, OutputKind, Output};
|
use super::{Field, NoSuchOutput, OutputKind, Output};
|
||||||
use ethcore::encoded;
|
use ethcore::encoded;
|
||||||
use rlp::{Encodable, Decodable, Decoder, DecoderError, RlpStream, Stream};
|
use rlp::{Encodable, Decodable, Decoder, DecoderError, RlpStream, Stream, View};
|
||||||
use util::{Bytes, U256, H256};
|
use util::{Bytes, U256, H256};
|
||||||
|
|
||||||
/// Potentially incomplete block body request.
|
/// Potentially incomplete block body request.
|
||||||
@ -736,13 +865,38 @@ pub mod block_body {
|
|||||||
/// Fill reusable outputs by providing them to the function.
|
/// Fill reusable outputs by providing them to the function.
|
||||||
pub fn fill_outputs<F>(&self, _: F) where F: FnMut(usize, Output) {}
|
pub fn fill_outputs<F>(&self, _: F) where F: FnMut(usize, Output) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Decodable for Response {
|
||||||
|
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||||
|
use ethcore::header::Header as FullHeader;
|
||||||
|
use ethcore::transaction::SignedTransaction;
|
||||||
|
|
||||||
|
let rlp = decoder.as_rlp();
|
||||||
|
let body_rlp = rlp.at(0)?;
|
||||||
|
|
||||||
|
// check body validity.
|
||||||
|
let _: Vec<FullHeader> = rlp.val_at(0)?;
|
||||||
|
let _: Vec<SignedTransaction> = rlp.val_at(1)?;
|
||||||
|
|
||||||
|
Ok(Response {
|
||||||
|
body: encoded::Body::new(body_rlp.as_raw().to_owned()),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Encodable for Response {
|
||||||
|
fn rlp_append(&self, s: &mut RlpStream) {
|
||||||
|
s.begin_list(2)
|
||||||
|
.append_raw(&self.body.rlp().as_raw(), 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A request for an account proof.
|
/// A request for an account proof.
|
||||||
pub mod account {
|
pub mod account {
|
||||||
use super::{Field, NoSuchOutput, OutputKind, Output};
|
use super::{Field, NoSuchOutput, OutputKind, Output};
|
||||||
use ethcore::encoded;
|
use ethcore::encoded;
|
||||||
use rlp::{Encodable, Decodable, Decoder, DecoderError, RlpStream, Stream};
|
use rlp::{Encodable, Decodable, Decoder, DecoderError, RlpStream, Stream, View};
|
||||||
use util::{Bytes, U256, H256};
|
use util::{Bytes, U256, H256};
|
||||||
|
|
||||||
/// Potentially incomplete request for an account proof.
|
/// Potentially incomplete request for an account proof.
|
||||||
@ -852,13 +1006,38 @@ pub mod account {
|
|||||||
f(1, Output::Hash(self.storage_root));
|
f(1, Output::Hash(self.storage_root));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Decodable for Response {
|
||||||
|
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||||
|
let rlp = decoder.as_rlp();
|
||||||
|
|
||||||
|
Ok(Response {
|
||||||
|
proof: rlp.val_at(0)?,
|
||||||
|
nonce: rlp.val_at(1)?,
|
||||||
|
balance: rlp.val_at(2)?,
|
||||||
|
code_hash: rlp.val_at(3)?,
|
||||||
|
storage_root: rlp.val_at(4)?
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Encodable for Response {
|
||||||
|
fn rlp_append(&self, s: &mut RlpStream) {
|
||||||
|
s.begin_list(5)
|
||||||
|
.append(&self.proof)
|
||||||
|
.append(&self.nonce)
|
||||||
|
.append(&self.balance)
|
||||||
|
.append(&self.code_hash)
|
||||||
|
.append(&self.storage_root)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A request for a storage proof.
|
/// A request for a storage proof.
|
||||||
pub mod storage {
|
pub mod storage {
|
||||||
use super::{Field, NoSuchOutput, OutputKind, Output};
|
use super::{Field, NoSuchOutput, OutputKind, Output};
|
||||||
use ethcore::encoded;
|
use ethcore::encoded;
|
||||||
use rlp::{Encodable, Decodable, Decoder, DecoderError, RlpStream, Stream};
|
use rlp::{Encodable, Decodable, Decoder, DecoderError, RlpStream, Stream, View};
|
||||||
use util::{Bytes, U256, H256};
|
use util::{Bytes, U256, H256};
|
||||||
|
|
||||||
/// Potentially incomplete request for an storage proof.
|
/// Potentially incomplete request for an storage proof.
|
||||||
@ -979,16 +1158,35 @@ pub mod storage {
|
|||||||
f(0, Output::Hash(self.value));
|
f(0, Output::Hash(self.value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Decodable for Response {
|
||||||
|
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||||
|
let rlp = decoder.as_rlp();
|
||||||
|
|
||||||
|
Ok(Response {
|
||||||
|
proof: rlp.val_at(0)?,
|
||||||
|
value: rlp.val_at(1)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Encodable for Response {
|
||||||
|
fn rlp_append(&self, s: &mut RlpStream) {
|
||||||
|
s.begin_list(2)
|
||||||
|
.append(&self.proof)
|
||||||
|
.append(&self.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A request for contract code.
|
/// A request for contract code.
|
||||||
pub mod contract_code {
|
pub mod contract_code {
|
||||||
use super::{Field, NoSuchOutput, OutputKind, Output};
|
use super::{Field, NoSuchOutput, OutputKind, Output};
|
||||||
use ethcore::encoded;
|
use ethcore::encoded;
|
||||||
use rlp::{Encodable, Decodable, Decoder, DecoderError, RlpStream, Stream};
|
use rlp::{Encodable, Decodable, Decoder, DecoderError, RlpStream, Stream, View};
|
||||||
use util::{Bytes, U256, H256};
|
use util::{Bytes, U256, H256};
|
||||||
|
|
||||||
/// Potentially incomplete _ request.
|
/// Potentially incomplete contract code request.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct Incomplete {
|
pub struct Incomplete {
|
||||||
/// The block hash to request the state for.
|
/// The block hash to request the state for.
|
||||||
@ -1080,4 +1278,177 @@ pub mod contract_code {
|
|||||||
/// Fill reusable outputs by providing them to the function.
|
/// Fill reusable outputs by providing them to the function.
|
||||||
pub fn fill_outputs<F>(&self, _: F) where F: FnMut(usize, Output) {}
|
pub fn fill_outputs<F>(&self, _: F) where F: FnMut(usize, Output) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Decodable for Response {
|
||||||
|
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||||
|
let rlp = decoder.as_rlp();
|
||||||
|
|
||||||
|
Ok(Response {
|
||||||
|
code: rlp.val_at(0)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Encodable for Response {
|
||||||
|
fn rlp_append(&self, s: &mut RlpStream) {
|
||||||
|
s.append(&self.code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A request for proof of execution.
|
||||||
|
pub mod execution {
|
||||||
|
use super::{Field, NoSuchOutput, OutputKind, Output};
|
||||||
|
use ethcore::encoded;
|
||||||
|
use ethcore::transaction::Action;
|
||||||
|
use rlp::{Encodable, Decodable, Decoder, DecoderError, RlpStream, Stream, View};
|
||||||
|
use util::{Bytes, Address, U256, H256, DBValue};
|
||||||
|
|
||||||
|
/// Potentially incomplete execution proof request.
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct Incomplete {
|
||||||
|
/// The block hash to request the state for.
|
||||||
|
pub block_hash: Field<H256>,
|
||||||
|
/// The address the transaction should be from.
|
||||||
|
pub from: Address,
|
||||||
|
/// The action of the transaction.
|
||||||
|
pub action: Action,
|
||||||
|
/// The amount of gas to prove.
|
||||||
|
pub gas: U256,
|
||||||
|
/// The gas price.
|
||||||
|
pub gas_price: U256,
|
||||||
|
/// The value to transfer.
|
||||||
|
pub value: U256,
|
||||||
|
/// Call data.
|
||||||
|
pub data: Bytes,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Decodable for Incomplete {
|
||||||
|
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||||
|
let rlp = decoder.as_rlp();
|
||||||
|
Ok(Incomplete {
|
||||||
|
block_hash: rlp.val_at(0)?,
|
||||||
|
address: rlp.val_at(1)?,
|
||||||
|
action: rlp.val_at(2)?,
|
||||||
|
gas: rlp.val_at(3)?,
|
||||||
|
gas_price: rlp.val_at(4)?,
|
||||||
|
value: rlp.val_at(5)?,
|
||||||
|
data: rlp.val_at(6)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Encodable for Incomplete {
|
||||||
|
fn rlp_append(&self, s: &mut RlpStream) {
|
||||||
|
s.begin_list(7)
|
||||||
|
.append(&self.block_hash)
|
||||||
|
.append(&self.from);
|
||||||
|
|
||||||
|
match *self.action {
|
||||||
|
Action::Create => s.append_empty_data(),
|
||||||
|
Action::Call(ref addr) => s.append(addr),
|
||||||
|
};
|
||||||
|
|
||||||
|
s.append(&self.gas)
|
||||||
|
.append(&self.gas_price)
|
||||||
|
.append(&self.value)
|
||||||
|
.append(&self.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)?,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Complete {
|
||||||
|
block_hash: block_hash,
|
||||||
|
from: self.from,
|
||||||
|
action: self.action,
|
||||||
|
gas: self.gas,
|
||||||
|
gas_price: self.gas_price,
|
||||||
|
value: self.value,
|
||||||
|
data: self.data,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A complete request.
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct Complete {
|
||||||
|
/// The block hash to request the state for.
|
||||||
|
pub block_hash: H256,
|
||||||
|
/// The address the transaction should be from.
|
||||||
|
pub from: Address,
|
||||||
|
/// The action of the transaction.
|
||||||
|
pub action: Action,
|
||||||
|
/// The amount of gas to prove.
|
||||||
|
pub gas: U256,
|
||||||
|
/// The gas price.
|
||||||
|
pub gas_price: U256,
|
||||||
|
/// The value to transfer.
|
||||||
|
pub value: U256,
|
||||||
|
/// Call data.
|
||||||
|
pub data: Bytes,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The output of a request for proof of execution
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct Response {
|
||||||
|
/// All state items (trie nodes, code) necessary to re-prove the transaction.
|
||||||
|
pub items: Vec<DBValue>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Response {
|
||||||
|
/// Fill reusable outputs by providing them to the function.
|
||||||
|
pub fn fill_outputs<F>(&self, _: F) where F: FnMut(usize, Output) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Decodable for Response {
|
||||||
|
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||||
|
let rlp = decoder.as_rlp();
|
||||||
|
let mut items = Vec::new();
|
||||||
|
for raw_item in rlp.at(0)?.iter() {
|
||||||
|
let mut item = DBValue::new();
|
||||||
|
item.append_slice(raw_item.data());
|
||||||
|
items.push(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Response {
|
||||||
|
items: items,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Encodable for Response {
|
||||||
|
fn rlp_append(&self, s: &mut RlpStream) {
|
||||||
|
s.begin_list(&self.items.len());
|
||||||
|
|
||||||
|
for item in &self.items {
|
||||||
|
s.append(&&**item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user