light: give free credits for reserved peers (#9448)

* light: give free credits for reserved peers

* Fix ethcore-light tests

* Test free_flow_params
This commit is contained in:
Wei Tang 2018-09-10 19:45:49 +08:00 committed by GitHub
parent 2177a0179e
commit 44531e3009
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 59 additions and 5 deletions

View File

@ -44,6 +44,9 @@ pub trait IoContext {
/// Persistent peer id
fn persistent_peer_id(&self, peer: PeerId) -> Option<NodeId>;
/// Whether given peer id is reserved peer
fn is_reserved_peer(&self, peer: PeerId) -> bool;
}
impl<T> IoContext for T where T: ?Sized + NetworkContext {
@ -76,6 +79,10 @@ impl<T> IoContext for T where T: ?Sized + NetworkContext {
fn persistent_peer_id(&self, peer: PeerId) -> Option<NodeId> {
self.session_info(peer).and_then(|info| info.id)
}
fn is_reserved_peer(&self, peer: PeerId) -> bool {
NetworkContext::is_reserved_peer(self, peer)
}
}
/// Basic context for the protocol.

View File

@ -354,6 +354,7 @@ pub struct LightProtocol {
peers: RwLock<PeerMap>,
capabilities: RwLock<Capabilities>,
flow_params: RwLock<Arc<FlowParams>>,
free_flow_params: Arc<FlowParams>,
handlers: Vec<Arc<Handler>>,
req_id: AtomicUsize,
sample_store: Box<SampleStore>,
@ -383,6 +384,7 @@ impl LightProtocol {
peers: RwLock::new(HashMap::new()),
capabilities: RwLock::new(params.capabilities),
flow_params: RwLock::new(Arc::new(flow_params)),
free_flow_params: Arc::new(FlowParams::free()),
handlers: Vec::new(),
req_id: AtomicUsize::new(0),
sample_store,
@ -706,8 +708,13 @@ impl LightProtocol {
};
let capabilities = self.capabilities.read();
let local_flow = self.flow_params.read();
let status_packet = status::write_handshake(&status, &capabilities, Some(&**local_flow));
let cost_local_flow = self.flow_params.read();
let local_flow = if io.is_reserved_peer(peer) {
&*self.free_flow_params
} else {
&**cost_local_flow
};
let status_packet = status::write_handshake(&status, &capabilities, Some(local_flow));
self.pending_peers.write().insert(peer, PendingPeer {
sent_head: chain_info.best_block_hash,
@ -818,7 +825,11 @@ impl LightProtocol {
}
let remote_flow = flow_params.map(|params| (params.create_credits(), params));
let local_flow = self.flow_params.read().clone();
let local_flow = if io.is_reserved_peer(peer) {
self.free_flow_params.clone()
} else {
self.flow_params.read().clone()
};
self.peers.write().insert(peer, Mutex::new(Peer {
local_credits: local_flow.create_credits(),

View File

@ -87,6 +87,10 @@ impl IoContext for Expect {
fn persistent_peer_id(&self, _peer: PeerId) -> Option<NodeId> {
None
}
fn is_reserved_peer(&self, peer: PeerId) -> bool {
peer == 0xff
}
}
// can't implement directly for Arc due to cross-crate orphan rules.
@ -190,6 +194,10 @@ fn write_handshake(status: &Status, capabilities: &Capabilities, proto: &LightPr
::net::status::write_handshake(status, capabilities, Some(&*flow_params))
}
fn write_free_handshake(status: &Status, capabilities: &Capabilities, proto: &LightProtocol) -> Vec<u8> {
::net::status::write_handshake(status, capabilities, Some(&proto.free_flow_params))
}
// helper for setting up the protocol handler and provider.
fn setup(capabilities: Capabilities) -> (Arc<TestProviderInner>, LightProtocol) {
let provider = Arc::new(TestProviderInner {
@ -231,6 +239,19 @@ fn handshake_expected() {
proto.on_connect(1, &Expect::Send(1, packet::STATUS, packet_body));
}
#[test]
fn reserved_handshake_expected() {
let capabilities = capabilities();
let (provider, proto) = setup(capabilities);
let status = status(provider.client.chain_info());
let packet_body = write_free_handshake(&status, &capabilities, &proto);
proto.on_connect(0xff, &Expect::Send(0xff, packet::STATUS, packet_body));
}
#[test]
#[should_panic]
fn genesis_mismatch() {

View File

@ -68,6 +68,7 @@ impl<'a> IoContext for TestIoContext<'a> {
fn protocol_version(&self, _peer: PeerId) -> Option<u8> { Some(::light::net::MAX_PROTOCOL_VERSION) }
fn persistent_peer_id(&self, _peer: PeerId) -> Option<NodeId> { unimplemented!() }
fn is_reserved_peer(&self, _peer: PeerId) -> bool { false }
}
// peer-specific data.

View File

@ -102,7 +102,7 @@ pub struct NetworkContext<'s> {
sessions: Arc<RwLock<Slab<SharedSession>>>,
session: Option<SharedSession>,
session_id: Option<StreamToken>,
_reserved_peers: &'s HashSet<NodeId>,
reserved_peers: &'s HashSet<NodeId>,
}
impl<'s> NetworkContext<'s> {
@ -121,7 +121,7 @@ impl<'s> NetworkContext<'s> {
session_id: id,
session,
sessions,
_reserved_peers: reserved_peers,
reserved_peers: reserved_peers,
}
}
@ -190,6 +190,13 @@ impl<'s> NetworkContextTrait for NetworkContext<'s> {
}
fn subprotocol_name(&self) -> ProtocolId { self.protocol }
fn is_reserved_peer(&self, peer: PeerId) -> bool {
self.session_info(peer)
.and_then(|info| info.id)
.map(|node| self.reserved_peers.contains(&node))
.unwrap_or(false)
}
}
/// Shared host information

View File

@ -285,6 +285,9 @@ pub trait NetworkContext {
/// Returns this object's subprotocol name.
fn subprotocol_name(&self) -> ProtocolId;
/// Returns whether the given peer ID is a reserved peer.
fn is_reserved_peer(&self, peer: PeerId) -> bool;
}
impl<'a, T> NetworkContext for &'a T where T: ?Sized + NetworkContext {
@ -331,6 +334,10 @@ impl<'a, T> NetworkContext for &'a T where T: ?Sized + NetworkContext {
fn subprotocol_name(&self) -> ProtocolId {
(**self).subprotocol_name()
}
fn is_reserved_peer(&self, peer: PeerId) -> bool {
(**self).is_reserved_peer(peer)
}
}
/// Network IO protocol handler. This needs to be implemented for each new subprotocol.