mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 05:51:02 +00:00
refactor+feat: allow subsystems to send only declared messages, generate graphviz (#5314)
Closes #3774 Closes #3826
This commit is contained in:
committed by
GitHub
parent
26340b9054
commit
511891dcce
@@ -34,8 +34,7 @@ use polkadot_node_subsystem::{
|
||||
ApprovalCheckResult, ApprovalDistributionMessage, ApprovalVotingMessage,
|
||||
AssignmentCheckResult, NetworkBridgeEvent, NetworkBridgeMessage,
|
||||
},
|
||||
overseer, ActiveLeavesUpdate, FromOverseer, OverseerSignal, SpawnedSubsystem, SubsystemContext,
|
||||
SubsystemError,
|
||||
overseer, ActiveLeavesUpdate, FromOverseer, OverseerSignal, SpawnedSubsystem, SubsystemError,
|
||||
};
|
||||
use polkadot_primitives::v2::{
|
||||
BlockNumber, CandidateIndex, Hash, SessionIndex, ValidatorIndex, ValidatorSignature,
|
||||
@@ -321,11 +320,11 @@ enum PendingMessage {
|
||||
Approval(IndirectSignedApprovalVote),
|
||||
}
|
||||
|
||||
#[overseer::contextbounds(ApprovalDistribution, prefix = self::overseer)]
|
||||
impl State {
|
||||
async fn handle_network_msg(
|
||||
async fn handle_network_msg<Context>(
|
||||
&mut self,
|
||||
ctx: &mut (impl SubsystemContext<Message = ApprovalDistributionMessage>
|
||||
+ overseer::SubsystemContext<Message = ApprovalDistributionMessage>),
|
||||
ctx: &mut Context,
|
||||
metrics: &Metrics,
|
||||
event: NetworkBridgeEvent<net_protocol::ApprovalDistributionMessage>,
|
||||
rng: &mut (impl CryptoRng + Rng),
|
||||
@@ -377,10 +376,9 @@ impl State {
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_new_blocks(
|
||||
async fn handle_new_blocks<Context>(
|
||||
&mut self,
|
||||
ctx: &mut (impl SubsystemContext<Message = ApprovalDistributionMessage>
|
||||
+ overseer::SubsystemContext<Message = ApprovalDistributionMessage>),
|
||||
ctx: &mut Context,
|
||||
metrics: &Metrics,
|
||||
metas: Vec<BlockApprovalMeta>,
|
||||
rng: &mut (impl CryptoRng + Rng),
|
||||
@@ -421,11 +419,12 @@ impl State {
|
||||
);
|
||||
|
||||
{
|
||||
let sender = ctx.sender();
|
||||
for (peer_id, view) in self.peer_views.iter() {
|
||||
let intersection = view.iter().filter(|h| new_hashes.contains(h));
|
||||
let view_intersection = View::new(intersection.cloned(), view.finalized_number);
|
||||
Self::unify_with_peer(
|
||||
ctx,
|
||||
sender,
|
||||
metrics,
|
||||
&mut self.blocks,
|
||||
&self.topologies,
|
||||
@@ -496,10 +495,9 @@ impl State {
|
||||
self.enable_aggression(ctx, Resend::Yes, metrics).await;
|
||||
}
|
||||
|
||||
async fn handle_new_session_topology(
|
||||
async fn handle_new_session_topology<Context>(
|
||||
&mut self,
|
||||
ctx: &mut (impl SubsystemContext<Message = ApprovalDistributionMessage>
|
||||
+ overseer::SubsystemContext<Message = ApprovalDistributionMessage>),
|
||||
ctx: &mut Context,
|
||||
session: SessionIndex,
|
||||
topology: SessionGridTopology,
|
||||
) {
|
||||
@@ -520,15 +518,16 @@ impl State {
|
||||
.await;
|
||||
}
|
||||
|
||||
async fn process_incoming_peer_message(
|
||||
async fn process_incoming_peer_message<Context, R>(
|
||||
&mut self,
|
||||
ctx: &mut (impl SubsystemContext<Message = ApprovalDistributionMessage>
|
||||
+ overseer::SubsystemContext<Message = ApprovalDistributionMessage>),
|
||||
ctx: &mut Context,
|
||||
metrics: &Metrics,
|
||||
peer_id: PeerId,
|
||||
msg: protocol_v1::ApprovalDistributionMessage,
|
||||
rng: &mut (impl CryptoRng + Rng),
|
||||
) {
|
||||
rng: &mut R,
|
||||
) where
|
||||
R: CryptoRng + Rng,
|
||||
{
|
||||
match msg {
|
||||
protocol_v1::ApprovalDistributionMessage::Assignments(assignments) => {
|
||||
gum::trace!(
|
||||
@@ -612,15 +611,16 @@ impl State {
|
||||
|
||||
// handle a peer view change: requires that the peer is already connected
|
||||
// and has an entry in the `PeerData` struct.
|
||||
async fn handle_peer_view_change(
|
||||
async fn handle_peer_view_change<Context, R>(
|
||||
&mut self,
|
||||
ctx: &mut (impl SubsystemContext<Message = ApprovalDistributionMessage>
|
||||
+ overseer::SubsystemContext<Message = ApprovalDistributionMessage>),
|
||||
ctx: &mut Context,
|
||||
metrics: &Metrics,
|
||||
peer_id: PeerId,
|
||||
view: View,
|
||||
rng: &mut (impl CryptoRng + Rng),
|
||||
) {
|
||||
rng: &mut R,
|
||||
) where
|
||||
R: CryptoRng + Rng,
|
||||
{
|
||||
gum::trace!(target: LOG_TARGET, ?view, "Peer view change");
|
||||
let finalized_number = view.finalized_number;
|
||||
let old_view =
|
||||
@@ -646,7 +646,7 @@ impl State {
|
||||
}
|
||||
|
||||
Self::unify_with_peer(
|
||||
ctx,
|
||||
ctx.sender(),
|
||||
metrics,
|
||||
&mut self.blocks,
|
||||
&self.topologies,
|
||||
@@ -658,10 +658,9 @@ impl State {
|
||||
.await;
|
||||
}
|
||||
|
||||
async fn handle_block_finalized(
|
||||
async fn handle_block_finalized<Context>(
|
||||
&mut self,
|
||||
ctx: &mut (impl SubsystemContext<Message = ApprovalDistributionMessage>
|
||||
+ overseer::SubsystemContext<Message = ApprovalDistributionMessage>),
|
||||
ctx: &mut Context,
|
||||
metrics: &Metrics,
|
||||
finalized_number: BlockNumber,
|
||||
) {
|
||||
@@ -687,16 +686,17 @@ impl State {
|
||||
self.enable_aggression(ctx, Resend::No, metrics).await;
|
||||
}
|
||||
|
||||
async fn import_and_circulate_assignment(
|
||||
async fn import_and_circulate_assignment<Context, R>(
|
||||
&mut self,
|
||||
ctx: &mut (impl SubsystemContext<Message = ApprovalDistributionMessage>
|
||||
+ overseer::SubsystemContext<Message = ApprovalDistributionMessage>),
|
||||
ctx: &mut Context,
|
||||
metrics: &Metrics,
|
||||
source: MessageSource,
|
||||
assignment: IndirectAssignmentCert,
|
||||
claimed_candidate_index: CandidateIndex,
|
||||
rng: &mut (impl CryptoRng + Rng),
|
||||
) {
|
||||
rng: &mut R,
|
||||
) where
|
||||
R: CryptoRng + Rng,
|
||||
{
|
||||
let block_hash = assignment.block_hash.clone();
|
||||
let validator_index = assignment.validator;
|
||||
|
||||
@@ -712,7 +712,7 @@ impl State {
|
||||
"Unexpected assignment",
|
||||
);
|
||||
if !self.recent_outdated_blocks.is_recent_outdated(&block_hash) {
|
||||
modify_reputation(ctx, peer_id, COST_UNEXPECTED_MESSAGE).await;
|
||||
modify_reputation(ctx.sender(), peer_id, COST_UNEXPECTED_MESSAGE).await;
|
||||
}
|
||||
}
|
||||
return
|
||||
@@ -737,7 +737,7 @@ impl State {
|
||||
?message_subject,
|
||||
"Duplicate assignment",
|
||||
);
|
||||
modify_reputation(ctx, peer_id, COST_DUPLICATE_MESSAGE).await;
|
||||
modify_reputation(ctx.sender(), peer_id, COST_DUPLICATE_MESSAGE).await;
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -749,13 +749,13 @@ impl State {
|
||||
?message_subject,
|
||||
"Assignment from a peer is out of view",
|
||||
);
|
||||
modify_reputation(ctx, peer_id.clone(), COST_UNEXPECTED_MESSAGE).await;
|
||||
modify_reputation(ctx.sender(), peer_id.clone(), COST_UNEXPECTED_MESSAGE).await;
|
||||
},
|
||||
}
|
||||
|
||||
// if the assignment is known to be valid, reward the peer
|
||||
if entry.knowledge.contains(&message_subject, message_kind) {
|
||||
modify_reputation(ctx, peer_id.clone(), BENEFIT_VALID_MESSAGE).await;
|
||||
modify_reputation(ctx.sender(), peer_id.clone(), BENEFIT_VALID_MESSAGE).await;
|
||||
if let Some(peer_knowledge) = entry.known_by.get_mut(&peer_id) {
|
||||
gum::trace!(target: LOG_TARGET, ?peer_id, ?message_subject, "Known assignment");
|
||||
peer_knowledge.received.insert(message_subject, message_kind);
|
||||
@@ -791,7 +791,8 @@ impl State {
|
||||
);
|
||||
match result {
|
||||
AssignmentCheckResult::Accepted => {
|
||||
modify_reputation(ctx, peer_id.clone(), BENEFIT_VALID_MESSAGE_FIRST).await;
|
||||
modify_reputation(ctx.sender(), peer_id.clone(), BENEFIT_VALID_MESSAGE_FIRST)
|
||||
.await;
|
||||
entry.knowledge.known_messages.insert(message_subject.clone(), message_kind);
|
||||
if let Some(peer_knowledge) = entry.known_by.get_mut(&peer_id) {
|
||||
peer_knowledge.received.insert(message_subject.clone(), message_kind);
|
||||
@@ -819,7 +820,8 @@ impl State {
|
||||
?peer_id,
|
||||
"Got an assignment too far in the future",
|
||||
);
|
||||
modify_reputation(ctx, peer_id, COST_ASSIGNMENT_TOO_FAR_IN_THE_FUTURE).await;
|
||||
modify_reputation(ctx.sender(), peer_id, COST_ASSIGNMENT_TOO_FAR_IN_THE_FUTURE)
|
||||
.await;
|
||||
return
|
||||
},
|
||||
AssignmentCheckResult::Bad(error) => {
|
||||
@@ -830,7 +832,7 @@ impl State {
|
||||
%error,
|
||||
"Got a bad assignment from peer",
|
||||
);
|
||||
modify_reputation(ctx, peer_id, COST_INVALID_MESSAGE).await;
|
||||
modify_reputation(ctx.sender(), peer_id, COST_INVALID_MESSAGE).await;
|
||||
return
|
||||
},
|
||||
}
|
||||
@@ -946,10 +948,9 @@ impl State {
|
||||
}
|
||||
}
|
||||
|
||||
async fn import_and_circulate_approval(
|
||||
async fn import_and_circulate_approval<Context>(
|
||||
&mut self,
|
||||
ctx: &mut (impl SubsystemContext<Message = ApprovalDistributionMessage>
|
||||
+ overseer::SubsystemContext<Message = ApprovalDistributionMessage>),
|
||||
ctx: &mut Context,
|
||||
metrics: &Metrics,
|
||||
source: MessageSource,
|
||||
vote: IndirectSignedApprovalVote,
|
||||
@@ -963,7 +964,7 @@ impl State {
|
||||
_ => {
|
||||
if let Some(peer_id) = source.peer_id() {
|
||||
if !self.recent_outdated_blocks.is_recent_outdated(&block_hash) {
|
||||
modify_reputation(ctx, peer_id, COST_UNEXPECTED_MESSAGE).await;
|
||||
modify_reputation(ctx.sender(), peer_id, COST_UNEXPECTED_MESSAGE).await;
|
||||
}
|
||||
}
|
||||
return
|
||||
@@ -982,7 +983,7 @@ impl State {
|
||||
?message_subject,
|
||||
"Unknown approval assignment",
|
||||
);
|
||||
modify_reputation(ctx, peer_id, COST_UNEXPECTED_MESSAGE).await;
|
||||
modify_reputation(ctx.sender(), peer_id, COST_UNEXPECTED_MESSAGE).await;
|
||||
return
|
||||
}
|
||||
|
||||
@@ -999,7 +1000,7 @@ impl State {
|
||||
"Duplicate approval",
|
||||
);
|
||||
|
||||
modify_reputation(ctx, peer_id, COST_DUPLICATE_MESSAGE).await;
|
||||
modify_reputation(ctx.sender(), peer_id, COST_DUPLICATE_MESSAGE).await;
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -1011,14 +1012,14 @@ impl State {
|
||||
?message_subject,
|
||||
"Approval from a peer is out of view",
|
||||
);
|
||||
modify_reputation(ctx, peer_id.clone(), COST_UNEXPECTED_MESSAGE).await;
|
||||
modify_reputation(ctx.sender(), peer_id.clone(), COST_UNEXPECTED_MESSAGE).await;
|
||||
},
|
||||
}
|
||||
|
||||
// if the approval is known to be valid, reward the peer
|
||||
if entry.knowledge.contains(&message_subject, message_kind) {
|
||||
gum::trace!(target: LOG_TARGET, ?peer_id, ?message_subject, "Known approval");
|
||||
modify_reputation(ctx, peer_id.clone(), BENEFIT_VALID_MESSAGE).await;
|
||||
modify_reputation(ctx.sender(), peer_id.clone(), BENEFIT_VALID_MESSAGE).await;
|
||||
if let Some(peer_knowledge) = entry.known_by.get_mut(&peer_id) {
|
||||
peer_knowledge.received.insert(message_subject.clone(), message_kind);
|
||||
}
|
||||
@@ -1049,7 +1050,8 @@ impl State {
|
||||
);
|
||||
match result {
|
||||
ApprovalCheckResult::Accepted => {
|
||||
modify_reputation(ctx, peer_id.clone(), BENEFIT_VALID_MESSAGE_FIRST).await;
|
||||
modify_reputation(ctx.sender(), peer_id.clone(), BENEFIT_VALID_MESSAGE_FIRST)
|
||||
.await;
|
||||
|
||||
entry.knowledge.insert(message_subject.clone(), message_kind);
|
||||
if let Some(peer_knowledge) = entry.known_by.get_mut(&peer_id) {
|
||||
@@ -1057,7 +1059,7 @@ impl State {
|
||||
}
|
||||
},
|
||||
ApprovalCheckResult::Bad(error) => {
|
||||
modify_reputation(ctx, peer_id, COST_INVALID_MESSAGE).await;
|
||||
modify_reputation(ctx.sender(), peer_id, COST_INVALID_MESSAGE).await;
|
||||
gum::info!(
|
||||
target: LOG_TARGET,
|
||||
?peer_id,
|
||||
@@ -1209,8 +1211,7 @@ impl State {
|
||||
}
|
||||
|
||||
async fn unify_with_peer(
|
||||
ctx: &mut (impl SubsystemContext<Message = ApprovalDistributionMessage>
|
||||
+ overseer::SubsystemContext<Message = ApprovalDistributionMessage>),
|
||||
sender: &mut impl overseer::ApprovalDistributionSenderTrait,
|
||||
metrics: &Metrics,
|
||||
entries: &mut HashMap<Hash, BlockEntry>,
|
||||
topologies: &SessionGridTopologies,
|
||||
@@ -1326,13 +1327,14 @@ impl State {
|
||||
"Sending assignments to unified peer",
|
||||
);
|
||||
|
||||
ctx.send_message(NetworkBridgeMessage::SendValidationMessage(
|
||||
vec![peer_id.clone()],
|
||||
Versioned::V1(protocol_v1::ValidationProtocol::ApprovalDistribution(
|
||||
protocol_v1::ApprovalDistributionMessage::Assignments(assignments_to_send),
|
||||
)),
|
||||
))
|
||||
.await;
|
||||
sender
|
||||
.send_message(NetworkBridgeMessage::SendValidationMessage(
|
||||
vec![peer_id.clone()],
|
||||
Versioned::V1(protocol_v1::ValidationProtocol::ApprovalDistribution(
|
||||
protocol_v1::ApprovalDistributionMessage::Assignments(assignments_to_send),
|
||||
)),
|
||||
))
|
||||
.await;
|
||||
}
|
||||
|
||||
if !approvals_to_send.is_empty() {
|
||||
@@ -1343,20 +1345,20 @@ impl State {
|
||||
"Sending approvals to unified peer",
|
||||
);
|
||||
|
||||
ctx.send_message(NetworkBridgeMessage::SendValidationMessage(
|
||||
vec![peer_id],
|
||||
Versioned::V1(protocol_v1::ValidationProtocol::ApprovalDistribution(
|
||||
protocol_v1::ApprovalDistributionMessage::Approvals(approvals_to_send),
|
||||
)),
|
||||
))
|
||||
.await;
|
||||
sender
|
||||
.send_message(NetworkBridgeMessage::SendValidationMessage(
|
||||
vec![peer_id],
|
||||
Versioned::V1(protocol_v1::ValidationProtocol::ApprovalDistribution(
|
||||
protocol_v1::ApprovalDistributionMessage::Approvals(approvals_to_send),
|
||||
)),
|
||||
))
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
async fn enable_aggression(
|
||||
async fn enable_aggression<Context>(
|
||||
&mut self,
|
||||
ctx: &mut (impl SubsystemContext<Message = ApprovalDistributionMessage>
|
||||
+ overseer::SubsystemContext<Message = ApprovalDistributionMessage>),
|
||||
ctx: &mut Context,
|
||||
resend: Resend,
|
||||
metrics: &Metrics,
|
||||
) {
|
||||
@@ -1457,14 +1459,17 @@ impl State {
|
||||
//
|
||||
// Note that the required routing of a message can be modified even if the
|
||||
// topology is unknown yet.
|
||||
async fn adjust_required_routing_and_propagate(
|
||||
ctx: &mut (impl SubsystemContext<Message = ApprovalDistributionMessage>
|
||||
+ overseer::SubsystemContext<Message = ApprovalDistributionMessage>),
|
||||
#[overseer::contextbounds(ApprovalDistribution, prefix = self::overseer)]
|
||||
async fn adjust_required_routing_and_propagate<Context, BlockFilter, RoutingModifier>(
|
||||
ctx: &mut Context,
|
||||
blocks: &mut HashMap<Hash, BlockEntry>,
|
||||
topologies: &SessionGridTopologies,
|
||||
block_filter: impl Fn(&mut BlockEntry) -> bool,
|
||||
routing_modifier: impl Fn(&mut RequiredRouting, bool, &ValidatorIndex),
|
||||
) {
|
||||
block_filter: BlockFilter,
|
||||
routing_modifier: RoutingModifier,
|
||||
) where
|
||||
BlockFilter: Fn(&mut BlockEntry) -> bool,
|
||||
RoutingModifier: Fn(&mut RequiredRouting, bool, &ValidatorIndex),
|
||||
{
|
||||
let mut peer_assignments = HashMap::new();
|
||||
let mut peer_approvals = HashMap::new();
|
||||
|
||||
@@ -1566,8 +1571,7 @@ async fn adjust_required_routing_and_propagate(
|
||||
|
||||
/// Modify the reputation of a peer based on its behavior.
|
||||
async fn modify_reputation(
|
||||
ctx: &mut (impl SubsystemContext<Message = ApprovalDistributionMessage>
|
||||
+ overseer::SubsystemContext<Message = ApprovalDistributionMessage>),
|
||||
sender: &mut impl overseer::ApprovalDistributionSenderTrait,
|
||||
peer_id: PeerId,
|
||||
rep: Rep,
|
||||
) {
|
||||
@@ -1578,20 +1582,17 @@ async fn modify_reputation(
|
||||
"Reputation change for peer",
|
||||
);
|
||||
|
||||
ctx.send_message(NetworkBridgeMessage::ReportPeer(peer_id, rep)).await;
|
||||
sender.send_message(NetworkBridgeMessage::ReportPeer(peer_id, rep)).await;
|
||||
}
|
||||
|
||||
#[overseer::contextbounds(ApprovalDistribution, prefix = self::overseer)]
|
||||
impl ApprovalDistribution {
|
||||
/// Create a new instance of the [`ApprovalDistribution`] subsystem.
|
||||
pub fn new(metrics: Metrics) -> Self {
|
||||
Self { metrics }
|
||||
}
|
||||
|
||||
async fn run<Context>(self, ctx: Context)
|
||||
where
|
||||
Context: SubsystemContext<Message = ApprovalDistributionMessage>,
|
||||
Context: overseer::SubsystemContext<Message = ApprovalDistributionMessage>,
|
||||
{
|
||||
async fn run<Context>(self, ctx: Context) {
|
||||
let mut state = State::default();
|
||||
|
||||
// According to the docs of `rand`, this is a ChaCha12 RNG in practice
|
||||
@@ -1606,10 +1607,7 @@ impl ApprovalDistribution {
|
||||
mut ctx: Context,
|
||||
state: &mut State,
|
||||
rng: &mut (impl CryptoRng + Rng),
|
||||
) where
|
||||
Context: SubsystemContext<Message = ApprovalDistributionMessage>,
|
||||
Context: overseer::SubsystemContext<Message = ApprovalDistributionMessage>,
|
||||
{
|
||||
) {
|
||||
loop {
|
||||
let message = match ctx.recv().await {
|
||||
Ok(message) => message,
|
||||
@@ -1644,10 +1642,7 @@ impl ApprovalDistribution {
|
||||
msg: ApprovalDistributionMessage,
|
||||
metrics: &Metrics,
|
||||
rng: &mut (impl CryptoRng + Rng),
|
||||
) where
|
||||
Context: SubsystemContext<Message = ApprovalDistributionMessage>,
|
||||
Context: overseer::SubsystemContext<Message = ApprovalDistributionMessage>,
|
||||
{
|
||||
) {
|
||||
match msg {
|
||||
ApprovalDistributionMessage::NetworkBridgeUpdate(event) => {
|
||||
state.handle_network_msg(ctx, metrics, event, rng).await;
|
||||
@@ -1690,11 +1685,8 @@ impl ApprovalDistribution {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Context> overseer::Subsystem<Context, SubsystemError> for ApprovalDistribution
|
||||
where
|
||||
Context: SubsystemContext<Message = ApprovalDistributionMessage>,
|
||||
Context: overseer::SubsystemContext<Message = ApprovalDistributionMessage>,
|
||||
{
|
||||
#[overseer::subsystem(ApprovalDistribution, error=SubsystemError, prefix=self::overseer)]
|
||||
impl<Context> ApprovalDistribution {
|
||||
fn start(self, ctx: Context) -> SpawnedSubsystem {
|
||||
let future = self.run(ctx).map(|_| Ok(())).boxed();
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ use sp_keystore::SyncCryptoStorePtr;
|
||||
use polkadot_node_network_protocol::request_response::{v1, IncomingRequestReceiver};
|
||||
use polkadot_node_subsystem::{
|
||||
messages::AvailabilityDistributionMessage, overseer, FromOverseer, OverseerSignal,
|
||||
SpawnedSubsystem, SubsystemContext, SubsystemError,
|
||||
SpawnedSubsystem, SubsystemError,
|
||||
};
|
||||
|
||||
/// Error and [`Result`] type for this subsystem.
|
||||
@@ -68,11 +68,8 @@ pub struct IncomingRequestReceivers {
|
||||
pub chunk_req_receiver: IncomingRequestReceiver<v1::ChunkFetchingRequest>,
|
||||
}
|
||||
|
||||
impl<Context> overseer::Subsystem<Context, SubsystemError> for AvailabilityDistributionSubsystem
|
||||
where
|
||||
Context: SubsystemContext<Message = AvailabilityDistributionMessage>,
|
||||
Context: overseer::SubsystemContext<Message = AvailabilityDistributionMessage>,
|
||||
{
|
||||
#[overseer::subsystem(AvailabilityDistribution, error=SubsystemError, prefix=self::overseer)]
|
||||
impl<Context> AvailabilityDistributionSubsystem {
|
||||
fn start(self, ctx: Context) -> SpawnedSubsystem {
|
||||
let future = self
|
||||
.run(ctx)
|
||||
@@ -83,6 +80,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[overseer::contextbounds(AvailabilityDistribution, prefix = self::overseer)]
|
||||
impl AvailabilityDistributionSubsystem {
|
||||
/// Create a new instance of the availability distribution.
|
||||
pub fn new(
|
||||
@@ -95,11 +93,7 @@ impl AvailabilityDistributionSubsystem {
|
||||
}
|
||||
|
||||
/// Start processing work as passed on from the Overseer.
|
||||
async fn run<Context>(self, mut ctx: Context) -> std::result::Result<(), FatalError>
|
||||
where
|
||||
Context: SubsystemContext<Message = AvailabilityDistributionMessage>,
|
||||
Context: overseer::SubsystemContext<Message = AvailabilityDistributionMessage>,
|
||||
{
|
||||
async fn run<Context>(self, mut ctx: Context) -> std::result::Result<(), FatalError> {
|
||||
let Self { mut runtime, recvs, metrics } = self;
|
||||
|
||||
let IncomingRequestReceivers { pov_req_receiver, chunk_req_receiver } = recvs;
|
||||
|
||||
@@ -27,7 +27,7 @@ use polkadot_node_primitives::PoV;
|
||||
use polkadot_node_subsystem::{
|
||||
jaeger,
|
||||
messages::{IfDisconnected, NetworkBridgeMessage},
|
||||
SubsystemContext,
|
||||
overseer,
|
||||
};
|
||||
use polkadot_node_subsystem_util::runtime::RuntimeInfo;
|
||||
use polkadot_primitives::v2::{AuthorityDiscoveryId, CandidateHash, Hash, ValidatorIndex};
|
||||
@@ -39,6 +39,7 @@ use crate::{
|
||||
};
|
||||
|
||||
/// Start background worker for taking care of fetching the requested `PoV` from the network.
|
||||
#[overseer::contextbounds(AvailabilityDistribution, prefix = self::overseer)]
|
||||
pub async fn fetch_pov<Context>(
|
||||
ctx: &mut Context,
|
||||
runtime: &mut RuntimeInfo,
|
||||
@@ -48,10 +49,7 @@ pub async fn fetch_pov<Context>(
|
||||
pov_hash: Hash,
|
||||
tx: oneshot::Sender<PoV>,
|
||||
metrics: Metrics,
|
||||
) -> Result<()>
|
||||
where
|
||||
Context: SubsystemContext,
|
||||
{
|
||||
) -> Result<()> {
|
||||
let info = &runtime.get_session_info(ctx.sender(), parent).await?.session_info;
|
||||
let authority_id = info
|
||||
.discovery_keys
|
||||
|
||||
@@ -30,8 +30,8 @@ use polkadot_node_network_protocol::request_response::{
|
||||
use polkadot_node_primitives::ErasureChunk;
|
||||
use polkadot_node_subsystem::{
|
||||
jaeger,
|
||||
messages::{AllMessages, AvailabilityStoreMessage, IfDisconnected, NetworkBridgeMessage},
|
||||
SubsystemContext,
|
||||
messages::{AvailabilityStoreMessage, IfDisconnected, NetworkBridgeMessage},
|
||||
overseer,
|
||||
};
|
||||
use polkadot_primitives::v2::{
|
||||
AuthorityDiscoveryId, BlakeTwo256, CandidateHash, GroupIndex, Hash, HashT, OccupiedCore,
|
||||
@@ -84,7 +84,7 @@ enum FetchedState {
|
||||
/// Messages sent from `FetchTask`s to be handled/forwarded.
|
||||
pub enum FromFetchTask {
|
||||
/// Message to other subsystem.
|
||||
Message(AllMessages),
|
||||
Message(overseer::AvailabilityDistributionOutgoingMessages),
|
||||
|
||||
/// Concluded with result.
|
||||
///
|
||||
@@ -171,14 +171,12 @@ impl FetchTaskConfig {
|
||||
}
|
||||
}
|
||||
|
||||
#[overseer::contextbounds(AvailabilityDistribution, prefix = self::overseer)]
|
||||
impl FetchTask {
|
||||
/// Start fetching a chunk.
|
||||
///
|
||||
/// A task handling the fetching of the configured chunk will be spawned.
|
||||
pub async fn start<Context>(config: FetchTaskConfig, ctx: &mut Context) -> Result<Self>
|
||||
where
|
||||
Context: SubsystemContext,
|
||||
{
|
||||
pub async fn start<Context>(config: FetchTaskConfig, ctx: &mut Context) -> Result<Self> {
|
||||
let FetchTaskConfig { prepared_running, live_in } = config;
|
||||
|
||||
if let Some(running) = prepared_running {
|
||||
@@ -333,9 +331,10 @@ impl RunningTask {
|
||||
let requests = Requests::ChunkFetchingV1(full_request);
|
||||
|
||||
self.sender
|
||||
.send(FromFetchTask::Message(AllMessages::NetworkBridge(
|
||||
NetworkBridgeMessage::SendRequests(vec![requests], IfDisconnected::ImmediateError),
|
||||
)))
|
||||
.send(FromFetchTask::Message(
|
||||
NetworkBridgeMessage::SendRequests(vec![requests], IfDisconnected::ImmediateError)
|
||||
.into(),
|
||||
))
|
||||
.await
|
||||
.map_err(|_| TaskError::ShuttingDown)?;
|
||||
|
||||
@@ -413,13 +412,14 @@ impl RunningTask {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
let r = self
|
||||
.sender
|
||||
.send(FromFetchTask::Message(AllMessages::AvailabilityStore(
|
||||
.send(FromFetchTask::Message(
|
||||
AvailabilityStoreMessage::StoreChunk {
|
||||
candidate_hash: self.request.candidate_hash,
|
||||
chunk,
|
||||
tx,
|
||||
},
|
||||
)))
|
||||
}
|
||||
.into(),
|
||||
))
|
||||
.await;
|
||||
if let Err(err) = r {
|
||||
gum::error!(target: LOG_TARGET, err= ?err, "Storing erasure chunk failed, system shutting down?");
|
||||
|
||||
@@ -227,7 +227,11 @@ impl TestRun {
|
||||
|
||||
/// Returns true, if after processing of the given message it would be OK for the stream to
|
||||
/// end.
|
||||
async fn handle_message(&self, msg: AllMessages) -> bool {
|
||||
async fn handle_message(
|
||||
&self,
|
||||
msg: overseer::AvailabilityDistributionOutgoingMessages,
|
||||
) -> bool {
|
||||
let msg = AllMessages::from(msg);
|
||||
match msg {
|
||||
AllMessages::NetworkBridge(NetworkBridgeMessage::SendRequests(
|
||||
reqs,
|
||||
|
||||
@@ -33,8 +33,8 @@ use futures::{
|
||||
};
|
||||
|
||||
use polkadot_node_subsystem::{
|
||||
messages::{AllMessages, ChainApiMessage},
|
||||
ActivatedLeaf, ActiveLeavesUpdate, LeafStatus, SubsystemContext,
|
||||
messages::{ChainApiMessage, RuntimeApiMessage},
|
||||
overseer, ActivatedLeaf, ActiveLeavesUpdate, LeafStatus,
|
||||
};
|
||||
use polkadot_node_subsystem_util::runtime::{get_occupied_cores, RuntimeInfo};
|
||||
use polkadot_primitives::v2::{CandidateHash, Hash, OccupiedCore, SessionIndex};
|
||||
@@ -78,6 +78,7 @@ pub struct Requester {
|
||||
metrics: Metrics,
|
||||
}
|
||||
|
||||
#[overseer::contextbounds(AvailabilityDistribution, prefix = self::overseer)]
|
||||
impl Requester {
|
||||
/// How many ancestors of the leaf should we consider along with it.
|
||||
pub(crate) const LEAF_ANCESTRY_LEN_WITHIN_SESSION: usize = 3;
|
||||
@@ -99,10 +100,7 @@ impl Requester {
|
||||
ctx: &mut Context,
|
||||
runtime: &mut RuntimeInfo,
|
||||
update: ActiveLeavesUpdate,
|
||||
) -> Result<()>
|
||||
where
|
||||
Context: SubsystemContext,
|
||||
{
|
||||
) -> Result<()> {
|
||||
gum::trace!(target: LOG_TARGET, ?update, "Update fetching heads");
|
||||
let ActiveLeavesUpdate { activated, deactivated } = update;
|
||||
// Stale leaves happen after a reversion - we don't want to re-run availability there.
|
||||
@@ -125,13 +123,11 @@ impl Requester {
|
||||
ctx: &mut Context,
|
||||
runtime: &mut RuntimeInfo,
|
||||
new_head: ActivatedLeaf,
|
||||
) -> Result<()>
|
||||
where
|
||||
Context: SubsystemContext,
|
||||
{
|
||||
) -> Result<()> {
|
||||
let sender = &mut ctx.sender().clone();
|
||||
let ActivatedLeaf { hash: leaf, .. } = new_head;
|
||||
let (leaf_session_index, ancestors_in_session) = get_block_ancestors_in_same_session(
|
||||
ctx,
|
||||
sender,
|
||||
runtime,
|
||||
leaf,
|
||||
Self::LEAF_ANCESTRY_LEN_WITHIN_SESSION,
|
||||
@@ -139,7 +135,7 @@ impl Requester {
|
||||
.await?;
|
||||
// Also spawn or bump tasks for candidates in ancestry in the same session.
|
||||
for hash in std::iter::once(leaf).chain(ancestors_in_session) {
|
||||
let cores = get_occupied_cores(ctx, hash).await?;
|
||||
let cores = get_occupied_cores(sender, hash).await?;
|
||||
gum::trace!(
|
||||
target: LOG_TARGET,
|
||||
occupied_cores = ?cores,
|
||||
@@ -177,15 +173,12 @@ impl Requester {
|
||||
/// passed in leaf might be some later block where the candidate is still pending availability.
|
||||
async fn add_cores<Context>(
|
||||
&mut self,
|
||||
ctx: &mut Context,
|
||||
context: &mut Context,
|
||||
runtime: &mut RuntimeInfo,
|
||||
leaf: Hash,
|
||||
leaf_session_index: SessionIndex,
|
||||
cores: impl IntoIterator<Item = OccupiedCore>,
|
||||
) -> Result<()>
|
||||
where
|
||||
Context: SubsystemContext,
|
||||
{
|
||||
) -> Result<()> {
|
||||
for core in cores {
|
||||
match self.fetches.entry(core.candidate_hash) {
|
||||
Entry::Occupied(mut e) =>
|
||||
@@ -200,7 +193,7 @@ impl Requester {
|
||||
let task_cfg = self
|
||||
.session_cache
|
||||
.with_session_info(
|
||||
ctx,
|
||||
context,
|
||||
runtime,
|
||||
// We use leaf here, the relay_parent must be in the same session as the
|
||||
// leaf. This is guaranteed by runtime which ensures that cores are cleared
|
||||
@@ -221,7 +214,7 @@ impl Requester {
|
||||
});
|
||||
|
||||
if let Ok(Some(task_cfg)) = task_cfg {
|
||||
e.insert(FetchTask::start(task_cfg, ctx).await?);
|
||||
e.insert(FetchTask::start(task_cfg, context).await?);
|
||||
}
|
||||
// Not a validator, nothing to do.
|
||||
},
|
||||
@@ -232,9 +225,9 @@ impl Requester {
|
||||
}
|
||||
|
||||
impl Stream for Requester {
|
||||
type Item = AllMessages;
|
||||
type Item = overseer::AvailabilityDistributionOutgoingMessages;
|
||||
|
||||
fn poll_next(mut self: Pin<&mut Self>, ctx: &mut Context) -> Poll<Option<AllMessages>> {
|
||||
fn poll_next(mut self: Pin<&mut Self>, ctx: &mut Context) -> Poll<Option<Self::Item>> {
|
||||
loop {
|
||||
match Pin::new(&mut self.rx).poll_next(ctx) {
|
||||
Poll::Ready(Some(FromFetchTask::Message(m))) => return Poll::Ready(Some(m)),
|
||||
@@ -257,26 +250,27 @@ impl Stream for Requester {
|
||||
/// Requests up to `limit` ancestor hashes of relay parent in the same session.
|
||||
///
|
||||
/// Also returns session index of the `head`.
|
||||
async fn get_block_ancestors_in_same_session<Context>(
|
||||
ctx: &mut Context,
|
||||
async fn get_block_ancestors_in_same_session<Sender>(
|
||||
sender: &mut Sender,
|
||||
runtime: &mut RuntimeInfo,
|
||||
head: Hash,
|
||||
limit: usize,
|
||||
) -> Result<(SessionIndex, Vec<Hash>)>
|
||||
where
|
||||
Context: SubsystemContext,
|
||||
Sender:
|
||||
overseer::SubsystemSender<RuntimeApiMessage> + overseer::SubsystemSender<ChainApiMessage>,
|
||||
{
|
||||
// The order is parent, grandparent, ...
|
||||
//
|
||||
// `limit + 1` since a session index for the last element in ancestry
|
||||
// is obtained through its parent. It always gets truncated because
|
||||
// `session_ancestry_len` can only be incremented `ancestors.len() - 1` times.
|
||||
let mut ancestors = get_block_ancestors(ctx, head, limit + 1).await?;
|
||||
let mut ancestors = get_block_ancestors(sender, head, limit + 1).await?;
|
||||
let mut ancestors_iter = ancestors.iter();
|
||||
|
||||
// `head` is the child of the first block in `ancestors`, request its session index.
|
||||
let head_session_index = match ancestors_iter.next() {
|
||||
Some(parent) => runtime.get_session_index_for_child(ctx.sender(), *parent).await?,
|
||||
Some(parent) => runtime.get_session_index_for_child(sender, *parent).await?,
|
||||
None => {
|
||||
// No first element, i.e. empty.
|
||||
return Ok((0, ancestors))
|
||||
@@ -287,7 +281,7 @@ where
|
||||
// The first parent is skipped.
|
||||
for parent in ancestors_iter {
|
||||
// Parent is the i-th ancestor, request session index for its child -- (i-1)th element.
|
||||
let session_index = runtime.get_session_index_for_child(ctx.sender(), *parent).await?;
|
||||
let session_index = runtime.get_session_index_for_child(sender, *parent).await?;
|
||||
if session_index == head_session_index {
|
||||
session_ancestry_len += 1;
|
||||
} else {
|
||||
@@ -302,21 +296,22 @@ where
|
||||
}
|
||||
|
||||
/// Request up to `limit` ancestor hashes of relay parent from the Chain API.
|
||||
async fn get_block_ancestors<Context>(
|
||||
ctx: &mut Context,
|
||||
async fn get_block_ancestors<Sender>(
|
||||
sender: &mut Sender,
|
||||
relay_parent: Hash,
|
||||
limit: usize,
|
||||
) -> Result<Vec<Hash>>
|
||||
where
|
||||
Context: SubsystemContext,
|
||||
Sender: overseer::SubsystemSender<ChainApiMessage>,
|
||||
{
|
||||
let (tx, rx) = oneshot::channel();
|
||||
ctx.send_message(ChainApiMessage::Ancestors {
|
||||
hash: relay_parent,
|
||||
k: limit,
|
||||
response_channel: tx,
|
||||
})
|
||||
.await;
|
||||
sender
|
||||
.send_message(ChainApiMessage::Ancestors {
|
||||
hash: relay_parent,
|
||||
k: limit,
|
||||
response_channel: tx,
|
||||
})
|
||||
.await;
|
||||
|
||||
let ancestors = rx
|
||||
.await
|
||||
|
||||
@@ -19,7 +19,7 @@ use std::collections::HashSet;
|
||||
use lru::LruCache;
|
||||
use rand::{seq::SliceRandom, thread_rng};
|
||||
|
||||
use polkadot_node_subsystem::SubsystemContext;
|
||||
use polkadot_node_subsystem::overseer;
|
||||
use polkadot_node_subsystem_util::runtime::RuntimeInfo;
|
||||
use polkadot_primitives::v2::{
|
||||
AuthorityDiscoveryId, GroupIndex, Hash, SessionIndex, ValidatorIndex,
|
||||
@@ -79,6 +79,7 @@ pub struct BadValidators {
|
||||
pub bad_validators: Vec<AuthorityDiscoveryId>,
|
||||
}
|
||||
|
||||
#[overseer::contextbounds(AvailabilityDistribution, prefix = self::overseer)]
|
||||
impl SessionCache {
|
||||
/// Create a new `SessionCache`.
|
||||
pub fn new() -> Self {
|
||||
@@ -103,7 +104,6 @@ impl SessionCache {
|
||||
with_info: F,
|
||||
) -> Result<Option<R>>
|
||||
where
|
||||
Context: SubsystemContext,
|
||||
F: FnOnce(&SessionInfo) -> R,
|
||||
{
|
||||
if let Some(o_info) = self.session_info_cache.get(&session_index) {
|
||||
@@ -178,10 +178,7 @@ impl SessionCache {
|
||||
runtime: &mut RuntimeInfo,
|
||||
relay_parent: Hash,
|
||||
session_index: SessionIndex,
|
||||
) -> Result<Option<SessionInfo>>
|
||||
where
|
||||
Context: SubsystemContext,
|
||||
{
|
||||
) -> Result<Option<SessionInfo>> {
|
||||
let info = runtime
|
||||
.get_session_info_by_index(ctx.sender(), relay_parent, session_index)
|
||||
.await?;
|
||||
|
||||
@@ -43,7 +43,7 @@ pub async fn run_pov_receiver<Sender>(
|
||||
mut receiver: IncomingRequestReceiver<v1::PoVFetchingRequest>,
|
||||
metrics: Metrics,
|
||||
) where
|
||||
Sender: SubsystemSender,
|
||||
Sender: SubsystemSender<AvailabilityStoreMessage>,
|
||||
{
|
||||
loop {
|
||||
match receiver.recv(|| vec![COST_INVALID_REQUEST]).await.into_nested() {
|
||||
@@ -71,7 +71,7 @@ pub async fn run_chunk_receiver<Sender>(
|
||||
mut receiver: IncomingRequestReceiver<v1::ChunkFetchingRequest>,
|
||||
metrics: Metrics,
|
||||
) where
|
||||
Sender: SubsystemSender,
|
||||
Sender: SubsystemSender<AvailabilityStoreMessage>,
|
||||
{
|
||||
loop {
|
||||
match receiver.recv(|| vec![COST_INVALID_REQUEST]).await.into_nested() {
|
||||
@@ -105,7 +105,7 @@ pub async fn answer_pov_request_log<Sender>(
|
||||
req: IncomingRequest<v1::PoVFetchingRequest>,
|
||||
metrics: &Metrics,
|
||||
) where
|
||||
Sender: SubsystemSender,
|
||||
Sender: SubsystemSender<AvailabilityStoreMessage>,
|
||||
{
|
||||
let res = answer_pov_request(sender, req).await;
|
||||
match res {
|
||||
@@ -130,7 +130,7 @@ pub async fn answer_chunk_request_log<Sender>(
|
||||
metrics: &Metrics,
|
||||
) -> ()
|
||||
where
|
||||
Sender: SubsystemSender,
|
||||
Sender: SubsystemSender<AvailabilityStoreMessage>,
|
||||
{
|
||||
let res = answer_chunk_request(sender, req).await;
|
||||
match res {
|
||||
@@ -154,7 +154,7 @@ pub async fn answer_pov_request<Sender>(
|
||||
req: IncomingRequest<v1::PoVFetchingRequest>,
|
||||
) -> Result<bool>
|
||||
where
|
||||
Sender: SubsystemSender,
|
||||
Sender: SubsystemSender<AvailabilityStoreMessage>,
|
||||
{
|
||||
let _span = jaeger::Span::new(req.payload.candidate_hash, "answer-pov-request");
|
||||
|
||||
@@ -182,7 +182,7 @@ pub async fn answer_chunk_request<Sender>(
|
||||
req: IncomingRequest<v1::ChunkFetchingRequest>,
|
||||
) -> Result<bool>
|
||||
where
|
||||
Sender: SubsystemSender,
|
||||
Sender: SubsystemSender<AvailabilityStoreMessage>,
|
||||
{
|
||||
let span = jaeger::Span::new(req.payload.candidate_hash, "answer-chunk-request");
|
||||
|
||||
@@ -217,7 +217,7 @@ async fn query_chunk<Sender>(
|
||||
validator_index: ValidatorIndex,
|
||||
) -> std::result::Result<Option<ErasureChunk>, JfyiError>
|
||||
where
|
||||
Sender: SubsystemSender,
|
||||
Sender: SubsystemSender<AvailabilityStoreMessage>,
|
||||
{
|
||||
let (tx, rx) = oneshot::channel();
|
||||
sender
|
||||
@@ -245,7 +245,7 @@ async fn query_available_data<Sender>(
|
||||
candidate_hash: CandidateHash,
|
||||
) -> Result<Option<AvailableData>>
|
||||
where
|
||||
Sender: SubsystemSender,
|
||||
Sender: SubsystemSender<AvailabilityStoreMessage>,
|
||||
{
|
||||
let (tx, rx) = oneshot::channel();
|
||||
sender
|
||||
|
||||
@@ -51,9 +51,8 @@ use polkadot_node_subsystem::{
|
||||
errors::RecoveryError,
|
||||
jaeger,
|
||||
messages::{AvailabilityRecoveryMessage, AvailabilityStoreMessage, NetworkBridgeMessage},
|
||||
overseer::{self, Subsystem},
|
||||
ActiveLeavesUpdate, FromOverseer, OverseerSignal, SpawnedSubsystem, SubsystemContext,
|
||||
SubsystemError, SubsystemResult, SubsystemSender,
|
||||
overseer, ActiveLeavesUpdate, FromOverseer, OverseerSignal, SpawnedSubsystem, SubsystemError,
|
||||
SubsystemResult,
|
||||
};
|
||||
use polkadot_node_subsystem_util::request_session_info;
|
||||
use polkadot_primitives::v2::{
|
||||
@@ -156,8 +155,8 @@ enum Source {
|
||||
|
||||
/// A stateful reconstruction of availability data in reference to
|
||||
/// a candidate hash.
|
||||
struct RecoveryTask<S> {
|
||||
sender: S,
|
||||
struct RecoveryTask<Sender> {
|
||||
sender: Sender,
|
||||
|
||||
/// The parameters of the recovery process.
|
||||
params: RecoveryParams,
|
||||
@@ -177,7 +176,7 @@ impl RequestFromBackers {
|
||||
async fn run(
|
||||
&mut self,
|
||||
params: &RecoveryParams,
|
||||
sender: &mut impl SubsystemSender,
|
||||
sender: &mut impl overseer::AvailabilityRecoverySenderTrait,
|
||||
) -> Result<AvailableData, RecoveryError> {
|
||||
gum::trace!(
|
||||
target: LOG_TARGET,
|
||||
@@ -199,13 +198,10 @@ impl RequestFromBackers {
|
||||
);
|
||||
|
||||
sender
|
||||
.send_message(
|
||||
NetworkBridgeMessage::SendRequests(
|
||||
vec![Requests::AvailableDataFetchingV1(req)],
|
||||
IfDisconnected::ImmediateError,
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
.send_message(NetworkBridgeMessage::SendRequests(
|
||||
vec![Requests::AvailableDataFetchingV1(req)],
|
||||
IfDisconnected::ImmediateError,
|
||||
))
|
||||
.await;
|
||||
|
||||
match response.await {
|
||||
@@ -298,11 +294,13 @@ impl RequestChunksFromValidators {
|
||||
)
|
||||
}
|
||||
|
||||
async fn launch_parallel_requests(
|
||||
async fn launch_parallel_requests<Sender>(
|
||||
&mut self,
|
||||
params: &RecoveryParams,
|
||||
sender: &mut impl SubsystemSender,
|
||||
) {
|
||||
sender: &mut Sender,
|
||||
) where
|
||||
Sender: overseer::AvailabilityRecoverySenderTrait,
|
||||
{
|
||||
let num_requests = self.get_desired_request_count(params.threshold);
|
||||
let candidate_hash = ¶ms.candidate_hash;
|
||||
let already_requesting_count = self.requesting_chunks.len();
|
||||
@@ -358,9 +356,10 @@ impl RequestChunksFromValidators {
|
||||
}
|
||||
|
||||
sender
|
||||
.send_message(
|
||||
NetworkBridgeMessage::SendRequests(requests, IfDisconnected::ImmediateError).into(),
|
||||
)
|
||||
.send_message(NetworkBridgeMessage::SendRequests(
|
||||
requests,
|
||||
IfDisconnected::ImmediateError,
|
||||
))
|
||||
.await;
|
||||
}
|
||||
|
||||
@@ -483,20 +482,21 @@ impl RequestChunksFromValidators {
|
||||
}
|
||||
}
|
||||
|
||||
async fn run(
|
||||
async fn run<Sender>(
|
||||
&mut self,
|
||||
params: &RecoveryParams,
|
||||
sender: &mut impl SubsystemSender,
|
||||
) -> Result<AvailableData, RecoveryError> {
|
||||
sender: &mut Sender,
|
||||
) -> Result<AvailableData, RecoveryError>
|
||||
where
|
||||
Sender: overseer::AvailabilityRecoverySenderTrait,
|
||||
{
|
||||
let metrics = ¶ms.metrics;
|
||||
|
||||
// First query the store for any chunks we've got.
|
||||
{
|
||||
let (tx, rx) = oneshot::channel();
|
||||
sender
|
||||
.send_message(
|
||||
AvailabilityStoreMessage::QueryAllChunks(params.candidate_hash, tx).into(),
|
||||
)
|
||||
.send_message(AvailabilityStoreMessage::QueryAllChunks(params.candidate_hash, tx))
|
||||
.await;
|
||||
|
||||
match rx.await {
|
||||
@@ -646,16 +646,19 @@ fn reconstructed_data_matches_root(
|
||||
branches.root() == *expected_root
|
||||
}
|
||||
|
||||
impl<S: SubsystemSender> RecoveryTask<S> {
|
||||
impl<Sender> RecoveryTask<Sender>
|
||||
where
|
||||
Sender: overseer::AvailabilityRecoverySenderTrait,
|
||||
{
|
||||
async fn run(mut self) -> Result<AvailableData, RecoveryError> {
|
||||
// First just see if we have the data available locally.
|
||||
{
|
||||
let (tx, rx) = oneshot::channel();
|
||||
self.sender
|
||||
.send_message(
|
||||
AvailabilityStoreMessage::QueryAvailableData(self.params.candidate_hash, tx)
|
||||
.into(),
|
||||
)
|
||||
.send_message(AvailabilityStoreMessage::QueryAvailableData(
|
||||
self.params.candidate_hash,
|
||||
tx,
|
||||
))
|
||||
.await;
|
||||
|
||||
match rx.await {
|
||||
@@ -799,11 +802,8 @@ impl Default for State {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Context> Subsystem<Context, SubsystemError> for AvailabilityRecoverySubsystem
|
||||
where
|
||||
Context: SubsystemContext<Message = AvailabilityRecoveryMessage>,
|
||||
Context: overseer::SubsystemContext<Message = AvailabilityRecoveryMessage>,
|
||||
{
|
||||
#[overseer::subsystem(AvailabilityRecovery, error=SubsystemError, prefix=self::overseer)]
|
||||
impl<Context> AvailabilityRecoverySubsystem {
|
||||
fn start(self, ctx: Context) -> SpawnedSubsystem {
|
||||
let future = self
|
||||
.run(ctx)
|
||||
@@ -832,6 +832,7 @@ async fn handle_signal(state: &mut State, signal: OverseerSignal) -> SubsystemRe
|
||||
}
|
||||
|
||||
/// Machinery around launching recovery tasks into the background.
|
||||
#[overseer::contextbounds(AvailabilityRecovery, prefix = self::overseer)]
|
||||
async fn launch_recovery_task<Context>(
|
||||
state: &mut State,
|
||||
ctx: &mut Context,
|
||||
@@ -840,11 +841,7 @@ async fn launch_recovery_task<Context>(
|
||||
backing_group: Option<GroupIndex>,
|
||||
response_sender: oneshot::Sender<Result<AvailableData, RecoveryError>>,
|
||||
metrics: &Metrics,
|
||||
) -> error::Result<()>
|
||||
where
|
||||
Context: SubsystemContext<Message = AvailabilityRecoveryMessage>,
|
||||
Context: overseer::SubsystemContext<Message = AvailabilityRecoveryMessage>,
|
||||
{
|
||||
) -> error::Result<()> {
|
||||
let candidate_hash = receipt.hash();
|
||||
|
||||
let params = RecoveryParams {
|
||||
@@ -885,6 +882,7 @@ where
|
||||
}
|
||||
|
||||
/// Handles an availability recovery request.
|
||||
#[overseer::contextbounds(AvailabilityRecovery, prefix = self::overseer)]
|
||||
async fn handle_recover<Context>(
|
||||
state: &mut State,
|
||||
ctx: &mut Context,
|
||||
@@ -893,11 +891,7 @@ async fn handle_recover<Context>(
|
||||
backing_group: Option<GroupIndex>,
|
||||
response_sender: oneshot::Sender<Result<AvailableData, RecoveryError>>,
|
||||
metrics: &Metrics,
|
||||
) -> error::Result<()>
|
||||
where
|
||||
Context: SubsystemContext<Message = AvailabilityRecoveryMessage>,
|
||||
Context: overseer::SubsystemContext<Message = AvailabilityRecoveryMessage>,
|
||||
{
|
||||
) -> error::Result<()> {
|
||||
let candidate_hash = receipt.hash();
|
||||
|
||||
let span = jaeger::Span::new(candidate_hash, "availbility-recovery")
|
||||
@@ -953,14 +947,11 @@ where
|
||||
}
|
||||
|
||||
/// Queries a chunk from av-store.
|
||||
#[overseer::contextbounds(AvailabilityRecovery, prefix = self::overseer)]
|
||||
async fn query_full_data<Context>(
|
||||
ctx: &mut Context,
|
||||
candidate_hash: CandidateHash,
|
||||
) -> error::Result<Option<AvailableData>>
|
||||
where
|
||||
Context: SubsystemContext<Message = AvailabilityRecoveryMessage>,
|
||||
Context: overseer::SubsystemContext<Message = AvailabilityRecoveryMessage>,
|
||||
{
|
||||
) -> error::Result<Option<AvailableData>> {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
ctx.send_message(AvailabilityStoreMessage::QueryAvailableData(candidate_hash, tx))
|
||||
.await;
|
||||
@@ -968,6 +959,7 @@ where
|
||||
Ok(rx.await.map_err(error::Error::CanceledQueryFullData)?)
|
||||
}
|
||||
|
||||
#[overseer::contextbounds(AvailabilityRecovery, prefix = self::overseer)]
|
||||
impl AvailabilityRecoverySubsystem {
|
||||
/// Create a new instance of `AvailabilityRecoverySubsystem` which starts with a fast path to
|
||||
/// request data from backers.
|
||||
@@ -986,11 +978,7 @@ impl AvailabilityRecoverySubsystem {
|
||||
Self { fast_path: false, req_receiver, metrics }
|
||||
}
|
||||
|
||||
async fn run<Context>(self, mut ctx: Context) -> SubsystemResult<()>
|
||||
where
|
||||
Context: SubsystemContext<Message = AvailabilityRecoveryMessage>,
|
||||
Context: overseer::SubsystemContext<Message = AvailabilityRecoveryMessage>,
|
||||
{
|
||||
async fn run<Context>(self, mut ctx: Context) -> SubsystemResult<()> {
|
||||
let mut state = State::default();
|
||||
let Self { fast_path, mut req_receiver, metrics } = self;
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ use polkadot_node_network_protocol::{
|
||||
};
|
||||
use polkadot_node_subsystem::{
|
||||
jaeger, messages::*, overseer, ActiveLeavesUpdate, FromOverseer, OverseerSignal, PerLeafSpan,
|
||||
SpawnedSubsystem, SubsystemContext, SubsystemError, SubsystemResult,
|
||||
SpawnedSubsystem, SubsystemError, SubsystemResult,
|
||||
};
|
||||
use polkadot_node_subsystem_util::{self as util};
|
||||
use polkadot_primitives::v2::{
|
||||
@@ -204,6 +204,7 @@ pub struct BitfieldDistribution {
|
||||
metrics: Metrics,
|
||||
}
|
||||
|
||||
#[overseer::contextbounds(BitfieldDistribution, prefix = self::overseer)]
|
||||
impl BitfieldDistribution {
|
||||
/// Create a new instance of the `BitfieldDistribution` subsystem.
|
||||
pub fn new(metrics: Metrics) -> Self {
|
||||
@@ -211,11 +212,7 @@ impl BitfieldDistribution {
|
||||
}
|
||||
|
||||
/// Start processing work as passed on from the Overseer.
|
||||
async fn run<Context>(self, ctx: Context)
|
||||
where
|
||||
Context: SubsystemContext<Message = BitfieldDistributionMessage>,
|
||||
Context: overseer::SubsystemContext<Message = BitfieldDistributionMessage>,
|
||||
{
|
||||
async fn run<Context>(self, ctx: Context) {
|
||||
let mut state = ProtocolState::default();
|
||||
let mut rng = rand::rngs::StdRng::from_entropy();
|
||||
self.run_inner(ctx, &mut state, &mut rng).await
|
||||
@@ -226,10 +223,7 @@ impl BitfieldDistribution {
|
||||
mut ctx: Context,
|
||||
state: &mut ProtocolState,
|
||||
rng: &mut (impl CryptoRng + Rng),
|
||||
) where
|
||||
Context: SubsystemContext<Message = BitfieldDistributionMessage>,
|
||||
Context: overseer::SubsystemContext<Message = BitfieldDistributionMessage>,
|
||||
{
|
||||
) {
|
||||
// work: process incoming messages from the overseer and process accordingly.
|
||||
|
||||
loop {
|
||||
@@ -316,17 +310,20 @@ impl BitfieldDistribution {
|
||||
}
|
||||
|
||||
/// Modify the reputation of a peer based on its behavior.
|
||||
async fn modify_reputation<Context>(ctx: &mut Context, relay_parent: Hash, peer: PeerId, rep: Rep)
|
||||
where
|
||||
Context: SubsystemContext<Message = BitfieldDistributionMessage>,
|
||||
{
|
||||
async fn modify_reputation(
|
||||
sender: &mut impl overseer::BitfieldDistributionSenderTrait,
|
||||
relay_parent: Hash,
|
||||
peer: PeerId,
|
||||
rep: Rep,
|
||||
) {
|
||||
gum::trace!(target: LOG_TARGET, ?relay_parent, ?rep, %peer, "reputation change");
|
||||
|
||||
ctx.send_message(NetworkBridgeMessage::ReportPeer(peer, rep)).await
|
||||
sender.send_message(NetworkBridgeMessage::ReportPeer(peer, rep)).await
|
||||
}
|
||||
/// Distribute a given valid and signature checked bitfield message.
|
||||
///
|
||||
/// For this variant the source is this node.
|
||||
#[overseer::contextbounds(BitfieldDistribution, prefix=self::overseer)]
|
||||
async fn handle_bitfield_distribution<Context>(
|
||||
ctx: &mut Context,
|
||||
state: &mut ProtocolState,
|
||||
@@ -334,9 +331,7 @@ async fn handle_bitfield_distribution<Context>(
|
||||
relay_parent: Hash,
|
||||
signed_availability: SignedAvailabilityBitfield,
|
||||
rng: &mut (impl CryptoRng + Rng),
|
||||
) where
|
||||
Context: SubsystemContext<Message = BitfieldDistributionMessage>,
|
||||
{
|
||||
) {
|
||||
let _timer = metrics.time_handle_bitfield_distribution();
|
||||
|
||||
// Ignore anything the overseer did not tell this subsystem to work on
|
||||
@@ -389,6 +384,7 @@ async fn handle_bitfield_distribution<Context>(
|
||||
/// Distribute a given valid and signature checked bitfield message.
|
||||
///
|
||||
/// Can be originated by another subsystem or received via network from another peer.
|
||||
#[overseer::contextbounds(BitfieldDistribution, prefix=self::overseer)]
|
||||
async fn relay_message<Context>(
|
||||
ctx: &mut Context,
|
||||
job_data: &mut PerRelayParentData,
|
||||
@@ -398,9 +394,7 @@ async fn relay_message<Context>(
|
||||
message: BitfieldGossipMessage,
|
||||
required_routing: RequiredRouting,
|
||||
rng: &mut (impl CryptoRng + Rng),
|
||||
) where
|
||||
Context: SubsystemContext<Message = BitfieldDistributionMessage>,
|
||||
{
|
||||
) {
|
||||
let relay_parent = message.relay_parent;
|
||||
let span = job_data.span.child("relay-msg");
|
||||
|
||||
@@ -478,6 +472,7 @@ async fn relay_message<Context>(
|
||||
}
|
||||
|
||||
/// Handle an incoming message from a peer.
|
||||
#[overseer::contextbounds(BitfieldDistribution, prefix=self::overseer)]
|
||||
async fn process_incoming_peer_message<Context>(
|
||||
ctx: &mut Context,
|
||||
state: &mut ProtocolState,
|
||||
@@ -485,9 +480,7 @@ async fn process_incoming_peer_message<Context>(
|
||||
origin: PeerId,
|
||||
message: protocol_v1::BitfieldDistributionMessage,
|
||||
rng: &mut (impl CryptoRng + Rng),
|
||||
) where
|
||||
Context: SubsystemContext<Message = BitfieldDistributionMessage>,
|
||||
{
|
||||
) {
|
||||
let protocol_v1::BitfieldDistributionMessage::Bitfield(relay_parent, bitfield) = message;
|
||||
gum::trace!(
|
||||
target: LOG_TARGET,
|
||||
@@ -497,7 +490,7 @@ async fn process_incoming_peer_message<Context>(
|
||||
);
|
||||
// we don't care about this, not part of our view.
|
||||
if !state.view.contains(&relay_parent) {
|
||||
modify_reputation(ctx, relay_parent, origin, COST_NOT_IN_VIEW).await;
|
||||
modify_reputation(ctx.sender(), relay_parent, origin, COST_NOT_IN_VIEW).await;
|
||||
return
|
||||
}
|
||||
|
||||
@@ -506,7 +499,7 @@ async fn process_incoming_peer_message<Context>(
|
||||
let job_data: &mut _ = if let Some(ref mut job_data) = job_data {
|
||||
job_data
|
||||
} else {
|
||||
modify_reputation(ctx, relay_parent, origin, COST_NOT_IN_VIEW).await;
|
||||
modify_reputation(ctx.sender(), relay_parent, origin, COST_NOT_IN_VIEW).await;
|
||||
return
|
||||
};
|
||||
|
||||
@@ -523,7 +516,7 @@ async fn process_incoming_peer_message<Context>(
|
||||
let validator_set = &job_data.validator_set;
|
||||
if validator_set.is_empty() {
|
||||
gum::trace!(target: LOG_TARGET, ?relay_parent, ?origin, "Validator set is empty",);
|
||||
modify_reputation(ctx, relay_parent, origin, COST_MISSING_PEER_SESSION_KEY).await;
|
||||
modify_reputation(ctx.sender(), relay_parent, origin, COST_MISSING_PEER_SESSION_KEY).await;
|
||||
return
|
||||
}
|
||||
|
||||
@@ -533,7 +526,7 @@ async fn process_incoming_peer_message<Context>(
|
||||
let validator = if let Some(validator) = validator_set.get(validator_index.0 as usize) {
|
||||
validator.clone()
|
||||
} else {
|
||||
modify_reputation(ctx, relay_parent, origin, COST_VALIDATOR_INDEX_INVALID).await;
|
||||
modify_reputation(ctx.sender(), relay_parent, origin, COST_VALIDATOR_INDEX_INVALID).await;
|
||||
return
|
||||
};
|
||||
|
||||
@@ -546,7 +539,7 @@ async fn process_incoming_peer_message<Context>(
|
||||
received_set.insert(validator.clone());
|
||||
} else {
|
||||
gum::trace!(target: LOG_TARGET, ?validator_index, ?origin, "Duplicate message");
|
||||
modify_reputation(ctx, relay_parent, origin, COST_PEER_DUPLICATE_MESSAGE).await;
|
||||
modify_reputation(ctx.sender(), relay_parent, origin, COST_PEER_DUPLICATE_MESSAGE).await;
|
||||
return
|
||||
};
|
||||
|
||||
@@ -560,13 +553,13 @@ async fn process_incoming_peer_message<Context>(
|
||||
"already received a message for validator",
|
||||
);
|
||||
if old_message.signed_availability.as_unchecked() == &bitfield {
|
||||
modify_reputation(ctx, relay_parent, origin, BENEFIT_VALID_MESSAGE).await;
|
||||
modify_reputation(ctx.sender(), relay_parent, origin, BENEFIT_VALID_MESSAGE).await;
|
||||
}
|
||||
return
|
||||
}
|
||||
let signed_availability = match bitfield.try_into_checked(&signing_context, &validator) {
|
||||
Err(_) => {
|
||||
modify_reputation(ctx, relay_parent, origin, COST_SIGNATURE_INVALID).await;
|
||||
modify_reputation(ctx.sender(), relay_parent, origin, COST_SIGNATURE_INVALID).await;
|
||||
return
|
||||
},
|
||||
Ok(bitfield) => bitfield,
|
||||
@@ -592,20 +585,19 @@ async fn process_incoming_peer_message<Context>(
|
||||
)
|
||||
.await;
|
||||
|
||||
modify_reputation(ctx, relay_parent, origin, BENEFIT_VALID_MESSAGE_FIRST).await
|
||||
modify_reputation(ctx.sender(), relay_parent, origin, BENEFIT_VALID_MESSAGE_FIRST).await
|
||||
}
|
||||
|
||||
/// Deal with network bridge updates and track what needs to be tracked
|
||||
/// which depends on the message type received.
|
||||
#[overseer::contextbounds(BitfieldDistribution, prefix=self::overseer)]
|
||||
async fn handle_network_msg<Context>(
|
||||
ctx: &mut Context,
|
||||
state: &mut ProtocolState,
|
||||
metrics: &Metrics,
|
||||
bridge_message: NetworkBridgeEvent<net_protocol::BitfieldDistributionMessage>,
|
||||
rng: &mut (impl CryptoRng + Rng),
|
||||
) where
|
||||
Context: SubsystemContext<Message = BitfieldDistributionMessage>,
|
||||
{
|
||||
) {
|
||||
let _timer = metrics.time_handle_network_msg();
|
||||
|
||||
match bridge_message {
|
||||
@@ -677,15 +669,14 @@ fn handle_our_view_change(state: &mut ProtocolState, view: OurView) {
|
||||
|
||||
// Send the difference between two views which were not sent
|
||||
// to that particular peer.
|
||||
#[overseer::contextbounds(BitfieldDistribution, prefix=self::overseer)]
|
||||
async fn handle_peer_view_change<Context>(
|
||||
ctx: &mut Context,
|
||||
state: &mut ProtocolState,
|
||||
origin: PeerId,
|
||||
view: View,
|
||||
rng: &mut (impl CryptoRng + Rng),
|
||||
) where
|
||||
Context: SubsystemContext<Message = BitfieldDistributionMessage>,
|
||||
{
|
||||
) {
|
||||
let added = state
|
||||
.peer_views
|
||||
.entry(origin.clone())
|
||||
@@ -736,15 +727,14 @@ async fn handle_peer_view_change<Context>(
|
||||
}
|
||||
|
||||
/// Send a gossip message and track it in the per relay parent data.
|
||||
#[overseer::contextbounds(BitfieldDistribution, prefix=self::overseer)]
|
||||
async fn send_tracked_gossip_message<Context>(
|
||||
ctx: &mut Context,
|
||||
state: &mut ProtocolState,
|
||||
dest: PeerId,
|
||||
validator: ValidatorId,
|
||||
message: BitfieldGossipMessage,
|
||||
) where
|
||||
Context: SubsystemContext<Message = BitfieldDistributionMessage>,
|
||||
{
|
||||
) {
|
||||
let job_data = if let Some(job_data) = state.per_relay_parent.get_mut(&message.relay_parent) {
|
||||
job_data
|
||||
} else {
|
||||
@@ -773,11 +763,8 @@ async fn send_tracked_gossip_message<Context>(
|
||||
.await;
|
||||
}
|
||||
|
||||
impl<Context> overseer::Subsystem<Context, SubsystemError> for BitfieldDistribution
|
||||
where
|
||||
Context: SubsystemContext<Message = BitfieldDistributionMessage>,
|
||||
Context: overseer::SubsystemContext<Message = BitfieldDistributionMessage>,
|
||||
{
|
||||
#[overseer::subsystem(BitfieldDistribution, error=SubsystemError, prefix=self::overseer)]
|
||||
impl<Context> BitfieldDistribution {
|
||||
fn start(self, ctx: Context) -> SpawnedSubsystem {
|
||||
let future = self.run(ctx).map(|_| Ok(())).boxed();
|
||||
|
||||
@@ -786,13 +773,11 @@ where
|
||||
}
|
||||
|
||||
/// Query our validator set and signing context for a particular relay parent.
|
||||
#[overseer::contextbounds(BitfieldDistribution, prefix=self::overseer)]
|
||||
async fn query_basics<Context>(
|
||||
ctx: &mut Context,
|
||||
relay_parent: Hash,
|
||||
) -> SubsystemResult<Option<(Vec<ValidatorId>, SigningContext)>>
|
||||
where
|
||||
Context: SubsystemContext<Message = BitfieldDistributionMessage>,
|
||||
{
|
||||
) -> SubsystemResult<Option<(Vec<ValidatorId>, SigningContext)>> {
|
||||
let (validators_tx, validators_rx) = oneshot::channel();
|
||||
let (session_tx, session_rx) = oneshot::channel();
|
||||
|
||||
|
||||
@@ -33,17 +33,18 @@ use polkadot_node_network_protocol::{
|
||||
v1 as protocol_v1, ObservedRole, OurView, PeerId, ProtocolVersion,
|
||||
UnifiedReputationChange as Rep, Versioned, View,
|
||||
};
|
||||
|
||||
use polkadot_node_subsystem::{
|
||||
errors::{SubsystemError, SubsystemResult},
|
||||
messages::{
|
||||
network_bridge_event::{NewGossipTopology, TopologyPeerInfo},
|
||||
AllMessages, CollatorProtocolMessage, NetworkBridgeEvent, NetworkBridgeMessage,
|
||||
ApprovalDistributionMessage, BitfieldDistributionMessage, CollatorProtocolMessage,
|
||||
GossipSupportMessage, NetworkBridgeEvent, NetworkBridgeMessage,
|
||||
StatementDistributionMessage,
|
||||
},
|
||||
overseer, ActivatedLeaf, ActiveLeavesUpdate, FromOverseer, OverseerSignal, SpawnedSubsystem,
|
||||
SubsystemContext, SubsystemSender,
|
||||
};
|
||||
use polkadot_node_subsystem_util::metrics::{self, prometheus};
|
||||
use polkadot_overseer::gen::{OverseerError, Subsystem};
|
||||
use polkadot_overseer::gen::OverseerError;
|
||||
use polkadot_primitives::v2::{AuthorityDiscoveryId, BlockNumber, Hash, ValidatorIndex};
|
||||
|
||||
/// Peer set info for network initialization.
|
||||
@@ -67,6 +68,9 @@ use network::{send_message, Network};
|
||||
|
||||
use crate::network::get_peer_id_by_authority_id;
|
||||
|
||||
mod metrics;
|
||||
use self::metrics::Metrics;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
@@ -83,206 +87,6 @@ const EMPTY_VIEW_COST: Rep = Rep::CostMajor("Peer sent us an empty view");
|
||||
// network bridge log target
|
||||
const LOG_TARGET: &'static str = "parachain::network-bridge";
|
||||
|
||||
/// Metrics for the network bridge.
|
||||
#[derive(Clone, Default)]
|
||||
pub struct Metrics(Option<MetricsInner>);
|
||||
|
||||
fn peer_set_label(peer_set: PeerSet, version: ProtocolVersion) -> &'static str {
|
||||
// Higher level code is meant to protect against this ever happening.
|
||||
peer_set.get_protocol_name_static(version).unwrap_or("<internal error>")
|
||||
}
|
||||
|
||||
impl Metrics {
|
||||
fn on_peer_connected(&self, peer_set: PeerSet, version: ProtocolVersion) {
|
||||
self.0.as_ref().map(|metrics| {
|
||||
metrics
|
||||
.connected_events
|
||||
.with_label_values(&[peer_set_label(peer_set, version)])
|
||||
.inc()
|
||||
});
|
||||
}
|
||||
|
||||
fn on_peer_disconnected(&self, peer_set: PeerSet, version: ProtocolVersion) {
|
||||
self.0.as_ref().map(|metrics| {
|
||||
metrics
|
||||
.disconnected_events
|
||||
.with_label_values(&[peer_set_label(peer_set, version)])
|
||||
.inc()
|
||||
});
|
||||
}
|
||||
|
||||
fn note_peer_count(&self, peer_set: PeerSet, version: ProtocolVersion, count: usize) {
|
||||
self.0.as_ref().map(|metrics| {
|
||||
metrics
|
||||
.peer_count
|
||||
.with_label_values(&[peer_set_label(peer_set, version)])
|
||||
.set(count as u64)
|
||||
});
|
||||
}
|
||||
|
||||
fn on_notification_received(&self, peer_set: PeerSet, version: ProtocolVersion, size: usize) {
|
||||
if let Some(metrics) = self.0.as_ref() {
|
||||
metrics
|
||||
.notifications_received
|
||||
.with_label_values(&[peer_set_label(peer_set, version)])
|
||||
.inc();
|
||||
|
||||
metrics
|
||||
.bytes_received
|
||||
.with_label_values(&[peer_set_label(peer_set, version)])
|
||||
.inc_by(size as u64);
|
||||
}
|
||||
}
|
||||
|
||||
fn on_notification_sent(
|
||||
&self,
|
||||
peer_set: PeerSet,
|
||||
version: ProtocolVersion,
|
||||
size: usize,
|
||||
to_peers: usize,
|
||||
) {
|
||||
if let Some(metrics) = self.0.as_ref() {
|
||||
metrics
|
||||
.notifications_sent
|
||||
.with_label_values(&[peer_set_label(peer_set, version)])
|
||||
.inc_by(to_peers as u64);
|
||||
|
||||
metrics
|
||||
.bytes_sent
|
||||
.with_label_values(&[peer_set_label(peer_set, version)])
|
||||
.inc_by((size * to_peers) as u64);
|
||||
}
|
||||
}
|
||||
|
||||
fn note_desired_peer_count(&self, peer_set: PeerSet, size: usize) {
|
||||
self.0.as_ref().map(|metrics| {
|
||||
metrics
|
||||
.desired_peer_count
|
||||
.with_label_values(&[peer_set.get_default_protocol_name()])
|
||||
.set(size as u64)
|
||||
});
|
||||
}
|
||||
|
||||
fn on_report_event(&self) {
|
||||
if let Some(metrics) = self.0.as_ref() {
|
||||
metrics.report_events.inc()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct MetricsInner {
|
||||
peer_count: prometheus::GaugeVec<prometheus::U64>,
|
||||
connected_events: prometheus::CounterVec<prometheus::U64>,
|
||||
disconnected_events: prometheus::CounterVec<prometheus::U64>,
|
||||
desired_peer_count: prometheus::GaugeVec<prometheus::U64>,
|
||||
report_events: prometheus::Counter<prometheus::U64>,
|
||||
|
||||
notifications_received: prometheus::CounterVec<prometheus::U64>,
|
||||
notifications_sent: prometheus::CounterVec<prometheus::U64>,
|
||||
|
||||
bytes_received: prometheus::CounterVec<prometheus::U64>,
|
||||
bytes_sent: prometheus::CounterVec<prometheus::U64>,
|
||||
}
|
||||
|
||||
impl metrics::Metrics for Metrics {
|
||||
fn try_register(
|
||||
registry: &prometheus::Registry,
|
||||
) -> std::result::Result<Self, prometheus::PrometheusError> {
|
||||
let metrics = MetricsInner {
|
||||
peer_count: prometheus::register(
|
||||
prometheus::GaugeVec::new(
|
||||
prometheus::Opts::new(
|
||||
"polkadot_parachain_peer_count",
|
||||
"The number of peers on a parachain-related peer-set",
|
||||
),
|
||||
&["protocol"]
|
||||
)?,
|
||||
registry,
|
||||
)?,
|
||||
connected_events: prometheus::register(
|
||||
prometheus::CounterVec::new(
|
||||
prometheus::Opts::new(
|
||||
"polkadot_parachain_peer_connect_events_total",
|
||||
"The number of peer connect events on a parachain notifications protocol",
|
||||
),
|
||||
&["protocol"]
|
||||
)?,
|
||||
registry,
|
||||
)?,
|
||||
disconnected_events: prometheus::register(
|
||||
prometheus::CounterVec::new(
|
||||
prometheus::Opts::new(
|
||||
"polkadot_parachain_peer_disconnect_events_total",
|
||||
"The number of peer disconnect events on a parachain notifications protocol",
|
||||
),
|
||||
&["protocol"]
|
||||
)?,
|
||||
registry,
|
||||
)?,
|
||||
desired_peer_count: prometheus::register(
|
||||
prometheus::GaugeVec::new(
|
||||
prometheus::Opts::new(
|
||||
"polkadot_parachain_desired_peer_count",
|
||||
"The number of peers that the local node is expected to connect to on a parachain-related peer-set (either including or not including unresolvable authorities, depending on whether `ConnectToValidators` or `ConnectToValidatorsResolved` was used.)",
|
||||
),
|
||||
&["protocol"]
|
||||
)?,
|
||||
registry,
|
||||
)?,
|
||||
report_events: prometheus::register(
|
||||
prometheus::Counter::new(
|
||||
"polkadot_parachain_network_report_events_total",
|
||||
"The amount of reputation changes issued by subsystems",
|
||||
)?,
|
||||
registry,
|
||||
)?,
|
||||
notifications_received: prometheus::register(
|
||||
prometheus::CounterVec::new(
|
||||
prometheus::Opts::new(
|
||||
"polkadot_parachain_notifications_received_total",
|
||||
"The number of notifications received on a parachain protocol",
|
||||
),
|
||||
&["protocol"]
|
||||
)?,
|
||||
registry,
|
||||
)?,
|
||||
notifications_sent: prometheus::register(
|
||||
prometheus::CounterVec::new(
|
||||
prometheus::Opts::new(
|
||||
"polkadot_parachain_notifications_sent_total",
|
||||
"The number of notifications sent on a parachain protocol",
|
||||
),
|
||||
&["protocol"]
|
||||
)?,
|
||||
registry,
|
||||
)?,
|
||||
bytes_received: prometheus::register(
|
||||
prometheus::CounterVec::new(
|
||||
prometheus::Opts::new(
|
||||
"polkadot_parachain_notification_bytes_received_total",
|
||||
"The number of bytes received on a parachain notification protocol",
|
||||
),
|
||||
&["protocol"]
|
||||
)?,
|
||||
registry,
|
||||
)?,
|
||||
bytes_sent: prometheus::register(
|
||||
prometheus::CounterVec::new(
|
||||
prometheus::Opts::new(
|
||||
"polkadot_parachain_notification_bytes_sent_total",
|
||||
"The number of bytes sent on a parachain notification protocol",
|
||||
),
|
||||
&["protocol"]
|
||||
)?,
|
||||
registry,
|
||||
)?,
|
||||
};
|
||||
|
||||
Ok(Metrics(Some(metrics)))
|
||||
}
|
||||
}
|
||||
|
||||
/// Messages from and to the network.
|
||||
///
|
||||
/// As transmitted to and received from subsystems.
|
||||
@@ -320,12 +124,11 @@ impl<N, AD> NetworkBridge<N, AD> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Net, AD, Context> Subsystem<Context, SubsystemError> for NetworkBridge<Net, AD>
|
||||
#[overseer::subsystem(NetworkBridge, error = SubsystemError, prefix = self::overseer)]
|
||||
impl<Net, AD, Context> NetworkBridge<Net, AD>
|
||||
where
|
||||
Net: Network + Sync,
|
||||
AD: validator_discovery::AuthorityDiscovery + Clone,
|
||||
Context: SubsystemContext<Message = NetworkBridgeMessage>
|
||||
+ overseer::SubsystemContext<Message = NetworkBridgeMessage>,
|
||||
{
|
||||
fn start(mut self, ctx: Context) -> SpawnedSubsystem {
|
||||
// The stream of networking events has to be created at initialization, otherwise the
|
||||
@@ -382,6 +185,7 @@ enum Mode {
|
||||
Active,
|
||||
}
|
||||
|
||||
#[overseer::contextbounds(NetworkBridge, prefix = self::overseer)]
|
||||
async fn handle_subsystem_messages<Context, N, AD>(
|
||||
mut ctx: Context,
|
||||
mut network_service: N,
|
||||
@@ -391,8 +195,6 @@ async fn handle_subsystem_messages<Context, N, AD>(
|
||||
metrics: Metrics,
|
||||
) -> Result<(), UnexpectedAbort>
|
||||
where
|
||||
Context: SubsystemContext<Message = NetworkBridgeMessage>,
|
||||
Context: overseer::SubsystemContext<Message = NetworkBridgeMessage>,
|
||||
N: Network,
|
||||
AD: validator_discovery::AuthorityDiscovery + Clone,
|
||||
{
|
||||
@@ -678,7 +480,7 @@ where
|
||||
}
|
||||
|
||||
async fn handle_network_messages<AD: validator_discovery::AuthorityDiscovery>(
|
||||
mut sender: impl SubsystemSender,
|
||||
mut sender: impl overseer::NetworkBridgeSenderTrait,
|
||||
mut network_service: impl Network,
|
||||
network_stream: BoxStream<'static, NetworkEvent>,
|
||||
mut authority_discovery_service: AD,
|
||||
@@ -1031,6 +833,7 @@ async fn handle_network_messages<AD: validator_discovery::AuthorityDiscovery>(
|
||||
/// #fn is_send<T: Send>();
|
||||
/// #is_send::<parking_lot::MutexGuard<'static, ()>();
|
||||
/// ```
|
||||
#[overseer::contextbounds(NetworkBridge, prefix = self::overseer)]
|
||||
async fn run_network<N, AD, Context>(
|
||||
bridge: NetworkBridge<N, AD>,
|
||||
mut ctx: Context,
|
||||
@@ -1039,8 +842,6 @@ async fn run_network<N, AD, Context>(
|
||||
where
|
||||
N: Network,
|
||||
AD: validator_discovery::AuthorityDiscovery + Clone,
|
||||
Context: SubsystemContext<Message = NetworkBridgeMessage>
|
||||
+ overseer::SubsystemContext<Message = NetworkBridgeMessage>,
|
||||
{
|
||||
let shared = Shared::default();
|
||||
|
||||
@@ -1105,14 +906,17 @@ fn construct_view(
|
||||
View::new(live_heads.take(MAX_VIEW_HEADS), finalized_number)
|
||||
}
|
||||
|
||||
fn update_our_view(
|
||||
net: &mut impl Network,
|
||||
ctx: &mut impl SubsystemContext<Message = NetworkBridgeMessage, AllMessages = AllMessages>,
|
||||
#[overseer::contextbounds(NetworkBridge, prefix = self::overseer)]
|
||||
fn update_our_view<Net, Context>(
|
||||
net: &mut Net,
|
||||
ctx: &mut Context,
|
||||
live_heads: &[ActivatedLeaf],
|
||||
shared: &Shared,
|
||||
finalized_number: BlockNumber,
|
||||
metrics: &Metrics,
|
||||
) {
|
||||
) where
|
||||
Net: Network,
|
||||
{
|
||||
let new_view = construct_view(live_heads.iter().map(|v| v.hash), finalized_number);
|
||||
|
||||
let (validation_peers, collation_peers) = {
|
||||
@@ -1238,54 +1042,79 @@ fn send_collation_message_v1(
|
||||
|
||||
async fn dispatch_validation_event_to_all(
|
||||
event: NetworkBridgeEvent<net_protocol::VersionedValidationProtocol>,
|
||||
ctx: &mut impl SubsystemSender,
|
||||
ctx: &mut impl overseer::NetworkBridgeSenderTrait,
|
||||
) {
|
||||
dispatch_validation_events_to_all(std::iter::once(event), ctx).await
|
||||
}
|
||||
|
||||
async fn dispatch_collation_event_to_all(
|
||||
event: NetworkBridgeEvent<net_protocol::VersionedCollationProtocol>,
|
||||
ctx: &mut impl SubsystemSender,
|
||||
ctx: &mut impl overseer::NetworkBridgeSenderTrait,
|
||||
) {
|
||||
dispatch_collation_events_to_all(std::iter::once(event), ctx).await
|
||||
}
|
||||
|
||||
fn dispatch_validation_event_to_all_unbounded(
|
||||
event: NetworkBridgeEvent<net_protocol::VersionedValidationProtocol>,
|
||||
ctx: &mut impl SubsystemSender,
|
||||
sender: &mut impl overseer::NetworkBridgeSenderTrait,
|
||||
) {
|
||||
for msg in AllMessages::dispatch_iter(event) {
|
||||
ctx.send_unbounded_message(msg);
|
||||
}
|
||||
event
|
||||
.focus()
|
||||
.ok()
|
||||
.map(StatementDistributionMessage::from)
|
||||
.and_then(|msg| Some(sender.send_unbounded_message(msg)));
|
||||
event
|
||||
.focus()
|
||||
.ok()
|
||||
.map(BitfieldDistributionMessage::from)
|
||||
.and_then(|msg| Some(sender.send_unbounded_message(msg)));
|
||||
event
|
||||
.focus()
|
||||
.ok()
|
||||
.map(ApprovalDistributionMessage::from)
|
||||
.and_then(|msg| Some(sender.send_unbounded_message(msg)));
|
||||
event
|
||||
.focus()
|
||||
.ok()
|
||||
.map(GossipSupportMessage::from)
|
||||
.and_then(|msg| Some(sender.send_unbounded_message(msg)));
|
||||
}
|
||||
|
||||
fn dispatch_collation_event_to_all_unbounded(
|
||||
event: NetworkBridgeEvent<net_protocol::VersionedCollationProtocol>,
|
||||
ctx: &mut impl SubsystemSender,
|
||||
sender: &mut impl overseer::NetworkBridgeSenderTrait,
|
||||
) {
|
||||
if let Some(msg) = event.focus().ok().map(CollatorProtocolMessage::NetworkBridgeUpdate) {
|
||||
ctx.send_unbounded_message(msg.into());
|
||||
if let Ok(msg) = event.focus() {
|
||||
sender.send_unbounded_message(CollatorProtocolMessage::NetworkBridgeUpdate(msg))
|
||||
}
|
||||
}
|
||||
|
||||
async fn dispatch_validation_events_to_all<I>(events: I, ctx: &mut impl SubsystemSender)
|
||||
where
|
||||
async fn dispatch_validation_events_to_all<I>(
|
||||
events: I,
|
||||
sender: &mut impl overseer::NetworkBridgeSenderTrait,
|
||||
) where
|
||||
I: IntoIterator<Item = NetworkBridgeEvent<net_protocol::VersionedValidationProtocol>>,
|
||||
I::IntoIter: Send,
|
||||
{
|
||||
ctx.send_messages(events.into_iter().flat_map(AllMessages::dispatch_iter)).await
|
||||
for event in events {
|
||||
sender
|
||||
.send_messages(event.focus().map(StatementDistributionMessage::from))
|
||||
.await;
|
||||
sender.send_messages(event.focus().map(BitfieldDistributionMessage::from)).await;
|
||||
sender.send_messages(event.focus().map(ApprovalDistributionMessage::from)).await;
|
||||
sender.send_messages(event.focus().map(GossipSupportMessage::from)).await;
|
||||
}
|
||||
}
|
||||
|
||||
async fn dispatch_collation_events_to_all<I>(events: I, ctx: &mut impl SubsystemSender)
|
||||
where
|
||||
async fn dispatch_collation_events_to_all<I>(
|
||||
events: I,
|
||||
ctx: &mut impl overseer::NetworkBridgeSenderTrait,
|
||||
) where
|
||||
I: IntoIterator<Item = NetworkBridgeEvent<net_protocol::VersionedCollationProtocol>>,
|
||||
I::IntoIter: Send,
|
||||
{
|
||||
let messages_for = |event: NetworkBridgeEvent<net_protocol::VersionedCollationProtocol>| {
|
||||
event
|
||||
.focus()
|
||||
.ok()
|
||||
.map(|m| AllMessages::CollatorProtocol(CollatorProtocolMessage::NetworkBridgeUpdate(m)))
|
||||
event.focus().ok().map(|m| CollatorProtocolMessage::NetworkBridgeUpdate(m))
|
||||
};
|
||||
|
||||
ctx.send_messages(events.into_iter().flat_map(messages_for)).await
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
// Copyright 2022 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use super::{PeerSet, ProtocolVersion};
|
||||
use polkadot_node_subsystem_util::metrics::{self, prometheus};
|
||||
|
||||
/// Metrics for the network bridge.
|
||||
#[derive(Clone, Default)]
|
||||
pub struct Metrics(pub(crate) Option<MetricsInner>);
|
||||
|
||||
fn peer_set_label(peer_set: PeerSet, version: ProtocolVersion) -> &'static str {
|
||||
// Higher level code is meant to protect against this ever happening.
|
||||
peer_set.get_protocol_name_static(version).unwrap_or("<internal error>")
|
||||
}
|
||||
|
||||
impl Metrics {
|
||||
pub fn on_peer_connected(&self, peer_set: PeerSet, version: ProtocolVersion) {
|
||||
self.0.as_ref().map(|metrics| {
|
||||
metrics
|
||||
.connected_events
|
||||
.with_label_values(&[peer_set_label(peer_set, version)])
|
||||
.inc()
|
||||
});
|
||||
}
|
||||
|
||||
pub fn on_peer_disconnected(&self, peer_set: PeerSet, version: ProtocolVersion) {
|
||||
self.0.as_ref().map(|metrics| {
|
||||
metrics
|
||||
.disconnected_events
|
||||
.with_label_values(&[peer_set_label(peer_set, version)])
|
||||
.inc()
|
||||
});
|
||||
}
|
||||
|
||||
pub fn note_peer_count(&self, peer_set: PeerSet, version: ProtocolVersion, count: usize) {
|
||||
self.0.as_ref().map(|metrics| {
|
||||
metrics
|
||||
.peer_count
|
||||
.with_label_values(&[peer_set_label(peer_set, version)])
|
||||
.set(count as u64)
|
||||
});
|
||||
}
|
||||
|
||||
pub fn on_notification_received(
|
||||
&self,
|
||||
peer_set: PeerSet,
|
||||
version: ProtocolVersion,
|
||||
size: usize,
|
||||
) {
|
||||
if let Some(metrics) = self.0.as_ref() {
|
||||
metrics
|
||||
.notifications_received
|
||||
.with_label_values(&[peer_set_label(peer_set, version)])
|
||||
.inc();
|
||||
|
||||
metrics
|
||||
.bytes_received
|
||||
.with_label_values(&[peer_set_label(peer_set, version)])
|
||||
.inc_by(size as u64);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_notification_sent(
|
||||
&self,
|
||||
peer_set: PeerSet,
|
||||
version: ProtocolVersion,
|
||||
size: usize,
|
||||
to_peers: usize,
|
||||
) {
|
||||
if let Some(metrics) = self.0.as_ref() {
|
||||
metrics
|
||||
.notifications_sent
|
||||
.with_label_values(&[peer_set_label(peer_set, version)])
|
||||
.inc_by(to_peers as u64);
|
||||
|
||||
metrics
|
||||
.bytes_sent
|
||||
.with_label_values(&[peer_set_label(peer_set, version)])
|
||||
.inc_by((size * to_peers) as u64);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn note_desired_peer_count(&self, peer_set: PeerSet, size: usize) {
|
||||
self.0.as_ref().map(|metrics| {
|
||||
metrics
|
||||
.desired_peer_count
|
||||
.with_label_values(&[peer_set.get_default_protocol_name()])
|
||||
.set(size as u64)
|
||||
});
|
||||
}
|
||||
|
||||
pub fn on_report_event(&self) {
|
||||
if let Some(metrics) = self.0.as_ref() {
|
||||
metrics.report_events.inc()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct MetricsInner {
|
||||
peer_count: prometheus::GaugeVec<prometheus::U64>,
|
||||
connected_events: prometheus::CounterVec<prometheus::U64>,
|
||||
disconnected_events: prometheus::CounterVec<prometheus::U64>,
|
||||
desired_peer_count: prometheus::GaugeVec<prometheus::U64>,
|
||||
report_events: prometheus::Counter<prometheus::U64>,
|
||||
|
||||
notifications_received: prometheus::CounterVec<prometheus::U64>,
|
||||
notifications_sent: prometheus::CounterVec<prometheus::U64>,
|
||||
|
||||
bytes_received: prometheus::CounterVec<prometheus::U64>,
|
||||
bytes_sent: prometheus::CounterVec<prometheus::U64>,
|
||||
}
|
||||
|
||||
impl metrics::Metrics for Metrics {
|
||||
fn try_register(
|
||||
registry: &prometheus::Registry,
|
||||
) -> std::result::Result<Self, prometheus::PrometheusError> {
|
||||
let metrics = MetricsInner {
|
||||
peer_count: prometheus::register(
|
||||
prometheus::GaugeVec::new(
|
||||
prometheus::Opts::new(
|
||||
"polkadot_parachain_peer_count",
|
||||
"The number of peers on a parachain-related peer-set",
|
||||
),
|
||||
&["protocol"]
|
||||
)?,
|
||||
registry,
|
||||
)?,
|
||||
connected_events: prometheus::register(
|
||||
prometheus::CounterVec::new(
|
||||
prometheus::Opts::new(
|
||||
"polkadot_parachain_peer_connect_events_total",
|
||||
"The number of peer connect events on a parachain notifications protocol",
|
||||
),
|
||||
&["protocol"]
|
||||
)?,
|
||||
registry,
|
||||
)?,
|
||||
disconnected_events: prometheus::register(
|
||||
prometheus::CounterVec::new(
|
||||
prometheus::Opts::new(
|
||||
"polkadot_parachain_peer_disconnect_events_total",
|
||||
"The number of peer disconnect events on a parachain notifications protocol",
|
||||
),
|
||||
&["protocol"]
|
||||
)?,
|
||||
registry,
|
||||
)?,
|
||||
desired_peer_count: prometheus::register(
|
||||
prometheus::GaugeVec::new(
|
||||
prometheus::Opts::new(
|
||||
"polkadot_parachain_desired_peer_count",
|
||||
"The number of peers that the local node is expected to connect to on a parachain-related peer-set (either including or not including unresolvable authorities, depending on whether `ConnectToValidators` or `ConnectToValidatorsResolved` was used.)",
|
||||
),
|
||||
&["protocol"]
|
||||
)?,
|
||||
registry,
|
||||
)?,
|
||||
report_events: prometheus::register(
|
||||
prometheus::Counter::new(
|
||||
"polkadot_parachain_network_report_events_total",
|
||||
"The amount of reputation changes issued by subsystems",
|
||||
)?,
|
||||
registry,
|
||||
)?,
|
||||
notifications_received: prometheus::register(
|
||||
prometheus::CounterVec::new(
|
||||
prometheus::Opts::new(
|
||||
"polkadot_parachain_notifications_received_total",
|
||||
"The number of notifications received on a parachain protocol",
|
||||
),
|
||||
&["protocol"]
|
||||
)?,
|
||||
registry,
|
||||
)?,
|
||||
notifications_sent: prometheus::register(
|
||||
prometheus::CounterVec::new(
|
||||
prometheus::Opts::new(
|
||||
"polkadot_parachain_notifications_sent_total",
|
||||
"The number of notifications sent on a parachain protocol",
|
||||
),
|
||||
&["protocol"]
|
||||
)?,
|
||||
registry,
|
||||
)?,
|
||||
bytes_received: prometheus::register(
|
||||
prometheus::CounterVec::new(
|
||||
prometheus::Opts::new(
|
||||
"polkadot_parachain_notification_bytes_received_total",
|
||||
"The number of bytes received on a parachain notification protocol",
|
||||
),
|
||||
&["protocol"]
|
||||
)?,
|
||||
registry,
|
||||
)?,
|
||||
bytes_sent: prometheus::register(
|
||||
prometheus::CounterVec::new(
|
||||
prometheus::Opts::new(
|
||||
"polkadot_parachain_notification_bytes_sent_total",
|
||||
"The number of bytes sent on a parachain notification protocol",
|
||||
),
|
||||
&["protocol"]
|
||||
)?,
|
||||
registry,
|
||||
)?,
|
||||
};
|
||||
|
||||
Ok(Metrics(Some(metrics)))
|
||||
}
|
||||
}
|
||||
@@ -34,8 +34,8 @@ use polkadot_node_network_protocol::{
|
||||
use polkadot_node_subsystem::{
|
||||
jaeger,
|
||||
messages::{
|
||||
ApprovalDistributionMessage, BitfieldDistributionMessage, GossipSupportMessage,
|
||||
StatementDistributionMessage,
|
||||
AllMessages, ApprovalDistributionMessage, BitfieldDistributionMessage,
|
||||
GossipSupportMessage, StatementDistributionMessage,
|
||||
},
|
||||
ActiveLeavesUpdate, FromOverseer, LeafStatus, OverseerSignal,
|
||||
};
|
||||
@@ -313,8 +313,9 @@ async fn assert_sends_validation_event_to_all(
|
||||
event: NetworkBridgeEvent<net_protocol::VersionedValidationProtocol>,
|
||||
virtual_overseer: &mut TestSubsystemContextHandle<NetworkBridgeMessage>,
|
||||
) {
|
||||
// Ordering must match the enum variant order
|
||||
// in `AllMessages`.
|
||||
// Ordering must be consistent across:
|
||||
// `fn dispatch_validation_event_to_all_unbounded`
|
||||
// `dispatch_validation_events_to_all`
|
||||
assert_matches!(
|
||||
virtual_overseer.recv().await,
|
||||
AllMessages::StatementDistribution(
|
||||
@@ -1190,54 +1191,6 @@ fn send_messages_to_peers() {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn spread_event_to_subsystems_is_up_to_date() {
|
||||
// Number of subsystems expected to be interested in a network event,
|
||||
// and hence the network event broadcasted to.
|
||||
const EXPECTED_COUNT: usize = 4;
|
||||
|
||||
let mut cnt = 0_usize;
|
||||
for msg in AllMessages::dispatch_iter(NetworkBridgeEvent::PeerDisconnected(PeerId::random())) {
|
||||
match msg {
|
||||
AllMessages::Empty => unreachable!("Nobody cares about the dummy"),
|
||||
AllMessages::CandidateValidation(_) => unreachable!("Not interested in network events"),
|
||||
AllMessages::CandidateBacking(_) => unreachable!("Not interested in network events"),
|
||||
AllMessages::ChainApi(_) => unreachable!("Not interested in network events"),
|
||||
AllMessages::CollatorProtocol(_) => unreachable!("Not interested in network events"),
|
||||
AllMessages::StatementDistribution(_) => {
|
||||
cnt += 1;
|
||||
},
|
||||
AllMessages::AvailabilityDistribution(_) =>
|
||||
unreachable!("Not interested in network events"),
|
||||
AllMessages::AvailabilityRecovery(_) =>
|
||||
unreachable!("Not interested in network events"),
|
||||
AllMessages::BitfieldDistribution(_) => {
|
||||
cnt += 1;
|
||||
},
|
||||
AllMessages::BitfieldSigning(_) => unreachable!("Not interested in network events"),
|
||||
AllMessages::Provisioner(_) => unreachable!("Not interested in network events"),
|
||||
AllMessages::RuntimeApi(_) => unreachable!("Not interested in network events"),
|
||||
AllMessages::AvailabilityStore(_) => unreachable!("Not interested in network events"),
|
||||
AllMessages::NetworkBridge(_) => unreachable!("Not interested in network events"),
|
||||
AllMessages::CollationGeneration(_) => unreachable!("Not interested in network events"),
|
||||
AllMessages::ApprovalVoting(_) => unreachable!("Not interested in network events"),
|
||||
AllMessages::ApprovalDistribution(_) => {
|
||||
cnt += 1;
|
||||
},
|
||||
AllMessages::GossipSupport(_) => {
|
||||
cnt += 1;
|
||||
},
|
||||
AllMessages::DisputeCoordinator(_) => unreachable!("Not interested in network events"),
|
||||
AllMessages::DisputeDistribution(_) => unreachable!("Not interested in network events"),
|
||||
AllMessages::ChainSelection(_) => unreachable!("Not interested in network events"),
|
||||
AllMessages::PvfChecker(_) => unreachable!("Not interested in network events"),
|
||||
// Add variants here as needed, `{ cnt += 1; }` for those that need to be
|
||||
// notified, `unreachable!()` for those that should not.
|
||||
}
|
||||
}
|
||||
assert_eq!(cnt, EXPECTED_COUNT);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn our_view_updates_decreasing_order_and_limited_to_max() {
|
||||
test_harness(done_syncing_oracle(), |test_harness| async move {
|
||||
|
||||
@@ -38,8 +38,10 @@ use polkadot_node_network_protocol::{
|
||||
use polkadot_node_primitives::{CollationSecondedSignal, PoV, Statement};
|
||||
use polkadot_node_subsystem::{
|
||||
jaeger,
|
||||
messages::{CollatorProtocolMessage, NetworkBridgeEvent, NetworkBridgeMessage},
|
||||
overseer, FromOverseer, OverseerSignal, PerLeafSpan, SubsystemContext,
|
||||
messages::{
|
||||
CollatorProtocolMessage, NetworkBridgeEvent, NetworkBridgeMessage, RuntimeApiMessage,
|
||||
},
|
||||
overseer, FromOverseer, OverseerSignal, PerLeafSpan,
|
||||
};
|
||||
use polkadot_node_subsystem_util::{
|
||||
metrics::{self, prometheus},
|
||||
@@ -360,6 +362,7 @@ impl State {
|
||||
/// or the relay-parent isn't in the active-leaves set, we ignore the message
|
||||
/// as it must be invalid in that case - although this indicates a logic error
|
||||
/// elsewhere in the node.
|
||||
#[overseer::contextbounds(CollatorProtocol, prefix = self::overseer)]
|
||||
async fn distribute_collation<Context>(
|
||||
ctx: &mut Context,
|
||||
runtime: &mut RuntimeInfo,
|
||||
@@ -368,11 +371,7 @@ async fn distribute_collation<Context>(
|
||||
receipt: CandidateReceipt,
|
||||
pov: PoV,
|
||||
result_sender: Option<oneshot::Sender<CollationSecondedSignal>>,
|
||||
) -> Result<()>
|
||||
where
|
||||
Context: SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
{
|
||||
) -> Result<()> {
|
||||
let relay_parent = receipt.descriptor.relay_parent;
|
||||
|
||||
// This collation is not in the active-leaves set.
|
||||
@@ -398,7 +397,7 @@ where
|
||||
|
||||
// Determine which core the para collated-on is assigned to.
|
||||
// If it is not scheduled then ignore the message.
|
||||
let (our_core, num_cores) = match determine_core(ctx, id, relay_parent).await? {
|
||||
let (our_core, num_cores) = match determine_core(ctx.sender(), id, relay_parent).await? {
|
||||
Some(core) => core,
|
||||
None => {
|
||||
gum::warn!(
|
||||
@@ -461,16 +460,12 @@ where
|
||||
|
||||
/// Get the Id of the Core that is assigned to the para being collated on if any
|
||||
/// and the total number of cores.
|
||||
async fn determine_core<Context>(
|
||||
ctx: &mut Context,
|
||||
async fn determine_core(
|
||||
sender: &mut impl overseer::SubsystemSender<RuntimeApiMessage>,
|
||||
para_id: ParaId,
|
||||
relay_parent: Hash,
|
||||
) -> Result<Option<(CoreIndex, usize)>>
|
||||
where
|
||||
Context: SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
{
|
||||
let cores = get_availability_cores(ctx, relay_parent).await?;
|
||||
) -> Result<Option<(CoreIndex, usize)>> {
|
||||
let cores = get_availability_cores(sender, relay_parent).await?;
|
||||
|
||||
for (idx, core) in cores.iter().enumerate() {
|
||||
if let CoreState::Scheduled(occupied) = core {
|
||||
@@ -493,17 +488,14 @@ struct GroupValidators {
|
||||
/// Figure out current group of validators assigned to the para being collated on.
|
||||
///
|
||||
/// Returns [`ValidatorId`]'s of current group as determined based on the `relay_parent`.
|
||||
#[overseer::contextbounds(CollatorProtocol, prefix = self::overseer)]
|
||||
async fn determine_our_validators<Context>(
|
||||
ctx: &mut Context,
|
||||
runtime: &mut RuntimeInfo,
|
||||
core_index: CoreIndex,
|
||||
cores: usize,
|
||||
relay_parent: Hash,
|
||||
) -> Result<GroupValidators>
|
||||
where
|
||||
Context: SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
{
|
||||
) -> Result<GroupValidators> {
|
||||
let session_index = runtime.get_session_index_for_child(ctx.sender(), relay_parent).await?;
|
||||
let info = &runtime
|
||||
.get_session_info_by_index(ctx.sender(), relay_parent, session_index)
|
||||
@@ -511,7 +503,7 @@ where
|
||||
.session_info;
|
||||
gum::debug!(target: LOG_TARGET, ?session_index, "Received session info");
|
||||
let groups = &info.validator_groups;
|
||||
let rotation_info = get_group_rotation_info(ctx, relay_parent).await?;
|
||||
let rotation_info = get_group_rotation_info(ctx.sender(), relay_parent).await?;
|
||||
|
||||
let current_group_index = rotation_info.group_for_core(core_index, cores);
|
||||
let current_validators = groups
|
||||
@@ -530,11 +522,8 @@ where
|
||||
}
|
||||
|
||||
/// Issue a `Declare` collation message to the given `peer`.
|
||||
async fn declare<Context>(ctx: &mut Context, state: &mut State, peer: PeerId)
|
||||
where
|
||||
Context: SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
{
|
||||
#[overseer::contextbounds(CollatorProtocol, prefix = self::overseer)]
|
||||
async fn declare<Context>(ctx: &mut Context, state: &mut State, peer: PeerId) {
|
||||
let declare_signature_payload = protocol_v1::declare_signature_payload(&state.local_peer_id);
|
||||
|
||||
if let Some(para_id) = state.collating_on {
|
||||
@@ -554,11 +543,11 @@ where
|
||||
|
||||
/// 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>)
|
||||
where
|
||||
Context: SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
{
|
||||
#[overseer::contextbounds(CollatorProtocol, prefix = self::overseer)]
|
||||
async fn connect_to_validators<Context>(
|
||||
ctx: &mut Context,
|
||||
validator_ids: Vec<AuthorityDiscoveryId>,
|
||||
) {
|
||||
// ignore address resolution failure
|
||||
// will reissue a new request on new collation
|
||||
let (failed, _) = oneshot::channel();
|
||||
@@ -574,15 +563,13 @@ where
|
||||
///
|
||||
/// This will only advertise a collation if there exists one for the given `relay_parent` and the given `peer` is
|
||||
/// set as validator for our para at the given `relay_parent`.
|
||||
#[overseer::contextbounds(CollatorProtocol, prefix = self::overseer)]
|
||||
async fn advertise_collation<Context>(
|
||||
ctx: &mut Context,
|
||||
state: &mut State,
|
||||
relay_parent: Hash,
|
||||
peer: PeerId,
|
||||
) where
|
||||
Context: SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
{
|
||||
) {
|
||||
let should_advertise = state
|
||||
.our_validators_groups
|
||||
.get(&relay_parent)
|
||||
@@ -635,16 +622,13 @@ async fn advertise_collation<Context>(
|
||||
}
|
||||
|
||||
/// The main incoming message dispatching switch.
|
||||
#[overseer::contextbounds(CollatorProtocol, prefix = self::overseer)]
|
||||
async fn process_msg<Context>(
|
||||
ctx: &mut Context,
|
||||
runtime: &mut RuntimeInfo,
|
||||
state: &mut State,
|
||||
msg: CollatorProtocolMessage,
|
||||
) -> Result<()>
|
||||
where
|
||||
Context: SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
{
|
||||
) -> Result<()> {
|
||||
use CollatorProtocolMessage::*;
|
||||
|
||||
match msg {
|
||||
@@ -748,17 +732,14 @@ async fn send_collation(
|
||||
}
|
||||
|
||||
/// A networking messages switch.
|
||||
#[overseer::contextbounds(CollatorProtocol, prefix = self::overseer)]
|
||||
async fn handle_incoming_peer_message<Context>(
|
||||
ctx: &mut Context,
|
||||
runtime: &mut RuntimeInfo,
|
||||
state: &mut State,
|
||||
origin: PeerId,
|
||||
msg: protocol_v1::CollatorProtocolMessage,
|
||||
) -> Result<()>
|
||||
where
|
||||
Context: SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
{
|
||||
) -> Result<()> {
|
||||
use protocol_v1::CollatorProtocolMessage::*;
|
||||
|
||||
match msg {
|
||||
@@ -831,15 +812,12 @@ where
|
||||
}
|
||||
|
||||
/// Process an incoming network request for a collation.
|
||||
#[overseer::contextbounds(CollatorProtocol, prefix = self::overseer)]
|
||||
async fn handle_incoming_request<Context>(
|
||||
ctx: &mut Context,
|
||||
state: &mut State,
|
||||
req: IncomingRequest<request_v1::CollationFetchingRequest>,
|
||||
) -> Result<()>
|
||||
where
|
||||
Context: SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
{
|
||||
) -> Result<()> {
|
||||
let _span = state
|
||||
.span_per_relay_parent
|
||||
.get(&req.payload.relay_parent)
|
||||
@@ -907,15 +885,13 @@ where
|
||||
}
|
||||
|
||||
/// Our view has changed.
|
||||
#[overseer::contextbounds(CollatorProtocol, prefix = self::overseer)]
|
||||
async fn handle_peer_view_change<Context>(
|
||||
ctx: &mut Context,
|
||||
state: &mut State,
|
||||
peer_id: PeerId,
|
||||
view: View,
|
||||
) where
|
||||
Context: SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
{
|
||||
) {
|
||||
let current = state.peer_views.entry(peer_id.clone()).or_default();
|
||||
|
||||
let added: Vec<Hash> = view.difference(&*current).cloned().collect();
|
||||
@@ -928,16 +904,13 @@ async fn handle_peer_view_change<Context>(
|
||||
}
|
||||
|
||||
/// Bridge messages switch.
|
||||
#[overseer::contextbounds(CollatorProtocol, prefix = self::overseer)]
|
||||
async fn handle_network_msg<Context>(
|
||||
ctx: &mut Context,
|
||||
runtime: &mut RuntimeInfo,
|
||||
state: &mut State,
|
||||
bridge_message: NetworkBridgeEvent<net_protocol::CollatorProtocolMessage>,
|
||||
) -> Result<()>
|
||||
where
|
||||
Context: SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
{
|
||||
) -> Result<()> {
|
||||
use NetworkBridgeEvent::*;
|
||||
|
||||
match bridge_message {
|
||||
@@ -1021,17 +994,14 @@ async fn handle_our_view_change(state: &mut State, view: OurView) -> Result<()>
|
||||
}
|
||||
|
||||
/// The collator protocol collator side main loop.
|
||||
#[overseer::contextbounds(CollatorProtocol, prefix = crate::overseer)]
|
||||
pub(crate) async fn run<Context>(
|
||||
mut ctx: Context,
|
||||
local_peer_id: PeerId,
|
||||
collator_pair: CollatorPair,
|
||||
mut req_receiver: IncomingRequestReceiver<request_v1::CollationFetchingRequest>,
|
||||
metrics: Metrics,
|
||||
) -> std::result::Result<(), FatalError>
|
||||
where
|
||||
Context: SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
{
|
||||
) -> std::result::Result<(), FatalError> {
|
||||
use OverseerSignal::*;
|
||||
|
||||
let mut state = State::new(local_peer_id, collator_pair, metrics);
|
||||
|
||||
@@ -34,9 +34,7 @@ use polkadot_node_network_protocol::{
|
||||
use polkadot_primitives::v2::CollatorPair;
|
||||
|
||||
use polkadot_node_subsystem::{
|
||||
errors::SubsystemError,
|
||||
messages::{CollatorProtocolMessage, NetworkBridgeMessage},
|
||||
overseer, SpawnedSubsystem, SubsystemContext, SubsystemSender,
|
||||
errors::SubsystemError, messages::NetworkBridgeMessage, overseer, SpawnedSubsystem,
|
||||
};
|
||||
|
||||
mod error;
|
||||
@@ -89,6 +87,7 @@ pub struct CollatorProtocolSubsystem {
|
||||
protocol_side: ProtocolSide,
|
||||
}
|
||||
|
||||
#[overseer::contextbounds(CollatorProtocol, prefix = self::overseer)]
|
||||
impl CollatorProtocolSubsystem {
|
||||
/// Start the collator protocol.
|
||||
/// If `id` is `Some` this is a collator side of the protocol.
|
||||
@@ -98,11 +97,7 @@ impl CollatorProtocolSubsystem {
|
||||
Self { protocol_side }
|
||||
}
|
||||
|
||||
async fn run<Context>(self, ctx: Context) -> std::result::Result<(), error::FatalError>
|
||||
where
|
||||
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
Context: SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
{
|
||||
async fn run<Context>(self, ctx: Context) -> std::result::Result<(), error::FatalError> {
|
||||
match self.protocol_side {
|
||||
ProtocolSide::Validator { keystore, eviction_policy, metrics } =>
|
||||
validator_side::run(ctx, keystore, eviction_policy, metrics).await,
|
||||
@@ -112,12 +107,8 @@ impl CollatorProtocolSubsystem {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Context> overseer::Subsystem<Context, SubsystemError> for CollatorProtocolSubsystem
|
||||
where
|
||||
Context: SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
<Context as SubsystemContext>::Sender: SubsystemSender,
|
||||
{
|
||||
#[overseer::subsystem(CollatorProtocol, error=SubsystemError, prefix=self::overseer)]
|
||||
impl<Context> CollatorProtocolSubsystem {
|
||||
fn start(self, ctx: Context) -> SpawnedSubsystem {
|
||||
let future = self
|
||||
.run(ctx)
|
||||
@@ -129,10 +120,11 @@ where
|
||||
}
|
||||
|
||||
/// Modify the reputation of a peer based on its behavior.
|
||||
async fn modify_reputation<Context>(ctx: &mut Context, peer: PeerId, rep: Rep)
|
||||
where
|
||||
Context: SubsystemContext,
|
||||
{
|
||||
async fn modify_reputation(
|
||||
sender: &mut impl overseer::CollatorProtocolSenderTrait,
|
||||
peer: PeerId,
|
||||
rep: Rep,
|
||||
) {
|
||||
gum::trace!(
|
||||
target: LOG_TARGET,
|
||||
rep = ?rep,
|
||||
@@ -140,5 +132,5 @@ where
|
||||
"reputation change for peer",
|
||||
);
|
||||
|
||||
ctx.send_message(NetworkBridgeMessage::ReportPeer(peer, rep)).await;
|
||||
sender.send_message(NetworkBridgeMessage::ReportPeer(peer, rep)).await;
|
||||
}
|
||||
|
||||
@@ -48,9 +48,9 @@ use polkadot_node_subsystem::{
|
||||
jaeger,
|
||||
messages::{
|
||||
CandidateBackingMessage, CollatorProtocolMessage, IfDisconnected, NetworkBridgeEvent,
|
||||
NetworkBridgeMessage,
|
||||
NetworkBridgeMessage, RuntimeApiMessage,
|
||||
},
|
||||
overseer, FromOverseer, OverseerSignal, PerLeafSpan, SubsystemContext, SubsystemSender,
|
||||
overseer, FromOverseer, OverseerSignal, PerLeafSpan, SubsystemSender,
|
||||
};
|
||||
use polkadot_node_subsystem_util::metrics::{self, prometheus};
|
||||
use polkadot_primitives::v2::{CandidateReceipt, CollatorId, Hash, Id as ParaId};
|
||||
@@ -362,7 +362,7 @@ struct ActiveParas {
|
||||
impl ActiveParas {
|
||||
async fn assign_incoming(
|
||||
&mut self,
|
||||
sender: &mut impl SubsystemSender,
|
||||
sender: &mut impl SubsystemSender<RuntimeApiMessage>,
|
||||
keystore: &SyncCryptoStorePtr,
|
||||
new_relay_parents: impl IntoIterator<Item = Hash>,
|
||||
) {
|
||||
@@ -630,25 +630,19 @@ fn collator_peer_id(
|
||||
})
|
||||
}
|
||||
|
||||
async fn disconnect_peer<Context>(ctx: &mut Context, peer_id: PeerId)
|
||||
where
|
||||
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
Context: SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
{
|
||||
ctx.send_message(NetworkBridgeMessage::DisconnectPeer(peer_id, PeerSet::Collation))
|
||||
async fn disconnect_peer(sender: &mut impl overseer::CollatorProtocolSenderTrait, peer_id: PeerId) {
|
||||
sender
|
||||
.send_message(NetworkBridgeMessage::DisconnectPeer(peer_id, PeerSet::Collation))
|
||||
.await
|
||||
}
|
||||
|
||||
/// Another subsystem has requested to fetch collations on a particular leaf for some para.
|
||||
async fn fetch_collation<Context>(
|
||||
ctx: &mut Context,
|
||||
async fn fetch_collation(
|
||||
sender: &mut impl overseer::CollatorProtocolSenderTrait,
|
||||
state: &mut State,
|
||||
pc: PendingCollation,
|
||||
id: CollatorId,
|
||||
) where
|
||||
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
Context: SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
{
|
||||
) {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
let PendingCollation { relay_parent, para_id, peer_id, .. } = pc;
|
||||
@@ -663,7 +657,7 @@ async fn fetch_collation<Context>(
|
||||
|
||||
if let Some(peer_data) = state.peer_data.get(&peer_id) {
|
||||
if peer_data.has_advertised(&relay_parent) {
|
||||
request_collation(ctx, state, relay_parent, para_id, peer_id, tx).await;
|
||||
request_collation(sender, state, relay_parent, para_id, peer_id, tx).await;
|
||||
} else {
|
||||
gum::debug!(
|
||||
target: LOG_TARGET,
|
||||
@@ -687,51 +681,44 @@ async fn fetch_collation<Context>(
|
||||
}
|
||||
|
||||
/// Report a collator for some malicious actions.
|
||||
async fn report_collator<Context>(
|
||||
ctx: &mut Context,
|
||||
async fn report_collator(
|
||||
sender: &mut impl overseer::CollatorProtocolSenderTrait,
|
||||
peer_data: &HashMap<PeerId, PeerData>,
|
||||
id: CollatorId,
|
||||
) 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;
|
||||
modify_reputation(sender, peer_id, COST_REPORT_BAD).await;
|
||||
}
|
||||
}
|
||||
|
||||
/// Some other subsystem has reported a collator as a good one, bump reputation.
|
||||
async fn note_good_collation<Context>(
|
||||
ctx: &mut Context,
|
||||
async fn note_good_collation(
|
||||
sender: &mut impl overseer::CollatorProtocolSenderTrait,
|
||||
peer_data: &HashMap<PeerId, PeerData>,
|
||||
id: CollatorId,
|
||||
) 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;
|
||||
modify_reputation(sender, peer_id, BENEFIT_NOTIFY_GOOD).await;
|
||||
}
|
||||
}
|
||||
|
||||
/// Notify a collator that its collation got seconded.
|
||||
async fn notify_collation_seconded<Context>(
|
||||
ctx: &mut Context,
|
||||
async fn notify_collation_seconded(
|
||||
sender: &mut impl overseer::CollatorProtocolSenderTrait,
|
||||
peer_id: PeerId,
|
||||
relay_parent: Hash,
|
||||
statement: SignedFullStatement,
|
||||
) 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],
|
||||
Versioned::V1(protocol_v1::CollationProtocol::CollatorProtocol(wire_message)),
|
||||
))
|
||||
.await;
|
||||
sender
|
||||
.send_message(NetworkBridgeMessage::SendCollationMessage(
|
||||
vec![peer_id],
|
||||
Versioned::V1(protocol_v1::CollationProtocol::CollatorProtocol(wire_message)),
|
||||
))
|
||||
.await;
|
||||
|
||||
modify_reputation(ctx, peer_id, BENEFIT_NOTIFY_GOOD).await;
|
||||
modify_reputation(sender, peer_id, BENEFIT_NOTIFY_GOOD).await;
|
||||
}
|
||||
|
||||
/// A peer's view has changed. A number of things should be done:
|
||||
@@ -754,17 +741,14 @@ async fn handle_peer_view_change(state: &mut State, peer_id: PeerId, view: View)
|
||||
/// - Check if the requested collation is in our view.
|
||||
/// - Update `PerRequest` records with the `result` field if necessary.
|
||||
/// And as such invocations of this function may rely on that.
|
||||
async fn request_collation<Context>(
|
||||
ctx: &mut Context,
|
||||
async fn request_collation(
|
||||
sender: &mut impl overseer::CollatorProtocolSenderTrait,
|
||||
state: &mut State,
|
||||
relay_parent: Hash,
|
||||
para_id: ParaId,
|
||||
peer_id: PeerId,
|
||||
result: oneshot::Sender<(CandidateReceipt, PoV)>,
|
||||
) where
|
||||
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
Context: SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
{
|
||||
) {
|
||||
if !state.view.contains(&relay_parent) {
|
||||
gum::debug!(
|
||||
target: LOG_TARGET,
|
||||
@@ -815,29 +799,28 @@ async fn request_collation<Context>(
|
||||
"Requesting collation",
|
||||
);
|
||||
|
||||
ctx.send_message(NetworkBridgeMessage::SendRequests(
|
||||
vec![requests],
|
||||
IfDisconnected::ImmediateError,
|
||||
))
|
||||
.await;
|
||||
sender
|
||||
.send_message(NetworkBridgeMessage::SendRequests(
|
||||
vec![requests],
|
||||
IfDisconnected::ImmediateError,
|
||||
))
|
||||
.await;
|
||||
}
|
||||
|
||||
/// Networking message has been received.
|
||||
#[overseer::contextbounds(CollatorProtocol, prefix = overseer)]
|
||||
async fn process_incoming_peer_message<Context>(
|
||||
ctx: &mut Context,
|
||||
state: &mut State,
|
||||
origin: PeerId,
|
||||
msg: protocol_v1::CollatorProtocolMessage,
|
||||
) where
|
||||
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
Context: SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
{
|
||||
) {
|
||||
use protocol_v1::CollatorProtocolMessage::*;
|
||||
use sp_runtime::traits::AppVerify;
|
||||
match msg {
|
||||
Declare(collator_id, para_id, signature) => {
|
||||
if collator_peer_id(&state.peer_data, &collator_id).is_some() {
|
||||
modify_reputation(ctx, origin, COST_UNEXPECTED_MESSAGE).await;
|
||||
modify_reputation(ctx.sender(), origin, COST_UNEXPECTED_MESSAGE).await;
|
||||
return
|
||||
}
|
||||
|
||||
@@ -850,7 +833,7 @@ async fn process_incoming_peer_message<Context>(
|
||||
?para_id,
|
||||
"Unknown peer",
|
||||
);
|
||||
modify_reputation(ctx, origin, COST_UNEXPECTED_MESSAGE).await;
|
||||
modify_reputation(ctx.sender(), origin, COST_UNEXPECTED_MESSAGE).await;
|
||||
return
|
||||
},
|
||||
};
|
||||
@@ -862,7 +845,7 @@ async fn process_incoming_peer_message<Context>(
|
||||
?para_id,
|
||||
"Peer is not in the collating state",
|
||||
);
|
||||
modify_reputation(ctx, origin, COST_UNEXPECTED_MESSAGE).await;
|
||||
modify_reputation(ctx.sender(), origin, COST_UNEXPECTED_MESSAGE).await;
|
||||
return
|
||||
}
|
||||
|
||||
@@ -873,7 +856,7 @@ async fn process_incoming_peer_message<Context>(
|
||||
?para_id,
|
||||
"Signature verification failure",
|
||||
);
|
||||
modify_reputation(ctx, origin, COST_INVALID_SIGNATURE).await;
|
||||
modify_reputation(ctx.sender(), origin, COST_INVALID_SIGNATURE).await;
|
||||
return
|
||||
}
|
||||
|
||||
@@ -896,9 +879,9 @@ async fn process_incoming_peer_message<Context>(
|
||||
"Declared as collator for unneeded para",
|
||||
);
|
||||
|
||||
modify_reputation(ctx, origin.clone(), COST_UNNEEDED_COLLATOR).await;
|
||||
modify_reputation(ctx.sender(), origin.clone(), COST_UNNEEDED_COLLATOR).await;
|
||||
gum::trace!(target: LOG_TARGET, "Disconnecting unneeded collator");
|
||||
disconnect_peer(ctx, origin).await;
|
||||
disconnect_peer(ctx.sender(), origin).await;
|
||||
}
|
||||
},
|
||||
AdvertiseCollation(relay_parent) => {
|
||||
@@ -914,7 +897,7 @@ async fn process_incoming_peer_message<Context>(
|
||||
"Advertise collation out of view",
|
||||
);
|
||||
|
||||
modify_reputation(ctx, origin, COST_UNEXPECTED_MESSAGE).await;
|
||||
modify_reputation(ctx.sender(), origin, COST_UNEXPECTED_MESSAGE).await;
|
||||
return
|
||||
}
|
||||
|
||||
@@ -926,7 +909,7 @@ async fn process_incoming_peer_message<Context>(
|
||||
?relay_parent,
|
||||
"Advertise collation message has been received from an unknown peer",
|
||||
);
|
||||
modify_reputation(ctx, origin, COST_UNEXPECTED_MESSAGE).await;
|
||||
modify_reputation(ctx.sender(), origin, COST_UNEXPECTED_MESSAGE).await;
|
||||
return
|
||||
},
|
||||
Some(p) => p,
|
||||
@@ -962,7 +945,8 @@ async fn process_incoming_peer_message<Context>(
|
||||
collations.status = CollationStatus::Fetching;
|
||||
collations.waiting_collation = Some(id.clone());
|
||||
|
||||
fetch_collation(ctx, state, pending_collation.clone(), id).await;
|
||||
fetch_collation(ctx.sender(), state, pending_collation.clone(), id)
|
||||
.await;
|
||||
},
|
||||
CollationStatus::Seconded => {
|
||||
gum::trace!(
|
||||
@@ -984,7 +968,7 @@ async fn process_incoming_peer_message<Context>(
|
||||
"Invalid advertisement",
|
||||
);
|
||||
|
||||
modify_reputation(ctx, origin, COST_UNEXPECTED_MESSAGE).await;
|
||||
modify_reputation(ctx.sender(), origin, COST_UNEXPECTED_MESSAGE).await;
|
||||
},
|
||||
}
|
||||
},
|
||||
@@ -1011,16 +995,13 @@ async fn remove_relay_parent(state: &mut State, relay_parent: Hash) -> Result<()
|
||||
}
|
||||
|
||||
/// Our view has changed.
|
||||
#[overseer::contextbounds(CollatorProtocol, prefix = self::overseer)]
|
||||
async fn handle_our_view_change<Context>(
|
||||
ctx: &mut Context,
|
||||
state: &mut State,
|
||||
keystore: &SyncCryptoStorePtr,
|
||||
view: OurView,
|
||||
) -> Result<()>
|
||||
where
|
||||
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
Context: SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
{
|
||||
) -> Result<()> {
|
||||
let old_view = std::mem::replace(&mut state.view, view);
|
||||
|
||||
let added: HashMap<Hash, Arc<jaeger::Span>> = state
|
||||
@@ -1061,7 +1042,7 @@ where
|
||||
?para_id,
|
||||
"Disconnecting peer on view change (not current parachain id)"
|
||||
);
|
||||
disconnect_peer(ctx, peer_id.clone()).await;
|
||||
disconnect_peer(ctx.sender(), peer_id.clone()).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1070,16 +1051,13 @@ where
|
||||
}
|
||||
|
||||
/// Bridge event switch.
|
||||
#[overseer::contextbounds(CollatorProtocol, prefix = self::overseer)]
|
||||
async fn handle_network_msg<Context>(
|
||||
ctx: &mut Context,
|
||||
state: &mut State,
|
||||
keystore: &SyncCryptoStorePtr,
|
||||
bridge_message: NetworkBridgeEvent<net_protocol::CollatorProtocolMessage>,
|
||||
) -> Result<()>
|
||||
where
|
||||
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
Context: SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
{
|
||||
) -> Result<()> {
|
||||
use NetworkBridgeEvent::*;
|
||||
|
||||
match bridge_message {
|
||||
@@ -1109,15 +1087,13 @@ where
|
||||
}
|
||||
|
||||
/// The main message receiver switch.
|
||||
#[overseer::contextbounds(CollatorProtocol, prefix = self::overseer)]
|
||||
async fn process_msg<Context>(
|
||||
ctx: &mut Context,
|
||||
keystore: &SyncCryptoStorePtr,
|
||||
msg: CollatorProtocolMessage,
|
||||
state: &mut State,
|
||||
) where
|
||||
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
Context: SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
{
|
||||
) {
|
||||
use CollatorProtocolMessage::*;
|
||||
|
||||
let _timer = state.metrics.time_process_msg();
|
||||
@@ -1137,7 +1113,7 @@ async fn process_msg<Context>(
|
||||
);
|
||||
},
|
||||
ReportCollator(id) => {
|
||||
report_collator(ctx, &state.peer_data, id).await;
|
||||
report_collator(ctx.sender(), &state.peer_data, id).await;
|
||||
},
|
||||
NetworkBridgeUpdate(event) => {
|
||||
if let Err(e) = handle_network_msg(ctx, state, keystore, event).await {
|
||||
@@ -1152,8 +1128,8 @@ async fn process_msg<Context>(
|
||||
if let Some(collation_event) = state.pending_candidates.remove(&parent) {
|
||||
let (collator_id, pending_collation) = collation_event;
|
||||
let PendingCollation { relay_parent, peer_id, .. } = pending_collation;
|
||||
note_good_collation(ctx, &state.peer_data, collator_id).await;
|
||||
notify_collation_seconded(ctx, peer_id, relay_parent, stmt).await;
|
||||
note_good_collation(ctx.sender(), &state.peer_data, collator_id).await;
|
||||
notify_collation_seconded(ctx.sender(), peer_id, relay_parent, stmt).await;
|
||||
|
||||
if let Some(collations) = state.collations_per_relay_parent.get_mut(&parent) {
|
||||
collations.status = CollationStatus::Seconded;
|
||||
@@ -1184,7 +1160,7 @@ async fn process_msg<Context>(
|
||||
Entry::Vacant(_) => return,
|
||||
};
|
||||
|
||||
report_collator(ctx, &state.peer_data, id.clone()).await;
|
||||
report_collator(ctx.sender(), &state.peer_data, id.clone()).await;
|
||||
|
||||
dequeue_next_collation_and_fetch(ctx, state, parent, id).await;
|
||||
},
|
||||
@@ -1211,16 +1187,13 @@ fn infinite_stream(every: Duration) -> impl FusedStream<Item = ()> {
|
||||
}
|
||||
|
||||
/// The main run loop.
|
||||
#[overseer::contextbounds(CollatorProtocol, prefix = self::overseer)]
|
||||
pub(crate) async fn run<Context>(
|
||||
mut ctx: Context,
|
||||
keystore: SyncCryptoStorePtr,
|
||||
eviction_policy: crate::CollatorEvictionPolicy,
|
||||
metrics: Metrics,
|
||||
) -> std::result::Result<(), crate::error::FatalError>
|
||||
where
|
||||
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
Context: SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
{
|
||||
) -> std::result::Result<(), crate::error::FatalError> {
|
||||
let mut state = State { metrics, ..Default::default() };
|
||||
|
||||
let next_inactivity_stream = infinite_stream(ACTIVITY_POLL);
|
||||
@@ -1247,7 +1220,7 @@ where
|
||||
}
|
||||
}
|
||||
_ = next_inactivity_stream.next() => {
|
||||
disconnect_inactive_peers(&mut ctx, &eviction_policy, &state.peer_data).await;
|
||||
disconnect_inactive_peers(ctx.sender(), &eviction_policy, &state.peer_data).await;
|
||||
}
|
||||
res = state.collation_fetches.select_next_some() => {
|
||||
handle_collation_fetched_result(&mut ctx, &mut state, res).await;
|
||||
@@ -1270,7 +1243,7 @@ where
|
||||
).await;
|
||||
|
||||
for (peer_id, rep) in reputation_changes {
|
||||
modify_reputation(&mut ctx, peer_id, rep).await;
|
||||
modify_reputation(ctx.sender(), peer_id, rep).await;
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -1304,9 +1277,9 @@ async fn poll_requests(
|
||||
}
|
||||
|
||||
/// Dequeue another collation and fetch.
|
||||
async fn dequeue_next_collation_and_fetch(
|
||||
ctx: &mut (impl SubsystemContext<Message = CollatorProtocolMessage>
|
||||
+ overseer::SubsystemContext<Message = CollatorProtocolMessage>),
|
||||
#[overseer::contextbounds(CollatorProtocol, prefix = self::overseer)]
|
||||
async fn dequeue_next_collation_and_fetch<Context>(
|
||||
ctx: &mut Context,
|
||||
state: &mut State,
|
||||
relay_parent: Hash,
|
||||
// The collator we tried to fetch from last.
|
||||
@@ -1323,7 +1296,7 @@ async fn dequeue_next_collation_and_fetch(
|
||||
?id,
|
||||
"Successfully dequeued next advertisement - fetching ..."
|
||||
);
|
||||
fetch_collation(ctx, state, next, id).await;
|
||||
fetch_collation(ctx.sender(), state, next, id).await;
|
||||
} else {
|
||||
gum::debug!(
|
||||
target: LOG_TARGET,
|
||||
@@ -1335,14 +1308,12 @@ async fn dequeue_next_collation_and_fetch(
|
||||
}
|
||||
|
||||
/// Handle a fetched collation result.
|
||||
#[overseer::contextbounds(CollatorProtocol, prefix = self::overseer)]
|
||||
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>,
|
||||
{
|
||||
) {
|
||||
// If no prior collation for this relay parent has been seconded, then
|
||||
// memorize the `collation_event` for that `relay_parent`, such that we may
|
||||
// notify the collator of their successful second backing
|
||||
@@ -1380,12 +1351,13 @@ async fn handle_collation_fetched_result<Context>(
|
||||
|
||||
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.sender()
|
||||
.send_message(CandidateBackingMessage::Second(
|
||||
relay_parent.clone(),
|
||||
candidate_receipt,
|
||||
pov,
|
||||
))
|
||||
.await;
|
||||
|
||||
entry.insert(collation_event);
|
||||
} else {
|
||||
@@ -1401,18 +1373,15 @@ async fn handle_collation_fetched_result<Context>(
|
||||
// This issues `NetworkBridge` notifications to disconnect from all inactive peers at the
|
||||
// earliest possible point. This does not yet clean up any metadata, as that will be done upon
|
||||
// receipt of the `PeerDisconnected` event.
|
||||
async fn disconnect_inactive_peers<Context>(
|
||||
ctx: &mut Context,
|
||||
async fn disconnect_inactive_peers(
|
||||
sender: &mut impl overseer::CollatorProtocolSenderTrait,
|
||||
eviction_policy: &crate::CollatorEvictionPolicy,
|
||||
peers: &HashMap<PeerId, PeerData>,
|
||||
) where
|
||||
Context: overseer::SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
Context: SubsystemContext<Message = CollatorProtocolMessage>,
|
||||
{
|
||||
) {
|
||||
for (peer, peer_data) in peers {
|
||||
if peer_data.is_inactive(&eviction_policy) {
|
||||
gum::trace!(target: LOG_TARGET, "Disconnecting inactive peer");
|
||||
disconnect_peer(ctx, peer.clone()).await;
|
||||
disconnect_peer(sender, peer.clone()).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ use polkadot_node_network_protocol::request_response::{incoming::IncomingRequest
|
||||
use polkadot_node_primitives::DISPUTE_WINDOW;
|
||||
use polkadot_node_subsystem::{
|
||||
messages::DisputeDistributionMessage, overseer, FromOverseer, OverseerSignal, SpawnedSubsystem,
|
||||
SubsystemContext, SubsystemError,
|
||||
SubsystemError,
|
||||
};
|
||||
use polkadot_node_subsystem_util::{runtime, runtime::RuntimeInfo};
|
||||
|
||||
@@ -114,12 +114,11 @@ pub struct DisputeDistributionSubsystem<AD> {
|
||||
metrics: Metrics,
|
||||
}
|
||||
|
||||
impl<Context, AD> overseer::Subsystem<Context, SubsystemError> for DisputeDistributionSubsystem<AD>
|
||||
#[overseer::subsystem(DisputeDistribution, error = SubsystemError, prefix = self::overseer)]
|
||||
impl<Context, AD> DisputeDistributionSubsystem<AD>
|
||||
where
|
||||
Context: SubsystemContext<Message = DisputeDistributionMessage>
|
||||
+ overseer::SubsystemContext<Message = DisputeDistributionMessage>
|
||||
+ Sync
|
||||
+ Send,
|
||||
<Context as overseer::DisputeDistributionContextTrait>::Sender:
|
||||
overseer::DisputeDistributionSenderTrait + Sync + Send,
|
||||
AD: AuthorityDiscovery + Clone,
|
||||
{
|
||||
fn start(self, ctx: Context) -> SpawnedSubsystem {
|
||||
@@ -132,6 +131,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[overseer::contextbounds(DisputeDistribution, prefix = self::overseer)]
|
||||
impl<AD> DisputeDistributionSubsystem<AD>
|
||||
where
|
||||
AD: AuthorityDiscovery + Clone,
|
||||
@@ -160,13 +160,7 @@ where
|
||||
}
|
||||
|
||||
/// Start processing work as passed on from the Overseer.
|
||||
async fn run<Context>(mut self, mut ctx: Context) -> std::result::Result<(), FatalError>
|
||||
where
|
||||
Context: SubsystemContext<Message = DisputeDistributionMessage>
|
||||
+ overseer::SubsystemContext<Message = DisputeDistributionMessage>
|
||||
+ Sync
|
||||
+ Send,
|
||||
{
|
||||
async fn run<Context>(mut self, mut ctx: Context) -> std::result::Result<(), FatalError> {
|
||||
let receiver = DisputesReceiver::new(
|
||||
ctx.sender().clone(),
|
||||
self.req_receiver
|
||||
@@ -205,7 +199,7 @@ where
|
||||
}
|
||||
|
||||
/// Handle overseer signals.
|
||||
async fn handle_signals<Context: SubsystemContext>(
|
||||
async fn handle_signals<Context>(
|
||||
&mut self,
|
||||
ctx: &mut Context,
|
||||
signal: OverseerSignal,
|
||||
@@ -221,7 +215,7 @@ where
|
||||
}
|
||||
|
||||
/// Handle `DisputeDistributionMessage`s.
|
||||
async fn handle_subsystem_message<Context: SubsystemContext>(
|
||||
async fn handle_subsystem_message<Context>(
|
||||
&mut self,
|
||||
ctx: &mut Context,
|
||||
msg: DisputeDistributionMessage,
|
||||
@@ -243,10 +237,10 @@ enum MuxedMessage {
|
||||
Sender(Option<TaskFinish>),
|
||||
}
|
||||
|
||||
#[overseer::contextbounds(DisputeDistribution, prefix = self::overseer)]
|
||||
impl MuxedMessage {
|
||||
async fn receive(
|
||||
ctx: &mut (impl SubsystemContext<Message = DisputeDistributionMessage>
|
||||
+ overseer::SubsystemContext<Message = DisputeDistributionMessage>),
|
||||
async fn receive<Context>(
|
||||
ctx: &mut Context,
|
||||
from_sender: &mut mpsc::Receiver<TaskFinish>,
|
||||
) -> Self {
|
||||
// We are only fusing here to make `select` happy, in reality we will quit if the stream
|
||||
|
||||
@@ -40,8 +40,8 @@ use polkadot_node_network_protocol::{
|
||||
};
|
||||
use polkadot_node_primitives::DISPUTE_WINDOW;
|
||||
use polkadot_node_subsystem::{
|
||||
messages::{AllMessages, DisputeCoordinatorMessage, ImportStatementsResult},
|
||||
SubsystemSender,
|
||||
messages::{DisputeCoordinatorMessage, ImportStatementsResult},
|
||||
overseer,
|
||||
};
|
||||
use polkadot_node_subsystem_util::{runtime, runtime::RuntimeInfo};
|
||||
|
||||
@@ -132,9 +132,10 @@ impl MuxedMessage {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Sender: SubsystemSender, AD> DisputesReceiver<Sender, AD>
|
||||
impl<Sender, AD> DisputesReceiver<Sender, AD>
|
||||
where
|
||||
AD: AuthorityDiscovery,
|
||||
Sender: overseer::DisputeDistributionSenderTrait,
|
||||
{
|
||||
/// Create a new receiver which can be `run`.
|
||||
pub fn new(
|
||||
@@ -265,15 +266,13 @@ where
|
||||
let (pending_confirmation, confirmation_rx) = oneshot::channel();
|
||||
let candidate_hash = candidate_receipt.hash();
|
||||
self.sender
|
||||
.send_message(AllMessages::DisputeCoordinator(
|
||||
DisputeCoordinatorMessage::ImportStatements {
|
||||
candidate_hash,
|
||||
candidate_receipt,
|
||||
session: valid_vote.0.session_index(),
|
||||
statements: vec![valid_vote, invalid_vote],
|
||||
pending_confirmation: Some(pending_confirmation),
|
||||
},
|
||||
))
|
||||
.send_message(DisputeCoordinatorMessage::ImportStatements {
|
||||
candidate_hash,
|
||||
candidate_receipt,
|
||||
session: valid_vote.0.session_index(),
|
||||
statements: vec![valid_vote, invalid_vote],
|
||||
pending_confirmation: Some(pending_confirmation),
|
||||
})
|
||||
.await;
|
||||
|
||||
self.pending_imports.push(peer, confirmation_rx, pending_response);
|
||||
|
||||
@@ -20,10 +20,7 @@ use futures::channel::{mpsc, oneshot};
|
||||
|
||||
use polkadot_node_network_protocol::request_response::v1::DisputeRequest;
|
||||
use polkadot_node_primitives::{CandidateVotes, DisputeMessage, SignedDisputeStatement};
|
||||
use polkadot_node_subsystem::{
|
||||
messages::{AllMessages, DisputeCoordinatorMessage},
|
||||
ActiveLeavesUpdate, SubsystemContext,
|
||||
};
|
||||
use polkadot_node_subsystem::{messages::DisputeCoordinatorMessage, overseer, ActiveLeavesUpdate};
|
||||
use polkadot_node_subsystem_util::runtime::RuntimeInfo;
|
||||
use polkadot_primitives::v2::{CandidateHash, DisputeStatement, Hash, SessionIndex};
|
||||
|
||||
@@ -66,6 +63,7 @@ pub struct DisputeSender {
|
||||
metrics: Metrics,
|
||||
}
|
||||
|
||||
#[overseer::contextbounds(DisputeDistribution, prefix = self::overseer)]
|
||||
impl DisputeSender {
|
||||
/// Create a new `DisputeSender` which can be used to start dispute sendings.
|
||||
pub fn new(tx: mpsc::Sender<TaskFinish>, metrics: Metrics) -> Self {
|
||||
@@ -79,7 +77,7 @@ impl DisputeSender {
|
||||
}
|
||||
|
||||
/// Create a `SendTask` for a particular new dispute.
|
||||
pub async fn start_sender<Context: SubsystemContext>(
|
||||
pub async fn start_sender<Context>(
|
||||
&mut self,
|
||||
ctx: &mut Context,
|
||||
runtime: &mut RuntimeInfo,
|
||||
@@ -114,7 +112,7 @@ impl DisputeSender {
|
||||
/// - Get new authorities to send messages to.
|
||||
/// - Get rid of obsolete tasks and disputes.
|
||||
/// - Get dispute sending started in case we missed one for some reason (e.g. on node startup)
|
||||
pub async fn update_leaves<Context: SubsystemContext>(
|
||||
pub async fn update_leaves<Context>(
|
||||
&mut self,
|
||||
ctx: &mut Context,
|
||||
runtime: &mut RuntimeInfo,
|
||||
@@ -179,7 +177,7 @@ impl DisputeSender {
|
||||
/// Call `start_sender` on all passed in disputes.
|
||||
///
|
||||
/// Recover necessary votes for building up `DisputeMessage` and start sending for all of them.
|
||||
async fn start_send_for_dispute<Context: SubsystemContext>(
|
||||
async fn start_send_for_dispute<Context>(
|
||||
&mut self,
|
||||
ctx: &mut Context,
|
||||
runtime: &mut RuntimeInfo,
|
||||
@@ -303,7 +301,7 @@ impl DisputeSender {
|
||||
/// Make active sessions correspond to currently active heads.
|
||||
///
|
||||
/// Returns: true if sessions changed.
|
||||
async fn refresh_sessions<Context: SubsystemContext>(
|
||||
async fn refresh_sessions<Context>(
|
||||
&mut self,
|
||||
ctx: &mut Context,
|
||||
runtime: &mut RuntimeInfo,
|
||||
@@ -321,7 +319,8 @@ impl DisputeSender {
|
||||
/// Retrieve the currently active sessions.
|
||||
///
|
||||
/// List is all indices of all active sessions together with the head that was used for the query.
|
||||
async fn get_active_session_indices<Context: SubsystemContext>(
|
||||
#[overseer::contextbounds(DisputeDistribution, prefix = self::overseer)]
|
||||
async fn get_active_session_indices<Context>(
|
||||
ctx: &mut Context,
|
||||
runtime: &mut RuntimeInfo,
|
||||
active_heads: &Vec<Hash>,
|
||||
@@ -336,27 +335,29 @@ async fn get_active_session_indices<Context: SubsystemContext>(
|
||||
}
|
||||
|
||||
/// Retrieve Set of active disputes from the dispute coordinator.
|
||||
async fn get_active_disputes<Context: SubsystemContext>(
|
||||
#[overseer::contextbounds(DisputeDistribution, prefix = self::overseer)]
|
||||
async fn get_active_disputes<Context>(
|
||||
ctx: &mut Context,
|
||||
) -> JfyiErrorResult<Vec<(SessionIndex, CandidateHash)>> {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
// Caller scope is in `update_leaves` and this is bounded by fork count.
|
||||
ctx.send_unbounded_message(AllMessages::DisputeCoordinator(
|
||||
DisputeCoordinatorMessage::ActiveDisputes(tx),
|
||||
));
|
||||
ctx.send_unbounded_message(DisputeCoordinatorMessage::ActiveDisputes(tx));
|
||||
rx.await.map_err(|_| JfyiError::AskActiveDisputesCanceled)
|
||||
}
|
||||
|
||||
/// Get all locally available dispute votes for a given dispute.
|
||||
async fn get_candidate_votes<Context: SubsystemContext>(
|
||||
#[overseer::contextbounds(DisputeDistribution, prefix = self::overseer)]
|
||||
async fn get_candidate_votes<Context>(
|
||||
ctx: &mut Context,
|
||||
session_index: SessionIndex,
|
||||
candidate_hash: CandidateHash,
|
||||
) -> JfyiErrorResult<Option<CandidateVotes>> {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
// Caller scope is in `update_leaves` and this is bounded by fork count.
|
||||
ctx.send_unbounded_message(AllMessages::DisputeCoordinator(
|
||||
DisputeCoordinatorMessage::QueryCandidateVotes(vec![(session_index, candidate_hash)], tx),
|
||||
ctx.send_unbounded_message(DisputeCoordinatorMessage::QueryCandidateVotes(
|
||||
vec![(session_index, candidate_hash)],
|
||||
tx,
|
||||
));
|
||||
rx.await
|
||||
.map(|v| v.get(0).map(|inner| inner.to_owned().2))
|
||||
|
||||
@@ -26,10 +26,7 @@ use polkadot_node_network_protocol::{
|
||||
},
|
||||
IfDisconnected,
|
||||
};
|
||||
use polkadot_node_subsystem::{
|
||||
messages::{AllMessages, NetworkBridgeMessage},
|
||||
SubsystemContext,
|
||||
};
|
||||
use polkadot_node_subsystem::{messages::NetworkBridgeMessage, overseer};
|
||||
use polkadot_node_subsystem_util::{metrics, runtime::RuntimeInfo};
|
||||
use polkadot_primitives::v2::{
|
||||
AuthorityDiscoveryId, CandidateHash, Hash, SessionIndex, ValidatorIndex,
|
||||
@@ -100,9 +97,10 @@ impl TaskResult {
|
||||
}
|
||||
}
|
||||
|
||||
#[overseer::contextbounds(DisputeDistribution, prefix = self::overseer)]
|
||||
impl SendTask {
|
||||
/// Initiates sending a dispute message to peers.
|
||||
pub async fn new<Context: SubsystemContext>(
|
||||
pub async fn new<Context>(
|
||||
ctx: &mut Context,
|
||||
runtime: &mut RuntimeInfo,
|
||||
active_sessions: &HashMap<SessionIndex, Hash>,
|
||||
@@ -120,7 +118,7 @@ impl SendTask {
|
||||
///
|
||||
/// This function is called at construction and should also be called whenever a session change
|
||||
/// happens and on a regular basis to ensure we are retrying failed attempts.
|
||||
pub async fn refresh_sends<Context: SubsystemContext>(
|
||||
pub async fn refresh_sends<Context>(
|
||||
&mut self,
|
||||
ctx: &mut Context,
|
||||
runtime: &mut RuntimeInfo,
|
||||
@@ -197,7 +195,8 @@ impl SendTask {
|
||||
///
|
||||
/// This is all parachain validators of the session the candidate occurred and all authorities
|
||||
/// of all currently active sessions, determined by currently active heads.
|
||||
async fn get_relevant_validators<Context: SubsystemContext>(
|
||||
|
||||
async fn get_relevant_validators<Context>(
|
||||
&self,
|
||||
ctx: &mut Context,
|
||||
runtime: &mut RuntimeInfo,
|
||||
@@ -241,7 +240,8 @@ impl SendTask {
|
||||
/// Start sending of the given message to all given authorities.
|
||||
///
|
||||
/// And spawn tasks for handling the response.
|
||||
async fn send_requests<Context: SubsystemContext>(
|
||||
#[overseer::contextbounds(DisputeDistribution, prefix = self::overseer)]
|
||||
async fn send_requests<Context>(
|
||||
ctx: &mut Context,
|
||||
tx: mpsc::Sender<TaskFinish>,
|
||||
receivers: Vec<AuthorityDiscoveryId>,
|
||||
@@ -271,7 +271,7 @@ async fn send_requests<Context: SubsystemContext>(
|
||||
}
|
||||
|
||||
let msg = NetworkBridgeMessage::SendRequests(reqs, IfDisconnected::ImmediateError);
|
||||
ctx.send_message(AllMessages::NetworkBridge(msg)).await;
|
||||
ctx.send_message(msg).await;
|
||||
Ok(statuses)
|
||||
}
|
||||
|
||||
|
||||
@@ -48,8 +48,7 @@ use polkadot_node_subsystem::{
|
||||
GossipSupportMessage, NetworkBridgeEvent, NetworkBridgeMessage, RuntimeApiMessage,
|
||||
RuntimeApiRequest,
|
||||
},
|
||||
overseer, ActiveLeavesUpdate, FromOverseer, OverseerSignal, SpawnedSubsystem, SubsystemContext,
|
||||
SubsystemError,
|
||||
overseer, ActiveLeavesUpdate, FromOverseer, OverseerSignal, SpawnedSubsystem, SubsystemError,
|
||||
};
|
||||
use polkadot_node_subsystem_util as util;
|
||||
use polkadot_primitives::v2::{
|
||||
@@ -115,6 +114,7 @@ pub struct GossipSupport<AD> {
|
||||
metrics: Metrics,
|
||||
}
|
||||
|
||||
#[overseer::contextbounds(GossipSupport, prefix = self::overseer)]
|
||||
impl<AD> GossipSupport<AD>
|
||||
where
|
||||
AD: AuthorityDiscovery,
|
||||
@@ -138,11 +138,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
async fn run<Context>(mut self, mut ctx: Context) -> Self
|
||||
where
|
||||
Context: SubsystemContext<Message = GossipSupportMessage>,
|
||||
Context: overseer::SubsystemContext<Message = GossipSupportMessage>,
|
||||
{
|
||||
async fn run<Context>(mut self, mut ctx: Context) -> Self {
|
||||
fn get_connectivity_check_delay() -> Delay {
|
||||
Delay::new(LOW_CONNECTIVITY_WARN_DELAY)
|
||||
}
|
||||
@@ -178,7 +174,7 @@ where
|
||||
gum::trace!(target: LOG_TARGET, "active leaves signal");
|
||||
|
||||
let leaves = activated.into_iter().map(|a| a.hash);
|
||||
if let Err(e) = self.handle_active_leaves(&mut ctx, leaves).await {
|
||||
if let Err(e) = self.handle_active_leaves(ctx.sender(), leaves).await {
|
||||
gum::debug!(target: LOG_TARGET, error = ?e);
|
||||
}
|
||||
},
|
||||
@@ -191,18 +187,13 @@ where
|
||||
/// 1. Determine if the current session index has changed.
|
||||
/// 2. If it has, determine relevant validators
|
||||
/// and issue a connection request.
|
||||
async fn handle_active_leaves<Context>(
|
||||
async fn handle_active_leaves(
|
||||
&mut self,
|
||||
ctx: &mut Context,
|
||||
sender: &mut impl overseer::GossipSupportSenderTrait,
|
||||
leaves: impl Iterator<Item = Hash>,
|
||||
) -> Result<(), util::Error>
|
||||
where
|
||||
Context: SubsystemContext<Message = GossipSupportMessage>,
|
||||
Context: overseer::SubsystemContext<Message = GossipSupportMessage>,
|
||||
{
|
||||
) -> Result<(), util::Error> {
|
||||
for leaf in leaves {
|
||||
let current_index =
|
||||
util::request_session_index_for_child(leaf, ctx.sender()).await.await??;
|
||||
let current_index = util::request_session_index_for_child(leaf, sender).await.await??;
|
||||
let since_failure = self.last_failure.map(|i| i.elapsed()).unwrap_or_default();
|
||||
let force_request = since_failure >= BACKOFF_DURATION;
|
||||
let leaf_session = Some((current_index, leaf));
|
||||
@@ -216,7 +207,7 @@ where
|
||||
|
||||
if let Some((session_index, relay_parent)) = maybe_issue_connection {
|
||||
let session_info =
|
||||
util::request_session_info(leaf, session_index, ctx.sender()).await.await??;
|
||||
util::request_session_info(leaf, session_index, sender).await.await??;
|
||||
|
||||
let session_info = match session_info {
|
||||
Some(s) => s,
|
||||
@@ -255,13 +246,13 @@ where
|
||||
// by virtue of a new session being entered. Therefore we maintain
|
||||
// connections to a much broader set of validators.
|
||||
{
|
||||
let mut connections = authorities_past_present_future(ctx, leaf).await?;
|
||||
let mut connections = authorities_past_present_future(sender, leaf).await?;
|
||||
|
||||
// Remove all of our locally controlled validator indices so we don't connect to ourself.
|
||||
// If we control none of them, don't issue connection requests - we're outside
|
||||
// of the 'clique' of recent validators.
|
||||
if remove_all_controlled(&self.keystore, &mut connections).await != 0 {
|
||||
self.issue_connection_request(ctx, connections).await;
|
||||
self.issue_connection_request(sender, connections).await;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,7 +264,7 @@ where
|
||||
self.update_authority_status_metrics(&session_info).await;
|
||||
|
||||
update_gossip_topology(
|
||||
ctx,
|
||||
sender,
|
||||
our_index,
|
||||
session_info.discovery_keys,
|
||||
relay_parent,
|
||||
@@ -317,13 +308,12 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
async fn issue_connection_request<Context>(
|
||||
async fn issue_connection_request<Sender>(
|
||||
&mut self,
|
||||
ctx: &mut Context,
|
||||
sender: &mut Sender,
|
||||
authorities: Vec<AuthorityDiscoveryId>,
|
||||
) where
|
||||
Context: SubsystemContext<Message = GossipSupportMessage>,
|
||||
Context: overseer::SubsystemContext<Message = GossipSupportMessage>,
|
||||
Sender: overseer::GossipSupportSenderTrait,
|
||||
{
|
||||
let num = authorities.len();
|
||||
let mut validator_addrs = Vec::with_capacity(authorities.len());
|
||||
@@ -347,11 +337,12 @@ where
|
||||
self.resolved_authorities = resolved;
|
||||
gum::debug!(target: LOG_TARGET, %num, "Issuing a connection request");
|
||||
|
||||
ctx.send_message(NetworkBridgeMessage::ConnectToResolvedValidators {
|
||||
validator_addrs,
|
||||
peer_set: PeerSet::Validation,
|
||||
})
|
||||
.await;
|
||||
sender
|
||||
.send_message(NetworkBridgeMessage::ConnectToResolvedValidators {
|
||||
validator_addrs,
|
||||
peer_set: PeerSet::Validation,
|
||||
})
|
||||
.await;
|
||||
|
||||
// issue another request for the same session
|
||||
// if at least a third of the authorities were not resolved.
|
||||
@@ -442,15 +433,11 @@ where
|
||||
}
|
||||
|
||||
// Get the authorities of the past, present, and future.
|
||||
async fn authorities_past_present_future<Context>(
|
||||
ctx: &mut Context,
|
||||
async fn authorities_past_present_future(
|
||||
sender: &mut impl overseer::GossipSupportSenderTrait,
|
||||
relay_parent: Hash,
|
||||
) -> Result<Vec<AuthorityDiscoveryId>, util::Error>
|
||||
where
|
||||
Context: SubsystemContext<Message = GossipSupportMessage>,
|
||||
Context: overseer::SubsystemContext<Message = GossipSupportMessage>,
|
||||
{
|
||||
let authorities = util::request_authorities(relay_parent, ctx.sender()).await.await??;
|
||||
) -> Result<Vec<AuthorityDiscoveryId>, util::Error> {
|
||||
let authorities = util::request_authorities(relay_parent, sender).await.await??;
|
||||
gum::debug!(
|
||||
target: LOG_TARGET,
|
||||
authority_count = ?authorities.len(),
|
||||
@@ -500,28 +487,25 @@ async fn remove_all_controlled(
|
||||
/// This limits the amount of gossip peers to 2 * `sqrt(len)` and ensures the diameter of 2.
|
||||
///
|
||||
/// [web3]: https://research.web3.foundation/en/latest/polkadot/networking/3-avail-valid.html#topology
|
||||
async fn update_gossip_topology<Context>(
|
||||
ctx: &mut Context,
|
||||
async fn update_gossip_topology(
|
||||
sender: &mut impl overseer::GossipSupportSenderTrait,
|
||||
our_index: usize,
|
||||
authorities: Vec<AuthorityDiscoveryId>,
|
||||
relay_parent: Hash,
|
||||
session_index: SessionIndex,
|
||||
) -> Result<(), util::Error>
|
||||
where
|
||||
Context: SubsystemContext<Message = GossipSupportMessage>,
|
||||
Context: overseer::SubsystemContext<Message = GossipSupportMessage>,
|
||||
{
|
||||
) -> Result<(), util::Error> {
|
||||
// retrieve BABE randomness
|
||||
let random_seed = {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
// TODO https://github.com/paritytech/polkadot/issues/5316:
|
||||
// get the random seed from the `SessionInfo` instead.
|
||||
ctx.send_message(RuntimeApiMessage::Request(
|
||||
relay_parent,
|
||||
RuntimeApiRequest::CurrentBabeEpoch(tx),
|
||||
))
|
||||
.await;
|
||||
sender
|
||||
.send_message(RuntimeApiMessage::Request(
|
||||
relay_parent,
|
||||
RuntimeApiRequest::CurrentBabeEpoch(tx),
|
||||
))
|
||||
.await;
|
||||
|
||||
let randomness = rx.await??.randomness;
|
||||
let mut subject = [0u8; 40];
|
||||
@@ -553,12 +537,13 @@ where
|
||||
.map(|i| (authorities[i].clone(), ValidatorIndex::from(i as u32)))
|
||||
.collect();
|
||||
|
||||
ctx.send_message(NetworkBridgeMessage::NewGossipTopology {
|
||||
session: session_index,
|
||||
our_neighbors_x: row_neighbors,
|
||||
our_neighbors_y: column_neighbors,
|
||||
})
|
||||
.await;
|
||||
sender
|
||||
.send_message(NetworkBridgeMessage::NewGossipTopology {
|
||||
session: session_index,
|
||||
our_neighbors_x: row_neighbors,
|
||||
our_neighbors_y: column_neighbors,
|
||||
})
|
||||
.await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -596,10 +581,9 @@ fn matrix_neighbors(
|
||||
}
|
||||
}
|
||||
|
||||
impl<Context, AD> overseer::Subsystem<Context, SubsystemError> for GossipSupport<AD>
|
||||
#[overseer::subsystem(GossipSupport, error = SubsystemError, prefix = self::overseer)]
|
||||
impl<Context, AD> GossipSupport<AD>
|
||||
where
|
||||
Context: SubsystemContext<Message = GossipSupportMessage>,
|
||||
Context: overseer::SubsystemContext<Message = GossipSupportMessage>,
|
||||
AD: AuthorityDiscovery + Clone,
|
||||
{
|
||||
fn start(self, ctx: Context) -> SpawnedSubsystem {
|
||||
|
||||
@@ -38,11 +38,11 @@ use polkadot_node_subsystem_util::{self as util, rand, MIN_GOSSIP_PEERS};
|
||||
use polkadot_node_subsystem::{
|
||||
jaeger,
|
||||
messages::{
|
||||
AllMessages, CandidateBackingMessage, NetworkBridgeEvent, NetworkBridgeMessage,
|
||||
CandidateBackingMessage, NetworkBridgeEvent, NetworkBridgeMessage,
|
||||
StatementDistributionMessage,
|
||||
},
|
||||
overseer, ActiveLeavesUpdate, FromOverseer, OverseerSignal, PerLeafSpan, SpawnedSubsystem,
|
||||
SubsystemContext, SubsystemError,
|
||||
SubsystemError,
|
||||
};
|
||||
use polkadot_primitives::v2::{
|
||||
AuthorityDiscoveryId, CandidateHash, CommittedCandidateReceipt, CompactStatement, Hash,
|
||||
@@ -127,12 +127,8 @@ pub struct StatementDistributionSubsystem<R> {
|
||||
rng: R,
|
||||
}
|
||||
|
||||
impl<Context, R: rand::Rng + Send + Sync + 'static> overseer::Subsystem<Context, SubsystemError>
|
||||
for StatementDistributionSubsystem<R>
|
||||
where
|
||||
Context: SubsystemContext<Message = StatementDistributionMessage>,
|
||||
Context: overseer::SubsystemContext<Message = StatementDistributionMessage>,
|
||||
{
|
||||
#[overseer::subsystem(StatementDistribution, error=SubsystemError, prefix=self::overseer)]
|
||||
impl<Context, R: rand::Rng + Send + Sync + 'static> StatementDistributionSubsystem<R> {
|
||||
fn start(self, ctx: Context) -> SpawnedSubsystem {
|
||||
// Swallow error because failure is fatal to the node and we log with more precision
|
||||
// within `run`.
|
||||
@@ -630,10 +626,10 @@ enum MuxedMessage {
|
||||
Responder(Option<ResponderMessage>),
|
||||
}
|
||||
|
||||
#[overseer::contextbounds(StatementDistribution, prefix = self::overseer)]
|
||||
impl MuxedMessage {
|
||||
async fn receive(
|
||||
ctx: &mut (impl SubsystemContext<Message = StatementDistributionMessage>
|
||||
+ overseer::SubsystemContext<Message = StatementDistributionMessage>),
|
||||
async fn receive<Context>(
|
||||
ctx: &mut Context,
|
||||
from_requester: &mut mpsc::Receiver<RequesterMessage>,
|
||||
from_responder: &mut mpsc::Receiver<ResponderMessage>,
|
||||
) -> MuxedMessage {
|
||||
@@ -890,11 +886,12 @@ fn check_statement_signature(
|
||||
/// circulates the statement to all peers who have not seen it yet, and
|
||||
/// sends all statements dependent on that statement to peers who could previously not receive
|
||||
/// them but now can.
|
||||
async fn circulate_statement_and_dependents(
|
||||
#[overseer::contextbounds(StatementDistribution, prefix=self::overseer)]
|
||||
async fn circulate_statement_and_dependents<Context>(
|
||||
gossip_peers: &HashSet<PeerId>,
|
||||
peers: &mut HashMap<PeerId, PeerData>,
|
||||
active_heads: &mut HashMap<Hash, ActiveHeadData>,
|
||||
ctx: &mut (impl SubsystemContext + overseer::SubsystemContext),
|
||||
ctx: &mut Context,
|
||||
relay_parent: Hash,
|
||||
statement: SignedFullStatement,
|
||||
priority_peers: Vec<PeerId>,
|
||||
@@ -1006,10 +1003,11 @@ fn is_statement_large(statement: &SignedFullStatement) -> (bool, Option<usize>)
|
||||
|
||||
/// Circulates a statement to all peers who have not seen it yet, and returns
|
||||
/// an iterator over peers who need to have dependent statements sent.
|
||||
async fn circulate_statement<'a>(
|
||||
#[overseer::contextbounds(StatementDistribution, prefix=self::overseer)]
|
||||
async fn circulate_statement<'a, Context>(
|
||||
gossip_peers: &HashSet<PeerId>,
|
||||
peers: &mut HashMap<PeerId, PeerData>,
|
||||
ctx: &mut (impl SubsystemContext + overseer::SubsystemContext),
|
||||
ctx: &mut Context,
|
||||
relay_parent: Hash,
|
||||
stored: StoredStatement<'a>,
|
||||
mut priority_peers: Vec<PeerId>,
|
||||
@@ -1081,10 +1079,10 @@ async fn circulate_statement<'a>(
|
||||
statement = ?stored.statement,
|
||||
"Sending statement",
|
||||
);
|
||||
ctx.send_message(AllMessages::NetworkBridge(NetworkBridgeMessage::SendValidationMessage(
|
||||
ctx.send_message(NetworkBridgeMessage::SendValidationMessage(
|
||||
peers_to_send.iter().map(|(p, _)| p.clone()).collect(),
|
||||
payload,
|
||||
)))
|
||||
))
|
||||
.await;
|
||||
}
|
||||
|
||||
@@ -1095,10 +1093,11 @@ async fn circulate_statement<'a>(
|
||||
}
|
||||
|
||||
/// Send all statements about a given candidate hash to a peer.
|
||||
async fn send_statements_about(
|
||||
#[overseer::contextbounds(StatementDistribution, prefix=self::overseer)]
|
||||
async fn send_statements_about<Context>(
|
||||
peer: PeerId,
|
||||
peer_data: &mut PeerData,
|
||||
ctx: &mut (impl SubsystemContext + overseer::SubsystemContext),
|
||||
ctx: &mut Context,
|
||||
relay_parent: Hash,
|
||||
candidate_hash: CandidateHash,
|
||||
active_head: &ActiveHeadData,
|
||||
@@ -1120,21 +1119,19 @@ async fn send_statements_about(
|
||||
statement = ?statement.statement,
|
||||
"Sending statement",
|
||||
);
|
||||
ctx.send_message(AllMessages::NetworkBridge(NetworkBridgeMessage::SendValidationMessage(
|
||||
vec![peer.clone()],
|
||||
payload,
|
||||
)))
|
||||
.await;
|
||||
ctx.send_message(NetworkBridgeMessage::SendValidationMessage(vec![peer.clone()], payload))
|
||||
.await;
|
||||
|
||||
metrics.on_statement_distributed();
|
||||
}
|
||||
}
|
||||
|
||||
/// Send all statements at a given relay-parent to a peer.
|
||||
async fn send_statements(
|
||||
#[overseer::contextbounds(StatementDistribution, prefix=self::overseer)]
|
||||
async fn send_statements<Context>(
|
||||
peer: PeerId,
|
||||
peer_data: &mut PeerData,
|
||||
ctx: &mut (impl SubsystemContext + overseer::SubsystemContext),
|
||||
ctx: &mut Context,
|
||||
relay_parent: Hash,
|
||||
active_head: &ActiveHeadData,
|
||||
metrics: &Metrics,
|
||||
@@ -1154,23 +1151,19 @@ async fn send_statements(
|
||||
statement = ?statement.statement,
|
||||
"Sending statement"
|
||||
);
|
||||
ctx.send_message(AllMessages::NetworkBridge(NetworkBridgeMessage::SendValidationMessage(
|
||||
vec![peer.clone()],
|
||||
payload,
|
||||
)))
|
||||
.await;
|
||||
ctx.send_message(NetworkBridgeMessage::SendValidationMessage(vec![peer.clone()], payload))
|
||||
.await;
|
||||
|
||||
metrics.on_statement_distributed();
|
||||
}
|
||||
}
|
||||
|
||||
async fn report_peer(
|
||||
ctx: &mut (impl SubsystemContext + overseer::SubsystemContext),
|
||||
sender: &mut impl overseer::StatementDistributionSenderTrait,
|
||||
peer: PeerId,
|
||||
rep: Rep,
|
||||
) {
|
||||
ctx.send_message(AllMessages::NetworkBridge(NetworkBridgeMessage::ReportPeer(peer, rep)))
|
||||
.await
|
||||
sender.send_message(NetworkBridgeMessage::ReportPeer(peer, rep)).await
|
||||
}
|
||||
|
||||
/// If message contains a statement, then retrieve it, otherwise fork task to fetch it.
|
||||
@@ -1180,11 +1173,12 @@ async fn report_peer(
|
||||
/// your statement.
|
||||
///
|
||||
/// If the message was large, but the result has been fetched already that one is returned.
|
||||
async fn retrieve_statement_from_message<'a>(
|
||||
#[overseer::contextbounds(StatementDistribution, prefix=self::overseer)]
|
||||
async fn retrieve_statement_from_message<'a, Context>(
|
||||
peer: PeerId,
|
||||
message: protocol_v1::StatementDistributionMessage,
|
||||
active_head: &'a mut ActiveHeadData,
|
||||
ctx: &mut (impl SubsystemContext + overseer::SubsystemContext),
|
||||
ctx: &mut Context,
|
||||
req_sender: &mpsc::Sender<RequesterMessage>,
|
||||
metrics: &Metrics,
|
||||
) -> Option<UncheckedSignedFullStatement> {
|
||||
@@ -1272,11 +1266,12 @@ async fn retrieve_statement_from_message<'a>(
|
||||
/// Launch request for a large statement and get tracking status.
|
||||
///
|
||||
/// Returns `None` if spawning task failed.
|
||||
async fn launch_request(
|
||||
#[overseer::contextbounds(StatementDistribution, prefix=self::overseer)]
|
||||
async fn launch_request<Context>(
|
||||
meta: StatementMetadata,
|
||||
peer: PeerId,
|
||||
req_sender: mpsc::Sender<RequesterMessage>,
|
||||
ctx: &mut (impl SubsystemContext + overseer::SubsystemContext),
|
||||
ctx: &mut Context,
|
||||
metrics: &Metrics,
|
||||
) -> Option<LargeStatementStatus> {
|
||||
let (task, handle) =
|
||||
@@ -1302,19 +1297,21 @@ async fn launch_request(
|
||||
}
|
||||
|
||||
/// Handle incoming message and circulate it to peers, if we did not know it already.
|
||||
///
|
||||
async fn handle_incoming_message_and_circulate<'a>(
|
||||
#[overseer::contextbounds(StatementDistribution, prefix=self::overseer)]
|
||||
async fn handle_incoming_message_and_circulate<'a, Context, R>(
|
||||
peer: PeerId,
|
||||
gossip_peers: &HashSet<PeerId>,
|
||||
peers: &mut HashMap<PeerId, PeerData>,
|
||||
active_heads: &'a mut HashMap<Hash, ActiveHeadData>,
|
||||
recent_outdated_heads: &RecentOutdatedHeads,
|
||||
ctx: &mut (impl SubsystemContext + overseer::SubsystemContext),
|
||||
ctx: &mut Context,
|
||||
message: protocol_v1::StatementDistributionMessage,
|
||||
req_sender: &mpsc::Sender<RequesterMessage>,
|
||||
metrics: &Metrics,
|
||||
rng: &mut impl rand::Rng,
|
||||
) {
|
||||
rng: &mut R,
|
||||
) where
|
||||
R: rand::Rng,
|
||||
{
|
||||
let handled_incoming = match peers.get_mut(&peer) {
|
||||
Some(data) =>
|
||||
handle_incoming_message(
|
||||
@@ -1360,12 +1357,13 @@ async fn handle_incoming_message_and_circulate<'a>(
|
||||
//
|
||||
// This function checks the signature and ensures the statement is compatible with our
|
||||
// view. It also notifies candidate backing if the statement was previously unknown.
|
||||
async fn handle_incoming_message<'a>(
|
||||
#[overseer::contextbounds(StatementDistribution, prefix=self::overseer)]
|
||||
async fn handle_incoming_message<'a, Context>(
|
||||
peer: PeerId,
|
||||
peer_data: &mut PeerData,
|
||||
active_heads: &'a mut HashMap<Hash, ActiveHeadData>,
|
||||
recent_outdated_heads: &RecentOutdatedHeads,
|
||||
ctx: &mut (impl SubsystemContext + overseer::SubsystemContext),
|
||||
ctx: &mut Context,
|
||||
message: protocol_v1::StatementDistributionMessage,
|
||||
req_sender: &mpsc::Sender<RequesterMessage>,
|
||||
metrics: &Metrics,
|
||||
@@ -1383,7 +1381,7 @@ async fn handle_incoming_message<'a>(
|
||||
);
|
||||
|
||||
if !recent_outdated_heads.is_recent_outdated(&relay_parent) {
|
||||
report_peer(ctx, peer, COST_UNEXPECTED_STATEMENT).await;
|
||||
report_peer(ctx.sender(), peer, COST_UNEXPECTED_STATEMENT).await;
|
||||
}
|
||||
|
||||
return None
|
||||
@@ -1393,7 +1391,7 @@ async fn handle_incoming_message<'a>(
|
||||
if let protocol_v1::StatementDistributionMessage::LargeStatement(_) = message {
|
||||
if let Err(rep) = peer_data.receive_large_statement(&relay_parent) {
|
||||
gum::debug!(target: LOG_TARGET, ?peer, ?message, ?rep, "Unexpected large statement.",);
|
||||
report_peer(ctx, peer, rep).await;
|
||||
report_peer(ctx.sender(), peer, rep).await;
|
||||
return None
|
||||
}
|
||||
}
|
||||
@@ -1434,16 +1432,16 @@ async fn handle_incoming_message<'a>(
|
||||
// Report peer merely if this is not a duplicate out-of-view statement that
|
||||
// was caused by a missing Seconded statement from this peer
|
||||
if unexpected_count == 0_usize {
|
||||
report_peer(ctx, peer, rep).await;
|
||||
report_peer(ctx.sender(), peer, rep).await;
|
||||
}
|
||||
},
|
||||
// This happens when we have an unexpected remote peer that announced Seconded
|
||||
COST_UNEXPECTED_STATEMENT_REMOTE => {
|
||||
metrics.on_unexpected_statement_seconded();
|
||||
report_peer(ctx, peer, rep).await;
|
||||
report_peer(ctx.sender(), peer, rep).await;
|
||||
},
|
||||
_ => {
|
||||
report_peer(ctx, peer, rep).await;
|
||||
report_peer(ctx.sender(), peer, rep).await;
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1464,7 +1462,7 @@ async fn handle_incoming_message<'a>(
|
||||
peer_data
|
||||
.receive(&relay_parent, &fingerprint, max_message_count)
|
||||
.expect("checked in `check_can_receive` above; qed");
|
||||
report_peer(ctx, peer, BENEFIT_VALID_STATEMENT).await;
|
||||
report_peer(ctx.sender(), peer, BENEFIT_VALID_STATEMENT).await;
|
||||
|
||||
return None
|
||||
},
|
||||
@@ -1474,7 +1472,7 @@ async fn handle_incoming_message<'a>(
|
||||
match check_statement_signature(&active_head, relay_parent, unchecked_compact) {
|
||||
Err(statement) => {
|
||||
gum::debug!(target: LOG_TARGET, ?peer, ?statement, "Invalid statement signature");
|
||||
report_peer(ctx, peer, COST_INVALID_SIGNATURE).await;
|
||||
report_peer(ctx.sender(), peer, COST_INVALID_SIGNATURE).await;
|
||||
return None
|
||||
},
|
||||
Ok(statement) => statement,
|
||||
@@ -1500,7 +1498,7 @@ async fn handle_incoming_message<'a>(
|
||||
is_large_statement,
|
||||
"Full statement had bad payload."
|
||||
);
|
||||
report_peer(ctx, peer, COST_WRONG_HASH).await;
|
||||
report_peer(ctx.sender(), peer, COST_WRONG_HASH).await;
|
||||
return None
|
||||
},
|
||||
Ok(statement) => statement,
|
||||
@@ -1539,7 +1537,7 @@ async fn handle_incoming_message<'a>(
|
||||
unreachable!("checked in `is_useful_or_unknown` above; qed");
|
||||
},
|
||||
NotedStatement::Fresh(statement) => {
|
||||
report_peer(ctx, peer, BENEFIT_VALID_STATEMENT_FIRST).await;
|
||||
report_peer(ctx.sender(), peer, BENEFIT_VALID_STATEMENT_FIRST).await;
|
||||
|
||||
let mut _span = handle_incoming_span.child("notify-backing");
|
||||
|
||||
@@ -1557,16 +1555,19 @@ async fn handle_incoming_message<'a>(
|
||||
}
|
||||
|
||||
/// Update a peer's view. Sends all newly unlocked statements based on the previous
|
||||
async fn update_peer_view_and_maybe_send_unlocked(
|
||||
#[overseer::contextbounds(StatementDistribution, prefix=self::overseer)]
|
||||
async fn update_peer_view_and_maybe_send_unlocked<Context, R>(
|
||||
peer: PeerId,
|
||||
gossip_peers: &HashSet<PeerId>,
|
||||
peer_data: &mut PeerData,
|
||||
ctx: &mut (impl SubsystemContext + overseer::SubsystemContext),
|
||||
ctx: &mut Context,
|
||||
active_heads: &HashMap<Hash, ActiveHeadData>,
|
||||
new_view: View,
|
||||
metrics: &Metrics,
|
||||
rng: &mut impl rand::Rng,
|
||||
) {
|
||||
rng: &mut R,
|
||||
) where
|
||||
R: rand::Rng,
|
||||
{
|
||||
let old_view = std::mem::replace(&mut peer_data.view, new_view);
|
||||
|
||||
// Remove entries for all relay-parents in the old view but not the new.
|
||||
@@ -1596,18 +1597,21 @@ async fn update_peer_view_and_maybe_send_unlocked(
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_network_update(
|
||||
#[overseer::contextbounds(StatementDistribution, prefix=self::overseer)]
|
||||
async fn handle_network_update<Context, R>(
|
||||
peers: &mut HashMap<PeerId, PeerData>,
|
||||
gossip_peers: &mut HashSet<PeerId>,
|
||||
authorities: &mut HashMap<AuthorityDiscoveryId, PeerId>,
|
||||
active_heads: &mut HashMap<Hash, ActiveHeadData>,
|
||||
recent_outdated_heads: &RecentOutdatedHeads,
|
||||
ctx: &mut (impl SubsystemContext + overseer::SubsystemContext),
|
||||
ctx: &mut Context,
|
||||
req_sender: &mpsc::Sender<RequesterMessage>,
|
||||
update: NetworkBridgeEvent<net_protocol::StatementDistributionMessage>,
|
||||
metrics: &Metrics,
|
||||
rng: &mut impl rand::Rng,
|
||||
) {
|
||||
rng: &mut R,
|
||||
) where
|
||||
R: rand::Rng,
|
||||
{
|
||||
match update {
|
||||
NetworkBridgeEvent::PeerConnected(peer, role, _, maybe_authority) => {
|
||||
gum::trace!(target: LOG_TARGET, ?peer, ?role, "Peer connected");
|
||||
@@ -1701,6 +1705,7 @@ async fn handle_network_update(
|
||||
}
|
||||
}
|
||||
|
||||
#[overseer::contextbounds(StatementDistribution, prefix = self::overseer)]
|
||||
impl<R: rand::Rng> StatementDistributionSubsystem<R> {
|
||||
/// Create a new Statement Distribution Subsystem
|
||||
pub fn new(
|
||||
@@ -1712,11 +1717,7 @@ impl<R: rand::Rng> StatementDistributionSubsystem<R> {
|
||||
Self { keystore, req_receiver: Some(req_receiver), metrics, rng }
|
||||
}
|
||||
|
||||
async fn run(
|
||||
mut self,
|
||||
mut ctx: (impl SubsystemContext<Message = StatementDistributionMessage>
|
||||
+ overseer::SubsystemContext<Message = StatementDistributionMessage>),
|
||||
) -> std::result::Result<(), FatalError> {
|
||||
async fn run<Context>(mut self, mut ctx: Context) -> std::result::Result<(), FatalError> {
|
||||
let mut peers: HashMap<PeerId, PeerData> = HashMap::new();
|
||||
let mut gossip_peers: HashSet<PeerId> = HashSet::new();
|
||||
let mut authorities: HashMap<AuthorityDiscoveryId, PeerId> = HashMap::new();
|
||||
@@ -1832,9 +1833,9 @@ impl<R: rand::Rng> StatementDistributionSubsystem<R> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn handle_requester_message(
|
||||
async fn handle_requester_message<Context>(
|
||||
&mut self,
|
||||
ctx: &mut impl SubsystemContext,
|
||||
ctx: &mut Context,
|
||||
gossip_peers: &HashSet<PeerId>,
|
||||
peers: &mut HashMap<PeerId, PeerData>,
|
||||
active_heads: &mut HashMap<Hash, ActiveHeadData>,
|
||||
@@ -1851,9 +1852,9 @@ impl<R: rand::Rng> StatementDistributionSubsystem<R> {
|
||||
bad_peers,
|
||||
} => {
|
||||
for bad in bad_peers {
|
||||
report_peer(ctx, bad, COST_FETCH_FAIL).await;
|
||||
report_peer(ctx.sender(), bad, COST_FETCH_FAIL).await;
|
||||
}
|
||||
report_peer(ctx, from_peer, BENEFIT_VALID_RESPONSE).await;
|
||||
report_peer(ctx.sender(), from_peer, BENEFIT_VALID_RESPONSE).await;
|
||||
|
||||
let active_head = active_heads
|
||||
.get_mut(&relay_parent)
|
||||
@@ -1898,10 +1899,10 @@ impl<R: rand::Rng> StatementDistributionSubsystem<R> {
|
||||
}
|
||||
},
|
||||
RequesterMessage::SendRequest(req) => {
|
||||
ctx.send_message(AllMessages::NetworkBridge(NetworkBridgeMessage::SendRequests(
|
||||
ctx.send_message(NetworkBridgeMessage::SendRequests(
|
||||
vec![req],
|
||||
IfDisconnected::ImmediateError,
|
||||
)))
|
||||
))
|
||||
.await;
|
||||
},
|
||||
RequesterMessage::GetMorePeers { relay_parent, candidate_hash, tx } => {
|
||||
@@ -1935,14 +1936,14 @@ impl<R: rand::Rng> StatementDistributionSubsystem<R> {
|
||||
}
|
||||
}
|
||||
},
|
||||
RequesterMessage::ReportPeer(peer, rep) => report_peer(ctx, peer, rep).await,
|
||||
RequesterMessage::ReportPeer(peer, rep) => report_peer(ctx.sender(), peer, rep).await,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn handle_subsystem_message(
|
||||
async fn handle_subsystem_message<Context>(
|
||||
&mut self,
|
||||
ctx: &mut (impl SubsystemContext + overseer::SubsystemContext),
|
||||
ctx: &mut Context,
|
||||
runtime: &mut RuntimeInfo,
|
||||
peers: &mut HashMap<PeerId, PeerData>,
|
||||
gossip_peers: &mut HashSet<PeerId>,
|
||||
|
||||
@@ -29,7 +29,7 @@ use polkadot_node_network_protocol::{
|
||||
use polkadot_node_primitives::{Statement, UncheckedSignedFullStatement};
|
||||
use polkadot_node_subsystem::{
|
||||
jaeger,
|
||||
messages::{network_bridge_event, RuntimeApiMessage, RuntimeApiRequest},
|
||||
messages::{network_bridge_event, AllMessages, RuntimeApiMessage, RuntimeApiRequest},
|
||||
ActivatedLeaf, LeafStatus,
|
||||
};
|
||||
use polkadot_node_subsystem_test_helpers::mock::make_ferdie_keystore;
|
||||
|
||||
Reference in New Issue
Block a user