mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 23:21:02 +00:00
Network bridge refactoring impl (#1537)
* update networking types * port over overseer-protocol message types * Add the collation protocol to network bridge * message sending * stub for ConnectToValidators * add some helper traits and methods to protocol types * add collator protocol message * leaves-updating * peer connection and disconnection * add utilities for dispatching multiple events * implement message handling * add an observedrole enum with equality and no sentry nodes * derive partial-eq on network bridge event * add PartialEq impls for network message types * add Into implementation for observedrole * port over existing network bridge tests * add some more tests * port bitfield distribution * port over bitfield distribution tests * add codec indices * port PoV distribution * port over PoV distribution tests * port over statement distribution * port over statement distribution tests * update overseer and service-new * address review comments * port availability distribution * port over availability distribution tests
This commit is contained in:
committed by
GitHub
parent
8e60a5197f
commit
a6b1d91d6e
@@ -23,15 +23,13 @@
|
||||
use codec::{Decode, Encode};
|
||||
use futures::{channel::oneshot, FutureExt};
|
||||
|
||||
use node_primitives::{ProtocolId, View};
|
||||
|
||||
use log::{trace, warn};
|
||||
use polkadot_subsystem::messages::*;
|
||||
use polkadot_subsystem::{
|
||||
ActiveLeavesUpdate, FromOverseer, OverseerSignal, SpawnedSubsystem, Subsystem, SubsystemContext, SubsystemResult,
|
||||
};
|
||||
use polkadot_primitives::v1::{Hash, SignedAvailabilityBitfield, SigningContext, ValidatorId};
|
||||
use sc_network::ReputationChange;
|
||||
use polkadot_node_network_protocol::{v1 as protocol_v1, PeerId, NetworkBridgeEvent, View, ReputationChange};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
const COST_SIGNATURE_INVALID: ReputationChange =
|
||||
@@ -42,8 +40,6 @@ const COST_MISSING_PEER_SESSION_KEY: ReputationChange =
|
||||
ReputationChange::new(-133, "Missing peer session key");
|
||||
const COST_NOT_IN_VIEW: ReputationChange =
|
||||
ReputationChange::new(-51, "Not interested in that parent hash");
|
||||
const COST_MESSAGE_NOT_DECODABLE: ReputationChange =
|
||||
ReputationChange::new(-100, "Not interested in that parent hash");
|
||||
const COST_PEER_DUPLICATE_MESSAGE: ReputationChange =
|
||||
ReputationChange::new(-500, "Peer sent the same message multiple times");
|
||||
const BENEFIT_VALID_MESSAGE_FIRST: ReputationChange =
|
||||
@@ -54,11 +50,28 @@ const BENEFIT_VALID_MESSAGE: ReputationChange =
|
||||
/// Checked signed availability bitfield that is distributed
|
||||
/// to other peers.
|
||||
#[derive(Encode, Decode, Debug, Clone, PartialEq, Eq)]
|
||||
pub struct BitfieldGossipMessage {
|
||||
struct BitfieldGossipMessage {
|
||||
/// The relay parent this message is relative to.
|
||||
pub relay_parent: Hash,
|
||||
relay_parent: Hash,
|
||||
/// The actual signed availability bitfield.
|
||||
pub signed_availability: SignedAvailabilityBitfield,
|
||||
signed_availability: SignedAvailabilityBitfield,
|
||||
}
|
||||
|
||||
impl BitfieldGossipMessage {
|
||||
fn into_validation_protocol(self) -> protocol_v1::ValidationProtocol {
|
||||
protocol_v1::ValidationProtocol::BitfieldDistribution(
|
||||
self.into_network_message()
|
||||
)
|
||||
}
|
||||
|
||||
fn into_network_message(self)
|
||||
-> protocol_v1::BitfieldDistributionMessage
|
||||
{
|
||||
protocol_v1::BitfieldDistributionMessage::Bitfield(
|
||||
self.relay_parent,
|
||||
self.signed_availability,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Data used to track information of peers and relay parents the
|
||||
@@ -114,28 +127,15 @@ impl PerRelayParentData {
|
||||
}
|
||||
}
|
||||
|
||||
fn network_update_message(n: NetworkBridgeEvent) -> AllMessages {
|
||||
AllMessages::BitfieldDistribution(BitfieldDistributionMessage::NetworkBridgeUpdate(n))
|
||||
}
|
||||
|
||||
/// The bitfield distribution subsystem.
|
||||
pub struct BitfieldDistribution;
|
||||
|
||||
impl BitfieldDistribution {
|
||||
/// The protocol identifier for bitfield distribution.
|
||||
const PROTOCOL_ID: ProtocolId = *b"bitd";
|
||||
|
||||
/// Start processing work as passed on from the Overseer.
|
||||
async fn run<Context>(mut ctx: Context) -> SubsystemResult<()>
|
||||
where
|
||||
Context: SubsystemContext<Message = BitfieldDistributionMessage>,
|
||||
{
|
||||
// startup: register the network protocol with the bridge.
|
||||
ctx.send_message(AllMessages::NetworkBridge(
|
||||
NetworkBridgeMessage::RegisterEventProducer(Self::PROTOCOL_ID, network_update_message),
|
||||
))
|
||||
.await?;
|
||||
|
||||
// work: process incoming messages from the overseer and process accordingly.
|
||||
let mut state = ProtocolState::default();
|
||||
loop {
|
||||
@@ -149,7 +149,7 @@ impl BitfieldDistribution {
|
||||
.await?;
|
||||
}
|
||||
FromOverseer::Communication {
|
||||
msg: BitfieldDistributionMessage::NetworkBridgeUpdate(event),
|
||||
msg: BitfieldDistributionMessage::NetworkBridgeUpdateV1(event),
|
||||
} => {
|
||||
trace!(target: "bitd", "Processing NetworkMessage");
|
||||
// a network message was received
|
||||
@@ -314,10 +314,9 @@ where
|
||||
);
|
||||
} else {
|
||||
ctx.send_message(AllMessages::NetworkBridge(
|
||||
NetworkBridgeMessage::SendMessage(
|
||||
NetworkBridgeMessage::SendValidationMessage(
|
||||
interested_peers,
|
||||
BitfieldDistribution::PROTOCOL_ID,
|
||||
message.encode(),
|
||||
message.into_validation_protocol(),
|
||||
),
|
||||
))
|
||||
.await?;
|
||||
@@ -413,7 +412,7 @@ where
|
||||
async fn handle_network_msg<Context>(
|
||||
ctx: &mut Context,
|
||||
state: &mut ProtocolState,
|
||||
bridge_message: NetworkBridgeEvent,
|
||||
bridge_message: NetworkBridgeEvent<protocol_v1::BitfieldDistributionMessage>,
|
||||
) -> SubsystemResult<()>
|
||||
where
|
||||
Context: SubsystemContext<Message = BitfieldDistributionMessage>,
|
||||
@@ -433,12 +432,16 @@ where
|
||||
NetworkBridgeEvent::OurViewChange(view) => {
|
||||
handle_our_view_change(state, view)?;
|
||||
}
|
||||
NetworkBridgeEvent::PeerMessage(remote, bytes) => {
|
||||
if let Ok(gossiped_bitfield) = BitfieldGossipMessage::decode(&mut (bytes.as_slice())) {
|
||||
trace!(target: "bitd", "Received bitfield gossip from peer {:?}", &remote);
|
||||
process_incoming_peer_message(ctx, state, remote, gossiped_bitfield).await?;
|
||||
} else {
|
||||
modify_reputation(ctx, remote, COST_MESSAGE_NOT_DECODABLE).await?;
|
||||
NetworkBridgeEvent::PeerMessage(remote, message) => {
|
||||
match message {
|
||||
protocol_v1::BitfieldDistributionMessage::Bitfield(relay_parent, bitfield) => {
|
||||
trace!(target: "bitd", "Received bitfield gossip from peer {:?}", &remote);
|
||||
let gossiped_bitfield = BitfieldGossipMessage {
|
||||
relay_parent,
|
||||
signed_availability: bitfield,
|
||||
};
|
||||
process_incoming_peer_message(ctx, state, remote, gossiped_bitfield).await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -541,10 +544,9 @@ where
|
||||
.insert(validator.clone());
|
||||
|
||||
ctx.send_message(AllMessages::NetworkBridge(
|
||||
NetworkBridgeMessage::SendMessage(
|
||||
NetworkBridgeMessage::SendValidationMessage(
|
||||
vec![dest],
|
||||
BitfieldDistribution::PROTOCOL_ID,
|
||||
message.encode(),
|
||||
message.into_validation_protocol(),
|
||||
),
|
||||
))
|
||||
.await?;
|
||||
@@ -612,6 +614,7 @@ mod test {
|
||||
use sp_core::crypto::Pair;
|
||||
use std::time::Duration;
|
||||
use assert_matches::assert_matches;
|
||||
use polkadot_node_network_protocol::ObservedRole;
|
||||
|
||||
macro_rules! view {
|
||||
( $( $hash:expr ),* $(,)? ) => [
|
||||
@@ -742,7 +745,7 @@ mod test {
|
||||
launch!(handle_network_msg(
|
||||
&mut ctx,
|
||||
&mut state,
|
||||
NetworkBridgeEvent::PeerMessage(peer_b.clone(), msg.encode()),
|
||||
NetworkBridgeEvent::PeerMessage(peer_b.clone(), msg.into_network_message()),
|
||||
));
|
||||
|
||||
// reputation change due to invalid validator index
|
||||
@@ -795,7 +798,7 @@ mod test {
|
||||
launch!(handle_network_msg(
|
||||
&mut ctx,
|
||||
&mut state,
|
||||
NetworkBridgeEvent::PeerMessage(peer_b.clone(), msg.encode()),
|
||||
NetworkBridgeEvent::PeerMessage(peer_b.clone(), msg.into_network_message()),
|
||||
));
|
||||
|
||||
// reputation change due to invalid validator index
|
||||
@@ -848,7 +851,10 @@ mod test {
|
||||
launch!(handle_network_msg(
|
||||
&mut ctx,
|
||||
&mut state,
|
||||
NetworkBridgeEvent::PeerMessage(peer_b.clone(), msg.encode()),
|
||||
NetworkBridgeEvent::PeerMessage(
|
||||
peer_b.clone(),
|
||||
msg.clone().into_network_message(),
|
||||
),
|
||||
));
|
||||
|
||||
// none of our peers has any interest in any messages
|
||||
@@ -878,7 +884,10 @@ mod test {
|
||||
launch!(handle_network_msg(
|
||||
&mut ctx,
|
||||
&mut state,
|
||||
NetworkBridgeEvent::PeerMessage(peer_a.clone(), msg.encode()),
|
||||
NetworkBridgeEvent::PeerMessage(
|
||||
peer_a.clone(),
|
||||
msg.clone().into_network_message(),
|
||||
),
|
||||
));
|
||||
|
||||
assert_matches!(
|
||||
@@ -895,7 +904,10 @@ mod test {
|
||||
launch!(handle_network_msg(
|
||||
&mut ctx,
|
||||
&mut state,
|
||||
NetworkBridgeEvent::PeerMessage(peer_b.clone(), msg.encode()),
|
||||
NetworkBridgeEvent::PeerMessage(
|
||||
peer_b.clone(),
|
||||
msg.clone().into_network_message(),
|
||||
),
|
||||
));
|
||||
|
||||
assert_matches!(
|
||||
@@ -909,6 +921,7 @@ mod test {
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn changing_view() {
|
||||
let _ = env_logger::builder()
|
||||
@@ -960,7 +973,10 @@ mod test {
|
||||
launch!(handle_network_msg(
|
||||
&mut ctx,
|
||||
&mut state,
|
||||
NetworkBridgeEvent::PeerMessage(peer_b.clone(), msg.encode()),
|
||||
NetworkBridgeEvent::PeerMessage(
|
||||
peer_b.clone(),
|
||||
msg.clone().into_network_message(),
|
||||
),
|
||||
));
|
||||
|
||||
// gossip to the overseer
|
||||
@@ -977,12 +993,11 @@ mod test {
|
||||
// gossip to the network
|
||||
assert_matches!(
|
||||
handle.recv().await,
|
||||
AllMessages::NetworkBridge(NetworkBridgeMessage::SendMessage (
|
||||
peers, proto, bytes
|
||||
AllMessages::NetworkBridge(NetworkBridgeMessage::SendValidationMessage (
|
||||
peers, out_msg,
|
||||
)) => {
|
||||
assert_eq!(peers, peers![peer_b]);
|
||||
assert_eq!(proto, BitfieldDistribution::PROTOCOL_ID);
|
||||
assert_eq!(bytes, msg.encode());
|
||||
assert_eq!(out_msg, msg.clone().into_validation_protocol());
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1014,7 +1029,10 @@ mod test {
|
||||
launch!(handle_network_msg(
|
||||
&mut ctx,
|
||||
&mut state,
|
||||
NetworkBridgeEvent::PeerMessage(peer_b.clone(), msg.encode()),
|
||||
NetworkBridgeEvent::PeerMessage(
|
||||
peer_b.clone(),
|
||||
msg.clone().into_network_message(),
|
||||
),
|
||||
));
|
||||
|
||||
// reputation change for peer B
|
||||
@@ -1042,7 +1060,10 @@ mod test {
|
||||
launch!(handle_network_msg(
|
||||
&mut ctx,
|
||||
&mut state,
|
||||
NetworkBridgeEvent::PeerMessage(peer_a.clone(), msg.encode()),
|
||||
NetworkBridgeEvent::PeerMessage(
|
||||
peer_a.clone(),
|
||||
msg.clone().into_network_message(),
|
||||
),
|
||||
));
|
||||
|
||||
// reputation change for peer B
|
||||
@@ -1058,59 +1079,4 @@ mod test {
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn invalid_peer_message() {
|
||||
let _ = env_logger::builder()
|
||||
.filter(None, log::LevelFilter::Trace)
|
||||
.is_test(true)
|
||||
.try_init();
|
||||
|
||||
let hash_a: Hash = [0; 32].into();
|
||||
let peer_a = PeerId::random();
|
||||
|
||||
// validator 0 key pair
|
||||
let (mut state, _signing_context, _validator_pair) = state_with_view(view![], hash_a.clone());
|
||||
|
||||
let pool = sp_core::testing::TaskExecutor::new();
|
||||
let (mut ctx, mut handle) =
|
||||
make_subsystem_context::<BitfieldDistributionMessage, _>(pool);
|
||||
|
||||
executor::block_on(async move {
|
||||
launch!(handle_network_msg(
|
||||
&mut ctx,
|
||||
&mut state,
|
||||
NetworkBridgeEvent::PeerConnected(peer_a.clone(), ObservedRole::Full),
|
||||
));
|
||||
|
||||
// make peer b interested
|
||||
launch!(handle_network_msg(
|
||||
&mut ctx,
|
||||
&mut state,
|
||||
NetworkBridgeEvent::PeerViewChange(peer_a.clone(), view![hash_a]),
|
||||
));
|
||||
|
||||
assert!(state.peer_views.contains_key(&peer_a));
|
||||
|
||||
// recv a first message from the network
|
||||
launch!(handle_network_msg(
|
||||
&mut ctx,
|
||||
&mut state,
|
||||
NetworkBridgeEvent::PeerMessage(peer_a.clone(), b"00AaBbCcDdEeFf".to_vec()),
|
||||
));
|
||||
|
||||
// reputation change for peer A
|
||||
assert_matches!(
|
||||
handle.recv().await,
|
||||
AllMessages::NetworkBridge(
|
||||
NetworkBridgeMessage::ReportPeer(peer, rep)
|
||||
) => {
|
||||
assert_eq!(peer, peer_a);
|
||||
assert_eq!(rep, COST_MESSAGE_NOT_DECODABLE);
|
||||
}
|
||||
);
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user