cargo +nightly fmt (#3540)

* cargo +nightly fmt

* add cargo-fmt check to ci

* update ci

* fmt

* fmt

* skip macro

* ignore bridges
This commit is contained in:
Shawn Tabrizi
2021-08-02 12:47:33 +02:00
committed by GitHub
parent 30e3012270
commit ff5d56fb76
350 changed files with 20617 additions and 21266 deletions
@@ -14,44 +14,49 @@
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
use std::{collections::{HashMap, HashSet, VecDeque}, pin::Pin, time::Duration};
use std::{
collections::{HashMap, HashSet, VecDeque},
pin::Pin,
time::Duration,
};
use futures::{FutureExt, StreamExt, channel::oneshot, stream::FuturesUnordered, select, Future};
use futures::{channel::oneshot, select, stream::FuturesUnordered, Future, FutureExt, StreamExt};
use sp_core::Pair;
use polkadot_node_network_protocol::{
peer_set::PeerSet,
request_response::{
request::OutgoingResponse,
v1::{CollationFetchingRequest, CollationFetchingResponse},
IncomingRequest,
},
v1 as protocol_v1, OurView, PeerId, UnifiedReputationChange as Rep, View,
};
use polkadot_node_primitives::{PoV, SignedFullStatement, Statement};
use polkadot_node_subsystem_util::{
metrics::{self, prometheus},
runtime::{get_availability_cores, get_group_rotation_info, RuntimeInfo},
TimeoutExt,
};
use polkadot_primitives::v1::{
AuthorityDiscoveryId, CandidateHash, CandidateReceipt, CollatorPair, CoreIndex, CoreState, GroupIndex, Hash,
Id as ParaId,
AuthorityDiscoveryId, CandidateHash, CandidateReceipt, CollatorPair, CoreIndex, CoreState,
GroupIndex, Hash, Id as ParaId,
};
use polkadot_subsystem::{
overseer,
FromOverseer, OverseerSignal, PerLeafSpan, SubsystemContext, jaeger,
messages::{
CollatorProtocolMessage, NetworkBridgeEvent, NetworkBridgeMessage,
},
jaeger,
messages::{CollatorProtocolMessage, NetworkBridgeEvent, NetworkBridgeMessage},
overseer, FromOverseer, OverseerSignal, PerLeafSpan, SubsystemContext,
};
use polkadot_node_network_protocol::{
OurView, PeerId, UnifiedReputationChange as Rep, View, peer_set::PeerSet,
request_response::{
IncomingRequest, request::OutgoingResponse, v1::{CollationFetchingRequest, CollationFetchingResponse}
},
v1 as protocol_v1,
};
use polkadot_node_subsystem_util::{
TimeoutExt,
metrics::{self, prometheus},
runtime::{RuntimeInfo, get_availability_cores, get_group_rotation_info}
};
use polkadot_node_primitives::{SignedFullStatement, Statement, PoV};
use crate::error::{Fatal, NonFatal, log_error};
use super::{LOG_TARGET, Result};
use super::{Result, LOG_TARGET};
use crate::error::{log_error, Fatal, NonFatal};
#[cfg(test)]
mod tests;
const COST_UNEXPECTED_MESSAGE: Rep = Rep::CostMinor("An unexpected message");
const COST_APPARENT_FLOOD: Rep = Rep::CostMinor("Message received when previous one was still being processed");
const COST_APPARENT_FLOOD: Rep =
Rep::CostMinor("Message received when previous one was still being processed");
/// Time after starting an upload to a validator we will start another one to the next validator,
/// even if the upload was not finished yet.
@@ -102,9 +107,9 @@ struct MetricsInner {
}
impl metrics::Metrics for Metrics {
fn try_register(registry: &prometheus::Registry)
-> std::result::Result<Self, prometheus::PrometheusError>
{
fn try_register(
registry: &prometheus::Registry,
) -> std::result::Result<Self, prometheus::PrometheusError> {
let metrics = MetricsInner {
advertisements_made: prometheus::register(
prometheus::Counter::new(
@@ -128,12 +133,10 @@ impl metrics::Metrics for Metrics {
registry,
)?,
process_msg: prometheus::register(
prometheus::Histogram::with_opts(
prometheus::HistogramOpts::new(
"parachain_collator_protocol_collator_process_msg",
"Time spent within `collator_protocol_collator::process_msg`",
)
)?,
prometheus::Histogram::with_opts(prometheus::HistogramOpts::new(
"parachain_collator_protocol_collator_process_msg",
"Time spent within `collator_protocol_collator::process_msg`",
))?,
registry,
)?,
};
@@ -157,8 +160,11 @@ struct ValidatorGroup {
impl ValidatorGroup {
/// Returns `true` if we should advertise our collation to the given peer.
fn should_advertise_to(&self, peer_ids: &HashMap<PeerId, AuthorityDiscoveryId>, peer: &PeerId)
-> bool {
fn should_advertise_to(
&self,
peer_ids: &HashMap<PeerId, AuthorityDiscoveryId>,
peer: &PeerId,
) -> bool {
match peer_ids.get(peer) {
Some(discovery_id) => !self.advertised_to.contains(discovery_id),
None => false,
@@ -166,7 +172,11 @@ impl ValidatorGroup {
}
/// Should be called after we advertised our collation to the given `peer` to keep track of it.
fn advertised_to_peer(&mut self, peer_ids: &HashMap<PeerId, AuthorityDiscoveryId>, peer: &PeerId) {
fn advertised_to_peer(
&mut self,
peer_ids: &HashMap<PeerId, AuthorityDiscoveryId>,
peer: &PeerId,
) {
if let Some(validator_id) = peer_ids.get(peer) {
self.advertised_to.insert(validator_id.clone());
}
@@ -175,10 +185,7 @@ impl ValidatorGroup {
impl From<HashSet<AuthorityDiscoveryId>> for ValidatorGroup {
fn from(discovery_ids: HashSet<AuthorityDiscoveryId>) -> Self {
Self {
discovery_ids,
advertised_to: HashSet::new(),
}
Self { discovery_ids, advertised_to: HashSet::new() }
}
}
@@ -229,7 +236,8 @@ struct WaitingCollationFetches {
waiting_peers: HashSet<PeerId>,
}
type ActiveCollationFetches = FuturesUnordered<Pin<Box<dyn Future<Output = (Hash, PeerId)> + Send + 'static>>>;
type ActiveCollationFetches =
FuturesUnordered<Pin<Box<dyn Future<Output = (Hash, PeerId)> + Send + 'static>>>;
struct State {
/// Our network peer id.
@@ -344,12 +352,12 @@ where
"distribute collation message parent is outside of our view",
);
return Ok(());
return Ok(())
}
// We have already seen collation for this relay parent.
if state.collations.contains_key(&relay_parent) {
return Ok(());
return Ok(())
}
// Determine which core the para collated-on is assigned to.
@@ -365,12 +373,12 @@ where
);
return Ok(())
}
},
};
// Determine the group on that core and the next group on that core.
let (current_validators, next_validators) =
determine_our_validators(ctx, runtime, our_core, num_cores, relay_parent,).await?;
determine_our_validators(ctx, runtime, our_core, num_cores, relay_parent).await?;
if current_validators.validators.is_empty() && next_validators.validators.is_empty() {
tracing::warn!(
@@ -379,7 +387,7 @@ where
"there are no validators assigned to core",
);
return Ok(());
return Ok(())
}
tracing::debug!(
@@ -394,16 +402,19 @@ where
"Accepted collation, connecting to validators."
);
let validator_group: HashSet<_> = current_validators.validators.iter().map(Clone::clone).collect();
let validator_group: HashSet<_> =
current_validators.validators.iter().map(Clone::clone).collect();
// Issue a discovery request for the validators of the current group and the next group:
connect_to_validators(
ctx,
current_validators.validators
current_validators
.validators
.into_iter()
.chain(next_validators.validators.into_iter())
.collect(),
).await;
)
.await;
state.our_validators_groups.insert(relay_parent, validator_group.into());
@@ -411,7 +422,9 @@ where
state.collation_result_senders.insert(receipt.hash(), result_sender);
}
state.collations.insert(relay_parent, Collation { receipt, pov, status: CollationStatus::Created });
state
.collations
.insert(relay_parent, Collation { receipt, pov, status: CollationStatus::Created });
let interested = state.peers_interested_in_leaf(&relay_parent);
// Make sure already connected peers get collations:
@@ -438,7 +451,7 @@ where
for (idx, core) in cores.iter().enumerate() {
if let CoreState::Scheduled(occupied) = core {
if occupied.para_id == para_id {
return Ok(Some(((idx as u32).into(), cores.len())));
return Ok(Some(((idx as u32).into(), cores.len())))
}
}
}
@@ -470,7 +483,8 @@ where
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
{
let session_index = runtime.get_session_index(ctx.sender(), relay_parent).await?;
let info = &runtime.get_session_info_by_index(ctx.sender(), relay_parent, session_index)
let info = &runtime
.get_session_info_by_index(ctx.sender(), relay_parent, session_index)
.await?
.session_info;
tracing::debug!(target: LOG_TARGET, ?session_index, "Received session info");
@@ -478,34 +492,31 @@ where
let rotation_info = get_group_rotation_info(ctx, relay_parent).await?;
let current_group_index = rotation_info.group_for_core(core_index, cores);
let current_validators = groups.get(current_group_index.0 as usize).map(|v| v.as_slice()).unwrap_or_default();
let current_validators = groups
.get(current_group_index.0 as usize)
.map(|v| v.as_slice())
.unwrap_or_default();
let next_group_idx = (current_group_index.0 as usize + 1) % groups.len();
let next_validators = groups.get(next_group_idx).map(|v| v.as_slice()).unwrap_or_default();
let validators = &info.discovery_keys;
let current_validators = current_validators.iter().map(|i| validators[i.0 as usize].clone()).collect();
let next_validators = next_validators.iter().map(|i| validators[i.0 as usize].clone()).collect();
let current_validators =
current_validators.iter().map(|i| validators[i.0 as usize].clone()).collect();
let next_validators =
next_validators.iter().map(|i| validators[i.0 as usize].clone()).collect();
let current_validators = GroupValidators {
group: current_group_index,
validators: current_validators,
};
let next_validators = GroupValidators {
group: GroupIndex(next_group_idx as u32),
validators: next_validators,
};
let current_validators =
GroupValidators { group: current_group_index, validators: current_validators };
let next_validators =
GroupValidators { group: GroupIndex(next_group_idx as u32), validators: next_validators };
Ok((current_validators, next_validators))
}
/// Issue a `Declare` collation message to the given `peer`.
async fn declare<Context>(
ctx: &mut Context,
state: &mut State,
peer: PeerId,
)
async fn declare<Context>(ctx: &mut Context, state: &mut State, peer: PeerId)
where
Context: SubsystemContext<Message = CollatorProtocolMessage>,
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
@@ -519,21 +530,17 @@ where
state.collator_pair.sign(&declare_signature_payload),
);
ctx.send_message(
NetworkBridgeMessage::SendCollationMessage(
vec![peer],
protocol_v1::CollationProtocol::CollatorProtocol(wire_message),
)
).await;
ctx.send_message(NetworkBridgeMessage::SendCollationMessage(
vec![peer],
protocol_v1::CollationProtocol::CollatorProtocol(wire_message),
))
.await;
}
}
/// Issue a connection request to a set of validators and
/// revoke the previous connection request.
async fn connect_to_validators<Context>(
ctx: &mut Context,
validator_ids: Vec<AuthorityDiscoveryId>,
)
async fn connect_to_validators<Context>(ctx: &mut Context, validator_ids: Vec<AuthorityDiscoveryId>)
where
Context: SubsystemContext<Message = CollatorProtocolMessage>,
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
@@ -542,8 +549,11 @@ where
// will reissue a new request on new collation
let (failed, _) = oneshot::channel();
ctx.send_message(NetworkBridgeMessage::ConnectToValidators {
validator_ids, peer_set: PeerSet::Collation, failed,
}).await;
validator_ids,
peer_set: PeerSet::Collation,
failed,
})
.await;
}
/// Advertise collation to the given `peer`.
@@ -555,12 +565,12 @@ async fn advertise_collation<Context>(
state: &mut State,
relay_parent: Hash,
peer: PeerId,
)
where
) where
Context: SubsystemContext<Message = CollatorProtocolMessage>,
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
{
let should_advertise = state.our_validators_groups
let should_advertise = state
.our_validators_groups
.get(&relay_parent)
.map(|g| g.should_advertise_to(&state.peer_ids, &peer))
.unwrap_or(false);
@@ -583,7 +593,7 @@ where
"Not advertising collation as we already advertised it to this validator.",
);
return
}
},
(Some(collation), true) => {
tracing::debug!(
target: LOG_TARGET,
@@ -595,16 +605,13 @@ where
},
}
let wire_message = protocol_v1::CollatorProtocolMessage::AdvertiseCollation(
relay_parent,
);
let wire_message = protocol_v1::CollatorProtocolMessage::AdvertiseCollation(relay_parent);
ctx.send_message(
NetworkBridgeMessage::SendCollationMessage(
vec![peer.clone()],
protocol_v1::CollationProtocol::CollatorProtocol(wire_message),
)
).await;
ctx.send_message(NetworkBridgeMessage::SendCollationMessage(
vec![peer.clone()],
protocol_v1::CollationProtocol::CollatorProtocol(wire_message),
))
.await;
if let Some(validators) = state.our_validators_groups.get_mut(&relay_parent) {
validators.advertised_to_peer(&state.peer_ids, &peer);
@@ -631,10 +638,12 @@ where
match msg {
CollateOn(id) => {
state.collating_on = Some(id);
}
},
DistributeCollation(receipt, pov, result_sender) => {
let _span1 = state.span_per_relay_parent
.get(&receipt.descriptor.relay_parent).map(|s| s.child("distributing-collation"));
let _span1 = state
.span_per_relay_parent
.get(&receipt.descriptor.relay_parent)
.map(|s| s.child("distributing-collation"));
let _span2 = jaeger::Span::new(&pov, "distributing-collation");
match state.collating_on {
Some(id) if receipt.descriptor.para_id != id => {
@@ -646,32 +655,28 @@ where
collating_on = %id,
"DistributeCollation for unexpected para_id",
);
}
},
Some(id) => {
distribute_collation(ctx, runtime, state, id, receipt, pov, result_sender).await?;
}
distribute_collation(ctx, runtime, state, id, receipt, pov, result_sender)
.await?;
},
None => {
tracing::warn!(
target: LOG_TARGET,
para_id = %receipt.descriptor.para_id,
"DistributeCollation message while not collating on any",
);
}
},
}
}
},
ReportCollator(_) => {
tracing::warn!(
target: LOG_TARGET,
"ReportCollator message is not expected on the collator side of the protocol",
);
}
},
NetworkBridgeUpdateV1(event) => {
if let Err(e) = handle_network_msg(
ctx,
runtime,
state,
event,
).await {
if let Err(e) = handle_network_msg(ctx, runtime, state, event).await {
tracing::warn!(
target: LOG_TARGET,
err = ?e,
@@ -680,11 +685,16 @@ where
}
},
CollationFetchingRequest(incoming) => {
let _span = state.span_per_relay_parent.get(&incoming.payload.relay_parent).map(|s| s.child("request-collation"));
let _span = state
.span_per_relay_parent
.get(&incoming.payload.relay_parent)
.map(|s| s.child("request-collation"));
match state.collating_on {
Some(our_para_id) => {
Some(our_para_id) =>
if our_para_id == incoming.payload.para_id {
let (receipt, pov) = if let Some(collation) = state.collations.get_mut(&incoming.payload.relay_parent) {
let (receipt, pov) = if let Some(collation) =
state.collations.get_mut(&incoming.payload.relay_parent)
{
collation.status.advance_to_requested();
(collation.receipt.clone(), collation.pov.clone())
} else {
@@ -694,23 +704,28 @@ where
"received a `RequestCollation` for a relay parent we don't have collation stored.",
);
return Ok(());
return Ok(())
};
state.metrics.on_collation_sent_requested();
let _span = _span.as_ref().map(|s| s.child("sending"));
let waiting = state.waiting_collation_fetches.entry(incoming.payload.relay_parent).or_default();
let waiting = state
.waiting_collation_fetches
.entry(incoming.payload.relay_parent)
.or_default();
if !waiting.waiting_peers.insert(incoming.peer) {
tracing::debug!(
target: LOG_TARGET,
"Dropping incoming request as peer has a request in flight already."
);
ctx.send_message(
NetworkBridgeMessage::ReportPeer(incoming.peer, COST_APPARENT_FLOOD)
).await;
ctx.send_message(NetworkBridgeMessage::ReportPeer(
incoming.peer,
COST_APPARENT_FLOOD,
))
.await;
return Ok(())
}
@@ -727,17 +742,16 @@ where
our_para_id = %our_para_id,
"received a `CollationFetchingRequest` for unexpected para_id",
);
}
}
},
None => {
tracing::warn!(
target: LOG_TARGET,
for_para_id = %incoming.payload.para_id,
"received a `RequestCollation` while not collating on any para",
);
}
},
}
}
},
_ => {},
}
@@ -763,24 +777,24 @@ async fn send_collation(
};
if let Err(_) = request.send_outgoing_response(response) {
tracing::warn!(
target: LOG_TARGET,
"Sending collation response failed",
);
tracing::warn!(target: LOG_TARGET, "Sending collation response failed",);
}
state.active_collation_fetches.push(async move {
let r = rx.timeout(MAX_UNSHARED_UPLOAD_TIME).await;
if r.is_none() {
tracing::debug!(
target: LOG_TARGET,
?relay_parent,
?peer_id,
"Sending collation to validator timed out, carrying on with next validator."
);
state.active_collation_fetches.push(
async move {
let r = rx.timeout(MAX_UNSHARED_UPLOAD_TIME).await;
if r.is_none() {
tracing::debug!(
target: LOG_TARGET,
?relay_parent,
?peer_id,
"Sending collation to validator timed out, carrying on with next validator."
);
}
(relay_parent, peer_id)
}
(relay_parent, peer_id)
}.boxed());
.boxed(),
);
state.metrics.on_collation_sent();
}
@@ -808,10 +822,9 @@ where
);
// If we are declared to, this is another collator, and we should disconnect.
ctx.send_message(
NetworkBridgeMessage::DisconnectPeer(origin, PeerSet::Collation)
).await;
}
ctx.send_message(NetworkBridgeMessage::DisconnectPeer(origin, PeerSet::Collation))
.await;
},
AdvertiseCollation(_) => {
tracing::trace!(
target: LOG_TARGET,
@@ -819,15 +832,16 @@ where
"AdvertiseCollation message is not expected on the collator side of the protocol",
);
ctx.send_message(
NetworkBridgeMessage::ReportPeer(origin.clone(), COST_UNEXPECTED_MESSAGE)
).await;
ctx.send_message(NetworkBridgeMessage::ReportPeer(
origin.clone(),
COST_UNEXPECTED_MESSAGE,
))
.await;
// If we are advertised to, this is another collator, and we should disconnect.
ctx.send_message(
NetworkBridgeMessage::DisconnectPeer(origin, PeerSet::Collation)
).await;
}
ctx.send_message(NetworkBridgeMessage::DisconnectPeer(origin, PeerSet::Collation))
.await;
},
CollationSeconded(relay_parent, statement) => {
if !matches!(statement.unchecked_payload(), Statement::Seconded(_)) {
tracing::warn!(
@@ -837,12 +851,13 @@ where
"Collation seconded message received with none-seconded statement.",
);
} else {
let statement = runtime.check_signature(ctx.sender(), relay_parent, statement)
let statement = runtime
.check_signature(ctx.sender(), relay_parent, statement)
.await?
.map_err(NonFatal::InvalidStatementSignature)?;
let removed = state.collation_result_senders
.remove(&statement.payload().candidate_hash());
let removed =
state.collation_result_senders.remove(&statement.payload().candidate_hash());
if let Some(sender) = removed {
tracing::trace!(
@@ -854,7 +869,7 @@ where
let _ = sender.send(statement);
}
}
}
},
}
Ok(())
@@ -866,8 +881,7 @@ async fn handle_peer_view_change<Context>(
state: &mut State,
peer_id: PeerId,
view: View,
)
where
) where
Context: SubsystemContext<Message = CollatorProtocolMessage>,
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
{
@@ -899,12 +913,7 @@ where
PeerConnected(peer_id, observed_role, maybe_authority) => {
// If it is possible that a disconnected validator would attempt a reconnect
// it should be handled here.
tracing::trace!(
target: LOG_TARGET,
?peer_id,
?observed_role,
"Peer connected",
);
tracing::trace!(target: LOG_TARGET, ?peer_id, ?observed_role, "Peer connected",);
if let Some(authority) = maybe_authority {
tracing::trace!(
target: LOG_TARGET,
@@ -916,49 +925,33 @@ where
declare(ctx, state, peer_id).await;
}
}
},
PeerViewChange(peer_id, view) => {
tracing::trace!(
target: LOG_TARGET,
?peer_id,
?view,
"Peer view change",
);
tracing::trace!(target: LOG_TARGET, ?peer_id, ?view, "Peer view change",);
handle_peer_view_change(ctx, state, peer_id, view).await;
}
},
PeerDisconnected(peer_id) => {
tracing::trace!(
target: LOG_TARGET,
?peer_id,
"Peer disconnected",
);
tracing::trace!(target: LOG_TARGET, ?peer_id, "Peer disconnected",);
state.peer_views.remove(&peer_id);
state.peer_ids.remove(&peer_id);
}
},
OurViewChange(view) => {
tracing::trace!(
target: LOG_TARGET,
?view,
"Own view change",
);
tracing::trace!(target: LOG_TARGET, ?view, "Own view change",);
handle_our_view_change(state, view).await?;
}
},
PeerMessage(remote, msg) => {
handle_incoming_peer_message(ctx, runtime, state, remote, msg).await?;
}
},
NewGossipTopology(..) => {
// impossibru!
}
},
}
Ok(())
}
/// Handles our view changes.
async fn handle_our_view_change(
state: &mut State,
view: OurView,
) -> Result<()> {
async fn handle_our_view_change(state: &mut State, view: OurView) -> Result<()> {
for removed in state.view.difference(&view) {
tracing::debug!(target: LOG_TARGET, relay_parent = ?removed, "Removing relay parent because our view changed.");
@@ -983,7 +976,7 @@ async fn handle_our_view_change(
candidate_hash = ?collation.receipt.hash(),
pov_hash = ?collation.pov.hash(),
"Collation was requested.",
)
),
}
}
state.our_validators_groups.remove(removed);
@@ -1005,7 +998,7 @@ pub(crate) async fn run<Context>(
) -> Result<()>
where
Context: SubsystemContext<Message = CollatorProtocolMessage>,
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
{
use OverseerSignal::*;
@@ -26,21 +26,17 @@ use sp_core::{crypto::Pair, Decode};
use sp_keyring::Sr25519Keyring;
use sp_runtime::traits::AppVerify;
use polkadot_node_network_protocol::{
our_view,
view,
request_response::request::IncomingRequest,
};
use polkadot_node_network_protocol::{our_view, request_response::request::IncomingRequest, view};
use polkadot_node_primitives::BlockData;
use polkadot_node_subsystem_util::TimeoutExt;
use polkadot_primitives::v1::{
AuthorityDiscoveryId, CandidateDescriptor, CollatorPair, GroupRotationInfo, ScheduledCore, SessionIndex,
SessionInfo, ValidatorId, ValidatorIndex,
AuthorityDiscoveryId, CandidateDescriptor, CollatorPair, GroupRotationInfo, ScheduledCore,
SessionIndex, SessionInfo, ValidatorId, ValidatorIndex,
};
use polkadot_node_primitives::BlockData;
use polkadot_subsystem::{
jaeger,
messages::{AllMessages, RuntimeApiMessage, RuntimeApiRequest},
ActiveLeavesUpdate, ActivatedLeaf, LeafStatus,
ActivatedLeaf, ActiveLeavesUpdate, LeafStatus,
};
use polkadot_subsystem_testhelpers as test_helpers;
@@ -103,22 +99,17 @@ impl Default for TestState {
let validator_public = validator_pubkeys(&validators);
let discovery_keys = validator_authority_id(&validators);
let validator_peer_id = std::iter::repeat_with(|| PeerId::random())
.take(discovery_keys.len())
.collect();
let validator_peer_id =
std::iter::repeat_with(|| PeerId::random()).take(discovery_keys.len()).collect();
let validator_groups = vec![vec![2, 0, 4], vec![3, 2, 4]]
.into_iter().map(|g| g.into_iter().map(ValidatorIndex).collect()).collect();
let group_rotation_info = GroupRotationInfo {
session_start_block: 0,
group_rotation_frequency: 100,
now: 1,
};
.into_iter()
.map(|g| g.into_iter().map(ValidatorIndex).collect())
.collect();
let group_rotation_info =
GroupRotationInfo { session_start_block: 0, group_rotation_frequency: 100, now: 1 };
let availability_core = CoreState::Scheduled(ScheduledCore {
para_id,
collator: None,
});
let availability_core = CoreState::Scheduled(ScheduledCore { para_id, collator: None });
let relay_parent = Hash::random();
@@ -155,7 +146,10 @@ impl TestState {
}
fn current_group_validator_peer_ids(&self) -> Vec<PeerId> {
self.current_group_validator_indices().iter().map(|i| self.validator_peer_id[i.0 as usize].clone()).collect()
self.current_group_validator_indices()
.iter()
.map(|i| self.validator_peer_id[i.0 as usize].clone())
.collect()
}
fn current_group_validator_authority_ids(&self) -> Vec<AuthorityDiscoveryId> {
@@ -169,7 +163,11 @@ impl TestState {
///
/// If `merge_views == true` it means the subsystem will be informed that we are working on the old `relay_parent`
/// and the new one.
async fn advance_to_new_round(&mut self, virtual_overseer: &mut VirtualOverseer, merge_views: bool) {
async fn advance_to_new_round(
&mut self,
virtual_overseer: &mut VirtualOverseer,
merge_views: bool,
) {
let old_relay_parent = self.relay_parent;
while self.relay_parent == old_relay_parent {
@@ -184,8 +182,11 @@ impl TestState {
overseer_send(
virtual_overseer,
CollatorProtocolMessage::NetworkBridgeUpdateV1(NetworkBridgeEvent::OurViewChange(our_view)),
).await;
CollatorProtocolMessage::NetworkBridgeUpdateV1(NetworkBridgeEvent::OurViewChange(
our_view,
)),
)
.await;
}
}
@@ -202,14 +203,8 @@ fn test_harness<T: Future<Output = VirtualOverseer>>(
) {
let _ = env_logger::builder()
.is_test(true)
.filter(
Some("polkadot_collator_protocol"),
log::LevelFilter::Trace,
)
.filter(
Some(LOG_TARGET),
log::LevelFilter::Trace,
)
.filter(Some("polkadot_collator_protocol"), log::LevelFilter::Trace)
.filter(Some(LOG_TARGET), log::LevelFilter::Trace)
.try_init();
let pool = sp_core::testing::TaskExecutor::new();
@@ -223,18 +218,20 @@ fn test_harness<T: Future<Output = VirtualOverseer>>(
futures::pin_mut!(test_fut);
futures::pin_mut!(subsystem);
executor::block_on(future::join(async move {
let mut overseer = test_fut.await;
overseer_signal(&mut overseer, OverseerSignal::Conclude).await;
}, subsystem)).1.unwrap();
executor::block_on(future::join(
async move {
let mut overseer = test_fut.await;
overseer_signal(&mut overseer, OverseerSignal::Conclude).await;
},
subsystem,
))
.1
.unwrap();
}
const TIMEOUT: Duration = Duration::from_millis(100);
async fn overseer_send(
overseer: &mut VirtualOverseer,
msg: CollatorProtocolMessage,
) {
async fn overseer_send(overseer: &mut VirtualOverseer, msg: CollatorProtocolMessage) {
tracing::trace!(?msg, "sending message");
overseer
.send(FromOverseer::Communication { msg })
@@ -243,9 +240,7 @@ async fn overseer_send(
.expect(&format!("{:?} is more than enough for sending messages.", TIMEOUT));
}
async fn overseer_recv(
overseer: &mut VirtualOverseer,
) -> AllMessages {
async fn overseer_recv(overseer: &mut VirtualOverseer) -> AllMessages {
let msg = overseer_recv_with_timeout(overseer, TIMEOUT)
.await
.expect(&format!("{:?} is more than enough to receive messages", TIMEOUT));
@@ -260,16 +255,10 @@ async fn overseer_recv_with_timeout(
timeout: Duration,
) -> Option<AllMessages> {
tracing::trace!("waiting for message...");
overseer
.recv()
.timeout(timeout)
.await
overseer.recv().timeout(timeout).await
}
async fn overseer_signal(
overseer: &mut VirtualOverseer,
signal: OverseerSignal,
) {
async fn overseer_signal(overseer: &mut VirtualOverseer, signal: OverseerSignal) {
overseer
.send(FromOverseer::Signal(signal))
.timeout(TIMEOUT)
@@ -279,10 +268,7 @@ async fn overseer_signal(
// Setup the system by sending the `CollateOn`, `ActiveLeaves` and `OurViewChange` messages.
async fn setup_system(virtual_overseer: &mut VirtualOverseer, test_state: &TestState) {
overseer_send(
virtual_overseer,
CollatorProtocolMessage::CollateOn(test_state.para_id),
).await;
overseer_send(virtual_overseer, CollatorProtocolMessage::CollateOn(test_state.para_id)).await;
overseer_signal(
virtual_overseer,
@@ -292,14 +278,16 @@ async fn setup_system(virtual_overseer: &mut VirtualOverseer, test_state: &TestS
status: LeafStatus::Fresh,
span: Arc::new(jaeger::Span::Disabled),
})),
).await;
)
.await;
overseer_send(
virtual_overseer,
CollatorProtocolMessage::NetworkBridgeUpdateV1(
NetworkBridgeEvent::OurViewChange(our_view![test_state.relay_parent]),
),
).await;
CollatorProtocolMessage::NetworkBridgeUpdateV1(NetworkBridgeEvent::OurViewChange(
our_view![test_state.relay_parent],
)),
)
.await;
}
/// Result of [`distribute_collation`]
@@ -316,9 +304,7 @@ async fn distribute_collation(
should_connect: bool,
) -> DistributeCollation {
// Now we want to distribute a PoVBlock
let pov_block = PoV {
block_data: BlockData(vec![42, 43, 44]),
};
let pov_block = PoV { block_data: BlockData(vec![42, 43, 44]) };
let pov_hash = pov_block.hash();
@@ -327,12 +313,14 @@ async fn distribute_collation(
relay_parent: test_state.relay_parent,
pov_hash,
..Default::default()
}.build();
}
.build();
overseer_send(
virtual_overseer,
CollatorProtocolMessage::DistributeCollation(candidate.clone(), pov_block.clone(), None),
).await;
)
.await;
// obtain the availability cores.
assert_matches!(
@@ -355,7 +343,7 @@ async fn distribute_collation(
)) => {
assert_eq!(relay_parent, test_state.relay_parent);
tx.send(Ok(test_state.current_session_index())).unwrap();
}
},
AllMessages::RuntimeApi(RuntimeApiMessage::Request(
relay_parent,
@@ -365,22 +353,22 @@ async fn distribute_collation(
assert_eq!(index, test_state.current_session_index());
tx.send(Ok(Some(test_state.session_info.clone()))).unwrap();
}
},
AllMessages::RuntimeApi(RuntimeApiMessage::Request(
relay_parent,
RuntimeApiRequest::ValidatorGroups(tx)
RuntimeApiRequest::ValidatorGroups(tx),
)) => {
assert_eq!(relay_parent, test_state.relay_parent);
tx.send(Ok((
test_state.session_info.validator_groups.clone(),
test_state.group_rotation_info.clone(),
))).unwrap();
)))
.unwrap();
// This call is mandatory - we are done:
break;
}
other =>
panic!("Unexpected message received: {:?}", other),
break
},
other => panic!("Unexpected message received: {:?}", other),
}
}
@@ -395,35 +383,33 @@ async fn distribute_collation(
);
}
DistributeCollation {
candidate,
pov_block,
}
DistributeCollation { candidate, pov_block }
}
/// Connect a peer
async fn connect_peer(
virtual_overseer: &mut VirtualOverseer,
peer: PeerId,
authority_id: Option<AuthorityDiscoveryId>
authority_id: Option<AuthorityDiscoveryId>,
) {
overseer_send(
virtual_overseer,
CollatorProtocolMessage::NetworkBridgeUpdateV1(
NetworkBridgeEvent::PeerConnected(
peer.clone(),
polkadot_node_network_protocol::ObservedRole::Authority,
authority_id,
),
),
).await;
CollatorProtocolMessage::NetworkBridgeUpdateV1(NetworkBridgeEvent::PeerConnected(
peer.clone(),
polkadot_node_network_protocol::ObservedRole::Authority,
authority_id,
)),
)
.await;
overseer_send(
virtual_overseer,
CollatorProtocolMessage::NetworkBridgeUpdateV1(
NetworkBridgeEvent::PeerViewChange(peer, view![]),
),
).await;
CollatorProtocolMessage::NetworkBridgeUpdateV1(NetworkBridgeEvent::PeerViewChange(
peer,
view![],
)),
)
.await;
}
/// Disconnect a peer
@@ -431,7 +417,8 @@ async fn disconnect_peer(virtual_overseer: &mut VirtualOverseer, peer: PeerId) {
overseer_send(
virtual_overseer,
CollatorProtocolMessage::NetworkBridgeUpdateV1(NetworkBridgeEvent::PeerDisconnected(peer)),
).await;
)
.await;
}
/// Check that the next received message is a `Declare` message.
@@ -496,13 +483,19 @@ async fn expect_advertise_collation_msg(
}
/// Send a message that the given peer's view changed.
async fn send_peer_view_change(virtual_overseer: &mut VirtualOverseer, peer: &PeerId, hashes: Vec<Hash>) {
async fn send_peer_view_change(
virtual_overseer: &mut VirtualOverseer,
peer: &PeerId,
hashes: Vec<Hash>,
) {
overseer_send(
virtual_overseer,
CollatorProtocolMessage::NetworkBridgeUpdateV1(
NetworkBridgeEvent::PeerViewChange(peer.clone(), View::new(hashes, 0)),
),
).await;
CollatorProtocolMessage::NetworkBridgeUpdateV1(NetworkBridgeEvent::PeerViewChange(
peer.clone(),
View::new(hashes, 0),
)),
)
.await;
}
#[test]
@@ -519,7 +512,8 @@ fn advertise_and_send_collation() {
let DistributeCollation { candidate, pov_block } =
distribute_collation(&mut virtual_overseer, &test_state, true).await;
for (val, peer) in test_state.current_group_validator_authority_ids()
for (val, peer) in test_state
.current_group_validator_authority_ids()
.into_iter()
.zip(test_state.current_group_validator_peer_ids())
{
@@ -546,33 +540,31 @@ fn advertise_and_send_collation() {
let (tx, rx) = oneshot::channel();
overseer_send(
&mut virtual_overseer,
CollatorProtocolMessage::CollationFetchingRequest(
IncomingRequest::new(
CollatorProtocolMessage::CollationFetchingRequest(IncomingRequest::new(
peer,
CollationFetchingRequest {
relay_parent: test_state.relay_parent,
para_id: test_state.para_id,
},
tx,
)),
)
.await;
// Second request by same validator should get dropped and peer reported:
{
let (tx, rx) = oneshot::channel();
overseer_send(
&mut virtual_overseer,
CollatorProtocolMessage::CollationFetchingRequest(IncomingRequest::new(
peer,
CollationFetchingRequest {
relay_parent: test_state.relay_parent,
para_id: test_state.para_id,
},
tx,
)
)),
)
).await;
// Second request by same validator should get dropped and peer reported:
{
let (tx, rx) = oneshot::channel();
overseer_send(
&mut virtual_overseer,
CollatorProtocolMessage::CollationFetchingRequest(
IncomingRequest::new(
peer,
CollationFetchingRequest {
relay_parent: test_state.relay_parent,
para_id: test_state.para_id,
},
tx,
)
)
).await;
.await;
assert_matches!(
overseer_recv(&mut virtual_overseer).await,
AllMessages::NetworkBridge(NetworkBridgeMessage::ReportPeer(bad_peer, _)) => {
@@ -609,17 +601,16 @@ fn advertise_and_send_collation() {
let (tx, rx) = oneshot::channel();
overseer_send(
&mut virtual_overseer,
CollatorProtocolMessage::CollationFetchingRequest(
IncomingRequest::new(
peer,
CollationFetchingRequest {
relay_parent: old_relay_parent,
para_id: test_state.para_id,
},
tx,
)
)
).await;
CollatorProtocolMessage::CollationFetchingRequest(IncomingRequest::new(
peer,
CollationFetchingRequest {
relay_parent: old_relay_parent,
para_id: test_state.para_id,
},
tx,
)),
)
.await;
// Re-requesting collation should fail:
rx.await.unwrap_err();
@@ -630,13 +621,12 @@ fn advertise_and_send_collation() {
// Send info about peer's view.
overseer_send(
&mut virtual_overseer,
CollatorProtocolMessage::NetworkBridgeUpdateV1(
NetworkBridgeEvent::PeerViewChange(
peer.clone(),
view![test_state.relay_parent],
)
)
).await;
CollatorProtocolMessage::NetworkBridgeUpdateV1(NetworkBridgeEvent::PeerViewChange(
peer.clone(),
view![test_state.relay_parent],
)),
)
.await;
expect_advertise_collation_msg(&mut virtual_overseer, &peer, test_state.relay_parent).await;
virtual_overseer
@@ -646,29 +636,26 @@ fn advertise_and_send_collation() {
#[test]
fn send_only_one_collation_per_relay_parent_at_a_time() {
test_validator_send_sequence(|mut second_response_receiver, feedback_first_tx| async move {
Delay::new(Duration::from_millis(100)).await;
assert!(
second_response_receiver.try_recv().unwrap().is_none(),
"We should not have send the collation yet to the second validator",
);
Delay::new(Duration::from_millis(100)).await;
assert!(
second_response_receiver.try_recv().unwrap().is_none(),
"We should not have send the collation yet to the second validator",
);
// Signal that the collation fetch is finished
feedback_first_tx.send(()).expect("Sending collation fetch finished");
second_response_receiver
}
);
// Signal that the collation fetch is finished
feedback_first_tx.send(()).expect("Sending collation fetch finished");
second_response_receiver
});
}
#[test]
fn send_next_collation_after_max_unshared_upload_time() {
test_validator_send_sequence(|second_response_receiver, _| async move {
Delay::new(MAX_UNSHARED_UPLOAD_TIME + Duration::from_millis(50)).await;
second_response_receiver
}
);
Delay::new(MAX_UNSHARED_UPLOAD_TIME + Duration::from_millis(50)).await;
second_response_receiver
});
}
#[test]
fn collators_declare_to_connected_peers() {
let test_state = TestState::default();
@@ -721,7 +708,8 @@ fn collations_are_only_advertised_to_validators_with_correct_view() {
distribute_collation(&mut virtual_overseer, &test_state, true).await;
expect_advertise_collation_msg(&mut virtual_overseer, &peer2, test_state.relay_parent).await;
expect_advertise_collation_msg(&mut virtual_overseer, &peer2, test_state.relay_parent)
.await;
// The other validator announces that it changed its view.
send_peer_view_change(&mut virtual_overseer, &peer, vec![test_state.relay_parent]).await;
@@ -772,7 +760,8 @@ fn collate_on_two_different_relay_chain_blocks() {
send_peer_view_change(&mut virtual_overseer, &peer2, vec![test_state.relay_parent]).await;
expect_advertise_collation_msg(&mut virtual_overseer, &peer2, test_state.relay_parent).await;
expect_advertise_collation_msg(&mut virtual_overseer, &peer2, test_state.relay_parent)
.await;
virtual_overseer
})
}
@@ -833,17 +822,16 @@ fn collators_reject_declare_messages() {
overseer_send(
&mut virtual_overseer,
CollatorProtocolMessage::NetworkBridgeUpdateV1(
NetworkBridgeEvent::PeerMessage(
peer.clone(),
protocol_v1::CollatorProtocolMessage::Declare(
collator_pair2.public(),
ParaId::from(5),
collator_pair2.sign(b"garbage"),
),
)
)
).await;
CollatorProtocolMessage::NetworkBridgeUpdateV1(NetworkBridgeEvent::PeerMessage(
peer.clone(),
protocol_v1::CollatorProtocolMessage::Declare(
collator_pair2.public(),
ParaId::from(5),
collator_pair2.sign(b"garbage"),
),
)),
)
.await;
assert_matches!(
overseer_recv(&mut virtual_overseer).await,
@@ -868,7 +856,7 @@ fn collators_reject_declare_messages() {
fn test_validator_send_sequence<T, F>(handle_first_response: T)
where
T: FnOnce(oneshot::Receiver<sc_network::config::OutgoingResponse>, oneshot::Sender<()>) -> F,
F: Future<Output=oneshot::Receiver<sc_network::config::OutgoingResponse>>
F: Future<Output = oneshot::Receiver<sc_network::config::OutgoingResponse>>,
{
let test_state = TestState::default();
let local_peer_id = test_state.local_peer_id.clone();
@@ -882,7 +870,8 @@ where
let DistributeCollation { candidate, pov_block } =
distribute_collation(&mut virtual_overseer, &test_state, true).await;
for (val, peer) in test_state.current_group_validator_authority_ids()
for (val, peer) in test_state
.current_group_validator_authority_ids()
.into_iter()
.zip(test_state.current_group_validator_peer_ids())
{
@@ -900,29 +889,40 @@ where
let validator_1 = test_state.current_group_validator_peer_ids()[1].clone();
// Send info about peer's view.
send_peer_view_change(&mut virtual_overseer, &validator_0, vec![test_state.relay_parent]).await;
send_peer_view_change(&mut virtual_overseer, &validator_1, vec![test_state.relay_parent]).await;
send_peer_view_change(&mut virtual_overseer, &validator_0, vec![test_state.relay_parent])
.await;
send_peer_view_change(&mut virtual_overseer, &validator_1, vec![test_state.relay_parent])
.await;
// The peer is interested in a leaf that we have a collation for;
// advertise it.
expect_advertise_collation_msg(&mut virtual_overseer, &validator_0, test_state.relay_parent).await;
expect_advertise_collation_msg(&mut virtual_overseer, &validator_1, test_state.relay_parent).await;
expect_advertise_collation_msg(
&mut virtual_overseer,
&validator_0,
test_state.relay_parent,
)
.await;
expect_advertise_collation_msg(
&mut virtual_overseer,
&validator_1,
test_state.relay_parent,
)
.await;
// Request a collation.
let (tx, rx) = oneshot::channel();
overseer_send(
&mut virtual_overseer,
CollatorProtocolMessage::CollationFetchingRequest(
IncomingRequest::new(
validator_0,
CollationFetchingRequest {
relay_parent: test_state.relay_parent,
para_id: test_state.para_id,
},
tx,
)
)
).await;
CollatorProtocolMessage::CollationFetchingRequest(IncomingRequest::new(
validator_0,
CollationFetchingRequest {
relay_parent: test_state.relay_parent,
para_id: test_state.para_id,
},
tx,
)),
)
.await;
// Keep the feedback channel alive because we need to use it to inform about the finished transfer.
let feedback_tx = assert_matches!(
@@ -945,17 +945,16 @@ where
let (tx, rx) = oneshot::channel();
overseer_send(
&mut virtual_overseer,
CollatorProtocolMessage::CollationFetchingRequest(
IncomingRequest::new(
validator_1,
CollationFetchingRequest {
relay_parent: test_state.relay_parent,
para_id: test_state.para_id,
},
tx,
)
)
).await;
CollatorProtocolMessage::CollationFetchingRequest(IncomingRequest::new(
validator_1,
CollationFetchingRequest {
relay_parent: test_state.relay_parent,
para_id: test_state.para_id,
},
tx,
)),
)
.await;
let rx = handle_first_response(rx, feedback_tx).await;
@@ -21,7 +21,7 @@ use polkadot_node_primitives::UncheckedSignedFullStatement;
use polkadot_subsystem::errors::SubsystemError;
use thiserror::Error;
use polkadot_node_subsystem_util::{Fault, runtime, unwrap_non_fatal};
use polkadot_node_subsystem_util::{runtime, unwrap_non_fatal, Fault};
use crate::LOG_TARGET;
@@ -82,9 +82,7 @@ pub enum NonFatal {
///
/// We basically always want to try and continue on error. This utility function is meant to
/// consume top-level errors by simply logging them.
pub fn log_error(result: Result<()>, ctx: &'static str)
-> FatalResult<()>
{
pub fn log_error(result: Result<()>, ctx: &'static str) -> FatalResult<()> {
if let Some(error) = unwrap_non_fatal(result.map_err(|e| e.0))? {
tracing::warn!(target: LOG_TARGET, error = ?error, ctx)
}
@@ -18,7 +18,7 @@
//! This subsystem implements both sides of the collator protocol.
#![deny(missing_docs, unused_crate_dependencies)]
#![recursion_limit="256"]
#![recursion_limit = "256"]
use std::time::Duration;
@@ -30,14 +30,9 @@ use polkadot_node_network_protocol::{PeerId, UnifiedReputationChange as Rep};
use polkadot_primitives::v1::CollatorPair;
use polkadot_subsystem::{
SpawnedSubsystem,
SubsystemContext,
SubsystemSender,
overseer,
messages::{
CollatorProtocolMessage, NetworkBridgeMessage,
},
errors::SubsystemError,
messages::{CollatorProtocolMessage, NetworkBridgeMessage},
overseer, SpawnedSubsystem, SubsystemContext, SubsystemSender,
};
mod error;
@@ -92,29 +87,19 @@ impl CollatorProtocolSubsystem {
/// If `id` is `None` this is a validator side of the protocol.
/// Caller must provide a registry for prometheus metrics.
pub fn new(protocol_side: ProtocolSide) -> Self {
Self {
protocol_side,
}
Self { protocol_side }
}
async fn run<Context>(self, ctx: Context) -> Result<()>
where
Context: overseer::SubsystemContext<Message=CollatorProtocolMessage>,
Context: SubsystemContext<Message=CollatorProtocolMessage>,
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
Context: SubsystemContext<Message = CollatorProtocolMessage>,
{
match self.protocol_side {
ProtocolSide::Validator { keystore, eviction_policy, metrics } => validator_side::run(
ctx,
keystore,
eviction_policy,
metrics,
).await,
ProtocolSide::Collator(local_peer_id, collator_pair, metrics) => collator_side::run(
ctx,
local_peer_id,
collator_pair,
metrics,
).await,
ProtocolSide::Validator { keystore, eviction_policy, metrics } =>
validator_side::run(ctx, keystore, eviction_policy, metrics).await,
ProtocolSide::Collator(local_peer_id, collator_pair, metrics) =>
collator_side::run(ctx, local_peer_id, collator_pair, metrics).await,
}
}
}
@@ -131,10 +116,7 @@ where
.map_err(|e| SubsystemError::with_origin("collator-protocol", e))
.boxed();
SpawnedSubsystem {
name: "collator-protocol-subsystem",
future,
}
SpawnedSubsystem { name: "collator-protocol-subsystem", future }
}
}
@@ -150,7 +132,5 @@ where
"reputation change for peer",
);
ctx.send_message(
NetworkBridgeMessage::ReportPeer(peer, rep),
).await;
ctx.send_message(NetworkBridgeMessage::ReportPeer(peer, rep)).await;
}
@@ -14,39 +14,44 @@
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
use std::{collections::{HashMap, HashSet}, sync::Arc, task::Poll};
use std::collections::hash_map::Entry;
use std::time::{Duration, Instant};
use always_assert::never;
use futures::{
channel::oneshot, future::{BoxFuture, Fuse, FusedFuture}, FutureExt, StreamExt,
stream::FuturesUnordered, select,
channel::oneshot,
future::{BoxFuture, Fuse, FusedFuture},
select,
stream::FuturesUnordered,
FutureExt, StreamExt,
};
use futures_timer::Delay;
use std::{
collections::{hash_map::Entry, HashMap, HashSet},
sync::Arc,
task::Poll,
time::{Duration, Instant},
};
use sp_keystore::SyncCryptoStorePtr;
use polkadot_node_network_protocol::{
request_response as req_res, v1 as protocol_v1,
peer_set::PeerSet,
request_response as req_res,
request_response::{
request::{Recipient, RequestError},
v1::{CollationFetchingRequest, CollationFetchingResponse},
OutgoingRequest, Requests,
},
OurView, PeerId, UnifiedReputationChange as Rep, View,
v1 as protocol_v1, OurView, PeerId, UnifiedReputationChange as Rep, View,
};
use polkadot_node_primitives::{SignedFullStatement, PoV};
use polkadot_node_primitives::{PoV, SignedFullStatement};
use polkadot_node_subsystem_util::metrics::{self, prometheus};
use polkadot_primitives::v1::{CandidateReceipt, CollatorId, Hash, Id as ParaId};
use polkadot_subsystem::{
overseer,
jaeger,
messages::{
CollatorProtocolMessage, IfDisconnected,
NetworkBridgeEvent, NetworkBridgeMessage, CandidateBackingMessage,
CandidateBackingMessage, CollatorProtocolMessage, IfDisconnected, NetworkBridgeEvent,
NetworkBridgeMessage,
},
FromOverseer, OverseerSignal, PerLeafSpan, SubsystemContext, SubsystemSender,
overseer, FromOverseer, OverseerSignal, PerLeafSpan, SubsystemContext, SubsystemSender,
};
use super::{modify_reputation, Result, LOG_TARGET};
@@ -64,7 +69,8 @@ const COST_INVALID_SIGNATURE: Rep = Rep::Malicious("Invalid network message sign
const COST_REPORT_BAD: Rep = Rep::Malicious("A collator was reported by another subsystem");
const COST_WRONG_PARA: Rep = Rep::Malicious("A collator provided a collation for the wrong para");
const COST_UNNEEDED_COLLATOR: Rep = Rep::CostMinor("An unneeded collator connected");
const BENEFIT_NOTIFY_GOOD: Rep = Rep::BenefitMinor("A collator was noted good by another subsystem");
const BENEFIT_NOTIFY_GOOD: Rep =
Rep::BenefitMinor("A collator was noted good by another subsystem");
/// Time after starting a collation download from a collator we will start another one from the
/// next collator even if the upload was not finished yet.
@@ -105,13 +111,19 @@ impl Metrics {
}
/// Provide a timer for `handle_collation_request_result` which observes on drop.
fn time_handle_collation_request_result(&self) -> Option<metrics::prometheus::prometheus::HistogramTimer> {
self.0.as_ref().map(|metrics| metrics.handle_collation_request_result.start_timer())
fn time_handle_collation_request_result(
&self,
) -> Option<metrics::prometheus::prometheus::HistogramTimer> {
self.0
.as_ref()
.map(|metrics| metrics.handle_collation_request_result.start_timer())
}
/// Note the current number of collator peers.
fn note_collator_peer_count(&self, collator_peers: usize) {
self.0.as_ref().map(|metrics| metrics.collator_peer_count.set(collator_peers as u64));
self.0
.as_ref()
.map(|metrics| metrics.collator_peer_count.set(collator_peers as u64));
}
}
@@ -124,9 +136,9 @@ struct MetricsInner {
}
impl metrics::Metrics for Metrics {
fn try_register(registry: &prometheus::Registry)
-> std::result::Result<Self, prometheus::PrometheusError>
{
fn try_register(
registry: &prometheus::Registry,
) -> std::result::Result<Self, prometheus::PrometheusError> {
let metrics = MetricsInner {
collation_requests: prometheus::register(
prometheus::CounterVec::new(
@@ -210,10 +222,7 @@ struct PeerData {
impl PeerData {
fn new(view: View) -> Self {
PeerData {
view,
state: PeerState::Connected(Instant::now()),
}
PeerData { view, state: PeerState::Connected(Instant::now()) }
}
/// Update the view, clearing all advertisements that are no longer in the
@@ -241,20 +250,17 @@ impl PeerData {
&mut self,
on_relay_parent: Hash,
our_view: &View,
)
-> std::result::Result<(CollatorId, ParaId), AdvertisementError>
{
) -> std::result::Result<(CollatorId, ParaId), AdvertisementError> {
match self.state {
PeerState::Connected(_) => Err(AdvertisementError::UndeclaredCollator),
_ if !our_view.contains(&on_relay_parent) => Err(AdvertisementError::OutOfOurView),
PeerState::Collating(ref mut state) => {
PeerState::Collating(ref mut state) =>
if state.advertisements.insert(on_relay_parent) {
state.last_active = Instant::now();
Ok((state.collator_id.clone(), state.para_id.clone()))
} else {
Err(AdvertisementError::Duplicate)
}
}
},
}
}
@@ -305,7 +311,8 @@ impl PeerData {
fn is_inactive(&self, policy: &crate::CollatorEvictionPolicy) -> bool {
match self.state {
PeerState::Connected(connected_at) => connected_at.elapsed() >= policy.undeclared,
PeerState::Collating(ref state) => state.last_active.elapsed() >= policy.inactive_collator,
PeerState::Collating(ref state) =>
state.last_active.elapsed() >= policy.inactive_collator,
}
}
}
@@ -325,7 +332,7 @@ struct GroupAssignments {
struct ActiveParas {
relay_parent_assignments: HashMap<Hash, GroupAssignments>,
current_assignments: HashMap<ParaId, usize>,
next_assignments: HashMap<ParaId, usize>
next_assignments: HashMap<ParaId, usize>,
}
impl ActiveParas {
@@ -350,7 +357,6 @@ impl ActiveParas {
.map(|x| x.ok())
.flatten();
let mc = polkadot_node_subsystem_util::request_availability_cores(relay_parent, sender)
.await
.await
@@ -368,38 +374,32 @@ impl ActiveParas {
);
continue
}
},
};
let (para_now, para_next) = match polkadot_node_subsystem_util
::signing_key_and_index(&validators, keystore)
.await
.and_then(|(_, index)| polkadot_node_subsystem_util::find_validator_group(
&groups,
index,
))
{
Some(group) => {
let next_rotation_info = rotation_info.bump_rotation();
let (para_now, para_next) =
match polkadot_node_subsystem_util::signing_key_and_index(&validators, keystore)
.await
.and_then(|(_, index)| {
polkadot_node_subsystem_util::find_validator_group(&groups, index)
}) {
Some(group) => {
let next_rotation_info = rotation_info.bump_rotation();
let core_now = rotation_info.core_for_group(group, cores.len());
let core_next = next_rotation_info.core_for_group(group, cores.len());
let core_now = rotation_info.core_for_group(group, cores.len());
let core_next = next_rotation_info.core_for_group(group, cores.len());
(
cores.get(core_now.0 as usize).and_then(|c| c.para_id()),
cores.get(core_next.0 as usize).and_then(|c| c.para_id()),
)
}
None => {
tracing::trace!(
target: LOG_TARGET,
?relay_parent,
"Not a validator",
);
(
cores.get(core_now.0 as usize).and_then(|c| c.para_id()),
cores.get(core_next.0 as usize).and_then(|c| c.para_id()),
)
},
None => {
tracing::trace!(target: LOG_TARGET, ?relay_parent, "Not a validator",);
continue
}
};
continue
},
};
// This code won't work well, if at all for parathreads. For parathreads we'll
// have to be aware of which core the parathread claim is going to be multiplexed
@@ -426,17 +426,12 @@ impl ActiveParas {
*self.next_assignments.entry(para_next).or_default() += 1;
}
self.relay_parent_assignments.insert(
relay_parent,
GroupAssignments { current: para_now, next: para_next },
);
self.relay_parent_assignments
.insert(relay_parent, GroupAssignments { current: para_now, next: para_next });
}
}
fn remove_outgoing(
&mut self,
old_relay_parents: impl IntoIterator<Item = Hash>,
) {
fn remove_outgoing(&mut self, old_relay_parents: impl IntoIterator<Item = Hash>) {
for old_relay_parent in old_relay_parents {
if let Some(assignments) = self.relay_parent_assignments.remove(&old_relay_parent) {
let GroupAssignments { current, next } = assignments;
@@ -482,16 +477,19 @@ struct PendingCollation {
impl PendingCollation {
fn new(relay_parent: Hash, para_id: &ParaId, peer_id: &PeerId) -> Self {
Self { relay_parent, para_id: para_id.clone(), peer_id: peer_id.clone(), commitments_hash: None }
Self {
relay_parent,
para_id: para_id.clone(),
peer_id: peer_id.clone(),
commitments_hash: None,
}
}
}
type CollationEvent = (CollatorId, PendingCollation);
type PendingCollationFetch = (
CollationEvent,
std::result::Result<(CandidateReceipt, PoV), oneshot::Canceled>,
);
type PendingCollationFetch =
(CollationEvent, std::result::Result<(CandidateReceipt, PoV), oneshot::Canceled>);
/// The status of the collations in [`CollationsPerRelayParent`].
#[derive(Debug, Clone, Copy)]
@@ -567,7 +565,7 @@ impl CollationsPerRelayParent {
let next = self.unfetched_collations.pop();
self.waiting_collation = next.as_ref().map(|(_, collator_id)| collator_id.clone());
next
}
},
CollationStatus::WaitingOnValidation | CollationStatus::Fetching =>
unreachable!("We have reset the status above!"),
}
@@ -622,20 +620,18 @@ fn collator_peer_id(
peer_data: &HashMap<PeerId, PeerData>,
collator_id: &CollatorId,
) -> Option<PeerId> {
peer_data.iter()
.find_map(|(peer, data)|
data.collator_id().filter(|c| c == &collator_id).map(|_| peer.clone())
)
peer_data.iter().find_map(|(peer, data)| {
data.collator_id().filter(|c| c == &collator_id).map(|_| peer.clone())
})
}
async fn disconnect_peer<Context>(ctx: &mut Context, peer_id: PeerId)
where
Context: overseer::SubsystemContext<Message=CollatorProtocolMessage>,
Context: SubsystemContext<Message=CollatorProtocolMessage>,
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
Context: SubsystemContext<Message = CollatorProtocolMessage>,
{
ctx.send_message(
NetworkBridgeMessage::DisconnectPeer(peer_id, PeerSet::Collation)
).await
ctx.send_message(NetworkBridgeMessage::DisconnectPeer(peer_id, PeerSet::Collation))
.await
}
/// Another subsystem has requested to fetch collations on a particular leaf for some para.
@@ -644,10 +640,9 @@ async fn fetch_collation<Context>(
state: &mut State,
pc: PendingCollation,
id: CollatorId,
)
where
Context: overseer::SubsystemContext<Message=CollatorProtocolMessage>,
Context: SubsystemContext<Message=CollatorProtocolMessage>,
) where
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
Context: SubsystemContext<Message = CollatorProtocolMessage>,
{
let (tx, rx) = oneshot::channel();
@@ -657,7 +652,9 @@ where
Delay::new(MAX_UNSHARED_DOWNLOAD_TIME).await;
(collator_id, relay_parent)
};
state.collation_fetch_timeouts.push(timeout(id.clone(), relay_parent.clone()).boxed());
state
.collation_fetch_timeouts
.push(timeout(id.clone(), relay_parent.clone()).boxed());
if state.peer_data.get(&peer_id).map_or(false, |d| d.has_advertised(&relay_parent)) {
request_collation(ctx, state, relay_parent, para_id, peer_id, tx).await;
@@ -671,9 +668,8 @@ async fn report_collator<Context>(
ctx: &mut Context,
peer_data: &HashMap<PeerId, PeerData>,
id: CollatorId,
)
where
Context: SubsystemContext<Message = CollatorProtocolMessage>
) where
Context: SubsystemContext<Message = CollatorProtocolMessage>,
{
if let Some(peer_id) = collator_peer_id(peer_data, &id) {
modify_reputation(ctx, peer_id, COST_REPORT_BAD).await;
@@ -685,10 +681,9 @@ async fn note_good_collation<Context>(
ctx: &mut Context,
peer_data: &HashMap<PeerId, PeerData>,
id: CollatorId,
)
where
Context: overseer::SubsystemContext<Message=CollatorProtocolMessage>,
Context: SubsystemContext<Message=CollatorProtocolMessage>,
) where
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
Context: SubsystemContext<Message = CollatorProtocolMessage>,
{
if let Some(peer_id) = collator_peer_id(peer_data, &id) {
modify_reputation(ctx, peer_id, BENEFIT_NOTIFY_GOOD).await;
@@ -701,18 +696,17 @@ async fn notify_collation_seconded<Context>(
peer_id: PeerId,
relay_parent: Hash,
statement: SignedFullStatement,
)
where
Context: overseer::SubsystemContext<Message=CollatorProtocolMessage>,
Context: SubsystemContext<Message=CollatorProtocolMessage>,
) where
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
Context: SubsystemContext<Message = CollatorProtocolMessage>,
{
let wire_message = protocol_v1::CollatorProtocolMessage::CollationSeconded(relay_parent, statement.into());
ctx.send_message(
NetworkBridgeMessage::SendCollationMessage(
vec![peer_id],
protocol_v1::CollationProtocol::CollatorProtocol(wire_message),
)
).await;
let wire_message =
protocol_v1::CollatorProtocolMessage::CollationSeconded(relay_parent, statement.into());
ctx.send_message(NetworkBridgeMessage::SendCollationMessage(
vec![peer_id],
protocol_v1::CollationProtocol::CollatorProtocol(wire_message),
))
.await;
modify_reputation(ctx, peer_id, BENEFIT_NOTIFY_GOOD).await;
}
@@ -720,15 +714,12 @@ where
/// A peer's view has changed. A number of things should be done:
/// - Ongoing collation requests have to be canceled.
/// - Advertisements by this peer that are no longer relevant have to be removed.
async fn handle_peer_view_change(
state: &mut State,
peer_id: PeerId,
view: View,
) -> Result<()> {
async fn handle_peer_view_change(state: &mut State, peer_id: PeerId, view: View) -> Result<()> {
let peer_data = state.peer_data.entry(peer_id.clone()).or_default();
peer_data.update_view(view);
state.requested_collations
state
.requested_collations
.retain(|pc, _| pc.peer_id != peer_id || !peer_data.has_advertised(&pc.relay_parent));
Ok(())
@@ -747,10 +738,9 @@ async fn request_collation<Context>(
para_id: ParaId,
peer_id: PeerId,
result: oneshot::Sender<(CandidateReceipt, PoV)>,
)
where
Context: overseer::SubsystemContext<Message=CollatorProtocolMessage>,
Context: SubsystemContext<Message=CollatorProtocolMessage>,
) where
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
Context: SubsystemContext<Message = CollatorProtocolMessage>,
{
if !state.view.contains(&relay_parent) {
tracing::debug!(
@@ -760,7 +750,7 @@ where
relay_parent = %relay_parent,
"collation is no longer in view",
);
return;
return
}
let pending_collation = PendingCollation::new(relay_parent, &para_id, &peer_id);
if state.requested_collations.contains_key(&pending_collation) {
@@ -771,29 +761,27 @@ where
?pending_collation.relay_parent,
"collation has already been requested",
);
return;
return
}
let (full_request, response_recv) =
OutgoingRequest::new(Recipient::Peer(peer_id), CollationFetchingRequest {
relay_parent,
para_id,
});
let (full_request, response_recv) = OutgoingRequest::new(
Recipient::Peer(peer_id),
CollationFetchingRequest { relay_parent, para_id },
);
let requests = Requests::CollationFetching(full_request);
let per_request = PerRequest {
from_collator: response_recv.boxed().fuse(),
to_requester: result,
span: state.span_per_relay_parent.get(&relay_parent).map(|s| {
s.child("collation-request")
.with_para_id(para_id)
}),
span: state
.span_per_relay_parent
.get(&relay_parent)
.map(|s| s.child("collation-request").with_para_id(para_id)),
};
state.requested_collations.insert(
PendingCollation::new(relay_parent, &para_id, &peer_id),
per_request
);
state
.requested_collations
.insert(PendingCollation::new(relay_parent, &para_id, &peer_id), per_request);
tracing::debug!(
target: LOG_TARGET,
@@ -803,9 +791,11 @@ where
"Requesting collation",
);
ctx.send_message(
NetworkBridgeMessage::SendRequests(vec![requests], IfDisconnected::ImmediateError)
).await;
ctx.send_message(NetworkBridgeMessage::SendRequests(
vec![requests],
IfDisconnected::ImmediateError,
))
.await;
}
/// Networking message has been received.
@@ -814,10 +804,9 @@ async fn process_incoming_peer_message<Context>(
state: &mut State,
origin: PeerId,
msg: protocol_v1::CollatorProtocolMessage,
)
where
Context: overseer::SubsystemContext<Message=CollatorProtocolMessage>,
Context: SubsystemContext<Message=CollatorProtocolMessage>,
) where
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
Context: SubsystemContext<Message = CollatorProtocolMessage>,
{
use protocol_v1::CollatorProtocolMessage::*;
use sp_runtime::traits::AppVerify;
@@ -833,7 +822,7 @@ where
None => {
modify_reputation(ctx, origin, COST_UNEXPECTED_MESSAGE).await;
return
}
},
};
if peer_data.is_collating() {
@@ -869,9 +858,12 @@ where
tracing::trace!(target: LOG_TARGET, "Disconnecting unneeded collator");
disconnect_peer(ctx, origin).await;
}
}
},
AdvertiseCollation(relay_parent) => {
let _span = state.span_per_relay_parent.get(&relay_parent).map(|s| s.child("advertise-collation"));
let _span = state
.span_per_relay_parent
.get(&relay_parent)
.map(|s| s.child("advertise-collation"));
if !state.view.contains(&relay_parent) {
tracing::debug!(
target: LOG_TARGET,
@@ -881,14 +873,14 @@ where
);
modify_reputation(ctx, origin, COST_UNEXPECTED_MESSAGE).await;
return;
return
}
let peer_data = match state.peer_data.get_mut(&origin) {
None => {
modify_reputation(ctx, origin, COST_UNEXPECTED_MESSAGE).await;
return;
}
return
},
Some(p) => p,
};
@@ -902,13 +894,10 @@ where
"Received advertise collation",
);
let pending_collation = PendingCollation::new(
relay_parent,
&para_id,
&origin,
);
let pending_collation = PendingCollation::new(relay_parent, &para_id, &origin);
let collations = state.collations_per_relay_parent.entry(relay_parent).or_default();
let collations =
state.collations_per_relay_parent.entry(relay_parent).or_default();
match collations.status {
CollationStatus::Fetching | CollationStatus::WaitingOnValidation =>
@@ -921,7 +910,7 @@ where
},
CollationStatus::Seconded => {},
}
}
},
Err(error) => {
tracing::debug!(
target: LOG_TARGET,
@@ -932,33 +921,26 @@ where
);
modify_reputation(ctx, origin, COST_UNEXPECTED_MESSAGE).await;
}
},
}
}
},
CollationSeconded(_, _) => {
tracing::warn!(
target: LOG_TARGET,
peer_id = ?origin,
"Unexpected `CollationSeconded` message, decreasing reputation",
);
}
},
}
}
/// A leaf has become inactive so we want to
/// - Cancel all ongoing collation requests that are on top of that leaf.
/// - Remove all stored collations relevant to that leaf.
async fn remove_relay_parent(
state: &mut State,
relay_parent: Hash,
) -> Result<()> {
state.requested_collations.retain(|k, _| {
k.relay_parent != relay_parent
});
async fn remove_relay_parent(state: &mut State, relay_parent: Hash) -> Result<()> {
state.requested_collations.retain(|k, _| k.relay_parent != relay_parent);
state.pending_candidates.retain(|k, _| {
k != &relay_parent
});
state.pending_candidates.retain(|k, _| k != &relay_parent);
state.collations_per_relay_parent.remove(&relay_parent);
Ok(())
@@ -972,12 +954,13 @@ async fn handle_our_view_change<Context>(
view: OurView,
) -> Result<()>
where
Context: overseer::SubsystemContext<Message=CollatorProtocolMessage>,
Context: SubsystemContext<Message=CollatorProtocolMessage>,
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
Context: SubsystemContext<Message = CollatorProtocolMessage>,
{
let old_view = std::mem::replace(&mut state.view, view);
let added: HashMap<Hash, Arc<jaeger::Span>> = state.view
let added: HashMap<Hash, Arc<jaeger::Span>> = state
.view
.span_per_head()
.iter()
.filter(|v| !old_view.contains(&v.0))
@@ -989,10 +972,7 @@ where
});
let added = state.view.difference(&old_view).cloned().collect::<Vec<_>>();
let removed = old_view
.difference(&state.view)
.cloned()
.collect::<Vec<_>>();
let removed = old_view.difference(&state.view).cloned().collect::<Vec<_>>();
for removed in removed.iter().cloned() {
remove_relay_parent(state, removed).await?;
@@ -1028,8 +1008,8 @@ async fn handle_network_msg<Context>(
bridge_message: NetworkBridgeEvent<protocol_v1::CollatorProtocolMessage>,
) -> Result<()>
where
Context: overseer::SubsystemContext<Message=CollatorProtocolMessage>,
Context: SubsystemContext<Message=CollatorProtocolMessage>,
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
Context: SubsystemContext<Message = CollatorProtocolMessage>,
{
use NetworkBridgeEvent::*;
@@ -1044,7 +1024,7 @@ where
},
NewGossipTopology(..) => {
// impossibru!
}
},
PeerViewChange(peer_id, view) => {
handle_peer_view_change(state, peer_id, view).await?;
},
@@ -1053,7 +1033,7 @@ where
},
PeerMessage(remote, msg) => {
process_incoming_peer_message(ctx, state, remote, msg).await;
}
},
}
Ok(())
@@ -1065,10 +1045,9 @@ async fn process_msg<Context>(
keystore: &SyncCryptoStorePtr,
msg: CollatorProtocolMessage,
state: &mut State,
)
where
Context: overseer::SubsystemContext<Message=CollatorProtocolMessage>,
Context: SubsystemContext<Message=CollatorProtocolMessage>,
) where
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
Context: SubsystemContext<Message = CollatorProtocolMessage>,
{
use CollatorProtocolMessage::*;
@@ -1081,36 +1060,31 @@ where
para_id = %id,
"CollateOn message is not expected on the validator side of the protocol",
);
}
},
DistributeCollation(_, _, _) => {
tracing::warn!(
target: LOG_TARGET,
"DistributeCollation message is not expected on the validator side of the protocol",
);
}
},
ReportCollator(id) => {
report_collator(ctx, &state.peer_data, id).await;
}
},
NetworkBridgeUpdateV1(event) => {
if let Err(e) = handle_network_msg(
ctx,
state,
keystore,
event,
).await {
if let Err(e) = handle_network_msg(ctx, state, keystore, event).await {
tracing::warn!(
target: LOG_TARGET,
err = ?e,
"Failed to handle incoming network message",
);
}
}
},
CollationFetchingRequest(_) => {
tracing::warn!(
target: LOG_TARGET,
"CollationFetchingRequest message is not expected on the validator side of the protocol",
);
}
},
Seconded(parent, stmt) => {
if let Some(collation_event) = state.pending_candidates.remove(&parent) {
let (collator_id, pending_collation) = collation_event;
@@ -1128,11 +1102,13 @@ where
"Collation has been seconded, but the relay parent is deactivated",
);
}
}
},
Invalid(parent, candidate_receipt) => {
let id = match state.pending_candidates.entry(parent) {
Entry::Occupied(entry)
if entry.get().1.commitments_hash == Some(candidate_receipt.commitments_hash) => entry.remove().0,
if entry.get().1.commitments_hash ==
Some(candidate_receipt.commitments_hash) =>
entry.remove().0,
Entry::Occupied(_) => {
tracing::error!(
target: LOG_TARGET,
@@ -1141,14 +1117,14 @@ where
"Reported invalid candidate for unknown `pending_candidate`!",
);
return
}
},
Entry::Vacant(_) => return,
};
report_collator(ctx, &state.peer_data, id.clone()).await;
dequeue_next_collation_and_fetch(ctx, state, parent, id).await;
}
},
}
}
@@ -1172,20 +1148,18 @@ pub(crate) async fn run<Context>(
metrics: Metrics,
) -> Result<()>
where
Context: overseer::SubsystemContext<Message=CollatorProtocolMessage>,
Context: SubsystemContext<Message=CollatorProtocolMessage>,
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
Context: SubsystemContext<Message = CollatorProtocolMessage>,
{
use OverseerSignal::*;
let mut state = State {
metrics,
..Default::default()
};
let mut state = State { metrics, ..Default::default() };
let next_inactivity_stream = futures::stream::unfold(
Instant::now() + ACTIVITY_POLL,
|next_check| async move { Some(((), wait_until_next_check(next_check).await)) }
).fuse();
let next_inactivity_stream =
futures::stream::unfold(Instant::now() + ACTIVITY_POLL, |next_check| async move {
Some(((), wait_until_next_check(next_check).await))
})
.fuse();
futures::pin_mut!(next_inactivity_stream);
@@ -1227,8 +1201,13 @@ where
for (pending_collation, per_req) in state.requested_collations.iter_mut() {
// Despite the await, this won't block on the response itself.
let finished = poll_collation_response(
&mut ctx, &state.metrics, &state.span_per_relay_parent, pending_collation, per_req,
).await;
&mut ctx,
&state.metrics,
&state.span_per_relay_parent,
pending_collation,
per_req,
)
.await;
if !finished {
retained_requested.insert(pending_collation.clone());
}
@@ -1240,13 +1219,15 @@ where
/// Dequeue another collation and fetch.
async fn dequeue_next_collation_and_fetch(
ctx: &mut (impl SubsystemContext<Message = CollatorProtocolMessage> + overseer::SubsystemContext<Message = CollatorProtocolMessage>),
ctx: &mut (impl SubsystemContext<Message = CollatorProtocolMessage>
+ overseer::SubsystemContext<Message = CollatorProtocolMessage>),
state: &mut State,
relay_parent: Hash,
// The collator we tried to fetch from last.
previous_fetch: CollatorId,
) {
if let Some((next, id)) = state.collations_per_relay_parent
if let Some((next, id)) = state
.collations_per_relay_parent
.get_mut(&relay_parent)
.and_then(|c| c.get_next_collation_to_fetch(Some(previous_fetch)))
{
@@ -1259,10 +1240,9 @@ async fn handle_collation_fetched_result<Context>(
ctx: &mut Context,
state: &mut State,
(mut collation_event, res): PendingCollationFetch,
)
where
Context: overseer::SubsystemContext<Message=CollatorProtocolMessage>,
Context: SubsystemContext<Message=CollatorProtocolMessage>,
) where
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
Context: SubsystemContext<Message = CollatorProtocolMessage>,
{
// If no prior collation for this relay parent has been seconded, then
// memoize the collation_event for that relay_parent, such that we may
@@ -1301,13 +1281,12 @@ where
if let Entry::Vacant(entry) = state.pending_candidates.entry(relay_parent) {
collation_event.1.commitments_hash = Some(candidate_receipt.commitments_hash);
ctx.send_message(
CandidateBackingMessage::Second(
relay_parent.clone(),
candidate_receipt,
pov,
)
).await;
ctx.send_message(CandidateBackingMessage::Second(
relay_parent.clone(),
candidate_receipt,
pov,
))
.await;
entry.insert(collation_event);
} else {
@@ -1327,10 +1306,9 @@ async fn disconnect_inactive_peers<Context>(
ctx: &mut Context,
eviction_policy: &crate::CollatorEvictionPolicy,
peers: &HashMap<PeerId, PeerData>,
)
where
Context: overseer::SubsystemContext<Message=CollatorProtocolMessage>,
Context: SubsystemContext<Message=CollatorProtocolMessage>,
) where
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
Context: SubsystemContext<Message = CollatorProtocolMessage>,
{
for (peer, peer_data) in peers {
if peer_data.is_inactive(&eviction_policy) {
@@ -1352,10 +1330,9 @@ async fn poll_collation_response<Context>(
spans: &HashMap<Hash, PerLeafSpan>,
pending_collation: &PendingCollation,
per_req: &mut PerRequest,
)
-> bool
) -> bool
where
Context: overseer::SubsystemContext<Message=CollatorProtocolMessage>,
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
Context: SubsystemContext,
{
if never!(per_req.from_collator.is_terminated()) {
@@ -1367,8 +1344,9 @@ where
}
if let Poll::Ready(response) = futures::poll!(&mut per_req.from_collator) {
let _span = spans.get(&pending_collation.relay_parent)
.map(|s| s.child("received-collation"));
let _span = spans
.get(&pending_collation.relay_parent)
.map(|s| s.child("received-collation"));
let _timer = metrics.time_handle_collation_request_result();
let mut metrics_result = Err(());
@@ -1384,12 +1362,9 @@ where
err = ?err,
"Collator provided response that could not be decoded"
);
modify_reputation(
ctx,
pending_collation.peer_id.clone(),
COST_CORRUPTED_MESSAGE
).await;
}
modify_reputation(ctx, pending_collation.peer_id.clone(), COST_CORRUPTED_MESSAGE)
.await;
},
Err(RequestError::NetworkError(err)) => {
tracing::warn!(
target: LOG_TARGET,
@@ -1404,7 +1379,7 @@ where
// which would result in reduced reputation for proper nodes, but the
// same can happen for penalties on timeouts, which we also have.
modify_reputation(ctx, pending_collation.peer_id.clone(), COST_NETWORK_ERROR).await;
}
},
Err(RequestError::Canceled(_)) => {
tracing::warn!(
target: LOG_TARGET,
@@ -1417,8 +1392,9 @@ where
// sensible. In theory this could be exploited, by DoSing this node,
// which would result in reduced reputation for proper nodes, but the
// same can happen for penalties on timeouts, which we also have.
modify_reputation(ctx, pending_collation.peer_id.clone(), COST_REQUEST_TIMED_OUT).await;
}
modify_reputation(ctx, pending_collation.peer_id.clone(), COST_REQUEST_TIMED_OUT)
.await;
},
Ok(CollationFetchingResponse::Collation(receipt, _))
if receipt.descriptor().para_id != pending_collation.para_id =>
{
@@ -1446,7 +1422,7 @@ where
std::mem::swap(&mut tx, &mut (per_req.to_requester));
let result = tx.send((receipt, pov));
if let Err(_) = result {
if let Err(_) = result {
tracing::warn!(
target: LOG_TARGET,
hash = ?pending_collation.relay_parent,
@@ -1458,7 +1434,7 @@ where
metrics_result = Ok(());
success = "true";
}
}
},
};
metrics.on_request(metrics_result);
per_req.span.as_mut().map(|s| s.add_string_tag("success", success));
@@ -15,26 +15,26 @@
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
use super::*;
use std::{iter, time::Duration};
use std::sync::Arc;
use assert_matches::assert_matches;
use futures::{executor, future, Future};
use sp_core::{crypto::Pair, Encode};
use sp_keystore::SyncCryptoStore;
use sp_keystore::testing::KeyStore as TestKeyStore;
use sp_keyring::Sr25519Keyring;
use assert_matches::assert_matches;
use sp_keystore::{testing::KeyStore as TestKeyStore, SyncCryptoStore};
use std::{iter, sync::Arc, time::Duration};
use polkadot_primitives::v1::{
CollatorPair, ValidatorId, ValidatorIndex, CoreState, CandidateDescriptor,
GroupRotationInfo, ScheduledCore, OccupiedCore, GroupIndex,
use polkadot_node_network_protocol::{
our_view,
request_response::{Requests, ResponseSender},
ObservedRole,
};
use polkadot_node_primitives::BlockData;
use polkadot_node_subsystem_util::TimeoutExt;
use polkadot_subsystem_testhelpers as test_helpers;
use polkadot_subsystem::messages::{AllMessages, RuntimeApiMessage, RuntimeApiRequest};
use polkadot_node_network_protocol::{
our_view, ObservedRole, request_response::{Requests, ResponseSender},
use polkadot_primitives::v1::{
CandidateDescriptor, CollatorPair, CoreState, GroupIndex, GroupRotationInfo, OccupiedCore,
ScheduledCore, ValidatorId, ValidatorIndex,
};
use polkadot_subsystem::messages::{AllMessages, RuntimeApiMessage, RuntimeApiRequest};
use polkadot_subsystem_testhelpers as test_helpers;
const ACTIVITY_TIMEOUT: Duration = Duration::from_millis(500);
const DECLARE_TIMEOUT: Duration = Duration::from_millis(25);
@@ -58,10 +58,7 @@ impl Default for TestState {
let chain_ids = vec![chain_a, chain_b];
let relay_parent = Hash::repeat_byte(0x05);
let collators = iter::repeat(())
.map(|_| CollatorPair::generate().0)
.take(5)
.collect();
let collators = iter::repeat(()).map(|_| CollatorPair::generate().0).take(5).collect();
let validators = vec![
Sr25519Keyring::Alice,
@@ -78,17 +75,11 @@ impl Default for TestState {
vec![ValidatorIndex(4)],
];
let group_rotation_info = GroupRotationInfo {
session_start_block: 0,
group_rotation_frequency: 1,
now: 0,
};
let group_rotation_info =
GroupRotationInfo { session_start_block: 0, group_rotation_frequency: 1, now: 0 };
let cores = vec![
CoreState::Scheduled(ScheduledCore {
para_id: chain_ids[0],
collator: None,
}),
CoreState::Scheduled(ScheduledCore { para_id: chain_ids[0], collator: None }),
CoreState::Free,
CoreState::Occupied(OccupiedCore {
next_up_on_available: None,
@@ -129,14 +120,8 @@ struct TestHarness {
fn test_harness<T: Future<Output = VirtualOverseer>>(test: impl FnOnce(TestHarness) -> T) {
let _ = env_logger::builder()
.is_test(true)
.filter(
Some("polkadot_collator_protocol"),
log::LevelFilter::Trace,
)
.filter(
Some(LOG_TARGET),
log::LevelFilter::Trace,
)
.filter(Some("polkadot_collator_protocol"), log::LevelFilter::Trace)
.filter(Some(LOG_TARGET), log::LevelFilter::Trace)
.try_init();
let pool = sp_core::testing::TaskExecutor::new();
@@ -144,10 +129,12 @@ fn test_harness<T: Future<Output = VirtualOverseer>>(test: impl FnOnce(TestHarne
let (context, virtual_overseer) = test_helpers::make_subsystem_context(pool.clone());
let keystore = TestKeyStore::new();
keystore.sr25519_generate_new(
polkadot_primitives::v1::PARACHAIN_KEY_TYPE_ID,
Some(&Sr25519Keyring::Alice.to_seed()),
).unwrap();
keystore
.sr25519_generate_new(
polkadot_primitives::v1::PARACHAIN_KEY_TYPE_ID,
Some(&Sr25519Keyring::Alice.to_seed()),
)
.unwrap();
let subsystem = run(
context,
@@ -164,18 +151,20 @@ fn test_harness<T: Future<Output = VirtualOverseer>>(test: impl FnOnce(TestHarne
futures::pin_mut!(test_fut);
futures::pin_mut!(subsystem);
executor::block_on(future::join(async move {
let mut overseer = test_fut.await;
overseer_signal(&mut overseer, OverseerSignal::Conclude).await;
}, subsystem)).1.unwrap();
executor::block_on(future::join(
async move {
let mut overseer = test_fut.await;
overseer_signal(&mut overseer, OverseerSignal::Conclude).await;
},
subsystem,
))
.1
.unwrap();
}
const TIMEOUT: Duration = Duration::from_millis(200);
async fn overseer_send(
overseer: &mut VirtualOverseer,
msg: CollatorProtocolMessage,
) {
async fn overseer_send(overseer: &mut VirtualOverseer, msg: CollatorProtocolMessage) {
tracing::trace!("Sending message:\n{:?}", &msg);
overseer
.send(FromOverseer::Communication { msg })
@@ -184,9 +173,7 @@ async fn overseer_send(
.expect(&format!("{:?} is enough for sending messages.", TIMEOUT));
}
async fn overseer_recv(
overseer: &mut VirtualOverseer,
) -> AllMessages {
async fn overseer_recv(overseer: &mut VirtualOverseer) -> AllMessages {
let msg = overseer_recv_with_timeout(overseer, TIMEOUT)
.await
.expect(&format!("{:?} is enough to receive messages.", TIMEOUT));
@@ -201,16 +188,10 @@ async fn overseer_recv_with_timeout(
timeout: Duration,
) -> Option<AllMessages> {
tracing::trace!("Waiting for message...");
overseer
.recv()
.timeout(timeout)
.await
overseer.recv().timeout(timeout).await
}
async fn overseer_signal(
overseer: &mut VirtualOverseer,
signal: OverseerSignal,
) {
async fn overseer_signal(overseer: &mut VirtualOverseer, signal: OverseerSignal) {
overseer
.send(FromOverseer::Signal(signal))
.timeout(TIMEOUT)
@@ -275,10 +256,7 @@ async fn assert_candidate_backing_second(
}
/// Assert that a collator got disconnected.
async fn assert_collator_disconnect(
virtual_overseer: &mut VirtualOverseer,
expected_peer: PeerId,
) {
async fn assert_collator_disconnect(virtual_overseer: &mut VirtualOverseer, expected_peer: PeerId) {
assert_matches!(
overseer_recv(virtual_overseer).await,
AllMessages::NetworkBridge(NetworkBridgeMessage::DisconnectPeer(
@@ -324,28 +302,26 @@ async fn connect_and_declare_collator(
) {
overseer_send(
virtual_overseer,
CollatorProtocolMessage::NetworkBridgeUpdateV1(
NetworkBridgeEvent::PeerConnected(
peer.clone(),
ObservedRole::Full,
None,
),
)
).await;
CollatorProtocolMessage::NetworkBridgeUpdateV1(NetworkBridgeEvent::PeerConnected(
peer.clone(),
ObservedRole::Full,
None,
)),
)
.await;
overseer_send(
virtual_overseer,
CollatorProtocolMessage::NetworkBridgeUpdateV1(
NetworkBridgeEvent::PeerMessage(
peer.clone(),
protocol_v1::CollatorProtocolMessage::Declare(
collator.public(),
para_id,
collator.sign(&protocol_v1::declare_signature_payload(&peer)),
)
)
)
).await;
CollatorProtocolMessage::NetworkBridgeUpdateV1(NetworkBridgeEvent::PeerMessage(
peer.clone(),
protocol_v1::CollatorProtocolMessage::Declare(
collator.public(),
para_id,
collator.sign(&protocol_v1::declare_signature_payload(&peer)),
),
)),
)
.await;
}
/// Advertise a collation.
@@ -356,15 +332,12 @@ async fn advertise_collation(
) {
overseer_send(
virtual_overseer,
CollatorProtocolMessage::NetworkBridgeUpdateV1(
NetworkBridgeEvent::PeerMessage(
peer,
protocol_v1::CollatorProtocolMessage::AdvertiseCollation(
relay_parent,
)
)
)
).await;
CollatorProtocolMessage::NetworkBridgeUpdateV1(NetworkBridgeEvent::PeerMessage(
peer,
protocol_v1::CollatorProtocolMessage::AdvertiseCollation(relay_parent),
)),
)
.await;
}
// As we receive a relevant advertisement act on it and issue a collation request.
@@ -373,29 +346,39 @@ fn act_on_advertisement() {
let test_state = TestState::default();
test_harness(|test_harness| async move {
let TestHarness {
mut virtual_overseer,
} = test_harness;
let TestHarness { mut virtual_overseer } = test_harness;
let pair = CollatorPair::generate().0;
tracing::trace!("activating");
overseer_send(
&mut virtual_overseer,
CollatorProtocolMessage::NetworkBridgeUpdateV1(
NetworkBridgeEvent::OurViewChange(our_view![test_state.relay_parent])
)
).await;
CollatorProtocolMessage::NetworkBridgeUpdateV1(NetworkBridgeEvent::OurViewChange(
our_view![test_state.relay_parent],
)),
)
.await;
respond_to_core_info_queries(&mut virtual_overseer, &test_state).await;
let peer_b = PeerId::random();
connect_and_declare_collator(&mut virtual_overseer, peer_b.clone(), pair.clone(), test_state.chain_ids[0]).await;
connect_and_declare_collator(
&mut virtual_overseer,
peer_b.clone(),
pair.clone(),
test_state.chain_ids[0],
)
.await;
advertise_collation(&mut virtual_overseer, peer_b.clone(), test_state.relay_parent).await;
assert_fetch_collation_request(&mut virtual_overseer, test_state.relay_parent, test_state.chain_ids[0]).await;
assert_fetch_collation_request(
&mut virtual_overseer,
test_state.relay_parent,
test_state.chain_ids[0],
)
.await;
virtual_overseer
});
@@ -407,16 +390,15 @@ fn collator_reporting_works() {
let test_state = TestState::default();
test_harness(|test_harness| async move {
let TestHarness {
mut virtual_overseer,
} = test_harness;
let TestHarness { mut virtual_overseer } = test_harness;
overseer_send(
&mut virtual_overseer,
CollatorProtocolMessage::NetworkBridgeUpdateV1(
NetworkBridgeEvent::OurViewChange(our_view![test_state.relay_parent])
)
).await;
CollatorProtocolMessage::NetworkBridgeUpdateV1(NetworkBridgeEvent::OurViewChange(
our_view![test_state.relay_parent],
)),
)
.await;
respond_to_core_info_queries(&mut virtual_overseer, &test_state).await;
@@ -428,19 +410,22 @@ fn collator_reporting_works() {
peer_b.clone(),
test_state.collators[0].clone(),
test_state.chain_ids[0].clone(),
).await;
)
.await;
connect_and_declare_collator(
&mut virtual_overseer,
peer_c.clone(),
test_state.collators[1].clone(),
test_state.chain_ids[0].clone(),
).await;
)
.await;
overseer_send(
&mut virtual_overseer,
CollatorProtocolMessage::ReportCollator(test_state.collators[0].public()),
).await;
)
.await;
assert_matches!(
overseer_recv(&mut virtual_overseer).await,
@@ -462,22 +447,19 @@ fn collator_authentication_verification_works() {
let test_state = TestState::default();
test_harness(|test_harness| async move {
let TestHarness {
mut virtual_overseer,
} = test_harness;
let TestHarness { mut virtual_overseer } = test_harness;
let peer_b = PeerId::random();
overseer_send(
&mut virtual_overseer,
CollatorProtocolMessage::NetworkBridgeUpdateV1(
NetworkBridgeEvent::PeerConnected(
peer_b,
ObservedRole::Full,
None,
),
)
).await;
CollatorProtocolMessage::NetworkBridgeUpdateV1(NetworkBridgeEvent::PeerConnected(
peer_b,
ObservedRole::Full,
None,
)),
)
.await;
// the peer sends a declare message but sign the wrong payload
overseer_send(
@@ -521,18 +503,17 @@ fn fetch_collations_works() {
let test_state = TestState::default();
test_harness(|test_harness| async move {
let TestHarness {
mut virtual_overseer,
} = test_harness;
let TestHarness { mut virtual_overseer } = test_harness;
let second = Hash::random();
overseer_send(
&mut virtual_overseer,
CollatorProtocolMessage::NetworkBridgeUpdateV1(
NetworkBridgeEvent::OurViewChange(our_view![test_state.relay_parent, second])
),
).await;
CollatorProtocolMessage::NetworkBridgeUpdateV1(NetworkBridgeEvent::OurViewChange(
our_view![test_state.relay_parent, second],
)),
)
.await;
respond_to_core_info_queries(&mut virtual_overseer, &test_state).await;
respond_to_core_info_queries(&mut virtual_overseer, &test_state).await;
@@ -545,14 +526,16 @@ fn fetch_collations_works() {
peer_b.clone(),
test_state.collators[0].clone(),
test_state.chain_ids[0].clone(),
).await;
)
.await;
connect_and_declare_collator(
&mut virtual_overseer,
peer_c.clone(),
test_state.collators[1].clone(),
test_state.chain_ids[0].clone(),
).await;
)
.await;
advertise_collation(&mut virtual_overseer, peer_b.clone(), test_state.relay_parent).await;
advertise_collation(&mut virtual_overseer, peer_c.clone(), test_state.relay_parent).await;
@@ -561,7 +544,8 @@ fn fetch_collations_works() {
&mut virtual_overseer,
test_state.relay_parent,
test_state.chain_ids[0],
).await;
)
.await;
assert!(
overseer_recv_with_timeout(&mut &mut virtual_overseer, Duration::from_millis(30)).await.is_none(),
@@ -572,29 +556,35 @@ fn fetch_collations_works() {
let mut candidate_a = CandidateReceipt::default();
candidate_a.descriptor.para_id = test_state.chain_ids[0];
candidate_a.descriptor.relay_parent = test_state.relay_parent;
response_channel.send(Ok(
CollationFetchingResponse::Collation(
candidate_a.clone(),
pov.clone(),
).encode()
)).expect("Sending response should succeed");
response_channel
.send(Ok(
CollationFetchingResponse::Collation(candidate_a.clone(), pov.clone()).encode()
))
.expect("Sending response should succeed");
assert_candidate_backing_second(
&mut virtual_overseer,
test_state.relay_parent,
test_state.chain_ids[0],
&pov,
).await;
)
.await;
overseer_send(
&mut virtual_overseer,
CollatorProtocolMessage::NetworkBridgeUpdateV1(NetworkBridgeEvent::PeerDisconnected(peer_b.clone())),
).await;
CollatorProtocolMessage::NetworkBridgeUpdateV1(NetworkBridgeEvent::PeerDisconnected(
peer_b.clone(),
)),
)
.await;
overseer_send(
&mut virtual_overseer,
CollatorProtocolMessage::NetworkBridgeUpdateV1(NetworkBridgeEvent::PeerDisconnected(peer_c.clone())),
).await;
CollatorProtocolMessage::NetworkBridgeUpdateV1(NetworkBridgeEvent::PeerDisconnected(
peer_c.clone(),
)),
)
.await;
let peer_b = PeerId::random();
let peer_c = PeerId::random();
@@ -605,32 +595,32 @@ fn fetch_collations_works() {
peer_b.clone(),
test_state.collators[2].clone(),
test_state.chain_ids[0].clone(),
).await;
)
.await;
connect_and_declare_collator(
&mut virtual_overseer,
peer_c.clone(),
test_state.collators[3].clone(),
test_state.chain_ids[0].clone(),
).await;
)
.await;
connect_and_declare_collator(
&mut virtual_overseer,
peer_d.clone(),
test_state.collators[4].clone(),
test_state.chain_ids[0].clone(),
).await;
)
.await;
advertise_collation(&mut virtual_overseer, peer_b.clone(), second).await;
advertise_collation(&mut virtual_overseer, peer_c.clone(), second).await;
advertise_collation(&mut virtual_overseer, peer_d.clone(), second).await;
// Dropping the response channel should lead to fetching the second collation.
assert_fetch_collation_request(
&mut virtual_overseer,
second,
test_state.chain_ids[0],
).await;
assert_fetch_collation_request(&mut virtual_overseer, second, test_state.chain_ids[0])
.await;
assert_matches!(
overseer_recv(&mut virtual_overseer).await,
@@ -643,20 +633,16 @@ fn fetch_collations_works() {
}
);
let response_channel_non_exclusive = assert_fetch_collation_request(
&mut virtual_overseer,
second,
test_state.chain_ids[0],
).await;
let response_channel_non_exclusive =
assert_fetch_collation_request(&mut virtual_overseer, second, test_state.chain_ids[0])
.await;
// Third collator should receive response after that timeout:
Delay::new(MAX_UNSHARED_DOWNLOAD_TIME + Duration::from_millis(50)).await;
let response_channel = assert_fetch_collation_request(
&mut virtual_overseer,
second,
test_state.chain_ids[0],
).await;
let response_channel =
assert_fetch_collation_request(&mut virtual_overseer, second, test_state.chain_ids[0])
.await;
let pov = PoV { block_data: BlockData(vec![1]) };
let mut candidate_a = CandidateReceipt::default();
@@ -664,26 +650,25 @@ fn fetch_collations_works() {
candidate_a.descriptor.relay_parent = second;
// First request finishes now:
response_channel_non_exclusive.send(Ok(
CollationFetchingResponse::Collation(
candidate_a.clone(),
pov.clone(),
).encode()
)).expect("Sending response should succeed");
response_channel_non_exclusive
.send(Ok(
CollationFetchingResponse::Collation(candidate_a.clone(), pov.clone()).encode()
))
.expect("Sending response should succeed");
response_channel.send(Ok(
CollationFetchingResponse::Collation(
candidate_a.clone(),
pov.clone(),
).encode()
)).expect("Sending response should succeed");
response_channel
.send(Ok(
CollationFetchingResponse::Collation(candidate_a.clone(), pov.clone()).encode()
))
.expect("Sending response should succeed");
assert_candidate_backing_second(
&mut virtual_overseer,
second,
test_state.chain_ids[0],
&pov,
).await;
)
.await;
virtual_overseer
});
@@ -695,18 +680,17 @@ fn fetch_next_collation_on_invalid_collation() {
let test_state = TestState::default();
test_harness(|test_harness| async move {
let TestHarness {
mut virtual_overseer,
} = test_harness;
let TestHarness { mut virtual_overseer } = test_harness;
let second = Hash::random();
overseer_send(
&mut virtual_overseer,
CollatorProtocolMessage::NetworkBridgeUpdateV1(
NetworkBridgeEvent::OurViewChange(our_view![test_state.relay_parent, second])
),
).await;
CollatorProtocolMessage::NetworkBridgeUpdateV1(NetworkBridgeEvent::OurViewChange(
our_view![test_state.relay_parent, second],
)),
)
.await;
respond_to_core_info_queries(&mut virtual_overseer, &test_state).await;
respond_to_core_info_queries(&mut virtual_overseer, &test_state).await;
@@ -719,14 +703,16 @@ fn fetch_next_collation_on_invalid_collation() {
peer_b.clone(),
test_state.collators[0].clone(),
test_state.chain_ids[0].clone(),
).await;
)
.await;
connect_and_declare_collator(
&mut virtual_overseer,
peer_c.clone(),
test_state.collators[1].clone(),
test_state.chain_ids[0].clone(),
).await;
)
.await;
advertise_collation(&mut virtual_overseer, peer_b.clone(), test_state.relay_parent).await;
advertise_collation(&mut virtual_overseer, peer_c.clone(), test_state.relay_parent).await;
@@ -735,28 +721,33 @@ fn fetch_next_collation_on_invalid_collation() {
&mut virtual_overseer,
test_state.relay_parent,
test_state.chain_ids[0],
).await;
)
.await;
let pov = PoV { block_data: BlockData(vec![]) };
let mut candidate_a = CandidateReceipt::default();
candidate_a.descriptor.para_id = test_state.chain_ids[0];
candidate_a.descriptor.relay_parent = test_state.relay_parent;
response_channel.send(Ok(
CollationFetchingResponse::Collation(
candidate_a.clone(),
pov.clone(),
).encode()
)).expect("Sending response should succeed");
response_channel
.send(Ok(
CollationFetchingResponse::Collation(candidate_a.clone(), pov.clone()).encode()
))
.expect("Sending response should succeed");
let receipt = assert_candidate_backing_second(
&mut virtual_overseer,
test_state.relay_parent,
test_state.chain_ids[0],
&pov,
).await;
)
.await;
// Inform that the candidate was invalid.
overseer_send(&mut virtual_overseer, CollatorProtocolMessage::Invalid(test_state.relay_parent, receipt)).await;
overseer_send(
&mut virtual_overseer,
CollatorProtocolMessage::Invalid(test_state.relay_parent, receipt),
)
.await;
assert_matches!(
overseer_recv(&mut virtual_overseer).await,
@@ -774,7 +765,8 @@ fn fetch_next_collation_on_invalid_collation() {
&mut virtual_overseer,
test_state.relay_parent,
test_state.chain_ids[0],
).await;
)
.await;
virtual_overseer
});
@@ -785,9 +777,7 @@ fn inactive_disconnected() {
let test_state = TestState::default();
test_harness(|test_harness| async move {
let TestHarness {
mut virtual_overseer,
} = test_harness;
let TestHarness { mut virtual_overseer } = test_harness;
let pair = CollatorPair::generate().0;
@@ -795,19 +785,31 @@ fn inactive_disconnected() {
overseer_send(
&mut virtual_overseer,
CollatorProtocolMessage::NetworkBridgeUpdateV1(
NetworkBridgeEvent::OurViewChange(our_view![hash_a])
)
).await;
CollatorProtocolMessage::NetworkBridgeUpdateV1(NetworkBridgeEvent::OurViewChange(
our_view![hash_a],
)),
)
.await;
respond_to_core_info_queries(&mut virtual_overseer, &test_state).await;
let peer_b = PeerId::random();
connect_and_declare_collator(&mut virtual_overseer, peer_b.clone(), pair.clone(), test_state.chain_ids[0]).await;
connect_and_declare_collator(
&mut virtual_overseer,
peer_b.clone(),
pair.clone(),
test_state.chain_ids[0],
)
.await;
advertise_collation(&mut virtual_overseer, peer_b.clone(), test_state.relay_parent).await;
assert_fetch_collation_request(&mut virtual_overseer, test_state.relay_parent, test_state.chain_ids[0]).await;
assert_fetch_collation_request(
&mut virtual_overseer,
test_state.relay_parent,
test_state.chain_ids[0],
)
.await;
Delay::new(ACTIVITY_TIMEOUT * 3).await;
@@ -832,9 +834,7 @@ fn activity_extends_life() {
let test_state = TestState::default();
test_harness(|test_harness| async move {
let TestHarness {
mut virtual_overseer,
} = test_harness;
let TestHarness { mut virtual_overseer } = test_harness;
let pair = CollatorPair::generate().0;
@@ -844,10 +844,11 @@ fn activity_extends_life() {
overseer_send(
&mut virtual_overseer,
CollatorProtocolMessage::NetworkBridgeUpdateV1(
NetworkBridgeEvent::OurViewChange(our_view![hash_a, hash_b, hash_c])
)
).await;
CollatorProtocolMessage::NetworkBridgeUpdateV1(NetworkBridgeEvent::OurViewChange(
our_view![hash_a, hash_b, hash_c],
)),
)
.await;
// 3 heads, 3 times.
respond_to_core_info_queries(&mut virtual_overseer, &test_state).await;
@@ -856,13 +857,20 @@ fn activity_extends_life() {
let peer_b = PeerId::random();
connect_and_declare_collator(&mut virtual_overseer, peer_b.clone(), pair.clone(), test_state.chain_ids[0]).await;
connect_and_declare_collator(
&mut virtual_overseer,
peer_b.clone(),
pair.clone(),
test_state.chain_ids[0],
)
.await;
Delay::new(ACTIVITY_TIMEOUT * 2 / 3).await;
advertise_collation(&mut virtual_overseer, peer_b.clone(), hash_a).await;
assert_fetch_collation_request(&mut virtual_overseer, hash_a, test_state.chain_ids[0]).await;
assert_fetch_collation_request(&mut virtual_overseer, hash_a, test_state.chain_ids[0])
.await;
Delay::new(ACTIVITY_TIMEOUT * 2 / 3).await;
@@ -879,7 +887,8 @@ fn activity_extends_life() {
}
);
assert_fetch_collation_request(&mut virtual_overseer, hash_b, test_state.chain_ids[0]).await;
assert_fetch_collation_request(&mut virtual_overseer, hash_b, test_state.chain_ids[0])
.await;
Delay::new(ACTIVITY_TIMEOUT * 2 / 3).await;
@@ -896,7 +905,8 @@ fn activity_extends_life() {
}
);
assert_fetch_collation_request(&mut virtual_overseer, hash_c, test_state.chain_ids[0]).await;
assert_fetch_collation_request(&mut virtual_overseer, hash_c, test_state.chain_ids[0])
.await;
Delay::new(ACTIVITY_TIMEOUT * 3 / 2).await;
@@ -922,16 +932,15 @@ fn disconnect_if_no_declare() {
let test_state = TestState::default();
test_harness(|test_harness| async move {
let TestHarness {
mut virtual_overseer,
} = test_harness;
let TestHarness { mut virtual_overseer } = test_harness;
overseer_send(
&mut virtual_overseer,
CollatorProtocolMessage::NetworkBridgeUpdateV1(
NetworkBridgeEvent::OurViewChange(our_view![test_state.relay_parent])
)
).await;
CollatorProtocolMessage::NetworkBridgeUpdateV1(NetworkBridgeEvent::OurViewChange(
our_view![test_state.relay_parent],
)),
)
.await;
respond_to_core_info_queries(&mut virtual_overseer, &test_state).await;
@@ -939,14 +948,13 @@ fn disconnect_if_no_declare() {
overseer_send(
&mut virtual_overseer,
CollatorProtocolMessage::NetworkBridgeUpdateV1(
NetworkBridgeEvent::PeerConnected(
peer_b.clone(),
ObservedRole::Full,
None,
)
)
).await;
CollatorProtocolMessage::NetworkBridgeUpdateV1(NetworkBridgeEvent::PeerConnected(
peer_b.clone(),
ObservedRole::Full,
None,
)),
)
.await;
assert_collator_disconnect(&mut virtual_overseer, peer_b.clone()).await;
@@ -959,18 +967,17 @@ fn disconnect_if_wrong_declare() {
let test_state = TestState::default();
test_harness(|test_harness| async move {
let TestHarness {
mut virtual_overseer,
} = test_harness;
let TestHarness { mut virtual_overseer } = test_harness;
let pair = CollatorPair::generate().0;
overseer_send(
&mut virtual_overseer,
CollatorProtocolMessage::NetworkBridgeUpdateV1(
NetworkBridgeEvent::OurViewChange(our_view![test_state.relay_parent])
)
).await;
CollatorProtocolMessage::NetworkBridgeUpdateV1(NetworkBridgeEvent::OurViewChange(
our_view![test_state.relay_parent],
)),
)
.await;
respond_to_core_info_queries(&mut virtual_overseer, &test_state).await;
@@ -978,28 +985,26 @@ fn disconnect_if_wrong_declare() {
overseer_send(
&mut virtual_overseer,
CollatorProtocolMessage::NetworkBridgeUpdateV1(
NetworkBridgeEvent::PeerConnected(
peer_b.clone(),
ObservedRole::Full,
None,
)
)
).await;
CollatorProtocolMessage::NetworkBridgeUpdateV1(NetworkBridgeEvent::PeerConnected(
peer_b.clone(),
ObservedRole::Full,
None,
)),
)
.await;
overseer_send(
&mut virtual_overseer,
CollatorProtocolMessage::NetworkBridgeUpdateV1(
NetworkBridgeEvent::PeerMessage(
peer_b.clone(),
protocol_v1::CollatorProtocolMessage::Declare(
pair.public(),
ParaId::from(69),
pair.sign(&protocol_v1::declare_signature_payload(&peer_b)),
)
)
)
).await;
CollatorProtocolMessage::NetworkBridgeUpdateV1(NetworkBridgeEvent::PeerMessage(
peer_b.clone(),
protocol_v1::CollatorProtocolMessage::Declare(
pair.public(),
ParaId::from(69),
pair.sign(&protocol_v1::declare_signature_payload(&peer_b)),
),
)),
)
.await;
assert_matches!(
overseer_recv(&mut virtual_overseer).await,
@@ -1023,33 +1028,39 @@ fn view_change_clears_old_collators() {
let mut test_state = TestState::default();
test_harness(|test_harness| async move {
let TestHarness {
mut virtual_overseer,
} = test_harness;
let TestHarness { mut virtual_overseer } = test_harness;
let pair = CollatorPair::generate().0;
overseer_send(
&mut virtual_overseer,
CollatorProtocolMessage::NetworkBridgeUpdateV1(
NetworkBridgeEvent::OurViewChange(our_view![test_state.relay_parent])
)
).await;
CollatorProtocolMessage::NetworkBridgeUpdateV1(NetworkBridgeEvent::OurViewChange(
our_view![test_state.relay_parent],
)),
)
.await;
respond_to_core_info_queries(&mut virtual_overseer, &test_state).await;
let peer_b = PeerId::random();
connect_and_declare_collator(&mut virtual_overseer, peer_b.clone(), pair.clone(), test_state.chain_ids[0]).await;
connect_and_declare_collator(
&mut virtual_overseer,
peer_b.clone(),
pair.clone(),
test_state.chain_ids[0],
)
.await;
let hash_b = Hash::repeat_byte(69);
overseer_send(
&mut virtual_overseer,
CollatorProtocolMessage::NetworkBridgeUpdateV1(
NetworkBridgeEvent::OurViewChange(our_view![hash_b])
)
).await;
CollatorProtocolMessage::NetworkBridgeUpdateV1(NetworkBridgeEvent::OurViewChange(
our_view![hash_b],
)),
)
.await;
test_state.group_rotation_info = test_state.group_rotation_info.bump_rotation();
respond_to_core_info_queries(&mut virtual_overseer, &test_state).await;