refactor grid topology to expose more info to subsystems (#6140)

* refactor grid topology to expose more info to subsystems

* fix grid_topology test

* fix overseer test

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

Co-authored-by: Vsevolod Stakhov <vsevolod.stakhov@parity.io>

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

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

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

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

* fix bug in populating topology

* fmt

Co-authored-by: Vsevolod Stakhov <vsevolod.stakhov@parity.io>
Co-authored-by: Andronik <write@reusable.software>
This commit is contained in:
asynchronous rob
2022-10-12 18:30:12 -05:00
committed by GitHub
parent bccffcad12
commit a7780e0797
17 changed files with 614 additions and 328 deletions
+19 -55
View File
@@ -525,73 +525,37 @@ async fn update_gossip_topology(
sp_core::blake2_256(&subject)
};
// shuffle the indices
let mut rng: ChaCha20Rng = SeedableRng::from_seed(random_seed);
let len = authorities.len();
let mut indices: Vec<usize> = (0..len).collect();
indices.shuffle(&mut rng);
let our_shuffled_position = indices
.iter()
.position(|i| *i == our_index)
.expect("our_index < len; indices contains it; qed");
// shuffle the validators and create the index mapping
let (shuffled_indices, canonical_shuffling) = {
let mut rng: ChaCha20Rng = SeedableRng::from_seed(random_seed);
let len = authorities.len();
let mut shuffled_indices = vec![0; len];
let mut canonical_shuffling: Vec<_> = authorities
.iter()
.enumerate()
.map(|(i, a)| (a.clone(), ValidatorIndex(i as _)))
.collect();
let neighbors = matrix_neighbors(our_shuffled_position, len);
let row_neighbors = neighbors
.row_neighbors
.map(|i| indices[i])
.map(|i| (authorities[i].clone(), ValidatorIndex::from(i as u32)))
.collect();
canonical_shuffling.shuffle(&mut rng);
for (i, (_, validator_index)) in canonical_shuffling.iter().enumerate() {
shuffled_indices[validator_index.0 as usize] = i;
}
let column_neighbors = neighbors
.column_neighbors
.map(|i| indices[i])
.map(|i| (authorities[i].clone(), ValidatorIndex::from(i as u32)))
.collect();
(shuffled_indices, canonical_shuffling)
};
sender
.send_message(NetworkBridgeRxMessage::NewGossipTopology {
session: session_index,
our_neighbors_x: row_neighbors,
our_neighbors_y: column_neighbors,
local_index: Some(ValidatorIndex(our_index as _)),
canonical_shuffling,
shuffled_indices,
})
.await;
Ok(())
}
struct MatrixNeighbors<R, C> {
row_neighbors: R,
column_neighbors: C,
}
/// Compute our row and column neighbors in a matrix
fn matrix_neighbors(
our_index: usize,
len: usize,
) -> MatrixNeighbors<impl Iterator<Item = usize>, impl Iterator<Item = usize>> {
assert!(our_index < len, "our_index is computed using `enumerate`; qed");
// e.g. for size 11 the matrix would be
//
// 0 1 2
// 3 4 5
// 6 7 8
// 9 10
//
// and for index 10, the neighbors would be 1, 4, 7, 9
let sqrt = (len as f64).sqrt() as usize;
let our_row = our_index / sqrt;
let our_column = our_index % sqrt;
let row_neighbors = our_row * sqrt..std::cmp::min(our_row * sqrt + sqrt, len);
let column_neighbors = (our_column..len).step_by(sqrt);
MatrixNeighbors {
row_neighbors: row_neighbors.filter(move |i| *i != our_index),
column_neighbors: column_neighbors.filter(move |i| *i != our_index),
}
}
#[overseer::subsystem(GossipSupport, error = SubsystemError, prefix = self::overseer)]
impl<Context, AD> GossipSupport<AD>
where
@@ -29,6 +29,7 @@ use sp_consensus_babe::{AllowedSlots, BabeEpochConfiguration, Epoch as BabeEpoch
use sp_core::crypto::Pair as PairT;
use sp_keyring::Sr25519Keyring;
use polkadot_node_network_protocol::grid_topology::{SessionGridTopology, TopologyPeerInfo};
use polkadot_node_subsystem::{
jaeger,
messages::{AllMessages, RuntimeApiMessage, RuntimeApiRequest},
@@ -73,13 +74,15 @@ lazy_static! {
// [1 3]
// [0 ]
static ref ROW_NEIGHBORS: Vec<(AuthorityDiscoveryId, ValidatorIndex)> = vec![
(Sr25519Keyring::Charlie.public().into(), ValidatorIndex::from(2)),
static ref EXPECTED_SHUFFLING: Vec<usize> = vec![6, 4, 0, 5, 2, 3, 1];
static ref ROW_NEIGHBORS: Vec<ValidatorIndex> = vec![
ValidatorIndex::from(2),
];
static ref COLUMN_NEIGHBORS: Vec<(AuthorityDiscoveryId, ValidatorIndex)> = vec![
(Sr25519Keyring::Two.public().into(), ValidatorIndex::from(5)),
(Sr25519Keyring::Eve.public().into(), ValidatorIndex::from(3)),
static ref COLUMN_NEIGHBORS: Vec<ValidatorIndex> = vec![
ValidatorIndex::from(3),
ValidatorIndex::from(5),
];
}
@@ -257,12 +260,31 @@ async fn test_neighbors(overseer: &mut VirtualOverseer, expected_session: Sessio
overseer_recv(overseer).await,
AllMessages::NetworkBridgeRx(NetworkBridgeRxMessage::NewGossipTopology {
session: got_session,
our_neighbors_x,
our_neighbors_y,
local_index,
canonical_shuffling,
shuffled_indices,
}) => {
assert_eq!(expected_session, got_session);
let mut got_row: Vec<_> = our_neighbors_x.into_iter().collect();
let mut got_column: Vec<_> = our_neighbors_y.into_iter().collect();
assert_eq!(local_index, Some(ValidatorIndex(6)));
assert_eq!(shuffled_indices, EXPECTED_SHUFFLING.clone());
let grid_topology = SessionGridTopology::new(
shuffled_indices,
canonical_shuffling.into_iter()
.map(|(a, v)| TopologyPeerInfo {
validator_index: v,
discovery_id: a,
peer_ids: Vec::new(),
})
.collect(),
);
let grid_neighbors = grid_topology
.compute_grid_neighbors_for(local_index.unwrap())
.unwrap();
let mut got_row: Vec<_> = grid_neighbors.validator_indices_x.into_iter().collect();
let mut got_column: Vec<_> = grid_neighbors.validator_indices_y.into_iter().collect();
got_row.sort();
got_column.sort();
assert_eq!(got_row, ROW_NEIGHBORS.clone());
@@ -694,26 +716,3 @@ fn issues_a_connection_request_when_last_request_was_mostly_unresolved() {
assert_eq!(state.last_session_index, Some(1));
assert!(state.last_failure.is_none());
}
#[test]
fn test_matrix_neighbors() {
for (our_index, len, expected_row, expected_column) in vec![
(0usize, 1usize, vec![], vec![]),
(1, 2, vec![], vec![0usize]),
(0, 9, vec![1, 2], vec![3, 6]),
(9, 10, vec![], vec![0, 3, 6]),
(10, 11, vec![9], vec![1, 4, 7]),
(7, 11, vec![6, 8], vec![1, 4, 10]),
]
.into_iter()
{
let matrix = matrix_neighbors(our_index, len);
let mut row_result: Vec<_> = matrix.row_neighbors.collect();
let mut column_result: Vec<_> = matrix.column_neighbors.collect();
row_result.sort();
column_result.sort();
assert_eq!(row_result, expected_row);
assert_eq!(column_result, expected_column);
}
}