Skip to content
This repository was archived by the owner on Jul 4, 2022. It is now read-only.

Commit dbe2031

Browse files
mxindenwheresaddieexpenses
authored
client/network: Use request response for block requests (#7478)
* client/network: Add scaffolding for finality req to use req resp #sc * client/network/src/finality_requests: Remove * client/network/src/behaviour: Pass request id down to sync * client/network: Use request response for block requests * client/network: Move handler logic into *_*_handler.rs * client/network: Track ongoing finality requests in protocol.rs * client/network: Remove commented out finalization initialization * client/network: Add docs for request handlers * client/network/finality_request_handler: Log errors * client/network/block_request_handler: Log errors * client/network: Format * client/network: Handle block request failure * protocols/network: Fix tests * client/network/src/behaviour: Handle request sending errors * client/network: Move response handling into custom method * client/network/protocol: Handle block response errors * client/network/protocol: Remove tracking of obsolete requests * client/network/protocol: Remove block request start time tracking This will be handled generically via request-responses. * client/network/protocol: Refactor on_*_request_started * client/network: Pass protocol config instead of protocol name * client/network: Pass protocol config in tests * client/network/config: Document request response configs * client/network/src/_request_handler: Document protocol config gen * client/network/src/protocol: Document Peer request values * client/network: Rework request response to always use oneshot * client/network: Unified metric reporting for all request protocols * client/network: Move protobuf parsing into protocol.rs * client/network/src/protocol: Return pending events after poll * client/network: Improve error handling and documentation * client/network/behaviour: Remove outdated error types * Update client/network/src/block_request_handler.rs Co-authored-by: Ashley <[email protected]> * Update client/network/src/finality_request_handler.rs Co-authored-by: Ashley <[email protected]> * client/network/protocol: Reduce reputation on timeout * client/network/protocol: Refine reputation changes * client/network/block_request_handler: Set and explain queue length * client/service: Deny block requests when light client * client/service: Fix role matching * client: Enforce line width * client/network/request_responses: Fix unit tests * client/network: Expose time to build response via metrics * client/network/request_responses: Fix early connection closed error * client/network/protocol: Fix line length * client/network/protocol: Disconnect on most request failures * client/network/protocol: Disconnect peer when oneshot is canceled * client/network/protocol: Disconnect peer even when connection closed * client/network/protocol: Remove debugging log line * client/network/request_response: Use Clone::clone for error * client/network/request_response: Remove outdated comment With libp2p v0.33.0 libp2p-request-response properly sends inbound failures on connections being closed. Co-authored-by: Addie Wagenknecht <[email protected]> Co-authored-by: Ashley <[email protected]>
1 parent 1b840aa commit dbe2031

File tree

17 files changed

+774
-1293
lines changed

17 files changed

+774
-1293
lines changed

.maintain/sentry-node/docker-compose.yml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ services:
4747
- "--validator"
4848
- "--alice"
4949
- "--sentry-nodes"
50-
- "/dns/sentry-a/tcp/30333/p2p/QmV7EhW6J6KgmNdr558RH1mPx2xGGznW7At4BhXzntRFsi"
50+
- "/dns/sentry-a/tcp/30333/p2p/12D3KooWSCufgHzV4fCwRijfH2k3abrpAJxTKxEvN1FDuRXA2U9x"
5151
- "--reserved-nodes"
52-
- "/dns/sentry-a/tcp/30333/p2p/QmV7EhW6J6KgmNdr558RH1mPx2xGGznW7At4BhXzntRFsi"
52+
- "/dns/sentry-a/tcp/30333/p2p/12D3KooWSCufgHzV4fCwRijfH2k3abrpAJxTKxEvN1FDuRXA2U9x"
5353
# Not only bind to localhost.
5454
- "--unsafe-ws-external"
5555
- "--unsafe-rpc-external"
@@ -83,11 +83,11 @@ services:
8383
- "--port"
8484
- "30333"
8585
- "--sentry"
86-
- "/dns/validator-a/tcp/30333/p2p/QmRpheLN4JWdAnY7HGJfWFNbfkQCb6tFf4vvA6hgjMZKrR"
86+
- "/dns/validator-a/tcp/30333/p2p/12D3KooWEyoppNCUx8Yx66oV9fJnriXwCcXwDDUA2kj6vnc6iDEp"
8787
- "--reserved-nodes"
88-
- "/dns/validator-a/tcp/30333/p2p/QmRpheLN4JWdAnY7HGJfWFNbfkQCb6tFf4vvA6hgjMZKrR"
88+
- "/dns/validator-a/tcp/30333/p2p/12D3KooWEyoppNCUx8Yx66oV9fJnriXwCcXwDDUA2kj6vnc6iDEp"
8989
- "--bootnodes"
90-
- "/dns/validator-b/tcp/30333/p2p/QmSVnNf9HwVMT1Y4cK1P6aoJcEZjmoTXpjKBmAABLMnZEk"
90+
- "/dns/validator-b/tcp/30333/p2p/12D3KooWHdiAxVd8uMQR1hGWXccidmfCwLqcMpGwR6QcTP6QRMuD"
9191
- "--no-telemetry"
9292
- "--rpc-cors"
9393
- "all"
@@ -118,9 +118,9 @@ services:
118118
- "--validator"
119119
- "--bob"
120120
- "--bootnodes"
121-
- "/dns/validator-a/tcp/30333/p2p/QmRpheLN4JWdAnY7HGJfWFNbfkQCb6tFf4vvA6hgjMZKrR"
121+
- "/dns/validator-a/tcp/30333/p2p/12D3KooWEyoppNCUx8Yx66oV9fJnriXwCcXwDDUA2kj6vnc6iDEp"
122122
- "--bootnodes"
123-
- "/dns/sentry-a/tcp/30333/p2p/QmV7EhW6J6KgmNdr558RH1mPx2xGGznW7At4BhXzntRFsi"
123+
- "/dns/sentry-a/tcp/30333/p2p/12D3KooWSCufgHzV4fCwRijfH2k3abrpAJxTKxEvN1FDuRXA2U9x"
124124
- "--no-telemetry"
125125
- "--rpc-cors"
126126
- "all"

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client/network/src/behaviour.rs

Lines changed: 53 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,22 @@
1717
// along with this program. If not, see <https://www.gnu.org/licenses/>.
1818

1919
use crate::{
20-
config::{ProtocolId, Role}, block_requests, light_client_handler,
21-
peer_info, request_responses, discovery::{DiscoveryBehaviour, DiscoveryConfig, DiscoveryOut},
20+
config::{ProtocolId, Role}, light_client_handler, peer_info, request_responses,
21+
discovery::{DiscoveryBehaviour, DiscoveryConfig, DiscoveryOut},
2222
protocol::{message::Roles, CustomMessageOutcome, NotificationsSink, Protocol},
2323
ObservedRole, DhtEvent, ExHashT,
2424
};
2525

2626
use bytes::Bytes;
2727
use codec::Encode as _;
28+
use futures::channel::oneshot;
2829
use libp2p::NetworkBehaviour;
2930
use libp2p::core::{Multiaddr, PeerId, PublicKey};
3031
use libp2p::identify::IdentifyInfo;
3132
use libp2p::kad::record;
3233
use libp2p::swarm::{NetworkBehaviourAction, NetworkBehaviourEventProcess, PollParameters};
3334
use log::debug;
35+
use prost::Message;
3436
use sp_consensus::{BlockOrigin, import_queue::{IncomingBlock, Origin}};
3537
use sp_runtime::{traits::{Block as BlockT, NumberFor}, Justification};
3638
use std::{
@@ -42,7 +44,7 @@ use std::{
4244
};
4345

4446
pub use crate::request_responses::{
45-
ResponseFailure, InboundFailure, RequestFailure, OutboundFailure, RequestId, SendRequestError
47+
ResponseFailure, InboundFailure, RequestFailure, OutboundFailure, RequestId,
4648
};
4749

4850
/// General behaviour of the network. Combines all protocols together.
@@ -58,8 +60,6 @@ pub struct Behaviour<B: BlockT, H: ExHashT> {
5860
discovery: DiscoveryBehaviour,
5961
/// Generic request-reponse protocols.
6062
request_responses: request_responses::RequestResponsesBehaviour,
61-
/// Block request handling.
62-
block_requests: block_requests::BlockRequests<B>,
6363
/// Light client request handling.
6464
light_client_handler: light_client_handler::LightClientHandler<B>,
6565

@@ -70,6 +70,11 @@ pub struct Behaviour<B: BlockT, H: ExHashT> {
7070
/// Role of our local node, as originally passed from the configuration.
7171
#[behaviour(ignore)]
7272
role: Role,
73+
74+
/// Protocol name used to send out block requests via
75+
/// [`request_responses::RequestResponsesBehaviour`].
76+
#[behaviour(ignore)]
77+
block_request_protocol_name: String,
7378
}
7479

7580
/// Event generated by `Behaviour`.
@@ -93,34 +98,18 @@ pub enum BehaviourOut<B: BlockT> {
9398
result: Result<Duration, ResponseFailure>,
9499
},
95100

96-
/// A request initiated using [`Behaviour::send_request`] has succeeded or failed.
97-
RequestFinished {
98-
/// Request that has succeeded.
99-
request_id: RequestId,
100-
/// Response sent by the remote or reason for failure.
101-
result: Result<Vec<u8>, RequestFailure>,
102-
},
103-
104-
/// Started a new request with the given node.
105-
///
106-
/// This event is for statistics purposes only. The request and response handling are entirely
107-
/// internal to the behaviour.
108-
OpaqueRequestStarted {
109-
peer: PeerId,
110-
/// Protocol name of the request.
111-
protocol: String,
112-
},
113-
/// Finished, successfully or not, a previously-started request.
101+
/// A request has succeeded or failed.
114102
///
115-
/// This event is for statistics purposes only. The request and response handling are entirely
116-
/// internal to the behaviour.
117-
OpaqueRequestFinished {
118-
/// Who we were requesting.
103+
/// This event is generated for statistics purposes.
104+
RequestFinished {
105+
/// Peer that we send a request to.
119106
peer: PeerId,
120-
/// Protocol name of the request.
121-
protocol: String,
122-
/// How long before the response came or the request got cancelled.
123-
request_duration: Duration,
107+
/// Name of the protocol in question.
108+
protocol: Cow<'static, str>,
109+
/// Duration the request took.
110+
duration: Duration,
111+
/// Result of the request.
112+
result: Result<(), RequestFailure>,
124113
},
125114

126115
/// Opened a substream with the given node with the given notifications protocol.
@@ -180,21 +169,28 @@ impl<B: BlockT, H: ExHashT> Behaviour<B, H> {
180169
role: Role,
181170
user_agent: String,
182171
local_public_key: PublicKey,
183-
block_requests: block_requests::BlockRequests<B>,
184172
light_client_handler: light_client_handler::LightClientHandler<B>,
185173
disco_config: DiscoveryConfig,
186-
request_response_protocols: Vec<request_responses::ProtocolConfig>,
174+
// Block request protocol config.
175+
block_request_protocol_config: request_responses::ProtocolConfig,
176+
// All remaining request protocol configs.
177+
mut request_response_protocols: Vec<request_responses::ProtocolConfig>,
187178
) -> Result<Self, request_responses::RegisterError> {
179+
// Extract protocol name and add to `request_response_protocols`.
180+
let block_request_protocol_name = block_request_protocol_config.name.to_string();
181+
request_response_protocols.push(block_request_protocol_config);
182+
188183
Ok(Behaviour {
189184
substrate,
190185
peer_info: peer_info::PeerInfoBehaviour::new(user_agent, local_public_key),
191186
discovery: disco_config.finish(),
192187
request_responses:
193188
request_responses::RequestResponsesBehaviour::new(request_response_protocols.into_iter())?,
194-
block_requests,
195189
light_client_handler,
196190
events: VecDeque::new(),
197191
role,
192+
193+
block_request_protocol_name,
198194
})
199195
}
200196

@@ -236,13 +232,14 @@ impl<B: BlockT, H: ExHashT> Behaviour<B, H> {
236232
}
237233

238234
/// Initiates sending a request.
239-
///
240-
/// An error is returned if we are not connected to the target peer of if the protocol doesn't
241-
/// match one that has been registered.
242-
pub fn send_request(&mut self, target: &PeerId, protocol: &str, request: Vec<u8>)
243-
-> Result<RequestId, SendRequestError>
244-
{
245-
self.request_responses.send_request(target, protocol, request)
235+
pub fn send_request(
236+
&mut self,
237+
target: &PeerId,
238+
protocol: &str,
239+
request: Vec<u8>,
240+
pending_response: oneshot::Sender<Result<Vec<u8>, RequestFailure>>,
241+
) {
242+
self.request_responses.send_request(target, protocol, request, pending_response)
246243
}
247244

248245
/// Registers a new notifications protocol.
@@ -331,28 +328,20 @@ Behaviour<B, H> {
331328
self.events.push_back(BehaviourOut::BlockImport(origin, blocks)),
332329
CustomMessageOutcome::JustificationImport(origin, hash, nb, justification) =>
333330
self.events.push_back(BehaviourOut::JustificationImport(origin, hash, nb, justification)),
334-
CustomMessageOutcome::BlockRequest { target, request } => {
335-
match self.block_requests.send_request(&target, request) {
336-
block_requests::SendRequestOutcome::Ok => {
337-
self.events.push_back(BehaviourOut::OpaqueRequestStarted {
338-
peer: target,
339-
protocol: self.block_requests.protocol_name().to_owned(),
340-
});
341-
},
342-
block_requests::SendRequestOutcome::Replaced { request_duration, .. } => {
343-
self.events.push_back(BehaviourOut::OpaqueRequestFinished {
344-
peer: target.clone(),
345-
protocol: self.block_requests.protocol_name().to_owned(),
346-
request_duration,
347-
});
348-
self.events.push_back(BehaviourOut::OpaqueRequestStarted {
349-
peer: target,
350-
protocol: self.block_requests.protocol_name().to_owned(),
351-
});
352-
}
353-
block_requests::SendRequestOutcome::NotConnected |
354-
block_requests::SendRequestOutcome::EncodeError(_) => {},
331+
CustomMessageOutcome::BlockRequest { target, request, pending_response } => {
332+
let mut buf = Vec::with_capacity(request.encoded_len());
333+
if let Err(err) = request.encode(&mut buf) {
334+
log::warn!(
335+
target: "sync",
336+
"Failed to encode block request {:?}: {:?}",
337+
request, err
338+
);
339+
return
355340
}
341+
342+
self.request_responses.send_request(
343+
&target, &self.block_request_protocol_name, buf, pending_response,
344+
);
356345
},
357346
CustomMessageOutcome::NotificationStreamOpened { remote, protocols, roles, notifications_sink } => {
358347
let role = reported_roles_to_observed_role(&self.role, &remote, roles);
@@ -401,51 +390,15 @@ impl<B: BlockT, H: ExHashT> NetworkBehaviourEventProcess<request_responses::Even
401390
result,
402391
});
403392
}
404-
405-
request_responses::Event::RequestFinished { request_id, result } => {
393+
request_responses::Event::RequestFinished { peer, protocol, duration, result } => {
406394
self.events.push_back(BehaviourOut::RequestFinished {
407-
request_id,
408-
result,
395+
peer, protocol, duration, result,
409396
});
410397
},
411398
}
412399
}
413400
}
414401

415-
impl<B: BlockT, H: ExHashT> NetworkBehaviourEventProcess<block_requests::Event<B>> for Behaviour<B, H> {
416-
fn inject_event(&mut self, event: block_requests::Event<B>) {
417-
match event {
418-
block_requests::Event::AnsweredRequest { peer, total_handling_time } => {
419-
self.events.push_back(BehaviourOut::InboundRequest {
420-
peer,
421-
protocol: self.block_requests.protocol_name().to_owned().into(),
422-
result: Ok(total_handling_time),
423-
});
424-
},
425-
block_requests::Event::Response { peer, response, request_duration } => {
426-
self.events.push_back(BehaviourOut::OpaqueRequestFinished {
427-
peer: peer.clone(),
428-
protocol: self.block_requests.protocol_name().to_owned(),
429-
request_duration,
430-
});
431-
let ev = self.substrate.on_block_response(peer, response);
432-
self.inject_event(ev);
433-
}
434-
block_requests::Event::RequestCancelled { peer, request_duration, .. } |
435-
block_requests::Event::RequestTimeout { peer, request_duration, .. } => {
436-
// There doesn't exist any mechanism to report cancellations or timeouts yet, so
437-
// we process them by disconnecting the node.
438-
self.events.push_back(BehaviourOut::OpaqueRequestFinished {
439-
peer: peer.clone(),
440-
protocol: self.block_requests.protocol_name().to_owned(),
441-
request_duration,
442-
});
443-
self.substrate.on_block_request_failed(&peer);
444-
}
445-
}
446-
}
447-
}
448-
449402
impl<B: BlockT, H: ExHashT> NetworkBehaviourEventProcess<peer_info::PeerInfoEvent>
450403
for Behaviour<B, H> {
451404
fn inject_event(&mut self, event: peer_info::PeerInfoEvent) {

0 commit comments

Comments
 (0)