mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 11:07:56 +00:00
add fallback request for req-response protocols (#2771)
Previously, it was only possible to retry the same request on a different protocol name that had the exact same binary payloads. Introduce a way of trying a different request on a different protocol if the first one fails with Unsupported protocol. This helps with adding new req-response versions in polkadot while preserving compatibility with unupgraded nodes. The way req-response protocols were bumped previously was that they were bundled with some other notifications protocol upgrade, like for async backing (but that is more complicated, especially if the feature does not require any changes to a notifications protocol). Will be needed for implementing https://github.com/polkadot-fellows/RFCs/pull/47 TODO: - [x] add tests - [x] add guidance docs in polkadot about req-response protocol versioning
This commit is contained in:
@@ -18,7 +18,10 @@
|
||||
|
||||
use futures::channel::oneshot;
|
||||
use libp2p::PeerId;
|
||||
use sc_network::request_responses::{ProtocolConfig, RequestFailure};
|
||||
use sc_network::{
|
||||
request_responses::{ProtocolConfig, RequestFailure},
|
||||
ProtocolName,
|
||||
};
|
||||
use sc_network_common::sync::message::{BlockData, BlockRequest};
|
||||
use sp_runtime::traits::Block as BlockT;
|
||||
use std::sync::Arc;
|
||||
@@ -43,7 +46,7 @@ pub trait BlockDownloader<Block: BlockT>: Send + Sync {
|
||||
&self,
|
||||
who: PeerId,
|
||||
request: BlockRequest<Block>,
|
||||
) -> Result<Result<Vec<u8>, RequestFailure>, oneshot::Canceled>;
|
||||
) -> Result<Result<(Vec<u8>, ProtocolName), RequestFailure>, oneshot::Canceled>;
|
||||
|
||||
/// Parses the protocol specific response to retrieve the block data.
|
||||
fn block_response_into_blocks(
|
||||
|
||||
@@ -570,7 +570,7 @@ impl<B: BlockT> BlockDownloader<B> for FullBlockDownloader {
|
||||
&self,
|
||||
who: PeerId,
|
||||
request: BlockRequest<B>,
|
||||
) -> Result<Result<Vec<u8>, RequestFailure>, oneshot::Canceled> {
|
||||
) -> Result<Result<(Vec<u8>, ProtocolName), RequestFailure>, oneshot::Canceled> {
|
||||
// Build the request protobuf.
|
||||
let bytes = BlockRequestSchema {
|
||||
fields: request.fields.to_be_u32(),
|
||||
|
||||
@@ -1263,7 +1263,7 @@ where
|
||||
let ResponseEvent { peer_id, request, response } = response_event;
|
||||
|
||||
match response {
|
||||
Ok(Ok(resp)) => match request {
|
||||
Ok(Ok((resp, _))) => match request {
|
||||
PeerRequest::Block(req) => {
|
||||
match self.block_downloader.block_response_into_blocks(&req, resp) {
|
||||
Ok(blocks) => {
|
||||
|
||||
@@ -22,7 +22,7 @@ use crate::block_relay_protocol::{BlockDownloader as BlockDownloaderT, BlockResp
|
||||
|
||||
use futures::channel::oneshot;
|
||||
use libp2p::PeerId;
|
||||
use sc_network::RequestFailure;
|
||||
use sc_network::{ProtocolName, RequestFailure};
|
||||
use sc_network_common::sync::message::{BlockData, BlockRequest};
|
||||
use sp_runtime::traits::Block as BlockT;
|
||||
|
||||
@@ -35,7 +35,7 @@ mockall::mock! {
|
||||
&self,
|
||||
who: PeerId,
|
||||
request: BlockRequest<Block>,
|
||||
) -> Result<Result<Vec<u8>, RequestFailure>, oneshot::Canceled>;
|
||||
) -> Result<Result<(Vec<u8>, ProtocolName), RequestFailure>, oneshot::Canceled>;
|
||||
fn block_response_into_blocks(
|
||||
&self,
|
||||
request: &BlockRequest<Block>,
|
||||
|
||||
@@ -28,7 +28,7 @@ use futures::{
|
||||
};
|
||||
use libp2p::PeerId;
|
||||
use log::error;
|
||||
use sc_network::request_responses::RequestFailure;
|
||||
use sc_network::{request_responses::RequestFailure, types::ProtocolName};
|
||||
use sp_runtime::traits::Block as BlockT;
|
||||
use std::task::{Context, Poll, Waker};
|
||||
use tokio_stream::StreamMap;
|
||||
@@ -37,7 +37,7 @@ use tokio_stream::StreamMap;
|
||||
const LOG_TARGET: &'static str = "sync";
|
||||
|
||||
/// Response result.
|
||||
type ResponseResult = Result<Result<Vec<u8>, RequestFailure>, oneshot::Canceled>;
|
||||
type ResponseResult = Result<Result<(Vec<u8>, ProtocolName), RequestFailure>, oneshot::Canceled>;
|
||||
|
||||
/// A future yielding [`ResponseResult`].
|
||||
type ResponseFuture = BoxFuture<'static, ResponseResult>;
|
||||
|
||||
@@ -117,14 +117,16 @@ mockall::mock! {
|
||||
target: PeerId,
|
||||
protocol: ProtocolName,
|
||||
request: Vec<u8>,
|
||||
fallback_request: Option<(Vec<u8>, ProtocolName)>,
|
||||
connect: IfDisconnected,
|
||||
) -> Result<Vec<u8>, RequestFailure>;
|
||||
) -> Result<(Vec<u8>, ProtocolName), RequestFailure>;
|
||||
fn start_request(
|
||||
&self,
|
||||
target: PeerId,
|
||||
protocol: ProtocolName,
|
||||
request: Vec<u8>,
|
||||
tx: oneshot::Sender<Result<Vec<u8>, RequestFailure>>,
|
||||
fallback_request: Option<(Vec<u8>, ProtocolName)>,
|
||||
tx: oneshot::Sender<Result<(Vec<u8>, ProtocolName), RequestFailure>>,
|
||||
connect: IfDisconnected,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ pub enum ToServiceCommand {
|
||||
PeerId,
|
||||
ProtocolName,
|
||||
Vec<u8>,
|
||||
oneshot::Sender<Result<Vec<u8>, RequestFailure>>,
|
||||
oneshot::Sender<Result<(Vec<u8>, ProtocolName), RequestFailure>>,
|
||||
IfDisconnected,
|
||||
),
|
||||
|
||||
@@ -94,7 +94,7 @@ impl NetworkServiceHandle {
|
||||
who: PeerId,
|
||||
protocol: ProtocolName,
|
||||
request: Vec<u8>,
|
||||
tx: oneshot::Sender<Result<Vec<u8>, RequestFailure>>,
|
||||
tx: oneshot::Sender<Result<(Vec<u8>, ProtocolName), RequestFailure>>,
|
||||
connect: IfDisconnected,
|
||||
) {
|
||||
let _ = self
|
||||
@@ -134,7 +134,7 @@ impl NetworkServiceProvider {
|
||||
ToServiceCommand::ReportPeer(peer, reputation_change) =>
|
||||
service.report_peer(peer, reputation_change),
|
||||
ToServiceCommand::StartRequest(peer, protocol, request, tx, connect) =>
|
||||
service.start_request(peer, protocol, request, tx, connect),
|
||||
service.start_request(peer, protocol, request, None, tx, connect),
|
||||
ToServiceCommand::WriteNotification(peer, protocol, message) =>
|
||||
service.write_notification(peer, protocol, message),
|
||||
ToServiceCommand::SetNotificationHandshake(protocol, handshake) =>
|
||||
|
||||
Reference in New Issue
Block a user