mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 14:37:57 +00:00
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:
@@ -27,7 +27,7 @@ use parity_scale_codec::Encode;
|
||||
|
||||
use polkadot_node_network_protocol::{
|
||||
self as net_protocol,
|
||||
grid_topology::{RequiredRouting, SessionBoundGridTopologyStorage, SessionGridTopology},
|
||||
grid_topology::{GridNeighbors, RequiredRouting, SessionBoundGridTopologyStorage},
|
||||
peer_set::{IsAuthority, PeerSet},
|
||||
request_response::{v1 as request_v1, IncomingRequestReceiver},
|
||||
v1::{self as protocol_v1, StatementMetadata},
|
||||
@@ -910,7 +910,10 @@ async fn circulate_statement_and_dependents<Context>(
|
||||
.with_candidate(statement.payload().candidate_hash())
|
||||
.with_stage(jaeger::Stage::StatementDistribution);
|
||||
|
||||
let topology = topology_store.get_topology_or_fallback(active_head.session_index);
|
||||
let topology = topology_store
|
||||
.get_topology_or_fallback(active_head.session_index)
|
||||
.local_grid_neighbors();
|
||||
|
||||
// First circulate the statement directly to all peers needing it.
|
||||
// The borrow of `active_head` needs to encompass only this (Rust) statement.
|
||||
let outputs: Option<(CandidateHash, Vec<PeerId>)> = {
|
||||
@@ -1009,7 +1012,7 @@ fn is_statement_large(statement: &SignedFullStatement) -> (bool, Option<usize>)
|
||||
#[overseer::contextbounds(StatementDistribution, prefix=self::overseer)]
|
||||
async fn circulate_statement<'a, Context>(
|
||||
required_routing: RequiredRouting,
|
||||
topology: &SessionGridTopology,
|
||||
topology: &GridNeighbors,
|
||||
peers: &mut HashMap<PeerId, PeerData>,
|
||||
ctx: &mut Context,
|
||||
relay_parent: Hash,
|
||||
@@ -1352,7 +1355,8 @@ async fn handle_incoming_message_and_circulate<'a, Context, R>(
|
||||
|
||||
let session_index = runtime.get_session_index_for_child(ctx.sender(), relay_parent).await;
|
||||
let topology = match session_index {
|
||||
Ok(session_index) => topology_storage.get_topology_or_fallback(session_index),
|
||||
Ok(session_index) =>
|
||||
topology_storage.get_topology_or_fallback(session_index).local_grid_neighbors(),
|
||||
Err(e) => {
|
||||
gum::debug!(
|
||||
target: LOG_TARGET,
|
||||
@@ -1361,7 +1365,7 @@ async fn handle_incoming_message_and_circulate<'a, Context, R>(
|
||||
e
|
||||
);
|
||||
|
||||
topology_storage.get_current_topology()
|
||||
topology_storage.get_current_topology().local_grid_neighbors()
|
||||
},
|
||||
};
|
||||
let required_routing =
|
||||
@@ -1588,7 +1592,7 @@ async fn handle_incoming_message<'a, Context>(
|
||||
#[overseer::contextbounds(StatementDistribution, prefix=self::overseer)]
|
||||
async fn update_peer_view_and_maybe_send_unlocked<Context, R>(
|
||||
peer: PeerId,
|
||||
topology: &SessionGridTopology,
|
||||
topology: &GridNeighbors,
|
||||
peer_data: &mut PeerData,
|
||||
ctx: &mut Context,
|
||||
active_heads: &HashMap<Hash, ActiveHeadData>,
|
||||
@@ -1673,16 +1677,22 @@ async fn handle_network_update<Context, R>(
|
||||
let _ = metrics.time_network_bridge_update_v1("new_gossip_topology");
|
||||
|
||||
let new_session_index = topology.session;
|
||||
let new_topology: SessionGridTopology = topology.into();
|
||||
let old_topology = topology_storage.get_current_topology();
|
||||
let newly_added = new_topology.peers_diff(old_topology);
|
||||
topology_storage.update_topology(new_session_index, new_topology);
|
||||
let new_topology = topology.topology;
|
||||
let old_topology =
|
||||
topology_storage.get_current_topology().local_grid_neighbors().clone();
|
||||
topology_storage.update_topology(new_session_index, new_topology, topology.local_index);
|
||||
|
||||
let newly_added = topology_storage
|
||||
.get_current_topology()
|
||||
.local_grid_neighbors()
|
||||
.peers_diff(&old_topology);
|
||||
|
||||
for peer in newly_added {
|
||||
if let Some(data) = peers.get_mut(&peer) {
|
||||
let view = std::mem::take(&mut data.view);
|
||||
update_peer_view_and_maybe_send_unlocked(
|
||||
peer,
|
||||
topology_storage.get_current_topology(),
|
||||
topology_storage.get_current_topology().local_grid_neighbors(),
|
||||
data,
|
||||
ctx,
|
||||
&*active_heads,
|
||||
@@ -1717,7 +1727,7 @@ async fn handle_network_update<Context, R>(
|
||||
Some(data) =>
|
||||
update_peer_view_and_maybe_send_unlocked(
|
||||
peer,
|
||||
topology_storage.get_current_topology(),
|
||||
topology_storage.get_current_topology().local_grid_neighbors(),
|
||||
data,
|
||||
ctx,
|
||||
&*active_heads,
|
||||
|
||||
@@ -20,6 +20,7 @@ use futures::executor::{self, block_on};
|
||||
use futures_timer::Delay;
|
||||
use parity_scale_codec::{Decode, Encode};
|
||||
use polkadot_node_network_protocol::{
|
||||
grid_topology::{SessionGridTopology, TopologyPeerInfo},
|
||||
peer_set::ValidationVersion,
|
||||
request_response::{
|
||||
v1::{StatementFetchingRequest, StatementFetchingResponse},
|
||||
@@ -509,7 +510,7 @@ fn peer_view_update_sends_messages() {
|
||||
let peer = PeerId::random();
|
||||
|
||||
executor::block_on(async move {
|
||||
let mut topology: SessionGridTopology = Default::default();
|
||||
let mut topology = GridNeighbors::empty();
|
||||
topology.peers_x = HashSet::from_iter(vec![peer.clone()].into_iter());
|
||||
update_peer_view_and_maybe_send_unlocked(
|
||||
peer.clone(),
|
||||
@@ -639,7 +640,7 @@ fn circulated_statement_goes_to_all_peers_with_view() {
|
||||
};
|
||||
let statement = StoredStatement { comparator: &comparator, statement: &statement };
|
||||
|
||||
let mut topology: SessionGridTopology = Default::default();
|
||||
let mut topology = GridNeighbors::empty();
|
||||
topology.peers_x =
|
||||
HashSet::from_iter(vec![peer_a.clone(), peer_b.clone(), peer_c.clone()].into_iter());
|
||||
let needs_dependents = circulate_statement(
|
||||
@@ -2019,42 +2020,77 @@ fn handle_multiple_seconded_statements() {
|
||||
.await;
|
||||
}
|
||||
|
||||
// Explicitly add all `lucky` peers to the gossip peers to ensure that neither `peerA` not `peerB`
|
||||
// receive statements
|
||||
// Set up a topology which puts peers a & b in a column together.
|
||||
let gossip_topology = {
|
||||
let mut t = network_bridge_event::NewGossipTopology {
|
||||
session: 1,
|
||||
our_neighbors_x: HashMap::new(),
|
||||
our_neighbors_y: HashMap::new(),
|
||||
};
|
||||
// create a lucky_peers+1 * lucky_peers+1 grid topology where we are at index 2, sharing
|
||||
// a row with peer_a (0) and peer_b (1) and a column with all the lucky peers.
|
||||
// the rest is filled with junk.
|
||||
// This is an absolute garbage hack depending on quirks of the implementation
|
||||
// and not on sound architecture.
|
||||
|
||||
// Create a topology to ensure that we send messages not to `peer_a`/`peer_b`
|
||||
for (i, peer) in lucky_peers.iter().enumerate() {
|
||||
let authority_id = AuthorityPair::generate().0.public();
|
||||
t.our_neighbors_y.insert(
|
||||
authority_id,
|
||||
network_bridge_event::TopologyPeerInfo {
|
||||
peer_ids: vec![peer.clone()],
|
||||
validator_index: (i as u32 + 2_u32).into(),
|
||||
},
|
||||
);
|
||||
let n_lucky = lucky_peers.len();
|
||||
let dim = n_lucky + 1;
|
||||
let grid_size = dim * dim;
|
||||
let topology_peer_info: Vec<_> = (0..grid_size)
|
||||
.map(|i| {
|
||||
if i == 0 {
|
||||
TopologyPeerInfo {
|
||||
peer_ids: vec![peer_a.clone()],
|
||||
validator_index: ValidatorIndex(0),
|
||||
discovery_id: AuthorityPair::generate().0.public(),
|
||||
}
|
||||
} else if i == 1 {
|
||||
TopologyPeerInfo {
|
||||
peer_ids: vec![peer_b.clone()],
|
||||
validator_index: ValidatorIndex(1),
|
||||
discovery_id: AuthorityPair::generate().0.public(),
|
||||
}
|
||||
} else if i == 2 {
|
||||
TopologyPeerInfo {
|
||||
peer_ids: vec![],
|
||||
validator_index: ValidatorIndex(2),
|
||||
discovery_id: AuthorityPair::generate().0.public(),
|
||||
}
|
||||
} else if (i - 2) % dim == 0 {
|
||||
let lucky_index = ((i - 2) / dim) - 1;
|
||||
TopologyPeerInfo {
|
||||
peer_ids: vec![lucky_peers[lucky_index].clone()],
|
||||
validator_index: ValidatorIndex(i as _),
|
||||
discovery_id: AuthorityPair::generate().0.public(),
|
||||
}
|
||||
} else {
|
||||
TopologyPeerInfo {
|
||||
peer_ids: vec![PeerId::random()],
|
||||
validator_index: ValidatorIndex(i as _),
|
||||
discovery_id: AuthorityPair::generate().0.public(),
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
// also a hack: this is only required to be accurate for
|
||||
// the validator indices we compute grid neighbors for.
|
||||
let mut shuffled_indices = vec![0; grid_size];
|
||||
shuffled_indices[2] = 2;
|
||||
|
||||
// Some sanity checking to make sure this hack is set up correctly.
|
||||
let topology = SessionGridTopology::new(shuffled_indices, topology_peer_info);
|
||||
let grid_neighbors = topology.compute_grid_neighbors_for(ValidatorIndex(2)).unwrap();
|
||||
assert_eq!(grid_neighbors.peers_x.len(), 25);
|
||||
assert!(grid_neighbors.peers_x.contains(&peer_a));
|
||||
assert!(grid_neighbors.peers_x.contains(&peer_b));
|
||||
assert!(!grid_neighbors.peers_y.contains(&peer_b));
|
||||
assert!(!grid_neighbors.route_to_peer(RequiredRouting::GridY, &peer_b));
|
||||
assert_eq!(grid_neighbors.peers_y.len(), lucky_peers.len());
|
||||
for lucky in &lucky_peers {
|
||||
assert!(grid_neighbors.peers_y.contains(lucky));
|
||||
}
|
||||
t.our_neighbors_x.insert(
|
||||
AuthorityPair::generate().0.public(),
|
||||
network_bridge_event::TopologyPeerInfo {
|
||||
peer_ids: vec![peer_a.clone()],
|
||||
validator_index: 0_u32.into(),
|
||||
},
|
||||
);
|
||||
t.our_neighbors_x.insert(
|
||||
AuthorityPair::generate().0.public(),
|
||||
network_bridge_event::TopologyPeerInfo {
|
||||
peer_ids: vec![peer_b.clone()],
|
||||
validator_index: 1_u32.into(),
|
||||
},
|
||||
);
|
||||
|
||||
t
|
||||
network_bridge_event::NewGossipTopology {
|
||||
session: 1,
|
||||
topology,
|
||||
local_index: Some(ValidatorIndex(2)),
|
||||
}
|
||||
};
|
||||
|
||||
handle
|
||||
|
||||
Reference in New Issue
Block a user