validator_discovery: pass PeerSet to the request (#2372)

* validator_discovery: pass PeerSet to the request

* validator_discovery: track PeerSet of connected peers

* validator_discovery: fix tests

* validator_discovery: fix long line

* some fixes

* some validator_discovery logs

* log validator discovery request

* Also connect to validators on `DistributePoV`.

* validator_discovery: store the whole state per peer_set

* bump spec versions in kusama, polkadot and westend

* Correcting doc.

* validator_discovery: bump channel capacity

* pov-distribution: some cleanup

* this should fix the test, but it does not

* I just got some brain damage while fixing this

Why are you even reading this???

* wrap long line

* address some review nits

Co-authored-by: Robert Klotzner <robert.klotzner@gmx.at>
This commit is contained in:
Andronik Ordian
2021-02-08 08:57:59 +01:00
committed by GitHub
parent 28cab8e190
commit 6981a1c366
13 changed files with 228 additions and 119 deletions
@@ -40,7 +40,7 @@ use polkadot_node_subsystem_util::{
metrics::{self, prometheus},
};
use polkadot_node_network_protocol::{
v1 as protocol_v1, ReputationChange as Rep, PeerId, OurView,
peer_set::PeerSet, v1 as protocol_v1, ReputationChange as Rep, PeerId, OurView,
};
use futures::prelude::*;
@@ -296,6 +296,42 @@ async fn distribute_to_awaiting(
metrics.on_pov_distributed();
}
/// Connect to relevant validators in case we are not already.
async fn connect_to_relevant_validators(
connection_requests: &mut validator_discovery::ConnectionRequests,
ctx: &mut impl SubsystemContext<Message = PoVDistributionMessage>,
relay_parent: Hash,
descriptor: &CandidateDescriptor,
) {
if let Ok(Some(relevant_validators)) =
determine_relevant_validators(ctx, relay_parent, descriptor.para_id).await
{
// We only need one connection request per (relay_parent, para_id)
// so here we take this shortcut to avoid calling `connect_to_validators`
// more than once.
if !connection_requests.contains_request(&relay_parent) {
tracing::debug!(target: LOG_TARGET, validators=?relevant_validators, "connecting to validators");
match validator_discovery::connect_to_validators(
ctx,
relay_parent,
relevant_validators,
PeerSet::Validation,
).await {
Ok(new_connection_request) => {
connection_requests.put(relay_parent, new_connection_request);
}
Err(e) => {
tracing::debug!(
target: LOG_TARGET,
"Failed to create a validator connection request {:?}",
e,
);
}
}
}
}
}
/// Get the Id of the Core that is assigned to the para being collated on if any
/// and the total number of cores.
async fn determine_core(
@@ -394,35 +430,8 @@ async fn handle_fetch(
return;
}
Entry::Vacant(e) => {
if let Ok(Some(relevant_validators)) = determine_relevant_validators(
ctx,
relay_parent,
descriptor.para_id,
).await {
// We only need one connection request per (relay_parent, para_id)
// so here we take this shortcut to avoid calling `connect_to_validators`
// more than once.
if !state.connection_requests.contains_request(&relay_parent) {
match validator_discovery::connect_to_validators(
ctx,
relay_parent,
relevant_validators.clone(),
).await {
Ok(new_connection_request) => {
state.connection_requests.put(relay_parent, new_connection_request);
}
Err(e) => {
tracing::debug!(
target: LOG_TARGET,
"Failed to create a validator connection request {:?}",
e,
);
}
}
}
e.insert(vec![response_sender]);
}
connect_to_relevant_validators(&mut state.connection_requests, ctx, relay_parent, &descriptor).await;
e.insert(vec![response_sender]);
}
}
}
@@ -460,6 +469,8 @@ async fn handle_distribute(
None => return,
};
connect_to_relevant_validators(&mut state.connection_requests, ctx, relay_parent, &descriptor).await;
if let Some(our_awaited) = relay_parent_state.fetching.get_mut(&descriptor.pov_hash) {
// Drain all the senders, but keep the entry in the map around intentionally.
//
@@ -640,7 +651,7 @@ async fn handle_incoming_pov(
relay_parent_state.known.insert(pov_hash, (pov, encoded_pov));
}
/// Handles a newly connected validator in the context of some relay leaf.
/// Handles a newly or already connected validator in the context of some relay leaf.
fn handle_validator_connected(state: &mut State, peer_id: PeerId) {
state.peer_state.entry(peer_id).or_default();
}
@@ -719,9 +730,16 @@ impl PoVDistribution {
#[tracing::instrument(skip(self, ctx), fields(subsystem = LOG_TARGET))]
async fn run(
self,
mut ctx: impl SubsystemContext<Message = PoVDistributionMessage>,
ctx: impl SubsystemContext<Message = PoVDistributionMessage>,
) -> SubsystemResult<()> {
self.run_with_state(ctx, State::default()).await
}
async fn run_with_state(
self,
mut ctx: impl SubsystemContext<Message = PoVDistributionMessage>,
mut state: State,
) -> SubsystemResult<()> {
let mut state = State::default();
state.metrics = self.metrics;
loop {
@@ -60,6 +60,7 @@ struct TestHarness {
}
fn test_harness<T: Future<Output = ()>>(
state: State,
test: impl FnOnce(TestHarness) -> T,
) {
let _ = env_logger::builder()
@@ -80,7 +81,7 @@ fn test_harness<T: Future<Output = ()>>(
let subsystem = super::PoVDistribution::new(Metrics::default());
let subsystem = subsystem.run(context);
let subsystem = subsystem.run_with_state(context, state);
let test_fut = test(TestHarness { virtual_overseer });
@@ -257,7 +258,7 @@ async fn test_validator_discovery(
fn ask_validators_for_povs() {
let test_state = TestState::default();
test_harness(|test_harness| async move {
test_harness(State::default(), |test_harness| async move {
let mut virtual_overseer = test_harness.virtual_overseer;
let pov_block = PoV {
@@ -566,7 +567,7 @@ fn distributes_to_those_awaiting_and_completes_local() {
let pov = make_pov(vec![1, 2, 3]);
let pov_hash = pov.hash();
let mut state = State {
let state = State {
relay_parent_state: {
let mut s = HashMap::new();
let mut b = BlockBasedState {
@@ -607,28 +608,38 @@ fn distributes_to_those_awaiting_and_completes_local() {
connection_requests: Default::default(),
};
let pool = sp_core::testing::TaskExecutor::new();
let (mut ctx, mut handle) = polkadot_node_subsystem_test_helpers::make_subsystem_context(pool);
let mut descriptor = CandidateDescriptor::default();
descriptor.pov_hash = pov_hash;
executor::block_on(async move {
handle_distribute(
&mut state,
&mut ctx,
hash_a,
descriptor,
Arc::new(pov.clone()),
test_harness(state, |test_harness| async move {
let mut virtual_overseer = test_harness.virtual_overseer;
overseer_send(
&mut virtual_overseer,
PoVDistributionMessage::DistributePoV(
hash_a,
descriptor,
Arc::new(pov.clone())
)
).await;
assert!(!state.peer_state[&peer_a].awaited[&hash_a].contains(&pov_hash));
assert!(state.peer_state[&peer_c].awaited[&hash_b].contains(&pov_hash));
// Let's assume runtime call failed and we're already connected to the peers.
assert_matches!(
virtual_overseer.recv().await,
AllMessages::RuntimeApi(RuntimeApiMessage::Request(
relay_parent,
RuntimeApiRequest::AvailabilityCores(tx)
)) => {
assert_eq!(relay_parent, hash_a);
tx.send(Err("nope".to_string().into())).unwrap();
}
);
// our local sender also completed
assert_eq!(&*pov_recv.await.unwrap(), &pov);
assert_matches!(
handle.recv().await,
virtual_overseer.recv().await,
AllMessages::NetworkBridge(
NetworkBridgeMessage::SendValidationMessage(peers, message)
) => {