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:
Alin Dima
2024-01-10 15:19:50 +02:00
committed by GitHub
parent af2e30e383
commit f2a750ee86
29 changed files with 802 additions and 304 deletions
@@ -17,6 +17,7 @@
use super::*;
use assert_matches::assert_matches;
use futures::{executor, future, Future};
use sc_network::ProtocolName;
use sp_core::{crypto::Pair, Encode};
use sp_keyring::Sr25519Keyring;
use sp_keystore::Keystore;
@@ -559,11 +560,11 @@ fn act_on_advertisement_v2() {
.await;
response_channel
.send(Ok(request_v1::CollationFetchingResponse::Collation(
candidate_a.clone(),
pov.clone(),
)
.encode()))
.send(Ok((
request_v1::CollationFetchingResponse::Collation(candidate_a.clone(), pov.clone())
.encode(),
ProtocolName::from(""),
)))
.expect("Sending response should succeed");
assert_candidate_backing_second(
@@ -761,11 +762,11 @@ fn fetch_one_collation_at_a_time() {
candidate_a.descriptor.relay_parent = test_state.relay_parent;
candidate_a.descriptor.persisted_validation_data_hash = dummy_pvd().hash();
response_channel
.send(Ok(request_v1::CollationFetchingResponse::Collation(
candidate_a.clone(),
pov.clone(),
)
.encode()))
.send(Ok((
request_v1::CollationFetchingResponse::Collation(candidate_a.clone(), pov.clone())
.encode(),
ProtocolName::from(""),
)))
.expect("Sending response should succeed");
assert_candidate_backing_second(
@@ -885,19 +886,19 @@ fn fetches_next_collation() {
// First request finishes now:
response_channel_non_exclusive
.send(Ok(request_v1::CollationFetchingResponse::Collation(
candidate_a.clone(),
pov.clone(),
)
.encode()))
.send(Ok((
request_v1::CollationFetchingResponse::Collation(candidate_a.clone(), pov.clone())
.encode(),
ProtocolName::from(""),
)))
.expect("Sending response should succeed");
response_channel
.send(Ok(request_v1::CollationFetchingResponse::Collation(
candidate_a.clone(),
pov.clone(),
)
.encode()))
.send(Ok((
request_v1::CollationFetchingResponse::Collation(candidate_a.clone(), pov.clone())
.encode(),
ProtocolName::from(""),
)))
.expect("Sending response should succeed");
assert_candidate_backing_second(
@@ -1023,11 +1024,11 @@ fn fetch_next_collation_on_invalid_collation() {
candidate_a.descriptor.relay_parent = test_state.relay_parent;
candidate_a.descriptor.persisted_validation_data_hash = dummy_pvd().hash();
response_channel
.send(Ok(request_v1::CollationFetchingResponse::Collation(
candidate_a.clone(),
pov.clone(),
)
.encode()))
.send(Ok((
request_v1::CollationFetchingResponse::Collation(candidate_a.clone(), pov.clone())
.encode(),
ProtocolName::from(""),
)))
.expect("Sending response should succeed");
let receipt = assert_candidate_backing_second(
@@ -314,11 +314,11 @@ fn v1_advertisement_accepted_and_seconded() {
let pov = PoV { block_data: BlockData(vec![1]) };
response_channel
.send(Ok(request_v2::CollationFetchingResponse::Collation(
candidate.clone(),
pov.clone(),
)
.encode()))
.send(Ok((
request_v2::CollationFetchingResponse::Collation(candidate.clone(), pov.clone())
.encode(),
ProtocolName::from(""),
)))
.expect("Sending response should succeed");
assert_candidate_backing_second(
@@ -565,11 +565,14 @@ fn second_multiple_candidates_per_relay_parent() {
let pov = PoV { block_data: BlockData(vec![1]) };
response_channel
.send(Ok(request_v2::CollationFetchingResponse::Collation(
candidate.clone(),
pov.clone(),
)
.encode()))
.send(Ok((
request_v2::CollationFetchingResponse::Collation(
candidate.clone(),
pov.clone(),
)
.encode(),
ProtocolName::from(""),
)))
.expect("Sending response should succeed");
assert_candidate_backing_second(
@@ -717,11 +720,11 @@ fn fetched_collation_sanity_check() {
let pov = PoV { block_data: BlockData(vec![1]) };
response_channel
.send(Ok(request_v2::CollationFetchingResponse::Collation(
candidate.clone(),
pov.clone(),
)
.encode()))
.send(Ok((
request_v2::CollationFetchingResponse::Collation(candidate.clone(), pov.clone())
.encode(),
ProtocolName::from(""),
)))
.expect("Sending response should succeed");
// PVD request.