Implement PIP messages, request builder, and handlers (#4945)
* return errors on database corruption * fix tests, json tests * fix remainder of build * buffer flow -> request credits * proving state backend * generate transaction proofs from provider * network messages for transaction proof * transaction proof test * test for transaction proof message * fix call bug * request transaction proofs from on_demand * most of proved_execution rpc * proved execution future * initial request definitions * RLP encoding and decoding for requests * proofs of non-existance in ProvingBlockChainClient * new requests in provider. * encode and decode responses * complete initial request changes * handle request packet in LightProtocol * handle response packets * implement requesting from * re-do cost table * get tests compiling * fix cost table RLP encoding * roundtrip tests for request types * request builder tests * move request_builder -> request::builder * get network tests working * return only complete headers responses * request builder improvements * New version of jsonrpc. * split request filling into fill,complete * Better invalid encoding messages * Fixing deprecated methods of tokio_core * use PIP messages in on_demand, old API * migrate oneshot::complete to send in on_demand * get on_demand tests to compile * port ethsync to PIP messages * adjust to minor on_demand API changes in RPC * Using dedicated branch for jsonrpc * Bump
This commit is contained in:
committed by
Gav Wood
parent
b931a225ba
commit
64cec5ff7d
@@ -12,7 +12,7 @@
|
||||
// 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/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! I/O and event context generalizations.
|
||||
|
||||
@@ -20,7 +20,7 @@ use network::{NetworkContext, PeerId, NodeId};
|
||||
|
||||
use super::{Announcement, LightProtocol, ReqId};
|
||||
use super::error::Error;
|
||||
use request::{self, Request};
|
||||
use request::Requests;
|
||||
|
||||
/// An I/O context which allows sending and receiving packets as well as
|
||||
/// disconnecting peers. This is used as a generalization of the portions
|
||||
@@ -50,13 +50,13 @@ pub trait IoContext {
|
||||
impl<'a> IoContext for NetworkContext<'a> {
|
||||
fn send(&self, peer: PeerId, packet_id: u8, packet_body: Vec<u8>) {
|
||||
if let Err(e) = self.send(peer, packet_id, packet_body) {
|
||||
debug!(target: "les", "Error sending packet to peer {}: {}", peer, e);
|
||||
debug!(target: "pip", "Error sending packet to peer {}: {}", peer, e);
|
||||
}
|
||||
}
|
||||
|
||||
fn respond(&self, packet_id: u8, packet_body: Vec<u8>) {
|
||||
if let Err(e) = self.respond(packet_id, packet_body) {
|
||||
debug!(target: "les", "Error responding to peer message: {}", e);
|
||||
debug!(target: "pip", "Error responding to peer message: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,16 +83,17 @@ pub trait BasicContext {
|
||||
fn persistent_peer_id(&self, peer: PeerId) -> Option<NodeId>;
|
||||
|
||||
/// Make a request from a peer.
|
||||
fn request_from(&self, peer: PeerId, request: Request) -> Result<ReqId, Error>;
|
||||
///
|
||||
/// Fails on: nonexistent peer, network error, peer not server,
|
||||
/// insufficient credits. Does not check capabilities before sending.
|
||||
/// On success, returns a request id which can later be coordinated
|
||||
/// with an event.
|
||||
fn request_from(&self, peer: PeerId, request: Requests) -> Result<ReqId, Error>;
|
||||
|
||||
/// Make an announcement of new capabilities to the rest of the peers.
|
||||
// TODO: maybe just put this on a timer in LightProtocol?
|
||||
fn make_announcement(&self, announcement: Announcement);
|
||||
|
||||
/// Find the maximum number of requests of a specific type which can be made from
|
||||
/// supplied peer.
|
||||
fn max_requests(&self, peer: PeerId, kind: request::Kind) -> usize;
|
||||
|
||||
/// Disconnect a peer.
|
||||
fn disconnect_peer(&self, peer: PeerId);
|
||||
|
||||
@@ -123,18 +124,14 @@ impl<'a> BasicContext for TickCtx<'a> {
|
||||
self.io.persistent_peer_id(id)
|
||||
}
|
||||
|
||||
fn request_from(&self, peer: PeerId, request: Request) -> Result<ReqId, Error> {
|
||||
self.proto.request_from(self.io, &peer, request)
|
||||
fn request_from(&self, peer: PeerId, requests: Requests) -> Result<ReqId, Error> {
|
||||
self.proto.request_from(self.io, &peer, requests)
|
||||
}
|
||||
|
||||
fn make_announcement(&self, announcement: Announcement) {
|
||||
self.proto.make_announcement(self.io, announcement);
|
||||
}
|
||||
|
||||
fn max_requests(&self, peer: PeerId, kind: request::Kind) -> usize {
|
||||
self.proto.max_requests(peer, kind)
|
||||
}
|
||||
|
||||
fn disconnect_peer(&self, peer: PeerId) {
|
||||
self.io.disconnect_peer(peer);
|
||||
}
|
||||
@@ -160,18 +157,14 @@ impl<'a> BasicContext for Ctx<'a> {
|
||||
self.io.persistent_peer_id(id)
|
||||
}
|
||||
|
||||
fn request_from(&self, peer: PeerId, request: Request) -> Result<ReqId, Error> {
|
||||
self.proto.request_from(self.io, &peer, request)
|
||||
fn request_from(&self, peer: PeerId, requests: Requests) -> Result<ReqId, Error> {
|
||||
self.proto.request_from(self.io, &peer, requests)
|
||||
}
|
||||
|
||||
fn make_announcement(&self, announcement: Announcement) {
|
||||
self.proto.make_announcement(self.io, announcement);
|
||||
}
|
||||
|
||||
fn max_requests(&self, peer: PeerId, kind: request::Kind) -> usize {
|
||||
self.proto.max_requests(peer, kind)
|
||||
}
|
||||
|
||||
fn disconnect_peer(&self, peer: PeerId) {
|
||||
self.io.disconnect_peer(peer);
|
||||
}
|
||||
|
||||
@@ -56,6 +56,8 @@ pub enum Error {
|
||||
UnknownPeer,
|
||||
/// Unsolicited response.
|
||||
UnsolicitedResponse,
|
||||
/// Bad back-reference in request.
|
||||
BadBackReference,
|
||||
/// Not a server.
|
||||
NotServer,
|
||||
/// Unsupported protocol version.
|
||||
@@ -78,6 +80,7 @@ impl Error {
|
||||
Error::WrongNetwork => Punishment::Disable,
|
||||
Error::UnknownPeer => Punishment::Disconnect,
|
||||
Error::UnsolicitedResponse => Punishment::Disable,
|
||||
Error::BadBackReference => Punishment::Disable,
|
||||
Error::NotServer => Punishment::Disable,
|
||||
Error::UnsupportedProtocolVersion(_) => Punishment::Disable,
|
||||
Error::BadProtocolVersion => Punishment::Disable,
|
||||
@@ -109,6 +112,7 @@ impl fmt::Display for Error {
|
||||
Error::WrongNetwork => write!(f, "Wrong network"),
|
||||
Error::UnknownPeer => write!(f, "Unknown peer"),
|
||||
Error::UnsolicitedResponse => write!(f, "Peer provided unsolicited data"),
|
||||
Error::BadBackReference => write!(f, "Bad back-reference in request."),
|
||||
Error::NotServer => write!(f, "Peer not a server."),
|
||||
Error::UnsupportedProtocolVersion(pv) => write!(f, "Unsupported protocol version: {}", pv),
|
||||
Error::BadProtocolVersion => write!(f, "Bad protocol version in handshake"),
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -26,18 +26,13 @@
|
||||
//! Current default costs are picked completely arbitrarily, not based
|
||||
//! on any empirical timings or mathematical models.
|
||||
|
||||
use request;
|
||||
use super::packet;
|
||||
use request::{self, Request};
|
||||
use super::error::Error;
|
||||
|
||||
use rlp::*;
|
||||
use util::U256;
|
||||
use time::{Duration, SteadyTime};
|
||||
|
||||
/// A request cost specification.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Cost(pub U256, pub U256);
|
||||
|
||||
/// Credits value.
|
||||
///
|
||||
/// Produced and recharged using `FlowParams`.
|
||||
@@ -81,90 +76,95 @@ impl Credits {
|
||||
/// A cost table, mapping requests to base and per-request costs.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct CostTable {
|
||||
headers: Cost, // cost per header
|
||||
bodies: Cost,
|
||||
receipts: Cost,
|
||||
state_proofs: Cost,
|
||||
contract_codes: Cost,
|
||||
header_proofs: Cost,
|
||||
transaction_proof: Cost, // cost per gas.
|
||||
base: U256, // cost per packet.
|
||||
headers: U256, // cost per header
|
||||
body: U256,
|
||||
receipts: U256,
|
||||
account: U256,
|
||||
storage: U256,
|
||||
code: U256,
|
||||
header_proof: U256,
|
||||
transaction_proof: U256, // cost per gas.
|
||||
}
|
||||
|
||||
impl Default for CostTable {
|
||||
fn default() -> Self {
|
||||
// arbitrarily chosen constants.
|
||||
CostTable {
|
||||
headers: Cost(100000.into(), 10000.into()),
|
||||
bodies: Cost(150000.into(), 15000.into()),
|
||||
receipts: Cost(50000.into(), 5000.into()),
|
||||
state_proofs: Cost(250000.into(), 25000.into()),
|
||||
contract_codes: Cost(200000.into(), 20000.into()),
|
||||
header_proofs: Cost(150000.into(), 15000.into()),
|
||||
transaction_proof: Cost(100000.into(), 2.into()),
|
||||
base: 100000.into(),
|
||||
headers: 10000.into(),
|
||||
body: 15000.into(),
|
||||
receipts: 5000.into(),
|
||||
account: 25000.into(),
|
||||
storage: 25000.into(),
|
||||
code: 20000.into(),
|
||||
header_proof: 15000.into(),
|
||||
transaction_proof: 2.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Encodable for CostTable {
|
||||
fn rlp_append(&self, s: &mut RlpStream) {
|
||||
fn append_cost(s: &mut RlpStream, msg_id: u8, cost: &Cost) {
|
||||
s.begin_list(3)
|
||||
.append(&msg_id)
|
||||
.append(&cost.0)
|
||||
.append(&cost.1);
|
||||
fn append_cost(s: &mut RlpStream, cost: &U256, kind: request::Kind) {
|
||||
s.begin_list(2);
|
||||
|
||||
// hack around https://github.com/ethcore/parity/issues/4356
|
||||
Encodable::rlp_append(&kind, s);
|
||||
s.append(cost);
|
||||
}
|
||||
|
||||
s.begin_list(7);
|
||||
|
||||
append_cost(s, packet::GET_BLOCK_HEADERS, &self.headers);
|
||||
append_cost(s, packet::GET_BLOCK_BODIES, &self.bodies);
|
||||
append_cost(s, packet::GET_RECEIPTS, &self.receipts);
|
||||
append_cost(s, packet::GET_PROOFS, &self.state_proofs);
|
||||
append_cost(s, packet::GET_CONTRACT_CODES, &self.contract_codes);
|
||||
append_cost(s, packet::GET_HEADER_PROOFS, &self.header_proofs);
|
||||
append_cost(s, packet::GET_TRANSACTION_PROOF, &self.transaction_proof);
|
||||
s.begin_list(9).append(&self.base);
|
||||
append_cost(s, &self.headers, request::Kind::Headers);
|
||||
append_cost(s, &self.body, request::Kind::Body);
|
||||
append_cost(s, &self.receipts, request::Kind::Receipts);
|
||||
append_cost(s, &self.account, request::Kind::Account);
|
||||
append_cost(s, &self.storage, request::Kind::Storage);
|
||||
append_cost(s, &self.code, request::Kind::Code);
|
||||
append_cost(s, &self.header_proof, request::Kind::HeaderProof);
|
||||
append_cost(s, &self.transaction_proof, request::Kind::Execution);
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for CostTable {
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
let base = rlp.val_at(0)?;
|
||||
|
||||
let mut headers = None;
|
||||
let mut bodies = None;
|
||||
let mut body = None;
|
||||
let mut receipts = None;
|
||||
let mut state_proofs = None;
|
||||
let mut contract_codes = None;
|
||||
let mut header_proofs = None;
|
||||
let mut account = None;
|
||||
let mut storage = None;
|
||||
let mut code = None;
|
||||
let mut header_proof = None;
|
||||
let mut transaction_proof = None;
|
||||
|
||||
for row in rlp.iter() {
|
||||
let msg_id: u8 = row.val_at(0)?;
|
||||
let cost = {
|
||||
let base = row.val_at(1)?;
|
||||
let per = row.val_at(2)?;
|
||||
|
||||
Cost(base, per)
|
||||
};
|
||||
|
||||
match msg_id {
|
||||
packet::GET_BLOCK_HEADERS => headers = Some(cost),
|
||||
packet::GET_BLOCK_BODIES => bodies = Some(cost),
|
||||
packet::GET_RECEIPTS => receipts = Some(cost),
|
||||
packet::GET_PROOFS => state_proofs = Some(cost),
|
||||
packet::GET_CONTRACT_CODES => contract_codes = Some(cost),
|
||||
packet::GET_HEADER_PROOFS => header_proofs = Some(cost),
|
||||
packet::GET_TRANSACTION_PROOF => transaction_proof = Some(cost),
|
||||
_ => return Err(DecoderError::Custom("Unrecognized message in cost table")),
|
||||
for cost_list in rlp.iter().skip(1) {
|
||||
let cost = cost_list.val_at(1)?;
|
||||
match cost_list.val_at(0)? {
|
||||
request::Kind::Headers => headers = Some(cost),
|
||||
request::Kind::Body => body = Some(cost),
|
||||
request::Kind::Receipts => receipts = Some(cost),
|
||||
request::Kind::Account => account = Some(cost),
|
||||
request::Kind::Storage => storage = Some(cost),
|
||||
request::Kind::Code => code = Some(cost),
|
||||
request::Kind::HeaderProof => header_proof = Some(cost),
|
||||
request::Kind::Execution => transaction_proof = Some(cost),
|
||||
}
|
||||
}
|
||||
|
||||
let unwrap_cost = |cost: Option<U256>| cost.ok_or(DecoderError::Custom("Not all costs specified in cost table."));
|
||||
|
||||
Ok(CostTable {
|
||||
headers: headers.ok_or(DecoderError::Custom("No headers cost specified"))?,
|
||||
bodies: bodies.ok_or(DecoderError::Custom("No bodies cost specified"))?,
|
||||
receipts: receipts.ok_or(DecoderError::Custom("No receipts cost specified"))?,
|
||||
state_proofs: state_proofs.ok_or(DecoderError::Custom("No proofs cost specified"))?,
|
||||
contract_codes: contract_codes.ok_or(DecoderError::Custom("No contract codes specified"))?,
|
||||
header_proofs: header_proofs.ok_or(DecoderError::Custom("No header proofs cost specified"))?,
|
||||
transaction_proof: transaction_proof.ok_or(DecoderError::Custom("No transaction proof gas cost specified"))?,
|
||||
base: base,
|
||||
headers: unwrap_cost(headers)?,
|
||||
body: unwrap_cost(body)?,
|
||||
receipts: unwrap_cost(receipts)?,
|
||||
account: unwrap_cost(account)?,
|
||||
storage: unwrap_cost(storage)?,
|
||||
code: unwrap_cost(code)?,
|
||||
header_proof: unwrap_cost(header_proof)?,
|
||||
transaction_proof: unwrap_cost(transaction_proof)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -190,17 +190,19 @@ impl FlowParams {
|
||||
|
||||
/// Create effectively infinite flow params.
|
||||
pub fn free() -> Self {
|
||||
let free_cost = Cost(0.into(), 0.into());
|
||||
let free_cost: U256 = 0.into();
|
||||
FlowParams {
|
||||
limit: (!0u64).into(),
|
||||
recharge: 1.into(),
|
||||
costs: CostTable {
|
||||
base: free_cost.clone(),
|
||||
headers: free_cost.clone(),
|
||||
bodies: free_cost.clone(),
|
||||
body: free_cost.clone(),
|
||||
receipts: free_cost.clone(),
|
||||
state_proofs: free_cost.clone(),
|
||||
contract_codes: free_cost.clone(),
|
||||
header_proofs: free_cost.clone(),
|
||||
account: free_cost.clone(),
|
||||
storage: free_cost.clone(),
|
||||
code: free_cost.clone(),
|
||||
header_proof: free_cost.clone(),
|
||||
transaction_proof: free_cost,
|
||||
}
|
||||
}
|
||||
@@ -212,61 +214,34 @@ impl FlowParams {
|
||||
/// Get a reference to the cost table.
|
||||
pub fn cost_table(&self) -> &CostTable { &self.costs }
|
||||
|
||||
/// Get the base cost of a request.
|
||||
pub fn base_cost(&self) -> U256 { self.costs.base }
|
||||
|
||||
/// Get a reference to the recharge rate.
|
||||
pub fn recharge_rate(&self) -> &U256 { &self.recharge }
|
||||
|
||||
/// Compute the actual cost of a request, given the kind of request
|
||||
/// and number of requests made.
|
||||
pub fn compute_cost(&self, kind: request::Kind, amount: usize) -> U256 {
|
||||
let cost = match kind {
|
||||
request::Kind::Headers => &self.costs.headers,
|
||||
request::Kind::Bodies => &self.costs.bodies,
|
||||
request::Kind::Receipts => &self.costs.receipts,
|
||||
request::Kind::StateProofs => &self.costs.state_proofs,
|
||||
request::Kind::Codes => &self.costs.contract_codes,
|
||||
request::Kind::HeaderProofs => &self.costs.header_proofs,
|
||||
request::Kind::TransactionProof => &self.costs.transaction_proof,
|
||||
};
|
||||
|
||||
let amount: U256 = amount.into();
|
||||
cost.0 + (amount * cost.1)
|
||||
}
|
||||
|
||||
/// Compute the maximum number of costs of a specific kind which can be made
|
||||
/// with the given amount of credits
|
||||
/// Saturates at `usize::max()`. This is not a problem in practice because
|
||||
/// this amount of requests is already prohibitively large.
|
||||
pub fn max_amount(&self, credits: &Credits, kind: request::Kind) -> usize {
|
||||
use util::Uint;
|
||||
use std::usize;
|
||||
|
||||
let cost = match kind {
|
||||
request::Kind::Headers => &self.costs.headers,
|
||||
request::Kind::Bodies => &self.costs.bodies,
|
||||
request::Kind::Receipts => &self.costs.receipts,
|
||||
request::Kind::StateProofs => &self.costs.state_proofs,
|
||||
request::Kind::Codes => &self.costs.contract_codes,
|
||||
request::Kind::HeaderProofs => &self.costs.header_proofs,
|
||||
request::Kind::TransactionProof => &self.costs.transaction_proof,
|
||||
};
|
||||
|
||||
let start = credits.current();
|
||||
|
||||
if start <= cost.0 {
|
||||
return 0;
|
||||
} else if cost.1 == U256::zero() {
|
||||
return usize::MAX;
|
||||
}
|
||||
|
||||
let max = (start - cost.0) / cost.1;
|
||||
if max >= usize::MAX.into() {
|
||||
usize::MAX
|
||||
} else {
|
||||
max.as_u64() as usize
|
||||
pub fn compute_cost(&self, request: &Request) -> U256 {
|
||||
match *request {
|
||||
Request::Headers(ref req) => self.costs.headers * req.max.into(),
|
||||
Request::HeaderProof(_) => self.costs.header_proof,
|
||||
Request::Body(_) => self.costs.body,
|
||||
Request::Receipts(_) => self.costs.receipts,
|
||||
Request::Account(_) => self.costs.account,
|
||||
Request::Storage(_) => self.costs.storage,
|
||||
Request::Code(_) => self.costs.code,
|
||||
Request::Execution(ref req) => self.costs.transaction_proof * req.gas,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create initial credits..
|
||||
/// Compute the cost of a set of requests.
|
||||
/// This is the base cost plus the cost of each individual request.
|
||||
pub fn compute_cost_multi(&self, requests: &[Request]) -> U256 {
|
||||
requests.iter().fold(self.costs.base, |cost, req| cost + self.compute_cost(req))
|
||||
}
|
||||
|
||||
/// Create initial credits.
|
||||
pub fn create_credits(&self) -> Credits {
|
||||
Credits {
|
||||
estimate: self.limit,
|
||||
|
||||
@@ -24,7 +24,8 @@
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::iter::FromIterator;
|
||||
|
||||
use request::{self, Request};
|
||||
use request::Request;
|
||||
use request::Requests;
|
||||
use net::{timeout, ReqId};
|
||||
|
||||
use time::{Duration, SteadyTime};
|
||||
@@ -35,7 +36,7 @@ pub struct RequestSet {
|
||||
counter: u64,
|
||||
base: Option<SteadyTime>,
|
||||
ids: HashMap<ReqId, u64>,
|
||||
reqs: BTreeMap<u64, Request>,
|
||||
reqs: BTreeMap<u64, Requests>,
|
||||
}
|
||||
|
||||
impl Default for RequestSet {
|
||||
@@ -50,8 +51,8 @@ impl Default for RequestSet {
|
||||
}
|
||||
|
||||
impl RequestSet {
|
||||
/// Push a request onto the stack.
|
||||
pub fn insert(&mut self, req_id: ReqId, req: Request, now: SteadyTime) {
|
||||
/// Push requests onto the stack.
|
||||
pub fn insert(&mut self, req_id: ReqId, req: Requests, now: SteadyTime) {
|
||||
let counter = self.counter;
|
||||
self.ids.insert(req_id, counter);
|
||||
self.reqs.insert(counter, req);
|
||||
@@ -63,8 +64,8 @@ impl RequestSet {
|
||||
self.counter += 1;
|
||||
}
|
||||
|
||||
/// Remove a request from the stack.
|
||||
pub fn remove(&mut self, req_id: &ReqId, now: SteadyTime) -> Option<Request> {
|
||||
/// Remove a set of requests from the stack.
|
||||
pub fn remove(&mut self, req_id: &ReqId, now: SteadyTime) -> Option<Requests> {
|
||||
let id = match self.ids.remove(&req_id) {
|
||||
Some(id) => id,
|
||||
None => return None,
|
||||
@@ -89,22 +90,10 @@ impl RequestSet {
|
||||
None => return false,
|
||||
};
|
||||
|
||||
let kind = self.reqs.values()
|
||||
.next()
|
||||
.map(|r| r.kind())
|
||||
.expect("base time implies `reqs` non-empty; qed");
|
||||
let first_req = self.reqs.values().next()
|
||||
.expect("base existing implies `reqs` non-empty; qed");
|
||||
|
||||
let kind_timeout = match kind {
|
||||
request::Kind::Headers => timeout::HEADERS,
|
||||
request::Kind::Bodies => timeout::BODIES,
|
||||
request::Kind::Receipts => timeout::RECEIPTS,
|
||||
request::Kind::StateProofs => timeout::PROOFS,
|
||||
request::Kind::Codes => timeout::CONTRACT_CODES,
|
||||
request::Kind::HeaderProofs => timeout::HEADER_PROOFS,
|
||||
request::Kind::TransactionProof => timeout::TRANSACTION_PROOF,
|
||||
};
|
||||
|
||||
base + Duration::milliseconds(kind_timeout) <= now
|
||||
base + compute_timeout(&first_req) <= now
|
||||
}
|
||||
|
||||
/// Collect all pending request ids.
|
||||
@@ -121,25 +110,43 @@ impl RequestSet {
|
||||
pub fn is_empty(&self) -> bool { self.len() == 0 }
|
||||
}
|
||||
|
||||
// helper to calculate timeout for a specific set of requests.
|
||||
// it's a base amount + some amount per request.
|
||||
fn compute_timeout(reqs: &Requests) -> Duration {
|
||||
Duration::milliseconds(reqs.requests().iter().fold(timeout::BASE, |tm, req| {
|
||||
tm + match *req {
|
||||
Request::Headers(_) => timeout::HEADERS,
|
||||
Request::HeaderProof(_) => timeout::HEADER_PROOF,
|
||||
Request::Receipts(_) => timeout::RECEIPT,
|
||||
Request::Body(_) => timeout::BODY,
|
||||
Request::Account(_) => timeout::PROOF,
|
||||
Request::Storage(_) => timeout::PROOF,
|
||||
Request::Code(_) => timeout::CONTRACT_CODE,
|
||||
Request::Execution(_) => timeout::TRANSACTION_PROOF,
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use net::{timeout, ReqId};
|
||||
use request::{Request, Receipts};
|
||||
use net::ReqId;
|
||||
use request::RequestBuilder;
|
||||
use time::{SteadyTime, Duration};
|
||||
use super::RequestSet;
|
||||
use super::{RequestSet, compute_timeout};
|
||||
|
||||
#[test]
|
||||
fn multi_timeout() {
|
||||
let test_begin = SteadyTime::now();
|
||||
let mut req_set = RequestSet::default();
|
||||
|
||||
let the_req = Request::Receipts(Receipts { block_hashes: Vec::new() });
|
||||
let the_req = RequestBuilder::default().build();
|
||||
let req_time = compute_timeout(&the_req);
|
||||
req_set.insert(ReqId(0), the_req.clone(), test_begin);
|
||||
req_set.insert(ReqId(1), the_req, test_begin + Duration::seconds(1));
|
||||
|
||||
assert_eq!(req_set.base, Some(test_begin));
|
||||
|
||||
let test_end = test_begin + Duration::milliseconds(timeout::RECEIPTS);
|
||||
let test_end = test_begin + req_time;
|
||||
assert!(req_set.check_timeout(test_end));
|
||||
|
||||
req_set.remove(&ReqId(0), test_begin + Duration::seconds(1)).unwrap();
|
||||
|
||||
@@ -27,15 +27,31 @@ use network::{PeerId, NodeId};
|
||||
use net::request_credits::FlowParams;
|
||||
use net::context::IoContext;
|
||||
use net::status::{Capabilities, Status, write_handshake};
|
||||
use net::{encode_request, LightProtocol, Params, packet, Peer};
|
||||
use net::{LightProtocol, Params, packet, Peer};
|
||||
use provider::Provider;
|
||||
use request::{self, Request, Headers};
|
||||
use request;
|
||||
use request::*;
|
||||
|
||||
use rlp::*;
|
||||
use util::{Address, Bytes, DBValue, H256, U256};
|
||||
use util::{Address, H256, U256};
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
// helper for encoding a single request into a packet.
|
||||
// panics on bad backreference.
|
||||
fn encode_single(request: Request) -> Requests {
|
||||
let mut builder = RequestBuilder::default();
|
||||
builder.push(request).unwrap();
|
||||
builder.build()
|
||||
}
|
||||
|
||||
// helper for making a packet out of `Requests`.
|
||||
fn make_packet(req_id: usize, requests: &Requests) -> Vec<u8> {
|
||||
let mut stream = RlpStream::new_list(2);
|
||||
stream.append(&req_id).append_list(&requests.requests());
|
||||
stream.out()
|
||||
}
|
||||
|
||||
// expected result from a call.
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
enum Expect {
|
||||
@@ -99,35 +115,45 @@ impl Provider for TestProvider {
|
||||
self.0.client.block_header(id)
|
||||
}
|
||||
|
||||
fn block_body(&self, id: BlockId) -> Option<encoded::Body> {
|
||||
self.0.client.block_body(id)
|
||||
fn block_body(&self, req: request::CompleteBodyRequest) -> Option<request::BodyResponse> {
|
||||
self.0.client.block_body(req)
|
||||
}
|
||||
|
||||
fn block_receipts(&self, hash: &H256) -> Option<Bytes> {
|
||||
self.0.client.block_receipts(&hash)
|
||||
fn block_receipts(&self, req: request::CompleteReceiptsRequest) -> Option<request::ReceiptsResponse> {
|
||||
self.0.client.block_receipts(req)
|
||||
}
|
||||
|
||||
fn state_proof(&self, req: request::StateProof) -> Vec<Bytes> {
|
||||
match req.key2 {
|
||||
Some(_) => vec![::util::sha3::SHA3_NULL_RLP.to_vec()],
|
||||
None => {
|
||||
// sort of a leaf node
|
||||
let mut stream = RlpStream::new_list(2);
|
||||
stream.append(&req.key1).append_empty_data();
|
||||
vec![stream.out()]
|
||||
}
|
||||
}
|
||||
fn account_proof(&self, req: request::CompleteAccountRequest) -> Option<request::AccountResponse> {
|
||||
// sort of a leaf node
|
||||
let mut stream = RlpStream::new_list(2);
|
||||
stream.append(&req.address_hash).append_empty_data();
|
||||
Some(AccountResponse {
|
||||
proof: vec![stream.out()],
|
||||
balance: 10.into(),
|
||||
nonce: 100.into(),
|
||||
code_hash: Default::default(),
|
||||
storage_root: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
fn contract_code(&self, req: request::ContractCode) -> Bytes {
|
||||
req.account_key.iter().chain(req.account_key.iter()).cloned().collect()
|
||||
fn storage_proof(&self, req: request::CompleteStorageRequest) -> Option<request::StorageResponse> {
|
||||
Some(StorageResponse {
|
||||
proof: vec![::rlp::encode(&req.key_hash).to_vec()],
|
||||
value: req.key_hash | req.address_hash,
|
||||
})
|
||||
}
|
||||
|
||||
fn header_proof(&self, _req: request::HeaderProof) -> Option<(encoded::Header, Vec<Bytes>)> {
|
||||
fn contract_code(&self, req: request::CompleteCodeRequest) -> Option<request::CodeResponse> {
|
||||
Some(CodeResponse {
|
||||
code: req.block_hash.iter().chain(req.code_hash.iter()).cloned().collect(),
|
||||
})
|
||||
}
|
||||
|
||||
fn header_proof(&self, _req: request::CompleteHeaderProofRequest) -> Option<request::HeaderProofResponse> {
|
||||
None
|
||||
}
|
||||
|
||||
fn transaction_proof(&self, _req: request::TransactionProof) -> Option<Vec<DBValue>> {
|
||||
fn transaction_proof(&self, _req: request::CompleteExecutionRequest) -> Option<request::ExecutionResponse> {
|
||||
None
|
||||
}
|
||||
|
||||
@@ -226,14 +252,15 @@ fn credit_overflow() {
|
||||
}
|
||||
|
||||
// 1000 requests is far too many for the default flow params.
|
||||
let request = encode_request(&Request::Headers(Headers {
|
||||
start: 1.into(),
|
||||
let requests = encode_single(Request::Headers(IncompleteHeadersRequest {
|
||||
start: HashOrNumber::Number(1).into(),
|
||||
max: 1000,
|
||||
skip: 0,
|
||||
reverse: false,
|
||||
}), 111);
|
||||
}));
|
||||
let request = make_packet(111, &requests);
|
||||
|
||||
proto.handle_packet(&Expect::Punish(1), &1, packet::GET_BLOCK_HEADERS, &request);
|
||||
proto.handle_packet(&Expect::Punish(1), &1, packet::REQUEST, &request);
|
||||
}
|
||||
|
||||
// test the basic request types -- these just make sure that requests are parsed
|
||||
@@ -259,33 +286,36 @@ fn get_block_headers() {
|
||||
proto.handle_packet(&Expect::Nothing, &1, packet::STATUS, &my_status);
|
||||
}
|
||||
|
||||
let request = Headers {
|
||||
start: 1.into(),
|
||||
let request = Request::Headers(IncompleteHeadersRequest {
|
||||
start: HashOrNumber::Number(1).into(),
|
||||
max: 10,
|
||||
skip: 0,
|
||||
reverse: false,
|
||||
};
|
||||
});
|
||||
|
||||
let req_id = 111;
|
||||
|
||||
let request_body = encode_request(&Request::Headers(request.clone()), req_id);
|
||||
let requests = encode_single(request.clone());
|
||||
let request_body = make_packet(req_id, &requests);
|
||||
|
||||
let response = {
|
||||
let headers: Vec<_> = (0..10).map(|i| provider.client.block_header(BlockId::Number(i + 1)).unwrap()).collect();
|
||||
assert_eq!(headers.len(), 10);
|
||||
|
||||
let new_creds = *flow_params.limit() - flow_params.compute_cost(request::Kind::Headers, 10);
|
||||
let new_creds = *flow_params.limit() - flow_params.compute_cost_multi(requests.requests());
|
||||
|
||||
let mut response_stream = RlpStream::new_list(3);
|
||||
let response = vec![Response::Headers(HeadersResponse {
|
||||
headers: headers,
|
||||
})];
|
||||
|
||||
response_stream.append(&req_id).append(&new_creds).begin_list(10);
|
||||
for header in headers {
|
||||
response_stream.append_raw(&header.into_inner(), 1);
|
||||
}
|
||||
let mut stream = RlpStream::new_list(3);
|
||||
stream.append(&req_id).append(&new_creds).append_list(&response);
|
||||
|
||||
response_stream.out()
|
||||
stream.out()
|
||||
};
|
||||
|
||||
let expected = Expect::Respond(packet::BLOCK_HEADERS, response);
|
||||
proto.handle_packet(&expected, &1, packet::GET_BLOCK_HEADERS, &request_body);
|
||||
let expected = Expect::Respond(packet::RESPONSE, response);
|
||||
proto.handle_packet(&expected, &1, packet::REQUEST, &request_body);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -308,33 +338,32 @@ fn get_block_bodies() {
|
||||
proto.handle_packet(&Expect::Nothing, &1, packet::STATUS, &my_status);
|
||||
}
|
||||
|
||||
let request = request::Bodies {
|
||||
block_hashes: (0..10).map(|i|
|
||||
provider.client.block_header(BlockId::Number(i)).unwrap().hash()
|
||||
).collect()
|
||||
};
|
||||
let mut builder = RequestBuilder::default();
|
||||
let mut bodies = Vec::new();
|
||||
|
||||
for i in 0..10 {
|
||||
let hash = provider.client.block_header(BlockId::Number(i)).unwrap().hash();
|
||||
builder.push(Request::Body(IncompleteBodyRequest {
|
||||
hash: hash.into(),
|
||||
})).unwrap();
|
||||
bodies.push(Response::Body(provider.client.block_body(CompleteBodyRequest {
|
||||
hash: hash,
|
||||
}).unwrap()));
|
||||
}
|
||||
let req_id = 111;
|
||||
let requests = builder.build();
|
||||
let request_body = make_packet(req_id, &requests);
|
||||
|
||||
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_creds = *flow_params.limit() - flow_params.compute_cost(request::Kind::Bodies, 10);
|
||||
let new_creds = *flow_params.limit() - flow_params.compute_cost_multi(requests.requests());
|
||||
|
||||
let mut response_stream = RlpStream::new_list(3);
|
||||
|
||||
response_stream.append(&req_id).append(&new_creds).begin_list(10);
|
||||
for body in bodies {
|
||||
response_stream.append_raw(&body.into_inner(), 1);
|
||||
}
|
||||
|
||||
response_stream.append(&req_id).append(&new_creds).append_list(&bodies);
|
||||
response_stream.out()
|
||||
};
|
||||
|
||||
let expected = Expect::Respond(packet::BLOCK_BODIES, response);
|
||||
proto.handle_packet(&expected, &1, packet::GET_BLOCK_BODIES, &request_body);
|
||||
let expected = Expect::Respond(packet::RESPONSE, response);
|
||||
proto.handle_packet(&expected, &1, packet::REQUEST, &request_body);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -359,36 +388,37 @@ fn get_block_receipts() {
|
||||
|
||||
// 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_header(BlockId::Number(i)).unwrap().hash()
|
||||
).filter(|hash| format!("{}", hash).starts_with("f")).take(10).collect();
|
||||
let block_hashes: Vec<H256> = (0..1000)
|
||||
.map(|i| provider.client.block_header(BlockId::Number(i)).unwrap().hash())
|
||||
.filter(|hash| format!("{}", hash).starts_with("f"))
|
||||
.take(10)
|
||||
.collect();
|
||||
|
||||
let request = request::Receipts {
|
||||
block_hashes: block_hashes.clone(),
|
||||
};
|
||||
let mut builder = RequestBuilder::default();
|
||||
let mut receipts = Vec::new();
|
||||
for hash in block_hashes.iter().cloned() {
|
||||
builder.push(Request::Receipts(IncompleteReceiptsRequest { hash: hash.into() })).unwrap();
|
||||
receipts.push(Response::Receipts(provider.client.block_receipts(CompleteReceiptsRequest {
|
||||
hash: hash
|
||||
}).unwrap()));
|
||||
}
|
||||
|
||||
let req_id = 111;
|
||||
let requests = builder.build();
|
||||
let request_body = make_packet(req_id, &requests);
|
||||
|
||||
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();
|
||||
assert_eq!(receipts.len(), 10);
|
||||
|
||||
let new_creds = *flow_params.limit() - flow_params.compute_cost(request::Kind::Receipts, receipts.len());
|
||||
let new_creds = *flow_params.limit() - flow_params.compute_cost_multi(requests.requests());
|
||||
|
||||
let mut response_stream = RlpStream::new_list(3);
|
||||
|
||||
response_stream.append(&req_id).append(&new_creds).begin_list(receipts.len());
|
||||
for block_receipts in receipts {
|
||||
response_stream.append_raw(&block_receipts, 1);
|
||||
}
|
||||
|
||||
response_stream.append(&req_id).append(&new_creds).append_list(&receipts);
|
||||
response_stream.out()
|
||||
};
|
||||
|
||||
let expected = Expect::Respond(packet::RECEIPTS, response);
|
||||
proto.handle_packet(&expected, &1, packet::GET_RECEIPTS, &request_body);
|
||||
let expected = Expect::Respond(packet::RESPONSE, response);
|
||||
proto.handle_packet(&expected, &1, packet::REQUEST, &request_body);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -397,8 +427,9 @@ fn get_state_proofs() {
|
||||
let capabilities = capabilities();
|
||||
|
||||
let (provider, proto) = setup(flow_params.clone(), capabilities.clone());
|
||||
let provider = TestProvider(provider);
|
||||
|
||||
let cur_status = status(provider.client.chain_info());
|
||||
let cur_status = status(provider.0.client.chain_info());
|
||||
|
||||
{
|
||||
let packet_body = write_handshake(&cur_status, &capabilities, Some(&flow_params));
|
||||
@@ -407,40 +438,45 @@ fn get_state_proofs() {
|
||||
}
|
||||
|
||||
let req_id = 112;
|
||||
let key1 = U256::from(11223344).into();
|
||||
let key2 = U256::from(99988887).into();
|
||||
let key1: H256 = U256::from(11223344).into();
|
||||
let key2: H256 = U256::from(99988887).into();
|
||||
|
||||
let request = Request::StateProofs (request::StateProofs {
|
||||
requests: vec![
|
||||
request::StateProof { block: H256::default(), key1: key1, key2: None, from_level: 0 },
|
||||
request::StateProof { block: H256::default(), key1: key1, key2: Some(key2), from_level: 0},
|
||||
]
|
||||
});
|
||||
let mut builder = RequestBuilder::default();
|
||||
builder.push(Request::Account(IncompleteAccountRequest {
|
||||
block_hash: H256::default().into(),
|
||||
address_hash: key1.into(),
|
||||
})).unwrap();
|
||||
builder.push(Request::Storage(IncompleteStorageRequest {
|
||||
block_hash: H256::default().into(),
|
||||
address_hash: key1.into(),
|
||||
key_hash: key2.into(),
|
||||
})).unwrap();
|
||||
|
||||
let request_body = encode_request(&request, req_id);
|
||||
let requests = builder.build();
|
||||
|
||||
let request_body = make_packet(req_id, &requests);
|
||||
let response = {
|
||||
let proofs = vec![
|
||||
{ let mut stream = RlpStream::new_list(2); stream.append(&key1).append_empty_data(); vec![stream.out()] },
|
||||
vec![::util::sha3::SHA3_NULL_RLP.to_vec()],
|
||||
let responses = vec![
|
||||
Response::Account(provider.account_proof(CompleteAccountRequest {
|
||||
block_hash: H256::default(),
|
||||
address_hash: key1,
|
||||
}).unwrap()),
|
||||
Response::Storage(provider.storage_proof(CompleteStorageRequest {
|
||||
block_hash: H256::default(),
|
||||
address_hash: key1,
|
||||
key_hash: key2,
|
||||
}).unwrap()),
|
||||
];
|
||||
|
||||
let new_creds = *flow_params.limit() - flow_params.compute_cost(request::Kind::StateProofs, 2);
|
||||
let new_creds = *flow_params.limit() - flow_params.compute_cost_multi(requests.requests());
|
||||
|
||||
let mut response_stream = RlpStream::new_list(3);
|
||||
|
||||
response_stream.append(&req_id).append(&new_creds).begin_list(2);
|
||||
for proof in proofs {
|
||||
response_stream.begin_list(proof.len());
|
||||
for node in proof {
|
||||
response_stream.append_raw(&node, 1);
|
||||
}
|
||||
}
|
||||
|
||||
response_stream.append(&req_id).append(&new_creds).append_list(&responses);
|
||||
response_stream.out()
|
||||
};
|
||||
|
||||
let expected = Expect::Respond(packet::PROOFS, response);
|
||||
proto.handle_packet(&expected, &1, packet::GET_PROOFS, &request_body);
|
||||
let expected = Expect::Respond(packet::RESPONSE, response);
|
||||
proto.handle_packet(&expected, &1, packet::REQUEST, &request_body);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -459,37 +495,31 @@ fn get_contract_code() {
|
||||
}
|
||||
|
||||
let req_id = 112;
|
||||
let key1 = U256::from(11223344).into();
|
||||
let key2 = U256::from(99988887).into();
|
||||
let key1: H256 = U256::from(11223344).into();
|
||||
let key2: H256 = U256::from(99988887).into();
|
||||
|
||||
let request = Request::Codes (request::ContractCodes {
|
||||
code_requests: vec![
|
||||
request::ContractCode { block_hash: H256::default(), account_key: key1 },
|
||||
request::ContractCode { block_hash: H256::default(), account_key: key2 },
|
||||
],
|
||||
let request = Request::Code(IncompleteCodeRequest {
|
||||
block_hash: key1.into(),
|
||||
code_hash: key2.into(),
|
||||
});
|
||||
|
||||
let request_body = encode_request(&request, req_id);
|
||||
let requests = encode_single(request.clone());
|
||||
let request_body = make_packet(req_id, &requests);
|
||||
let response = {
|
||||
let codes: Vec<Vec<_>> = vec![
|
||||
key1.iter().chain(key1.iter()).cloned().collect(),
|
||||
key2.iter().chain(key2.iter()).cloned().collect(),
|
||||
];
|
||||
let response = vec![Response::Code(CodeResponse {
|
||||
code: key1.iter().chain(key2.iter()).cloned().collect(),
|
||||
})];
|
||||
|
||||
let new_creds = *flow_params.limit() - flow_params.compute_cost(request::Kind::Codes, 2);
|
||||
let new_creds = *flow_params.limit() - flow_params.compute_cost_multi(requests.requests());
|
||||
|
||||
let mut response_stream = RlpStream::new_list(3);
|
||||
|
||||
response_stream.append(&req_id).append(&new_creds).begin_list(2);
|
||||
for code in codes {
|
||||
response_stream.append(&code);
|
||||
}
|
||||
|
||||
response_stream.append(&req_id).append(&new_creds).append_list(&response);
|
||||
response_stream.out()
|
||||
};
|
||||
|
||||
let expected = Expect::Respond(packet::CONTRACT_CODES, response);
|
||||
proto.handle_packet(&expected, &1, packet::GET_CONTRACT_CODES, &request_body);
|
||||
let expected = Expect::Respond(packet::RESPONSE, response);
|
||||
proto.handle_packet(&expected, &1, packet::REQUEST, &request_body);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -508,8 +538,8 @@ fn proof_of_execution() {
|
||||
}
|
||||
|
||||
let req_id = 112;
|
||||
let mut request = Request::TransactionProof (request::TransactionProof {
|
||||
at: H256::default(),
|
||||
let mut request = Request::Execution(request::IncompleteExecutionRequest {
|
||||
block_hash: H256::default().into(),
|
||||
from: Address::default(),
|
||||
action: Action::Call(Address::default()),
|
||||
gas: 100.into(),
|
||||
@@ -519,9 +549,11 @@ fn proof_of_execution() {
|
||||
});
|
||||
|
||||
// first: a valid amount to request execution of.
|
||||
let request_body = encode_request(&request, req_id);
|
||||
let requests = encode_single(request.clone());
|
||||
let request_body = make_packet(req_id, &requests);
|
||||
|
||||
let response = {
|
||||
let new_creds = *flow_params.limit() - flow_params.compute_cost(request::Kind::TransactionProof, 100);
|
||||
let new_creds = *flow_params.limit() - flow_params.compute_cost_multi(requests.requests());
|
||||
|
||||
let mut response_stream = RlpStream::new_list(3);
|
||||
response_stream.append(&req_id).append(&new_creds).begin_list(0);
|
||||
@@ -529,17 +561,19 @@ fn proof_of_execution() {
|
||||
response_stream.out()
|
||||
};
|
||||
|
||||
let expected = Expect::Respond(packet::TRANSACTION_PROOF, response);
|
||||
proto.handle_packet(&expected, &1, packet::GET_TRANSACTION_PROOF, &request_body);
|
||||
let expected = Expect::Respond(packet::RESPONSE, response);
|
||||
proto.handle_packet(&expected, &1, packet::REQUEST, &request_body);
|
||||
|
||||
// next: way too much requested gas.
|
||||
if let Request::TransactionProof(ref mut req) = request {
|
||||
if let Request::Execution(ref mut req) = request {
|
||||
req.gas = 100_000_000.into();
|
||||
}
|
||||
let req_id = 113;
|
||||
let request_body = encode_request(&request, req_id);
|
||||
let requests = encode_single(request.clone());
|
||||
let request_body = make_packet(req_id, &requests);
|
||||
|
||||
let expected = Expect::Punish(1);
|
||||
proto.handle_packet(&expected, &1, packet::GET_TRANSACTION_PROOF, &request_body);
|
||||
proto.handle_packet(&expected, &1, packet::REQUEST, &request_body);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -554,12 +588,13 @@ fn id_guard() {
|
||||
|
||||
let req_id_1 = ReqId(5143);
|
||||
let req_id_2 = ReqId(1111);
|
||||
let req = Request::Headers(request::Headers {
|
||||
start: 5u64.into(),
|
||||
|
||||
let req = encode_single(Request::Headers(IncompleteHeadersRequest {
|
||||
start: HashOrNumber::Number(5u64).into(),
|
||||
max: 100,
|
||||
skip: 0,
|
||||
reverse: false,
|
||||
});
|
||||
}));
|
||||
|
||||
let peer_id = 9876;
|
||||
|
||||
@@ -579,15 +614,15 @@ fn id_guard() {
|
||||
failed_requests: Vec::new(),
|
||||
}));
|
||||
|
||||
// first, supply wrong request type.
|
||||
// first, malformed responses.
|
||||
{
|
||||
let mut stream = RlpStream::new_list(3);
|
||||
stream.append(&req_id_1.0);
|
||||
stream.append(&4_000_000usize);
|
||||
stream.begin_list(0);
|
||||
stream.begin_list(2).append(&125usize).append(&3usize);
|
||||
|
||||
let packet = stream.out();
|
||||
assert!(proto.block_bodies(&peer_id, &Expect::Nothing, UntrustedRlp::new(&packet)).is_err());
|
||||
assert!(proto.response(&peer_id, &Expect::Nothing, UntrustedRlp::new(&packet)).is_err());
|
||||
}
|
||||
|
||||
// next, do an unexpected response.
|
||||
@@ -598,7 +633,7 @@ fn id_guard() {
|
||||
stream.begin_list(0);
|
||||
|
||||
let packet = stream.out();
|
||||
assert!(proto.receipts(&peer_id, &Expect::Nothing, UntrustedRlp::new(&packet)).is_err());
|
||||
assert!(proto.response(&peer_id, &Expect::Nothing, UntrustedRlp::new(&packet)).is_err());
|
||||
}
|
||||
|
||||
// lastly, do a valid (but empty) response.
|
||||
@@ -609,7 +644,7 @@ fn id_guard() {
|
||||
stream.begin_list(0);
|
||||
|
||||
let packet = stream.out();
|
||||
assert!(proto.block_headers(&peer_id, &Expect::Nothing, UntrustedRlp::new(&packet)).is_ok());
|
||||
assert!(proto.response(&peer_id, &Expect::Nothing, UntrustedRlp::new(&packet)).is_ok());
|
||||
}
|
||||
|
||||
let peers = proto.peers.read();
|
||||
|
||||
Reference in New Issue
Block a user