From 44531e300918788fb6f809b34d75f023e15f8b31 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Mon, 10 Sep 2018 19:45:49 +0800 Subject: [PATCH] light: give free credits for reserved peers (#9448) * light: give free credits for reserved peers * Fix ethcore-light tests * Test free_flow_params --- ethcore/light/src/net/context.rs | 7 +++++++ ethcore/light/src/net/mod.rs | 17 ++++++++++++--- ethcore/light/src/net/tests/mod.rs | 21 +++++++++++++++++++ ethcore/sync/src/light_sync/tests/test_net.rs | 1 + util/network-devp2p/src/host.rs | 11 ++++++++-- util/network/src/lib.rs | 7 +++++++ 6 files changed, 59 insertions(+), 5 deletions(-) diff --git a/ethcore/light/src/net/context.rs b/ethcore/light/src/net/context.rs index 6ef78af2d..083bb49cf 100644 --- a/ethcore/light/src/net/context.rs +++ b/ethcore/light/src/net/context.rs @@ -44,6 +44,9 @@ pub trait IoContext { /// Persistent peer id fn persistent_peer_id(&self, peer: PeerId) -> Option; + + /// Whether given peer id is reserved peer + fn is_reserved_peer(&self, peer: PeerId) -> bool; } impl IoContext for T where T: ?Sized + NetworkContext { @@ -76,6 +79,10 @@ impl IoContext for T where T: ?Sized + NetworkContext { fn persistent_peer_id(&self, peer: PeerId) -> Option { 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. diff --git a/ethcore/light/src/net/mod.rs b/ethcore/light/src/net/mod.rs index 9df8baf63..590be038e 100644 --- a/ethcore/light/src/net/mod.rs +++ b/ethcore/light/src/net/mod.rs @@ -354,6 +354,7 @@ pub struct LightProtocol { peers: RwLock, capabilities: RwLock, flow_params: RwLock>, + free_flow_params: Arc, handlers: Vec>, req_id: AtomicUsize, sample_store: Box, @@ -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(), diff --git a/ethcore/light/src/net/tests/mod.rs b/ethcore/light/src/net/tests/mod.rs index bc125380f..b20349fec 100644 --- a/ethcore/light/src/net/tests/mod.rs +++ b/ethcore/light/src/net/tests/mod.rs @@ -87,6 +87,10 @@ impl IoContext for Expect { fn persistent_peer_id(&self, _peer: PeerId) -> Option { 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 { + ::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, 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() { diff --git a/ethcore/sync/src/light_sync/tests/test_net.rs b/ethcore/sync/src/light_sync/tests/test_net.rs index d3d51afb0..e843e97dd 100644 --- a/ethcore/sync/src/light_sync/tests/test_net.rs +++ b/ethcore/sync/src/light_sync/tests/test_net.rs @@ -68,6 +68,7 @@ impl<'a> IoContext for TestIoContext<'a> { fn protocol_version(&self, _peer: PeerId) -> Option { Some(::light::net::MAX_PROTOCOL_VERSION) } fn persistent_peer_id(&self, _peer: PeerId) -> Option { unimplemented!() } + fn is_reserved_peer(&self, _peer: PeerId) -> bool { false } } // peer-specific data. diff --git a/util/network-devp2p/src/host.rs b/util/network-devp2p/src/host.rs index f56ff676f..f16701b6a 100644 --- a/util/network-devp2p/src/host.rs +++ b/util/network-devp2p/src/host.rs @@ -102,7 +102,7 @@ pub struct NetworkContext<'s> { sessions: Arc>>, session: Option, session_id: Option, - _reserved_peers: &'s HashSet, + reserved_peers: &'s HashSet, } 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 diff --git a/util/network/src/lib.rs b/util/network/src/lib.rs index f29df4e5b..395075e9f 100644 --- a/util/network/src/lib.rs +++ b/util/network/src/lib.rs @@ -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.