buffer flow -> request credits

This commit is contained in:
Robert Habermeier 2017-02-23 23:10:29 +01:00
parent f169c8dbb0
commit ddbdfafc05
6 changed files with 97 additions and 97 deletions

View File

@ -44,8 +44,8 @@ pub enum Error {
Rlp(DecoderError), Rlp(DecoderError),
/// A network error. /// A network error.
Network(NetworkError), Network(NetworkError),
/// Out of buffer. /// Out of credits.
BufferEmpty, NoCredits,
/// Unrecognized packet code. /// Unrecognized packet code.
UnrecognizedPacket(u8), UnrecognizedPacket(u8),
/// Unexpected handshake. /// Unexpected handshake.
@ -72,7 +72,7 @@ impl Error {
match *self { match *self {
Error::Rlp(_) => Punishment::Disable, Error::Rlp(_) => Punishment::Disable,
Error::Network(_) => Punishment::None, Error::Network(_) => Punishment::None,
Error::BufferEmpty => Punishment::Disable, Error::NoCredits => Punishment::Disable,
Error::UnrecognizedPacket(_) => Punishment::Disconnect, Error::UnrecognizedPacket(_) => Punishment::Disconnect,
Error::UnexpectedHandshake => Punishment::Disconnect, Error::UnexpectedHandshake => Punishment::Disconnect,
Error::WrongNetwork => Punishment::Disable, Error::WrongNetwork => Punishment::Disable,
@ -103,7 +103,7 @@ impl fmt::Display for Error {
match *self { match *self {
Error::Rlp(ref err) => err.fmt(f), Error::Rlp(ref err) => err.fmt(f),
Error::Network(ref err) => err.fmt(f), Error::Network(ref err) => err.fmt(f),
Error::BufferEmpty => write!(f, "Out of buffer"), Error::NoCredits => write!(f, "Out of request credits"),
Error::UnrecognizedPacket(code) => write!(f, "Unrecognized packet: 0x{:x}", code), Error::UnrecognizedPacket(code) => write!(f, "Unrecognized packet: 0x{:x}", code),
Error::UnexpectedHandshake => write!(f, "Unexpected handshake"), Error::UnexpectedHandshake => write!(f, "Unexpected handshake"),
Error::WrongNetwork => write!(f, "Wrong network"), Error::WrongNetwork => write!(f, "Wrong network"),

View File

@ -37,7 +37,7 @@ use std::sync::atomic::{AtomicUsize, Ordering};
use provider::Provider; use provider::Provider;
use request::{self, HashOrNumber, Request}; use request::{self, HashOrNumber, Request};
use self::buffer_flow::{Buffer, FlowParams}; use self::request_credits::{Credits, FlowParams};
use self::context::{Ctx, TickCtx}; use self::context::{Ctx, TickCtx};
use self::error::Punishment; use self::error::Punishment;
use self::request_set::RequestSet; use self::request_set::RequestSet;
@ -51,7 +51,7 @@ mod request_set;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
pub mod buffer_flow; pub mod request_credits;
pub use self::error::Error; pub use self::error::Error;
pub use self::context::{BasicContext, EventContext, IoContext}; pub use self::context::{BasicContext, EventContext, IoContext};
@ -143,10 +143,10 @@ struct PendingPeer {
/// Relevant data to each peer. Not accessible publicly, only `pub` due to /// Relevant data to each peer. Not accessible publicly, only `pub` due to
/// limitations of the privacy system. /// limitations of the privacy system.
pub struct Peer { pub struct Peer {
local_buffer: Buffer, // their buffer relative to us local_credits: Credits, // their credits relative to us
status: Status, status: Status,
capabilities: Capabilities, capabilities: Capabilities,
remote_flow: Option<(Buffer, FlowParams)>, remote_flow: Option<(Credits, FlowParams)>,
sent_head: H256, // last chain head we've given them. sent_head: H256, // last chain head we've given them.
last_update: SteadyTime, last_update: SteadyTime,
pending_requests: RequestSet, pending_requests: RequestSet,
@ -155,21 +155,21 @@ pub struct Peer {
impl Peer { impl Peer {
// check the maximum cost of a request, returning an error if there's // check the maximum cost of a request, returning an error if there's
// not enough buffer left. // not enough credits left.
// returns the calculated maximum cost. // returns the calculated maximum cost.
fn deduct_max(&mut self, flow_params: &FlowParams, kind: request::Kind, max: usize) -> Result<U256, Error> { fn deduct_max(&mut self, flow_params: &FlowParams, kind: request::Kind, max: usize) -> Result<U256, Error> {
flow_params.recharge(&mut self.local_buffer); flow_params.recharge(&mut self.local_credits);
let max_cost = flow_params.compute_cost(kind, max); let max_cost = flow_params.compute_cost(kind, max);
self.local_buffer.deduct_cost(max_cost)?; self.local_credits.deduct_cost(max_cost)?;
Ok(max_cost) Ok(max_cost)
} }
// refund buffer for a request. returns new buffer amount. // refund credits for a request. returns new amount of credits.
fn refund(&mut self, flow_params: &FlowParams, amount: U256) -> U256 { fn refund(&mut self, flow_params: &FlowParams, amount: U256) -> U256 {
flow_params.refund(&mut self.local_buffer, amount); flow_params.refund(&mut self.local_credits, amount);
self.local_buffer.current() self.local_credits.current()
} }
} }
@ -218,7 +218,7 @@ pub trait Handler: Send + Sync {
pub struct Params { pub struct Params {
/// Network id. /// Network id.
pub network_id: u64, pub network_id: u64,
/// Buffer flow parameters. /// Request credits parameters.
pub flow_params: FlowParams, pub flow_params: FlowParams,
/// Initial capabilities. /// Initial capabilities.
pub capabilities: Capabilities, pub capabilities: Capabilities,
@ -324,14 +324,14 @@ impl LightProtocol {
/// Check the maximum amount of requests of a specific type /// Check the maximum amount of requests of a specific type
/// which a peer would be able to serve. Returns zero if the /// which a peer would be able to serve. Returns zero if the
/// peer is unknown or has no buffer flow parameters. /// peer is unknown or has no credit parameters.
fn max_requests(&self, peer: PeerId, kind: request::Kind) -> usize { fn max_requests(&self, peer: PeerId, kind: request::Kind) -> usize {
self.peers.read().get(&peer).and_then(|peer| { self.peers.read().get(&peer).and_then(|peer| {
let mut peer = peer.lock(); let mut peer = peer.lock();
match peer.remote_flow { match peer.remote_flow {
Some((ref mut buf, ref flow)) => { Some((ref mut c, ref flow)) => {
flow.recharge(buf); flow.recharge(c);
Some(flow.max_amount(&*buf, kind)) Some(flow.max_amount(&*c, kind))
} }
None => None, None => None,
} }
@ -341,7 +341,7 @@ impl LightProtocol {
/// Make a request to a peer. /// Make a request to a peer.
/// ///
/// Fails on: nonexistent peer, network error, peer not server, /// Fails on: nonexistent peer, network error, peer not server,
/// insufficient buffer. Does not check capabilities before sending. /// insufficient credits. Does not check capabilities before sending.
/// On success, returns a request id which can later be coordinated /// On success, returns a request id which can later be coordinated
/// with an event. /// with an event.
pub fn request_from(&self, io: &IoContext, peer_id: &PeerId, request: Request) -> Result<ReqId, Error> { pub fn request_from(&self, io: &IoContext, peer_id: &PeerId, request: Request) -> Result<ReqId, Error> {
@ -350,10 +350,10 @@ impl LightProtocol {
let mut peer = peer.lock(); let mut peer = peer.lock();
match peer.remote_flow { match peer.remote_flow {
Some((ref mut buf, ref flow)) => { Some((ref mut c, ref flow)) => {
flow.recharge(buf); flow.recharge(c);
let max = flow.compute_cost(request.kind(), request.amount()); let max = flow.compute_cost(request.kind(), request.amount());
buf.deduct_cost(max)?; c.deduct_cost(max)?;
} }
None => return Err(Error::NotServer), None => return Err(Error::NotServer),
} }
@ -454,7 +454,7 @@ impl LightProtocol {
// - check whether request kinds match // - check whether request kinds match
fn pre_verify_response(&self, peer: &PeerId, kind: request::Kind, raw: &UntrustedRlp) -> Result<IdGuard, Error> { fn pre_verify_response(&self, peer: &PeerId, kind: request::Kind, raw: &UntrustedRlp) -> Result<IdGuard, Error> {
let req_id = ReqId(raw.val_at(0)?); let req_id = ReqId(raw.val_at(0)?);
let cur_buffer: U256 = raw.val_at(1)?; let cur_credits: U256 = raw.val_at(1)?;
trace!(target: "les", "pre-verifying response from peer {}, kind={:?}", peer, kind); trace!(target: "les", "pre-verifying response from peer {}, kind={:?}", peer, kind);
@ -470,9 +470,9 @@ impl LightProtocol {
(Some(request), Some(flow_info)) => { (Some(request), Some(flow_info)) => {
had_req = true; had_req = true;
let &mut (ref mut buf, ref mut flow) = flow_info; let &mut (ref mut c, ref mut flow) = flow_info;
let actual_buffer = ::std::cmp::min(cur_buffer, *flow.limit()); let actual_credits = ::std::cmp::min(cur_credits, *flow.limit());
buf.update_to(actual_buffer); c.update_to(actual_credits);
if request.kind() != kind { if request.kind() != kind {
Some(Error::UnsolicitedResponse) Some(Error::UnsolicitedResponse)
@ -675,10 +675,10 @@ impl LightProtocol {
return Err(Error::BadProtocolVersion); return Err(Error::BadProtocolVersion);
} }
let remote_flow = flow_params.map(|params| (params.create_buffer(), params)); let remote_flow = flow_params.map(|params| (params.create_credits(), params));
self.peers.write().insert(*peer, Mutex::new(Peer { self.peers.write().insert(*peer, Mutex::new(Peer {
local_buffer: self.flow_params.create_buffer(), local_credits: self.flow_params.create_credits(),
status: status.clone(), status: status.clone(),
capabilities: capabilities.clone(), capabilities: capabilities.clone(),
remote_flow: remote_flow, remote_flow: remote_flow,
@ -783,10 +783,10 @@ impl LightProtocol {
let actual_cost = self.flow_params.compute_cost(request::Kind::Headers, response.len()); let actual_cost = self.flow_params.compute_cost(request::Kind::Headers, response.len());
assert!(max_cost >= actual_cost, "Actual cost exceeded maximum computed cost."); assert!(max_cost >= actual_cost, "Actual cost exceeded maximum computed cost.");
let cur_buffer = peer.refund(&self.flow_params, max_cost - actual_cost); let cur_credits = peer.refund(&self.flow_params, max_cost - actual_cost);
io.respond(packet::BLOCK_HEADERS, { io.respond(packet::BLOCK_HEADERS, {
let mut stream = RlpStream::new_list(3); let mut stream = RlpStream::new_list(3);
stream.append(&req_id).append(&cur_buffer).begin_list(response.len()); stream.append(&req_id).append(&cur_credits).begin_list(response.len());
for header in response { for header in response {
stream.append_raw(&header.into_inner(), 1); stream.append_raw(&header.into_inner(), 1);
@ -845,11 +845,11 @@ impl LightProtocol {
let actual_cost = self.flow_params.compute_cost(request::Kind::Bodies, response_len); let actual_cost = self.flow_params.compute_cost(request::Kind::Bodies, response_len);
assert!(max_cost >= actual_cost, "Actual cost exceeded maximum computed cost."); assert!(max_cost >= actual_cost, "Actual cost exceeded maximum computed cost.");
let cur_buffer = peer.refund(&self.flow_params, max_cost - actual_cost); let cur_credits = peer.refund(&self.flow_params, max_cost - actual_cost);
io.respond(packet::BLOCK_BODIES, { io.respond(packet::BLOCK_BODIES, {
let mut stream = RlpStream::new_list(3); let mut stream = RlpStream::new_list(3);
stream.append(&req_id).append(&cur_buffer).begin_list(response.len()); stream.append(&req_id).append(&cur_credits).begin_list(response.len());
for body in response { for body in response {
match body { match body {
@ -911,11 +911,11 @@ impl LightProtocol {
let actual_cost = self.flow_params.compute_cost(request::Kind::Receipts, response_len); let actual_cost = self.flow_params.compute_cost(request::Kind::Receipts, response_len);
assert!(max_cost >= actual_cost, "Actual cost exceeded maximum computed cost."); assert!(max_cost >= actual_cost, "Actual cost exceeded maximum computed cost.");
let cur_buffer = peer.refund(&self.flow_params, max_cost - actual_cost); let cur_credits = peer.refund(&self.flow_params, max_cost - actual_cost);
io.respond(packet::RECEIPTS, { io.respond(packet::RECEIPTS, {
let mut stream = RlpStream::new_list(3); let mut stream = RlpStream::new_list(3);
stream.append(&req_id).append(&cur_buffer).begin_list(response.len()); stream.append(&req_id).append(&cur_credits).begin_list(response.len());
for receipts in response { for receipts in response {
stream.append_raw(&receipts, 1); stream.append_raw(&receipts, 1);
@ -985,11 +985,11 @@ impl LightProtocol {
let actual_cost = self.flow_params.compute_cost(request::Kind::StateProofs, response_len); let actual_cost = self.flow_params.compute_cost(request::Kind::StateProofs, response_len);
assert!(max_cost >= actual_cost, "Actual cost exceeded maximum computed cost."); assert!(max_cost >= actual_cost, "Actual cost exceeded maximum computed cost.");
let cur_buffer = peer.refund(&self.flow_params, max_cost - actual_cost); let cur_credits = peer.refund(&self.flow_params, max_cost - actual_cost);
io.respond(packet::PROOFS, { io.respond(packet::PROOFS, {
let mut stream = RlpStream::new_list(3); let mut stream = RlpStream::new_list(3);
stream.append(&req_id).append(&cur_buffer).begin_list(response.len()); stream.append(&req_id).append(&cur_credits).begin_list(response.len());
for proof in response { for proof in response {
stream.append_raw(&proof, 1); stream.append_raw(&proof, 1);
@ -1057,11 +1057,11 @@ impl LightProtocol {
let actual_cost = self.flow_params.compute_cost(request::Kind::Codes, response_len); let actual_cost = self.flow_params.compute_cost(request::Kind::Codes, response_len);
assert!(max_cost >= actual_cost, "Actual cost exceeded maximum computed cost."); assert!(max_cost >= actual_cost, "Actual cost exceeded maximum computed cost.");
let cur_buffer = peer.refund(&self.flow_params, max_cost - actual_cost); let cur_credits = peer.refund(&self.flow_params, max_cost - actual_cost);
io.respond(packet::CONTRACT_CODES, { io.respond(packet::CONTRACT_CODES, {
let mut stream = RlpStream::new_list(3); let mut stream = RlpStream::new_list(3);
stream.append(&req_id).append(&cur_buffer).begin_list(response.len()); stream.append(&req_id).append(&cur_credits).begin_list(response.len());
for code in response { for code in response {
stream.append(&code); stream.append(&code);
@ -1130,11 +1130,11 @@ impl LightProtocol {
let actual_cost = self.flow_params.compute_cost(request::Kind::HeaderProofs, response_len); let actual_cost = self.flow_params.compute_cost(request::Kind::HeaderProofs, response_len);
assert!(max_cost >= actual_cost, "Actual cost exceeded maximum computed cost."); assert!(max_cost >= actual_cost, "Actual cost exceeded maximum computed cost.");
let cur_buffer = peer.refund(&self.flow_params, max_cost - actual_cost); let cur_credits = peer.refund(&self.flow_params, max_cost - actual_cost);
io.respond(packet::HEADER_PROOFS, { io.respond(packet::HEADER_PROOFS, {
let mut stream = RlpStream::new_list(3); let mut stream = RlpStream::new_list(3);
stream.append(&req_id).append(&cur_buffer).begin_list(response.len()); stream.append(&req_id).append(&cur_credits).begin_list(response.len());
for proof in response { for proof in response {
stream.append_raw(&proof, 1); stream.append_raw(&proof, 1);

View File

@ -14,14 +14,14 @@
// You should have received a copy of the GNU General Public License // 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/>.
//! LES buffer flow management. //! Request credit management.
//! //!
//! Every request in the LES protocol leads to a reduction //! Every request in the light protocol leads to a reduction
//! of the requester's buffer value as a rate-limiting mechanism. //! of the requester's amount of credits as a rate-limiting mechanism.
//! This buffer value will recharge at a set rate. //! The amount of credits will recharge at a set rate.
//! //!
//! This module provides an interface for configuration of buffer //! This module provides an interface for configuration of
//! flow costs and recharge rates. //! costs and recharge rates of request credits.
//! //!
//! Current default costs are picked completely arbitrarily, not based //! Current default costs are picked completely arbitrarily, not based
//! on any empirical timings or mathematical models. //! on any empirical timings or mathematical models.
@ -38,19 +38,19 @@ use time::{Duration, SteadyTime};
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct Cost(pub U256, pub U256); pub struct Cost(pub U256, pub U256);
/// Buffer value. /// Credits value.
/// ///
/// Produced and recharged using `FlowParams`. /// Produced and recharged using `FlowParams`.
/// Definitive updates can be made as well -- these will reset the recharge /// Definitive updates can be made as well -- these will reset the recharge
/// point to the time of the update. /// point to the time of the update.
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct Buffer { pub struct Credits {
estimate: U256, estimate: U256,
recharge_point: SteadyTime, recharge_point: SteadyTime,
} }
impl Buffer { impl Credits {
/// Get the current buffer value. /// Get the current amount of credits..
pub fn current(&self) -> U256 { self.estimate.clone() } pub fn current(&self) -> U256 { self.estimate.clone() }
/// Make a definitive update. /// Make a definitive update.
@ -61,7 +61,7 @@ impl Buffer {
self.recharge_point = SteadyTime::now(); self.recharge_point = SteadyTime::now();
} }
/// Attempt to apply the given cost to the buffer. /// Attempt to apply the given cost to the amount of credits.
/// ///
/// If successful, the cost will be deducted successfully. /// If successful, the cost will be deducted successfully.
/// ///
@ -69,7 +69,7 @@ impl Buffer {
/// error will be produced. /// error will be produced.
pub fn deduct_cost(&mut self, cost: U256) -> Result<(), Error> { pub fn deduct_cost(&mut self, cost: U256) -> Result<(), Error> {
match cost > self.estimate { match cost > self.estimate {
true => Err(Error::BufferEmpty), true => Err(Error::NoCredits),
false => { false => {
self.estimate = self.estimate - cost; self.estimate = self.estimate - cost;
Ok(()) Ok(())
@ -165,7 +165,7 @@ impl RlpDecodable for CostTable {
} }
} }
/// A buffer-flow manager handles costs, recharge, limits /// Handles costs, recharge, limits of request credits.
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct FlowParams { pub struct FlowParams {
costs: CostTable, costs: CostTable,
@ -175,7 +175,7 @@ pub struct FlowParams {
impl FlowParams { impl FlowParams {
/// Create new flow parameters from a request cost table, /// Create new flow parameters from a request cost table,
/// buffer limit, and (minimum) rate of recharge. /// credit limit, and (minimum) rate of recharge.
pub fn new(limit: U256, costs: CostTable, recharge: U256) -> Self { pub fn new(limit: U256, costs: CostTable, recharge: U256) -> Self {
FlowParams { FlowParams {
costs: costs, costs: costs,
@ -201,7 +201,7 @@ impl FlowParams {
} }
} }
/// Get a reference to the buffer limit. /// Get a reference to the credit limit.
pub fn limit(&self) -> &U256 { &self.limit } pub fn limit(&self) -> &U256 { &self.limit }
/// Get a reference to the cost table. /// Get a reference to the cost table.
@ -227,10 +227,10 @@ impl FlowParams {
} }
/// Compute the maximum number of costs of a specific kind which can be made /// Compute the maximum number of costs of a specific kind which can be made
/// with the given buffer. /// with the given amount of credits
/// Saturates at `usize::max()`. This is not a problem in practice because /// Saturates at `usize::max()`. This is not a problem in practice because
/// this amount of requests is already prohibitively large. /// this amount of requests is already prohibitively large.
pub fn max_amount(&self, buffer: &Buffer, kind: request::Kind) -> usize { pub fn max_amount(&self, credits: &Credits, kind: request::Kind) -> usize {
use util::Uint; use util::Uint;
use std::usize; use std::usize;
@ -243,7 +243,7 @@ impl FlowParams {
request::Kind::HeaderProofs => &self.costs.header_proofs, request::Kind::HeaderProofs => &self.costs.header_proofs,
}; };
let start = buffer.current(); let start = credits.current();
if start <= cost.0 { if start <= cost.0 {
return 0; return 0;
@ -259,36 +259,36 @@ impl FlowParams {
} }
} }
/// Create initial buffer parameter. /// Create initial credits..
pub fn create_buffer(&self) -> Buffer { pub fn create_credits(&self) -> Credits {
Buffer { Credits {
estimate: self.limit, estimate: self.limit,
recharge_point: SteadyTime::now(), recharge_point: SteadyTime::now(),
} }
} }
/// Recharge the buffer based on time passed since last /// Recharge the given credits based on time passed since last
/// update. /// update.
pub fn recharge(&self, buf: &mut Buffer) { pub fn recharge(&self, credits: &mut Credits) {
let now = SteadyTime::now(); let now = SteadyTime::now();
// recompute and update only in terms of full seconds elapsed // recompute and update only in terms of full seconds elapsed
// in order to keep the estimate as an underestimate. // in order to keep the estimate as an underestimate.
let elapsed = (now - buf.recharge_point).num_seconds(); let elapsed = (now - credits.recharge_point).num_seconds();
buf.recharge_point = buf.recharge_point + Duration::seconds(elapsed); credits.recharge_point = credits.recharge_point + Duration::seconds(elapsed);
let elapsed: U256 = elapsed.into(); let elapsed: U256 = elapsed.into();
buf.estimate = ::std::cmp::min(self.limit, buf.estimate + (elapsed * self.recharge)); credits.estimate = ::std::cmp::min(self.limit, credits.estimate + (elapsed * self.recharge));
} }
/// Refund some buffer which was previously deducted. /// Refund some credits which were previously deducted.
/// Does not update the recharge timestamp. /// Does not update the recharge timestamp.
pub fn refund(&self, buf: &mut Buffer, refund_amount: U256) { pub fn refund(&self, credits: &mut Credits, refund_amount: U256) {
buf.estimate = buf.estimate + refund_amount; credits.estimate = credits.estimate + refund_amount;
if buf.estimate > self.limit { if credits.estimate > self.limit {
buf.estimate = self.limit credits.estimate = self.limit
} }
} }
} }
@ -318,20 +318,20 @@ mod tests {
} }
#[test] #[test]
fn buffer_mechanism() { fn credits_mechanism() {
use std::thread; use std::thread;
use std::time::Duration; use std::time::Duration;
let flow_params = FlowParams::new(100.into(), Default::default(), 20.into()); let flow_params = FlowParams::new(100.into(), Default::default(), 20.into());
let mut buffer = flow_params.create_buffer(); let mut credits = flow_params.create_credits();
assert!(buffer.deduct_cost(101.into()).is_err()); assert!(credits.deduct_cost(101.into()).is_err());
assert!(buffer.deduct_cost(10.into()).is_ok()); assert!(credits.deduct_cost(10.into()).is_ok());
thread::sleep(Duration::from_secs(1)); thread::sleep(Duration::from_secs(1));
flow_params.recharge(&mut buffer); flow_params.recharge(&mut credits);
assert_eq!(buffer.estimate, 100.into()); assert_eq!(credits.estimate, 100.into());
} }
} }

View File

@ -19,7 +19,7 @@
use rlp::{DecoderError, RlpDecodable, RlpEncodable, RlpStream, Stream, UntrustedRlp, View}; use rlp::{DecoderError, RlpDecodable, RlpEncodable, RlpStream, Stream, UntrustedRlp, View};
use util::{H256, U256}; use util::{H256, U256};
use super::buffer_flow::FlowParams; use super::request_credits::FlowParams;
// recognized handshake/announcement keys. // recognized handshake/announcement keys.
// unknown keys are to be skipped, known keys have a defined order. // unknown keys are to be skipped, known keys have a defined order.
@ -207,7 +207,7 @@ impl Capabilities {
/// Attempt to parse a handshake message into its three parts: /// Attempt to parse a handshake message into its three parts:
/// - chain status /// - chain status
/// - serving capabilities /// - serving capabilities
/// - buffer flow parameters /// - request credit parameters
pub fn parse_handshake(rlp: UntrustedRlp) -> Result<(Status, Capabilities, Option<FlowParams>), DecoderError> { pub fn parse_handshake(rlp: UntrustedRlp) -> Result<(Status, Capabilities, Option<FlowParams>), DecoderError> {
let mut parser = Parser { let mut parser = Parser {
pos: 0, pos: 0,
@ -300,7 +300,7 @@ pub struct Announcement {
pub serve_chain_since: Option<u64>, pub serve_chain_since: Option<u64>,
/// optional new transaction-relay capability. false means "no change" /// optional new transaction-relay capability. false means "no change"
pub tx_relay: bool, pub tx_relay: bool,
// TODO: changes in buffer flow? // TODO: changes in request credits.
} }
/// Parse an announcement. /// Parse an announcement.
@ -372,7 +372,7 @@ pub fn write_announcement(announcement: &Announcement) -> Vec<u8> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use super::super::buffer_flow::FlowParams; use super::super::request_credits::FlowParams;
use util::{U256, H256, FixedHash}; use util::{U256, H256, FixedHash};
use rlp::{RlpStream, Stream ,UntrustedRlp, View}; use rlp::{RlpStream, Stream ,UntrustedRlp, View};

View File

@ -24,7 +24,7 @@ use ethcore::transaction::PendingTransaction;
use ethcore::encoded; use ethcore::encoded;
use network::{PeerId, NodeId}; use network::{PeerId, NodeId};
use net::buffer_flow::FlowParams; use net::request_credits::FlowParams;
use net::context::IoContext; use net::context::IoContext;
use net::status::{Capabilities, Status, write_handshake}; use net::status::{Capabilities, Status, write_handshake};
use net::{encode_request, LightProtocol, Params, packet, Peer}; use net::{encode_request, LightProtocol, Params, packet, Peer};
@ -203,7 +203,7 @@ fn genesis_mismatch() {
} }
#[test] #[test]
fn buffer_overflow() { fn credit_overflow() {
let flow_params = make_flow_params(); let flow_params = make_flow_params();
let capabilities = capabilities(); let capabilities = capabilities();
@ -268,11 +268,11 @@ fn get_block_headers() {
let headers: Vec<_> = (0..10).map(|i| provider.client.block_header(BlockId::Number(i + 1)).unwrap()).collect(); let headers: Vec<_> = (0..10).map(|i| provider.client.block_header(BlockId::Number(i + 1)).unwrap()).collect();
assert_eq!(headers.len(), 10); assert_eq!(headers.len(), 10);
let new_buf = *flow_params.limit() - flow_params.compute_cost(request::Kind::Headers, 10); let new_creds = *flow_params.limit() - flow_params.compute_cost(request::Kind::Headers, 10);
let mut response_stream = RlpStream::new_list(3); let mut response_stream = RlpStream::new_list(3);
response_stream.append(&req_id).append(&new_buf).begin_list(10); response_stream.append(&req_id).append(&new_creds).begin_list(10);
for header in headers { for header in headers {
response_stream.append_raw(&header.into_inner(), 1); response_stream.append_raw(&header.into_inner(), 1);
} }
@ -317,11 +317,11 @@ fn get_block_bodies() {
let bodies: Vec<_> = (0..10).map(|i| provider.client.block_body(BlockId::Number(i + 1)).unwrap()).collect(); let bodies: Vec<_> = (0..10).map(|i| provider.client.block_body(BlockId::Number(i + 1)).unwrap()).collect();
assert_eq!(bodies.len(), 10); assert_eq!(bodies.len(), 10);
let new_buf = *flow_params.limit() - flow_params.compute_cost(request::Kind::Bodies, 10); let new_creds = *flow_params.limit() - flow_params.compute_cost(request::Kind::Bodies, 10);
let mut response_stream = RlpStream::new_list(3); let mut response_stream = RlpStream::new_list(3);
response_stream.append(&req_id).append(&new_buf).begin_list(10); response_stream.append(&req_id).append(&new_creds).begin_list(10);
for body in bodies { for body in bodies {
response_stream.append_raw(&body.into_inner(), 1); response_stream.append_raw(&body.into_inner(), 1);
} }
@ -371,11 +371,11 @@ fn get_block_receipts() {
.map(|hash| provider.client.block_receipts(hash).unwrap()) .map(|hash| provider.client.block_receipts(hash).unwrap())
.collect(); .collect();
let new_buf = *flow_params.limit() - flow_params.compute_cost(request::Kind::Receipts, receipts.len()); let new_creds = *flow_params.limit() - flow_params.compute_cost(request::Kind::Receipts, receipts.len());
let mut response_stream = RlpStream::new_list(3); let mut response_stream = RlpStream::new_list(3);
response_stream.append(&req_id).append(&new_buf).begin_list(receipts.len()); response_stream.append(&req_id).append(&new_creds).begin_list(receipts.len());
for block_receipts in receipts { for block_receipts in receipts {
response_stream.append_raw(&block_receipts, 1); response_stream.append_raw(&block_receipts, 1);
} }
@ -420,11 +420,11 @@ fn get_state_proofs() {
vec![::util::sha3::SHA3_NULL_RLP.to_vec()], vec![::util::sha3::SHA3_NULL_RLP.to_vec()],
]; ];
let new_buf = *flow_params.limit() - flow_params.compute_cost(request::Kind::StateProofs, 2); let new_creds = *flow_params.limit() - flow_params.compute_cost(request::Kind::StateProofs, 2);
let mut response_stream = RlpStream::new_list(3); let mut response_stream = RlpStream::new_list(3);
response_stream.append(&req_id).append(&new_buf).begin_list(2); response_stream.append(&req_id).append(&new_creds).begin_list(2);
for proof in proofs { for proof in proofs {
response_stream.begin_list(proof.len()); response_stream.begin_list(proof.len());
for node in proof { for node in proof {
@ -472,11 +472,11 @@ fn get_contract_code() {
key2.iter().chain(key2.iter()).cloned().collect(), key2.iter().chain(key2.iter()).cloned().collect(),
]; ];
let new_buf = *flow_params.limit() - flow_params.compute_cost(request::Kind::Codes, 2); let new_creds = *flow_params.limit() - flow_params.compute_cost(request::Kind::Codes, 2);
let mut response_stream = RlpStream::new_list(3); let mut response_stream = RlpStream::new_list(3);
response_stream.append(&req_id).append(&new_buf).begin_list(2); response_stream.append(&req_id).append(&new_creds).begin_list(2);
for code in codes { for code in codes {
response_stream.append(&code); response_stream.append(&code);
} }
@ -515,10 +515,10 @@ fn id_guard() {
pending_requests.insert(req_id_2, req, ::time::SteadyTime::now()); pending_requests.insert(req_id_2, req, ::time::SteadyTime::now());
proto.peers.write().insert(peer_id, ::util::Mutex::new(Peer { proto.peers.write().insert(peer_id, ::util::Mutex::new(Peer {
local_buffer: flow_params.create_buffer(), local_credits: flow_params.create_credits(),
status: status(provider.client.chain_info()), status: status(provider.client.chain_info()),
capabilities: capabilities.clone(), capabilities: capabilities.clone(),
remote_flow: Some((flow_params.create_buffer(), flow_params)), remote_flow: Some((flow_params.create_credits(), flow_params)),
sent_head: provider.client.chain_info().best_block_hash, sent_head: provider.client.chain_info().best_block_hash,
last_update: ::time::SteadyTime::now(), last_update: ::time::SteadyTime::now(),
pending_requests: pending_requests, pending_requests: pending_requests,

View File

@ -27,7 +27,7 @@ use ethcore::spec::Spec;
use io::IoChannel; use io::IoChannel;
use light::client::Client as LightClient; use light::client::Client as LightClient;
use light::net::{LightProtocol, IoContext, Capabilities, Params as LightParams}; use light::net::{LightProtocol, IoContext, Capabilities, Params as LightParams};
use light::net::buffer_flow::FlowParams; use light::net::request_credits::FlowParams;
use network::{NodeId, PeerId}; use network::{NodeId, PeerId};
use util::RwLock; use util::RwLock;