split request filling into fill,complete
This commit is contained in:
parent
f0a587d310
commit
599f81daa9
@ -105,9 +105,8 @@ impl Requests {
|
|||||||
if self.answered == self.requests.len() {
|
if self.answered == self.requests.len() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let outputs = &self.outputs;
|
|
||||||
Some(self.requests[self.answered].clone()
|
Some(self.requests[self.answered].clone()
|
||||||
.fill(|req_idx, out_idx| outputs.get(&(req_idx, out_idx)).cloned().ok_or(NoSuchOutput))
|
.complete()
|
||||||
.expect("All outputs checked as invariant of `Requests` object; qed"))
|
.expect("All outputs checked as invariant of `Requests` object; qed"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -130,6 +129,12 @@ impl Requests {
|
|||||||
});
|
});
|
||||||
|
|
||||||
self.answered += 1;
|
self.answered += 1;
|
||||||
|
|
||||||
|
// fill as much of the next request as we can.
|
||||||
|
if let Some(ref mut req) = self.requests.get_mut(self.answered) {
|
||||||
|
req.fill(|req_idx, out_idx| outputs.get(&(req_idx, out_idx)).cloned().ok_or(NoSuchOutput))
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,6 +88,16 @@ pub enum Field<T> {
|
|||||||
BackReference(usize, usize),
|
BackReference(usize, usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> Field<T> {
|
||||||
|
// attempt conversion into scalar value.
|
||||||
|
fn into_scalar(self) -> Result<T, NoSuchOutput> {
|
||||||
|
match self {
|
||||||
|
Field::Scalar(val) => Ok(val),
|
||||||
|
_ => Err(NoSuchOutput),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> From<T> for Field<T> {
|
impl<T> From<T> for Field<T> {
|
||||||
fn from(val: T) -> Self {
|
fn from(val: T) -> Self {
|
||||||
Field::Scalar(val)
|
Field::Scalar(val)
|
||||||
@ -318,19 +328,30 @@ impl IncompleteRequest for Request {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fill<F>(self, oracle: F) -> Result<Self::Complete, NoSuchOutput>
|
fn fill<F>(&mut self, oracle: F) where F: Fn(usize, usize) -> Result<Output, NoSuchOutput> {
|
||||||
where F: Fn(usize, usize) -> Result<Output, NoSuchOutput>
|
match *self {
|
||||||
{
|
Request::Headers(ref mut req) => req.fill(oracle),
|
||||||
Ok(match self {
|
Request::HeaderProof(ref mut req) => req.fill(oracle),
|
||||||
Request::Headers(req) => CompleteRequest::Headers(req.fill(oracle)?),
|
Request::Receipts(ref mut req) => req.fill(oracle),
|
||||||
Request::HeaderProof(req) => CompleteRequest::HeaderProof(req.fill(oracle)?),
|
Request::Body(ref mut req) => req.fill(oracle),
|
||||||
Request::Receipts(req) => CompleteRequest::Receipts(req.fill(oracle)?),
|
Request::Account(ref mut req) => req.fill(oracle),
|
||||||
Request::Body(req) => CompleteRequest::Body(req.fill(oracle)?),
|
Request::Storage(ref mut req) => req.fill(oracle),
|
||||||
Request::Account(req) => CompleteRequest::Account(req.fill(oracle)?),
|
Request::Code(ref mut req) => req.fill(oracle),
|
||||||
Request::Storage(req) => CompleteRequest::Storage(req.fill(oracle)?),
|
Request::Execution(ref mut req) => req.fill(oracle),
|
||||||
Request::Code(req) => CompleteRequest::Code(req.fill(oracle)?),
|
}
|
||||||
Request::Execution(req) => CompleteRequest::Execution(req.fill(oracle)?),
|
}
|
||||||
})
|
|
||||||
|
fn complete(self) -> Result<Self::Complete, NoSuchOutput> {
|
||||||
|
match self {
|
||||||
|
Request::Headers(req) => req.complete().map(CompleteRequest::Headers),
|
||||||
|
Request::HeaderProof(req) => req.complete().map(CompleteRequest::HeaderProof),
|
||||||
|
Request::Receipts(req) => req.complete().map(CompleteRequest::Receipts),
|
||||||
|
Request::Body(req) => req.complete().map(CompleteRequest::Body),
|
||||||
|
Request::Account(req) => req.complete().map(CompleteRequest::Account),
|
||||||
|
Request::Storage(req) => req.complete().map(CompleteRequest::Storage),
|
||||||
|
Request::Code(req) => req.complete().map(CompleteRequest::Code),
|
||||||
|
Request::Execution(req) => req.complete().map(CompleteRequest::Execution),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -486,13 +507,16 @@ pub trait IncompleteRequest: Sized {
|
|||||||
/// Note that this request will produce the following outputs.
|
/// Note that this request will produce the following outputs.
|
||||||
fn note_outputs<F>(&self, f: F) where F: FnMut(usize, OutputKind);
|
fn note_outputs<F>(&self, f: F) where F: FnMut(usize, OutputKind);
|
||||||
|
|
||||||
/// Fill the request.
|
/// Fill fields of the request.
|
||||||
///
|
///
|
||||||
/// This function is provided an "output oracle" which allows fetching of
|
/// This function is provided an "output oracle" which allows fetching of
|
||||||
/// prior request outputs.
|
/// prior request outputs.
|
||||||
/// Only outputs previously checked with `check_outputs` will be available.
|
/// Only outputs previously checked with `check_outputs` may be available.
|
||||||
fn fill<F>(self, oracle: F) -> Result<Self::Complete, NoSuchOutput>
|
fn fill<F>(&mut self, oracle: F) where F: Fn(usize, usize) -> Result<Output, NoSuchOutput>;
|
||||||
where F: Fn(usize, usize) -> Result<Output, NoSuchOutput>;
|
|
||||||
|
/// Attempt to convert this request into its complete variant.
|
||||||
|
/// Will succeed if all fields have been filled, will fail otherwise.
|
||||||
|
fn complete(self) -> Result<Self::Complete, NoSuchOutput>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Header request.
|
/// Header request.
|
||||||
@ -551,25 +575,24 @@ pub mod header {
|
|||||||
|
|
||||||
fn note_outputs<F>(&self, _: F) where F: FnMut(usize, OutputKind) { }
|
fn note_outputs<F>(&self, _: F) where F: FnMut(usize, OutputKind) { }
|
||||||
|
|
||||||
fn fill<F>(self, oracle: F) -> Result<Self::Complete, NoSuchOutput>
|
fn fill<F>(&mut self, oracle: F) where F: Fn(usize, usize) -> Result<Output, NoSuchOutput> {
|
||||||
where F: Fn(usize, usize) -> Result<Output, NoSuchOutput>
|
if let Field::BackReference(req, idx) = self.start {
|
||||||
{
|
self.start = match oracle(req, idx) {
|
||||||
let start = match self.start {
|
Ok(Output::Hash(hash)) => Field::Scalar(hash.into()),
|
||||||
Field::Scalar(start) => start,
|
Ok(Output::Number(num)) => Field::Scalar(num.into()),
|
||||||
Field::BackReference(req, idx) => match oracle(req, idx)? {
|
Err(_) => Field::BackReference(req, idx),
|
||||||
Output::Hash(hash) => hash.into(),
|
}
|
||||||
Output::Number(num) => num.into(),
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
fn complete(self) -> Result<Self::Complete, NoSuchOutput> {
|
||||||
Ok(Complete {
|
Ok(Complete {
|
||||||
start: start,
|
start: self.start.into_scalar()?,
|
||||||
skip: self.skip,
|
skip: self.skip,
|
||||||
max: self.max,
|
max: self.max,
|
||||||
reverse: self.reverse,
|
reverse: self.reverse,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A complete header request.
|
/// A complete header request.
|
||||||
@ -671,22 +694,20 @@ pub mod header_proof {
|
|||||||
note(0, OutputKind::Hash);
|
note(0, OutputKind::Hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fill<F>(self, oracle: F) -> Result<Self::Complete, NoSuchOutput>
|
fn fill<F>(&mut self, oracle: F) where F: Fn(usize, usize) -> Result<Output, NoSuchOutput> {
|
||||||
where F: Fn(usize, usize) -> Result<Output, NoSuchOutput>
|
if let Field::BackReference(req, idx) = self.num {
|
||||||
{
|
self.num = match oracle(req, idx) {
|
||||||
let num = match self.num {
|
Ok(Output::Number(num)) => Field::Scalar(num.into()),
|
||||||
Field::Scalar(num) => num,
|
_ => Field::BackReference(req, idx),
|
||||||
Field::BackReference(req, idx) => match oracle(req, idx)? {
|
}
|
||||||
Output::Number(num) => num,
|
}
|
||||||
_ => return Err(NoSuchOutput),
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
fn complete(self) -> Result<Self::Complete, NoSuchOutput> {
|
||||||
Ok(Complete {
|
Ok(Complete {
|
||||||
num: num,
|
num: self.num.into_scalar()?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A complete header proof request.
|
/// A complete header proof request.
|
||||||
@ -779,19 +800,18 @@ pub mod block_receipts {
|
|||||||
|
|
||||||
fn note_outputs<F>(&self, _: F) where F: FnMut(usize, OutputKind) {}
|
fn note_outputs<F>(&self, _: F) where F: FnMut(usize, OutputKind) {}
|
||||||
|
|
||||||
fn fill<F>(self, oracle: F) -> Result<Self::Complete, NoSuchOutput>
|
fn fill<F>(&mut self, oracle: F) where F: Fn(usize, usize) -> Result<Output, NoSuchOutput> {
|
||||||
where F: Fn(usize, usize) -> Result<Output, NoSuchOutput>
|
if let Field::BackReference(req, idx) = self.hash {
|
||||||
{
|
self.hash = match oracle(req, idx) {
|
||||||
let hash = match self.hash {
|
Ok(Output::Number(hash)) => Field::Scalar(hash.into()),
|
||||||
Field::Scalar(hash) => hash,
|
_ => Field::BackReference(req, idx),
|
||||||
Field::BackReference(req, idx) => match oracle(req, idx)? {
|
}
|
||||||
Output::Hash(hash) => hash,
|
}
|
||||||
_ => return Err(NoSuchOutput),
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
fn complete(self) -> Result<Self::Complete, NoSuchOutput> {
|
||||||
Ok(Complete {
|
Ok(Complete {
|
||||||
hash: hash,
|
hash: self.hash.into_scalar()?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -875,22 +895,20 @@ pub mod block_body {
|
|||||||
|
|
||||||
fn note_outputs<F>(&self, _: F) where F: FnMut(usize, OutputKind) {}
|
fn note_outputs<F>(&self, _: F) where F: FnMut(usize, OutputKind) {}
|
||||||
|
|
||||||
fn fill<F>(self, oracle: F) -> Result<Self::Complete, NoSuchOutput>
|
fn fill<F>(&mut self, oracle: F) where F: Fn(usize, usize) -> Result<Output, NoSuchOutput> {
|
||||||
where F: Fn(usize, usize) -> Result<Output, NoSuchOutput>
|
if let Field::BackReference(req, idx) = self.hash {
|
||||||
{
|
self.hash = match oracle(req, idx) {
|
||||||
let hash = match self.hash {
|
Ok(Output::Hash(hash)) => Field::Scalar(hash.into()),
|
||||||
Field::Scalar(hash) => hash,
|
_ => Field::BackReference(req, idx),
|
||||||
Field::BackReference(req, idx) => match oracle(req, idx)? {
|
}
|
||||||
Output::Hash(hash) => hash,
|
}
|
||||||
_ => return Err(NoSuchOutput),
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
fn complete(self) -> Result<Self::Complete, NoSuchOutput> {
|
||||||
Ok(Complete {
|
Ok(Complete {
|
||||||
hash: hash,
|
hash: self.hash.into_scalar()?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A complete block body request.
|
/// A complete block body request.
|
||||||
@ -991,31 +1009,28 @@ pub mod account {
|
|||||||
f(1, OutputKind::Hash);
|
f(1, OutputKind::Hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fill<F>(self, oracle: F) -> Result<Self::Complete, NoSuchOutput>
|
fn fill<F>(&mut self, oracle: F) where F: Fn(usize, usize) -> Result<Output, NoSuchOutput> {
|
||||||
where F: Fn(usize, usize) -> Result<Output, NoSuchOutput>
|
if let Field::BackReference(req, idx) = self.block_hash {
|
||||||
{
|
self.block_hash = match oracle(req, idx) {
|
||||||
let block_hash = match self.block_hash {
|
Ok(Output::Hash(block_hash)) => Field::Scalar(block_hash.into()),
|
||||||
Field::Scalar(hash) => hash,
|
_ => Field::BackReference(req, idx),
|
||||||
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)?,
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
if let Field::BackReference(req, idx) = self.address_hash {
|
||||||
|
self.address_hash = match oracle(req, idx) {
|
||||||
|
Ok(Output::Hash(address_hash)) => Field::Scalar(address_hash.into()),
|
||||||
|
_ => Field::BackReference(req, idx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn complete(self) -> Result<Self::Complete, NoSuchOutput> {
|
||||||
Ok(Complete {
|
Ok(Complete {
|
||||||
block_hash: block_hash,
|
block_hash: self.block_hash.into_scalar()?,
|
||||||
address_hash: address_hash,
|
address_hash: self.address_hash.into_scalar()?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A complete request for an account.
|
/// A complete request for an account.
|
||||||
@ -1138,40 +1153,36 @@ pub mod storage {
|
|||||||
f(0, OutputKind::Hash);
|
f(0, OutputKind::Hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fill<F>(self, oracle: F) -> Result<Self::Complete, NoSuchOutput>
|
fn fill<F>(&mut self, oracle: F) where F: Fn(usize, usize) -> Result<Output, NoSuchOutput> {
|
||||||
where F: Fn(usize, usize) -> Result<Output, NoSuchOutput>
|
if let Field::BackReference(req, idx) = self.block_hash {
|
||||||
{
|
self.block_hash = match oracle(req, idx) {
|
||||||
let block_hash = match self.block_hash {
|
Ok(Output::Hash(block_hash)) => Field::Scalar(block_hash.into()),
|
||||||
Field::Scalar(hash) => hash,
|
_ => Field::BackReference(req, idx),
|
||||||
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 {
|
if let Field::BackReference(req, idx) = self.address_hash {
|
||||||
Field::Scalar(hash) => hash,
|
self.address_hash = match oracle(req, idx) {
|
||||||
Field::BackReference(req, idx) => match oracle(req, idx)? {
|
Ok(Output::Hash(address_hash)) => Field::Scalar(address_hash.into()),
|
||||||
Output::Hash(hash) => hash,
|
_ => Field::BackReference(req, idx),
|
||||||
_ => return Err(NoSuchOutput)?,
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
if let Field::BackReference(req, idx) = self.key_hash {
|
||||||
|
self.key_hash = match oracle(req, idx) {
|
||||||
|
Ok(Output::Hash(key_hash)) => Field::Scalar(key_hash.into()),
|
||||||
|
_ => Field::BackReference(req, idx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn complete(self) -> Result<Self::Complete, NoSuchOutput> {
|
||||||
Ok(Complete {
|
Ok(Complete {
|
||||||
block_hash: block_hash,
|
block_hash: self.block_hash.into_scalar()?,
|
||||||
address_hash: address_hash,
|
address_hash: self.address_hash.into_scalar()?,
|
||||||
key_hash: key_hash
|
key_hash: self.key_hash.into_scalar()?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A complete request for a storage proof.
|
/// A complete request for a storage proof.
|
||||||
@ -1272,31 +1283,28 @@ pub mod contract_code {
|
|||||||
|
|
||||||
fn note_outputs<F>(&self, _: F) where F: FnMut(usize, OutputKind) {}
|
fn note_outputs<F>(&self, _: F) where F: FnMut(usize, OutputKind) {}
|
||||||
|
|
||||||
fn fill<F>(self, oracle: F) -> Result<Self::Complete, NoSuchOutput>
|
fn fill<F>(&mut self, oracle: F) where F: Fn(usize, usize) -> Result<Output, NoSuchOutput> {
|
||||||
where F: Fn(usize, usize) -> Result<Output, NoSuchOutput>
|
if let Field::BackReference(req, idx) = self.block_hash {
|
||||||
{
|
self.block_hash = match oracle(req, idx) {
|
||||||
let block_hash = match self.block_hash {
|
Ok(Output::Hash(block_hash)) => Field::Scalar(block_hash.into()),
|
||||||
Field::Scalar(hash) => hash,
|
_ => Field::BackReference(req, idx),
|
||||||
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)?,
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
if let Field::BackReference(req, idx) = self.code_hash {
|
||||||
|
self.code_hash = match oracle(req, idx) {
|
||||||
|
Ok(Output::Hash(code_hash)) => Field::Scalar(code_hash.into()),
|
||||||
|
_ => Field::BackReference(req, idx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn complete(self) -> Result<Self::Complete, NoSuchOutput> {
|
||||||
Ok(Complete {
|
Ok(Complete {
|
||||||
block_hash: block_hash,
|
block_hash: self.block_hash.into_scalar()?,
|
||||||
code_hash: code_hash,
|
code_hash: self.code_hash.into_scalar()?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A complete request.
|
/// A complete request.
|
||||||
@ -1411,19 +1419,17 @@ pub mod execution {
|
|||||||
|
|
||||||
fn note_outputs<F>(&self, _: F) where F: FnMut(usize, OutputKind) {}
|
fn note_outputs<F>(&self, _: F) where F: FnMut(usize, OutputKind) {}
|
||||||
|
|
||||||
fn fill<F>(self, oracle: F) -> Result<Self::Complete, NoSuchOutput>
|
fn fill<F>(&mut self, oracle: F) where F: Fn(usize, usize) -> Result<Output, NoSuchOutput> {
|
||||||
where F: Fn(usize, usize) -> Result<Output, NoSuchOutput>
|
if let Field::BackReference(req, idx) = self.block_hash {
|
||||||
{
|
self.block_hash = match oracle(req, idx) {
|
||||||
let block_hash = match self.block_hash {
|
Ok(Output::Hash(block_hash)) => Field::Scalar(block_hash.into()),
|
||||||
Field::Scalar(hash) => hash,
|
_ => Field::BackReference(req, idx),
|
||||||
Field::BackReference(req, idx) => match oracle(req, idx)? {
|
|
||||||
Output::Hash(hash) => hash,
|
|
||||||
_ => return Err(NoSuchOutput)?,
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
fn complete(self) -> Result<Self::Complete, NoSuchOutput> {
|
||||||
Ok(Complete {
|
Ok(Complete {
|
||||||
block_hash: block_hash,
|
block_hash: self.block_hash.into_scalar()?,
|
||||||
from: self.from,
|
from: self.from,
|
||||||
action: self.action,
|
action: self.action,
|
||||||
gas: self.gas,
|
gas: self.gas,
|
||||||
@ -1432,7 +1438,6 @@ pub mod execution {
|
|||||||
data: self.data,
|
data: self.data,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A complete request.
|
/// A complete request.
|
||||||
|
Loading…
Reference in New Issue
Block a user