Implement grid topology routing for the statement distribution subsystem (#5476)

* Move NewGossipTopology -> SessionGridTopology outside as this implementation is shared

* Add method to return peers difference between topologies

* Implement basic grid topology usage for the bitfield distribution

* Fix tests

* Oops, fix tests

* Add some tests for random routing

* Add a unit test for topology distribution

* Store the current and the previous topology to match sessions boundaries

* Update tests

* Update node/network/bitfield-distribution/src/lib.rs

Co-authored-by: Andronik <write@reusable.software>

* Update node/network/protocol/src/grid_topology.rs

Co-authored-by: Andronik <write@reusable.software>

* Update node/network/bitfield-distribution/src/lib.rs

Co-authored-by: Andronik <write@reusable.software>

* Add some debug

* Fix tests as HashSet order is undefined

* Move session bounded topology to the common code part

* Fix tests

* Allow to select routing by peer index

* Implement grid topology in the statement distribution subsystem

* Fix tests compilation

* Fix test

* Refactor API slightly

* Address review comments

* Reduce runtime error logging severity

* Update node/network/protocol/src/grid_topology.rs

Co-authored-by: Bernhard Schuster <bernhard@ahoi.io>

* Update node/network/bitfield-distribution/src/tests.rs

Co-authored-by: Bernhard Schuster <bernhard@ahoi.io>

* Fmt run

* Use named struct

* Fix logging stuff

* One more accidental fmt damage

* Increase active queue size and add metrics

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* Revert "Increase active queue size and add metrics"

This reverts commit c4f48e8bded6dfeb9c62814ba2f8d815c34b04cf.

* Use validator index to choose the routing strategy

Noted by: @rphmeier

* Fix test after distribution logic fix

Co-authored-by: Andronik <write@reusable.software>
Co-authored-by: Bernhard Schuster <bernhard@ahoi.io>
Co-authored-by: Andrei Sandu <andrei-mihail@parity.io>
This commit is contained in:
Vsevolod Stakhov
2022-05-18 13:27:06 +01:00
committed by GitHub
parent 28cae2ef45
commit 195b901cc9
8 changed files with 189 additions and 92 deletions
@@ -26,7 +26,9 @@ use futures::{channel::oneshot, FutureExt};
use polkadot_node_network_protocol::{
self as net_protocol,
grid_topology::{RandomRouting, RequiredRouting, SessionGridTopology},
grid_topology::{
RandomRouting, RequiredRouting, SessionBoundGridTopologyStorage, SessionGridTopology,
},
v1 as protocol_v1, OurView, PeerId, UnifiedReputationChange as Rep, Versioned, View,
};
use polkadot_node_subsystem::{
@@ -34,9 +36,8 @@ use polkadot_node_subsystem::{
SpawnedSubsystem, SubsystemError, SubsystemResult,
};
use polkadot_node_subsystem_util::{self as util};
use polkadot_primitives::v2::{
Hash, SessionIndex, SignedAvailabilityBitfield, SigningContext, ValidatorId,
};
use polkadot_primitives::v2::{Hash, SignedAvailabilityBitfield, SigningContext, ValidatorId};
use rand::{CryptoRng, Rng, SeedableRng};
use std::collections::{HashMap, HashSet};
@@ -80,44 +81,6 @@ impl BitfieldGossipMessage {
}
}
/// A simple storage for a topology and the corresponding session index
#[derive(Default, Debug)]
struct GridTopologySessionBound(SessionGridTopology, SessionIndex);
/// A storage for the current and maybe previous topology
#[derive(Default, Debug)]
struct BitfieldGridTopologyStorage {
current_topology: GridTopologySessionBound,
prev_topology: Option<GridTopologySessionBound>,
}
impl BitfieldGridTopologyStorage {
/// Return a grid topology based on the session index:
/// If we need a previous session and it is registered in the storage, then return that session.
/// Otherwise, return a current session to have some grid topology in any case
fn get_topology(&self, idx: SessionIndex) -> &SessionGridTopology {
if let Some(prev_topology) = &self.prev_topology {
if idx == prev_topology.1 {
return &prev_topology.0
}
}
// Return the current topology by default
&self.current_topology.0
}
/// Update the current topology preserving the previous one
fn update_topology(&mut self, idx: SessionIndex, topology: SessionGridTopology) {
let old_current =
std::mem::replace(&mut self.current_topology, GridTopologySessionBound(topology, idx));
self.prev_topology.replace(old_current);
}
/// Returns a current grid topology
fn get_current_topology(&self) -> &SessionGridTopology {
&self.current_topology.0
}
}
/// Data used to track information of peers and relay parents the
/// overseer ordered us to work on.
#[derive(Default, Debug)]
@@ -127,7 +90,7 @@ struct ProtocolState {
peer_views: HashMap<PeerId, View>,
/// The current and previous gossip topologies
topologies: BitfieldGridTopologyStorage,
topologies: SessionBoundGridTopologyStorage,
/// Our current view.
view: OurView,
@@ -364,8 +327,9 @@ async fn handle_bitfield_distribution<Context>(
};
let msg = BitfieldGossipMessage { relay_parent, signed_availability };
let topology = state.topologies.get_topology(session_idx);
let required_routing = topology.required_routing_for(validator_index, true);
let topology = state.topologies.get_topology_or_fallback(session_idx);
let required_routing = topology.required_routing_by_index(validator_index, true);
relay_message(
ctx,
job_data,
@@ -567,8 +531,10 @@ async fn process_incoming_peer_message<Context>(
let message = BitfieldGossipMessage { relay_parent, signed_availability };
let topology = state.topologies.get_topology(job_data.signing_context.session_index);
let required_routing = topology.required_routing_for(validator_index, false);
let topology = state
.topologies
.get_topology_or_fallback(job_data.signing_context.session_index);
let required_routing = topology.required_routing_by_index(validator_index, false);
metrics.on_bitfield_received();
one_per_validator.insert(validator.clone(), message.clone());
@@ -19,7 +19,9 @@ use assert_matches::assert_matches;
use bitvec::bitvec;
use futures::executor;
use maplit::hashmap;
use polkadot_node_network_protocol::{our_view, view, ObservedRole};
use polkadot_node_network_protocol::{
grid_topology::SessionBoundGridTopologyStorage, our_view, view, ObservedRole,
};
use polkadot_node_subsystem::{
jaeger,
jaeger::{PerLeafSpan, Span},
@@ -60,7 +62,7 @@ fn prewarmed_state(
let relay_parent = known_message.relay_parent.clone();
let mut topology: SessionGridTopology = Default::default();
topology.peers_x = peers.iter().cloned().collect();
let mut topologies: BitfieldGridTopologyStorage = Default::default();
let mut topologies = SessionBoundGridTopologyStorage::default();
topologies.update_topology(0_u32, topology);
ProtocolState {
per_relay_parent: hashmap! {