mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-11 20:01:08 +00:00
refactor View to include finalized_number (#2128)
* refactor View to include finalized_number * guide: update the NetworkBridge on BlockFinalized * av-store: fix the tests * actually fix tests * grumbles * ignore macro doctest * use Hash::repeat_bytes more consistently * broadcast empty leaves updates as well * fix issuing view updates on empty leaves updates
This commit is contained in:
@@ -145,7 +145,7 @@ impl CollationGenerationSubsystem {
|
||||
}
|
||||
false
|
||||
}
|
||||
Ok(Signal(BlockFinalized(_))) => false,
|
||||
Ok(Signal(BlockFinalized(..))) => false,
|
||||
Err(err) => {
|
||||
tracing::error!(
|
||||
target: LOG_TARGET,
|
||||
|
||||
@@ -538,8 +538,8 @@ where
|
||||
process_block_activated(ctx, &subsystem.inner, activated, &subsystem.metrics).await?;
|
||||
}
|
||||
}
|
||||
FromOverseer::Signal(OverseerSignal::BlockFinalized(hash)) => {
|
||||
process_block_finalized(subsystem, ctx, &subsystem.inner, hash).await?;
|
||||
FromOverseer::Signal(OverseerSignal::BlockFinalized(_hash, number)) => {
|
||||
process_block_finalized(subsystem, &subsystem.inner, number).await?;
|
||||
}
|
||||
FromOverseer::Communication { msg } => {
|
||||
process_message(subsystem, ctx, msg).await?;
|
||||
@@ -564,20 +564,14 @@ where
|
||||
/// The state of data has to be changed from
|
||||
/// `CandidateState::Included` to `CandidateState::Finalized` and their pruning times have
|
||||
/// to be updated to `now` + keep_finalized_{block, chunk}_for`.
|
||||
#[tracing::instrument(level = "trace", skip(subsystem, ctx, db), fields(subsystem = LOG_TARGET))]
|
||||
async fn process_block_finalized<Context>(
|
||||
#[tracing::instrument(level = "trace", skip(subsystem, db), fields(subsystem = LOG_TARGET))]
|
||||
async fn process_block_finalized(
|
||||
subsystem: &AvailabilityStoreSubsystem,
|
||||
ctx: &mut Context,
|
||||
db: &Arc<dyn KeyValueDB>,
|
||||
hash: Hash,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
Context: SubsystemContext<Message=AvailabilityStoreMessage>
|
||||
{
|
||||
block_number: BlockNumber,
|
||||
) -> Result<(), Error> {
|
||||
let _timer = subsystem.metrics.time_process_block_finalized();
|
||||
|
||||
let block_number = get_block_number(ctx, hash).await?;
|
||||
|
||||
if let Some(mut pov_pruning) = pov_pruning(db) {
|
||||
// Since the records are sorted by time in which they need to be pruned and not by block
|
||||
// numbers we have to iterate through the whole collection here.
|
||||
|
||||
@@ -274,7 +274,7 @@ fn store_block_works() {
|
||||
let test_state = TestState::default();
|
||||
test_harness(test_state.pruning_config.clone(), store.clone(), |test_harness| async move {
|
||||
let TestHarness { mut virtual_overseer } = test_harness;
|
||||
let candidate_hash = CandidateHash(Hash::from([1; 32]));
|
||||
let candidate_hash = CandidateHash(Hash::repeat_byte(1));
|
||||
let validator_index = 5;
|
||||
let n_validators = 10;
|
||||
|
||||
@@ -328,7 +328,7 @@ fn store_pov_and_query_chunk_works() {
|
||||
|
||||
test_harness(test_state.pruning_config.clone(), store.clone(), |test_harness| async move {
|
||||
let TestHarness { mut virtual_overseer } = test_harness;
|
||||
let candidate_hash = CandidateHash(Hash::from([1; 32]));
|
||||
let candidate_hash = CandidateHash(Hash::repeat_byte(1));
|
||||
let n_validators = 10;
|
||||
|
||||
let pov = PoV {
|
||||
@@ -543,20 +543,9 @@ fn stored_data_kept_until_finalized() {
|
||||
|
||||
overseer_signal(
|
||||
&mut virtual_overseer,
|
||||
OverseerSignal::BlockFinalized(new_leaf)
|
||||
OverseerSignal::BlockFinalized(new_leaf, 10)
|
||||
).await;
|
||||
|
||||
assert_matches!(
|
||||
overseer_recv(&mut virtual_overseer).await,
|
||||
AllMessages::ChainApi(ChainApiMessage::BlockNumber(
|
||||
hash,
|
||||
tx,
|
||||
)) => {
|
||||
assert_eq!(hash, new_leaf);
|
||||
tx.send(Ok(Some(10))).unwrap();
|
||||
}
|
||||
);
|
||||
|
||||
// Wait for a half of the time finalized data should be available for
|
||||
Delay::new(test_state.pruning_config.keep_finalized_block_for / 2).await;
|
||||
|
||||
@@ -658,20 +647,9 @@ fn stored_chunk_kept_until_finalized() {
|
||||
|
||||
overseer_signal(
|
||||
&mut virtual_overseer,
|
||||
OverseerSignal::BlockFinalized(new_leaf)
|
||||
OverseerSignal::BlockFinalized(new_leaf, 10)
|
||||
).await;
|
||||
|
||||
assert_matches!(
|
||||
overseer_recv(&mut virtual_overseer).await,
|
||||
AllMessages::ChainApi(ChainApiMessage::BlockNumber(
|
||||
hash,
|
||||
tx,
|
||||
)) => {
|
||||
assert_eq!(hash, new_leaf);
|
||||
tx.send(Ok(Some(10))).unwrap();
|
||||
}
|
||||
);
|
||||
|
||||
// Wait for a half of the time finalized data should be available for
|
||||
Delay::new(test_state.pruning_config.keep_finalized_block_for / 2).await;
|
||||
|
||||
@@ -812,21 +790,9 @@ fn forkfullness_works() {
|
||||
|
||||
overseer_signal(
|
||||
&mut virtual_overseer,
|
||||
OverseerSignal::BlockFinalized(new_leaf_1)
|
||||
OverseerSignal::BlockFinalized(new_leaf_1, 5)
|
||||
).await;
|
||||
|
||||
assert_matches!(
|
||||
overseer_recv(&mut virtual_overseer).await,
|
||||
AllMessages::ChainApi(ChainApiMessage::BlockNumber(
|
||||
hash,
|
||||
tx,
|
||||
)) => {
|
||||
assert_eq!(hash, new_leaf_1);
|
||||
tx.send(Ok(Some(5))).unwrap();
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
// Data of both candidates should be still present in the DB.
|
||||
assert_eq!(
|
||||
query_available_data(&mut virtual_overseer, candidate_1_hash).await.unwrap(),
|
||||
|
||||
@@ -1157,7 +1157,7 @@ mod tests {
|
||||
let mut head_data = HashMap::new();
|
||||
head_data.insert(chain_a, HeadData(vec![4, 5, 6]));
|
||||
|
||||
let relay_parent = Hash::from([5; 32]);
|
||||
let relay_parent = Hash::repeat_byte(5);
|
||||
|
||||
let signing_context = SigningContext {
|
||||
session_index: 1,
|
||||
|
||||
@@ -95,7 +95,7 @@ async fn run(
|
||||
loop {
|
||||
match ctx.recv().await? {
|
||||
FromOverseer::Signal(OverseerSignal::ActiveLeaves(_)) => {}
|
||||
FromOverseer::Signal(OverseerSignal::BlockFinalized(_)) => {}
|
||||
FromOverseer::Signal(OverseerSignal::BlockFinalized(..)) => {}
|
||||
FromOverseer::Signal(OverseerSignal::Conclude) => return Ok(()),
|
||||
FromOverseer::Communication { msg } => match msg {
|
||||
CandidateValidationMessage::ValidateFromChainState(
|
||||
|
||||
@@ -89,7 +89,7 @@ where
|
||||
match ctx.recv().await? {
|
||||
FromOverseer::Signal(OverseerSignal::Conclude) => return Ok(()),
|
||||
FromOverseer::Signal(OverseerSignal::ActiveLeaves(_)) => {},
|
||||
FromOverseer::Signal(OverseerSignal::BlockFinalized(_)) => {},
|
||||
FromOverseer::Signal(OverseerSignal::BlockFinalized(..)) => {},
|
||||
FromOverseer::Communication { msg } => match msg {
|
||||
ChainApiMessage::BlockNumber(hash, response_channel) => {
|
||||
let _timer = subsystem.metrics.time_block_number();
|
||||
|
||||
@@ -152,7 +152,7 @@ async fn run<Client>(
|
||||
req = ctx.recv().fuse() => match req? {
|
||||
FromOverseer::Signal(OverseerSignal::Conclude) => return Ok(()),
|
||||
FromOverseer::Signal(OverseerSignal::ActiveLeaves(_)) => {},
|
||||
FromOverseer::Signal(OverseerSignal::BlockFinalized(_)) => {},
|
||||
FromOverseer::Signal(OverseerSignal::BlockFinalized(..)) => {},
|
||||
FromOverseer::Communication { msg } => match msg {
|
||||
RuntimeApiMessage::Request(relay_parent, request) => {
|
||||
subsystem.spawn_request(relay_parent, request);
|
||||
|
||||
@@ -416,7 +416,7 @@ where
|
||||
.filter(|(_peer, view)| {
|
||||
// collect all direct interests of a peer w/o ancestors
|
||||
state
|
||||
.cached_live_candidates_unioned(view.0.iter())
|
||||
.cached_live_candidates_unioned(view.heads.iter())
|
||||
.contains_key(&candidate_hash)
|
||||
})
|
||||
.map(|(peer, _view)| peer.clone())
|
||||
@@ -619,7 +619,7 @@ where
|
||||
let _timer = metrics.time_process_incoming_peer_message();
|
||||
|
||||
// obtain the set of candidates we are interested in based on our current view
|
||||
let live_candidates = state.cached_live_candidates_unioned(state.view.0.iter());
|
||||
let live_candidates = state.cached_live_candidates_unioned(state.view.heads.iter());
|
||||
|
||||
// check if the candidate is of interest
|
||||
let live_candidate = if let Some(live_candidate) = live_candidates.get(&message.candidate_hash) {
|
||||
@@ -707,7 +707,7 @@ where
|
||||
.filter(|(_peer, view)| {
|
||||
// peers view must contain the candidate hash too
|
||||
state
|
||||
.cached_live_candidates_unioned(view.0.iter())
|
||||
.cached_live_candidates_unioned(view.heads.iter())
|
||||
.contains_key(&message_id.0)
|
||||
})
|
||||
.map(|(peer, _)| -> PeerId { peer.clone() })
|
||||
@@ -781,7 +781,7 @@ impl AvailabilityDistributionSubsystem {
|
||||
})) => {
|
||||
// handled at view change
|
||||
}
|
||||
FromOverseer::Signal(OverseerSignal::BlockFinalized(_)) => {}
|
||||
FromOverseer::Signal(OverseerSignal::BlockFinalized(..)) => {}
|
||||
FromOverseer::Signal(OverseerSignal::Conclude) => {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
use super::*;
|
||||
use assert_matches::assert_matches;
|
||||
use polkadot_erasure_coding::{branches, obtain_chunks_v1 as obtain_chunks};
|
||||
use polkadot_node_network_protocol::ObservedRole;
|
||||
use polkadot_node_network_protocol::{view, ObservedRole};
|
||||
use polkadot_node_subsystem_util::TimeoutExt;
|
||||
use polkadot_primitives::v1::{
|
||||
AvailableData, BlockData, CandidateCommitments, CandidateDescriptor, GroupIndex,
|
||||
@@ -33,11 +33,6 @@ use sp_application_crypto::AppKey;
|
||||
use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr};
|
||||
use std::{sync::Arc, time::Duration};
|
||||
|
||||
macro_rules! view {
|
||||
( $( $hash:expr ),* $(,)? ) => [
|
||||
View(vec![ $( $hash.clone() ),* ])
|
||||
];
|
||||
}
|
||||
|
||||
macro_rules! delay {
|
||||
($delay:expr) => {
|
||||
|
||||
@@ -212,8 +212,8 @@ impl BitfieldDistribution {
|
||||
// defer the cleanup to the view change
|
||||
}
|
||||
}
|
||||
FromOverseer::Signal(OverseerSignal::BlockFinalized(hash)) => {
|
||||
tracing::trace!(target: LOG_TARGET, hash = %hash, "block finalized");
|
||||
FromOverseer::Signal(OverseerSignal::BlockFinalized(hash, number)) => {
|
||||
tracing::trace!(target: LOG_TARGET, hash = %hash, number = %number, "block finalized");
|
||||
}
|
||||
FromOverseer::Signal(OverseerSignal::Conclude) => {
|
||||
tracing::trace!(target: LOG_TARGET, "Conclude");
|
||||
@@ -770,13 +770,7 @@ mod test {
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use assert_matches::assert_matches;
|
||||
use polkadot_node_network_protocol::ObservedRole;
|
||||
|
||||
macro_rules! view {
|
||||
( $( $hash:expr ),* $(,)? ) => [
|
||||
View(vec![ $( $hash.clone() ),* ])
|
||||
];
|
||||
}
|
||||
use polkadot_node_network_protocol::{view, ObservedRole};
|
||||
|
||||
macro_rules! launch {
|
||||
($fut:expr) => {
|
||||
@@ -833,7 +827,7 @@ mod test {
|
||||
let validator = SyncCryptoStore::sr25519_generate_new(&*keystore, ValidatorId::ID, None)
|
||||
.expect("generating sr25519 key not to fail");
|
||||
|
||||
state.per_relay_parent = view.0.iter().map(|relay_parent| {(
|
||||
state.per_relay_parent = view.heads.iter().map(|relay_parent| {(
|
||||
relay_parent.clone(),
|
||||
PerRelayParentData {
|
||||
signing_context: signing_context.clone(),
|
||||
|
||||
@@ -37,7 +37,7 @@ use polkadot_subsystem::messages::{
|
||||
BitfieldDistributionMessage, PoVDistributionMessage, StatementDistributionMessage,
|
||||
CollatorProtocolMessage,
|
||||
};
|
||||
use polkadot_primitives::v1::{AuthorityDiscoveryId, Block, Hash};
|
||||
use polkadot_primitives::v1::{AuthorityDiscoveryId, Block, Hash, BlockNumber};
|
||||
use polkadot_node_network_protocol::{
|
||||
ObservedRole, ReputationChange, PeerId, PeerSet, View, NetworkBridgeEvent, v1 as protocol_v1
|
||||
};
|
||||
@@ -254,6 +254,7 @@ enum Action {
|
||||
ReportPeer(PeerId, ReputationChange),
|
||||
|
||||
ActiveLeaves(ActiveLeavesUpdate),
|
||||
BlockFinalized(BlockNumber),
|
||||
|
||||
PeerConnected(PeerSet, PeerId, ObservedRole),
|
||||
PeerDisconnected(PeerSet, PeerId),
|
||||
@@ -274,6 +275,8 @@ fn action_from_overseer_message(
|
||||
match res {
|
||||
Ok(FromOverseer::Signal(OverseerSignal::ActiveLeaves(active_leaves)))
|
||||
=> Action::ActiveLeaves(active_leaves),
|
||||
Ok(FromOverseer::Signal(OverseerSignal::BlockFinalized(_hash, number)))
|
||||
=> Action::BlockFinalized(number),
|
||||
Ok(FromOverseer::Signal(OverseerSignal::Conclude)) => Action::Abort,
|
||||
Ok(FromOverseer::Communication { msg }) => match msg {
|
||||
NetworkBridgeMessage::ReportPeer(peer, rep) => Action::ReportPeer(peer, rep),
|
||||
@@ -284,8 +287,6 @@ fn action_from_overseer_message(
|
||||
NetworkBridgeMessage::ConnectToValidators { validator_ids, connected }
|
||||
=> Action::ConnectToValidators { validator_ids, connected },
|
||||
},
|
||||
Ok(FromOverseer::Signal(OverseerSignal::BlockFinalized(_)))
|
||||
=> Action::Nop,
|
||||
Err(e) => {
|
||||
tracing::warn!(target: LOG_TARGET, err = ?e, "Shutting down Network Bridge due to error");
|
||||
Action::Abort
|
||||
@@ -348,21 +349,25 @@ fn action_from_network_message(event: Option<NetworkEvent>) -> Action {
|
||||
}
|
||||
}
|
||||
|
||||
fn construct_view(live_heads: &[Hash]) -> View {
|
||||
View(live_heads.iter().rev().take(MAX_VIEW_HEADS).cloned().collect())
|
||||
fn construct_view(live_heads: &[Hash], finalized_number: BlockNumber) -> View {
|
||||
View {
|
||||
heads: live_heads.iter().rev().take(MAX_VIEW_HEADS).cloned().collect(),
|
||||
finalized_number
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "trace", skip(net, ctx, validation_peers, collation_peers), fields(subsystem = LOG_TARGET))]
|
||||
async fn update_view(
|
||||
async fn update_our_view(
|
||||
net: &mut impl Network,
|
||||
ctx: &mut impl SubsystemContext<Message = NetworkBridgeMessage>,
|
||||
live_heads: &[Hash],
|
||||
local_view: &mut View,
|
||||
finalized_number: BlockNumber,
|
||||
validation_peers: &HashMap<PeerId, PeerData>,
|
||||
collation_peers: &HashMap<PeerId, PeerData>,
|
||||
) -> SubsystemResult<()> {
|
||||
let new_view = construct_view(live_heads);
|
||||
if *local_view == new_view { return Ok(()) }
|
||||
let new_view = construct_view(live_heads, finalized_number);
|
||||
if *local_view == new_view { return Ok(()) }
|
||||
|
||||
*local_view = new_view.clone();
|
||||
|
||||
@@ -413,7 +418,7 @@ async fn handle_peer_messages<M>(
|
||||
for message in messages {
|
||||
outgoing_messages.push(match message {
|
||||
WireMessage::ViewUpdate(new_view) => {
|
||||
if new_view.0.len() > MAX_VIEW_HEADS {
|
||||
if new_view.heads.len() > MAX_VIEW_HEADS {
|
||||
net.report_peer(
|
||||
peer.clone(),
|
||||
MALFORMED_VIEW_COST,
|
||||
@@ -580,7 +585,8 @@ where
|
||||
|
||||
// Most recent heads are at the back.
|
||||
let mut live_heads: Vec<Hash> = Vec::with_capacity(MAX_VIEW_HEADS);
|
||||
let mut local_view = View(Vec::new());
|
||||
let mut local_view = View::default();
|
||||
let mut finalized_number = 0;
|
||||
|
||||
let mut validation_peers: HashMap<PeerId, PeerData> = HashMap::new();
|
||||
let mut collation_peers: HashMap<PeerId, PeerData> = HashMap::new();
|
||||
@@ -638,16 +644,27 @@ where
|
||||
live_heads.extend(activated);
|
||||
live_heads.retain(|h| !deactivated.contains(h));
|
||||
|
||||
update_view(
|
||||
update_our_view(
|
||||
&mut network_service,
|
||||
&mut ctx,
|
||||
&live_heads,
|
||||
&mut local_view,
|
||||
finalized_number,
|
||||
&validation_peers,
|
||||
&collation_peers,
|
||||
).await?;
|
||||
}
|
||||
|
||||
Action::BlockFinalized(number) => {
|
||||
debug_assert!(finalized_number < number);
|
||||
|
||||
// we don't send the view updates here, but delay them until the next `Action::ActiveLeaves`
|
||||
// otherwise it might break assumptions of some of the subsystems
|
||||
// that we never send the same `ActiveLeavesUpdate`
|
||||
// this is fine, we will get `Action::ActiveLeaves` on block finalization anyway
|
||||
finalized_number = number;
|
||||
},
|
||||
|
||||
Action::PeerConnected(peer_set, peer, role) => {
|
||||
let peer_map = match peer_set {
|
||||
PeerSet::Validation => &mut validation_peers,
|
||||
@@ -660,7 +677,7 @@ where
|
||||
hash_map::Entry::Occupied(_) => continue,
|
||||
hash_map::Entry::Vacant(vacant) => {
|
||||
let _ = vacant.insert(PeerData {
|
||||
view: View(Vec::new()),
|
||||
view: View::default(),
|
||||
});
|
||||
|
||||
match peer_set {
|
||||
@@ -669,7 +686,7 @@ where
|
||||
NetworkBridgeEvent::PeerConnected(peer.clone(), role),
|
||||
NetworkBridgeEvent::PeerViewChange(
|
||||
peer,
|
||||
View(Default::default()),
|
||||
View::default(),
|
||||
),
|
||||
],
|
||||
&mut ctx,
|
||||
@@ -679,7 +696,7 @@ where
|
||||
NetworkBridgeEvent::PeerConnected(peer.clone(), role),
|
||||
NetworkBridgeEvent::PeerViewChange(
|
||||
peer,
|
||||
View(Default::default()),
|
||||
View::default(),
|
||||
),
|
||||
],
|
||||
&mut ctx,
|
||||
@@ -753,6 +770,7 @@ mod tests {
|
||||
use polkadot_node_subsystem_test_helpers::{
|
||||
SingleItemSink, SingleItemStream, TestSubsystemContextHandle,
|
||||
};
|
||||
use polkadot_node_network_protocol::view;
|
||||
use sc_network::Multiaddr;
|
||||
use sp_keyring::Sr25519Keyring;
|
||||
|
||||
@@ -978,7 +996,7 @@ mod tests {
|
||||
ObservedRole::Full,
|
||||
).await;
|
||||
|
||||
let hash_a = Hash::from([1; 32]);
|
||||
let hash_a = Hash::repeat_byte(1);
|
||||
|
||||
virtual_overseer.send(
|
||||
FromOverseer::Signal(OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(hash_a)))
|
||||
@@ -986,7 +1004,7 @@ mod tests {
|
||||
|
||||
let actions = network_handle.next_network_actions(2).await;
|
||||
let wire_message = WireMessage::<protocol_v1::ValidationProtocol>::ViewUpdate(
|
||||
View(vec![hash_a])
|
||||
view![hash_a]
|
||||
).encode();
|
||||
|
||||
assert!(network_actions_contains(
|
||||
@@ -1021,7 +1039,7 @@ mod tests {
|
||||
|
||||
network_handle.connect_peer(peer.clone(), PeerSet::Validation, ObservedRole::Full).await;
|
||||
|
||||
let view = View(vec![Hash::from([1u8; 32])]);
|
||||
let view = view![Hash::repeat_byte(1)];
|
||||
|
||||
// bridge will inform about all connected peers.
|
||||
{
|
||||
@@ -1031,7 +1049,7 @@ mod tests {
|
||||
).await;
|
||||
|
||||
assert_sends_validation_event_to_all(
|
||||
NetworkBridgeEvent::PeerViewChange(peer.clone(), View(Default::default())),
|
||||
NetworkBridgeEvent::PeerViewChange(peer.clone(), View::default()),
|
||||
&mut virtual_overseer,
|
||||
).await;
|
||||
}
|
||||
@@ -1075,7 +1093,7 @@ mod tests {
|
||||
).await;
|
||||
|
||||
assert_sends_validation_event_to_all(
|
||||
NetworkBridgeEvent::PeerViewChange(peer.clone(), View(Default::default())),
|
||||
NetworkBridgeEvent::PeerViewChange(peer.clone(), View::default()),
|
||||
&mut virtual_overseer,
|
||||
).await;
|
||||
}
|
||||
@@ -1140,7 +1158,7 @@ mod tests {
|
||||
).await;
|
||||
|
||||
assert_sends_validation_event_to_all(
|
||||
NetworkBridgeEvent::PeerViewChange(peer.clone(), View(Default::default())),
|
||||
NetworkBridgeEvent::PeerViewChange(peer.clone(), View::default()),
|
||||
&mut virtual_overseer,
|
||||
).await;
|
||||
}
|
||||
@@ -1152,7 +1170,7 @@ mod tests {
|
||||
).await;
|
||||
|
||||
assert_sends_collation_event_to_all(
|
||||
NetworkBridgeEvent::PeerViewChange(peer.clone(), View(Default::default())),
|
||||
NetworkBridgeEvent::PeerViewChange(peer.clone(), View::default()),
|
||||
&mut virtual_overseer,
|
||||
).await;
|
||||
}
|
||||
@@ -1166,7 +1184,7 @@ mod tests {
|
||||
|
||||
// to show that we're still connected on the collation protocol, send a view update.
|
||||
|
||||
let hash_a = Hash::from([1; 32]);
|
||||
let hash_a = Hash::repeat_byte(1);
|
||||
|
||||
virtual_overseer.send(
|
||||
FromOverseer::Signal(OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(hash_a)))
|
||||
@@ -1174,7 +1192,7 @@ mod tests {
|
||||
|
||||
let actions = network_handle.next_network_actions(1).await;
|
||||
let wire_message = WireMessage::<protocol_v1::ValidationProtocol>::ViewUpdate(
|
||||
View(vec![hash_a])
|
||||
view![hash_a]
|
||||
).encode();
|
||||
|
||||
assert!(network_actions_contains(
|
||||
@@ -1210,7 +1228,7 @@ mod tests {
|
||||
).await;
|
||||
|
||||
assert_sends_validation_event_to_all(
|
||||
NetworkBridgeEvent::PeerViewChange(peer_a.clone(), View(Default::default())),
|
||||
NetworkBridgeEvent::PeerViewChange(peer_a.clone(), View::default()),
|
||||
&mut virtual_overseer,
|
||||
).await;
|
||||
}
|
||||
@@ -1222,7 +1240,7 @@ mod tests {
|
||||
).await;
|
||||
|
||||
assert_sends_collation_event_to_all(
|
||||
NetworkBridgeEvent::PeerViewChange(peer_b.clone(), View(Default::default())),
|
||||
NetworkBridgeEvent::PeerViewChange(peer_b.clone(), View::default()),
|
||||
&mut virtual_overseer,
|
||||
).await;
|
||||
}
|
||||
@@ -1295,7 +1313,7 @@ mod tests {
|
||||
).await;
|
||||
|
||||
assert_sends_validation_event_to_all(
|
||||
NetworkBridgeEvent::PeerViewChange(peer.clone(), View(Default::default())),
|
||||
NetworkBridgeEvent::PeerViewChange(peer.clone(), View::default()),
|
||||
&mut virtual_overseer,
|
||||
).await;
|
||||
}
|
||||
@@ -1307,13 +1325,13 @@ mod tests {
|
||||
).await;
|
||||
|
||||
assert_sends_collation_event_to_all(
|
||||
NetworkBridgeEvent::PeerViewChange(peer.clone(), View(Default::default())),
|
||||
NetworkBridgeEvent::PeerViewChange(peer.clone(), View::default()),
|
||||
&mut virtual_overseer,
|
||||
).await;
|
||||
}
|
||||
|
||||
let view_a = View(vec![[1; 32].into()]);
|
||||
let view_b = View(vec![[2; 32].into()]);
|
||||
let view_a = view![Hash::repeat_byte(1)];
|
||||
let view_b = view![Hash::repeat_byte(2)];
|
||||
|
||||
network_handle.peer_message(
|
||||
peer.clone(),
|
||||
@@ -1339,6 +1357,74 @@ mod tests {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sent_views_include_finalized_number_update() {
|
||||
test_harness(|test_harness| async move {
|
||||
let TestHarness { mut network_handle, mut virtual_overseer } = test_harness;
|
||||
|
||||
let peer_a = PeerId::random();
|
||||
|
||||
network_handle.connect_peer(
|
||||
peer_a.clone(),
|
||||
PeerSet::Validation,
|
||||
ObservedRole::Full,
|
||||
).await;
|
||||
|
||||
let hash_a = Hash::repeat_byte(1);
|
||||
let hash_b = Hash::repeat_byte(2);
|
||||
let hash_c = Hash::repeat_byte(3);
|
||||
|
||||
virtual_overseer.send(
|
||||
FromOverseer::Signal(OverseerSignal::BlockFinalized(hash_a, 1))
|
||||
).await;
|
||||
virtual_overseer.send(
|
||||
FromOverseer::Signal(OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(hash_b)))
|
||||
).await;
|
||||
|
||||
let actions = network_handle.next_network_actions(1).await;
|
||||
let wire_message = WireMessage::<protocol_v1::ValidationProtocol>::ViewUpdate(
|
||||
View {
|
||||
heads: vec![hash_b],
|
||||
finalized_number: 1,
|
||||
}
|
||||
).encode();
|
||||
|
||||
assert!(network_actions_contains(
|
||||
&actions,
|
||||
&NetworkAction::WriteNotification(
|
||||
peer_a.clone(),
|
||||
PeerSet::Validation,
|
||||
wire_message.clone(),
|
||||
),
|
||||
));
|
||||
|
||||
// view updates are issued even when `ActiveLeavesUpdate` is empty
|
||||
virtual_overseer.send(
|
||||
FromOverseer::Signal(OverseerSignal::BlockFinalized(hash_c, 3))
|
||||
).await;
|
||||
virtual_overseer.send(
|
||||
FromOverseer::Signal(OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::default()))
|
||||
).await;
|
||||
|
||||
let actions = network_handle.next_network_actions(1).await;
|
||||
let wire_message = WireMessage::<protocol_v1::ValidationProtocol>::ViewUpdate(
|
||||
View {
|
||||
heads: vec![hash_b],
|
||||
finalized_number: 3,
|
||||
}
|
||||
).encode();
|
||||
|
||||
assert!(network_actions_contains(
|
||||
&actions,
|
||||
&NetworkAction::WriteNotification(
|
||||
peer_a,
|
||||
PeerSet::Validation,
|
||||
wire_message.clone(),
|
||||
),
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn send_messages_to_peers() {
|
||||
test_harness(|test_harness| async move {
|
||||
@@ -1360,7 +1446,7 @@ mod tests {
|
||||
).await;
|
||||
|
||||
assert_sends_validation_event_to_all(
|
||||
NetworkBridgeEvent::PeerViewChange(peer.clone(), View(Default::default())),
|
||||
NetworkBridgeEvent::PeerViewChange(peer.clone(), View::default()),
|
||||
&mut virtual_overseer,
|
||||
).await;
|
||||
}
|
||||
@@ -1372,7 +1458,7 @@ mod tests {
|
||||
).await;
|
||||
|
||||
assert_sends_collation_event_to_all(
|
||||
NetworkBridgeEvent::PeerViewChange(peer.clone(), View(Default::default())),
|
||||
NetworkBridgeEvent::PeerViewChange(peer.clone(), View::default()),
|
||||
&mut virtual_overseer,
|
||||
).await;
|
||||
}
|
||||
|
||||
@@ -714,7 +714,7 @@ pub(crate) async fn run(
|
||||
}
|
||||
},
|
||||
Signal(ActiveLeaves(_update)) => {}
|
||||
Signal(BlockFinalized(_)) => {}
|
||||
Signal(BlockFinalized(..)) => {}
|
||||
Signal(Conclude) => return Ok(()),
|
||||
}
|
||||
}
|
||||
@@ -742,6 +742,7 @@ mod tests {
|
||||
use polkadot_subsystem::{ActiveLeavesUpdate, messages::{RuntimeApiMessage, RuntimeApiRequest}};
|
||||
use polkadot_node_subsystem_util::TimeoutExt;
|
||||
use polkadot_subsystem_testhelpers as test_helpers;
|
||||
use polkadot_node_network_protocol::view;
|
||||
|
||||
#[derive(Default)]
|
||||
struct TestCandidateBuilder {
|
||||
@@ -896,7 +897,7 @@ mod tests {
|
||||
overseer_send(
|
||||
virtual_overseer,
|
||||
CollatorProtocolMessage::NetworkBridgeUpdateV1(
|
||||
NetworkBridgeEvent::OurViewChange(View(hashes)),
|
||||
NetworkBridgeEvent::OurViewChange(View { heads: hashes, finalized_number: 0 }),
|
||||
),
|
||||
).await;
|
||||
}
|
||||
@@ -1004,7 +1005,7 @@ mod tests {
|
||||
overseer_send(
|
||||
virtual_overseer,
|
||||
CollatorProtocolMessage::NetworkBridgeUpdateV1(
|
||||
NetworkBridgeEvent::OurViewChange(View(vec![test_state.relay_parent])),
|
||||
NetworkBridgeEvent::OurViewChange(view![test_state.relay_parent]),
|
||||
),
|
||||
).await;
|
||||
}
|
||||
@@ -1144,7 +1145,7 @@ mod tests {
|
||||
overseer_send(
|
||||
virtual_overseer,
|
||||
CollatorProtocolMessage::NetworkBridgeUpdateV1(
|
||||
NetworkBridgeEvent::PeerViewChange(peer, View(Default::default())),
|
||||
NetworkBridgeEvent::PeerViewChange(peer, view![]),
|
||||
),
|
||||
).await;
|
||||
}
|
||||
@@ -1213,7 +1214,7 @@ mod tests {
|
||||
overseer_send(
|
||||
virtual_overseer,
|
||||
CollatorProtocolMessage::NetworkBridgeUpdateV1(
|
||||
NetworkBridgeEvent::PeerViewChange(peer.clone(), View(hashes)),
|
||||
NetworkBridgeEvent::PeerViewChange(peer.clone(), View { heads: hashes, finalized_number: 0 }),
|
||||
),
|
||||
).await;
|
||||
}
|
||||
@@ -1323,7 +1324,7 @@ mod tests {
|
||||
CollatorProtocolMessage::NetworkBridgeUpdateV1(
|
||||
NetworkBridgeEvent::PeerViewChange(
|
||||
peer.clone(),
|
||||
View(vec![test_state.relay_parent]),
|
||||
view![test_state.relay_parent],
|
||||
)
|
||||
)
|
||||
).await;
|
||||
|
||||
@@ -714,7 +714,7 @@ where
|
||||
|
||||
match msg {
|
||||
Communication { msg } => process_msg(&mut ctx, msg, &mut state).await,
|
||||
Signal(BlockFinalized(_)) => {}
|
||||
Signal(BlockFinalized(..)) => {}
|
||||
Signal(ActiveLeaves(_)) => {}
|
||||
Signal(Conclude) => { break }
|
||||
}
|
||||
@@ -760,6 +760,7 @@ mod tests {
|
||||
|
||||
use polkadot_primitives::v1::{BlockData, CollatorPair};
|
||||
use polkadot_subsystem_testhelpers as test_helpers;
|
||||
use polkadot_node_network_protocol::view;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct TestState {
|
||||
@@ -872,7 +873,7 @@ mod tests {
|
||||
overseer_send(
|
||||
&mut virtual_overseer,
|
||||
CollatorProtocolMessage::NetworkBridgeUpdateV1(
|
||||
NetworkBridgeEvent::OurViewChange(View(vec![test_state.relay_parent]))
|
||||
NetworkBridgeEvent::OurViewChange(view![test_state.relay_parent])
|
||||
)
|
||||
).await;
|
||||
|
||||
@@ -930,7 +931,7 @@ mod tests {
|
||||
overseer_send(
|
||||
&mut virtual_overseer,
|
||||
CollatorProtocolMessage::NetworkBridgeUpdateV1(
|
||||
NetworkBridgeEvent::OurViewChange(View(vec![test_state.relay_parent]))
|
||||
NetworkBridgeEvent::OurViewChange(view![test_state.relay_parent])
|
||||
)
|
||||
).await;
|
||||
|
||||
@@ -1021,7 +1022,7 @@ mod tests {
|
||||
overseer_send(
|
||||
&mut virtual_overseer,
|
||||
CollatorProtocolMessage::NetworkBridgeUpdateV1(
|
||||
NetworkBridgeEvent::OurViewChange(View(vec![Hash::repeat_byte(0x42)]))
|
||||
NetworkBridgeEvent::OurViewChange(view![Hash::repeat_byte(0x42)])
|
||||
)
|
||||
).await;
|
||||
|
||||
@@ -1049,7 +1050,7 @@ mod tests {
|
||||
overseer_send(
|
||||
&mut virtual_overseer,
|
||||
CollatorProtocolMessage::NetworkBridgeUpdateV1(
|
||||
NetworkBridgeEvent::OurViewChange(View(vec![test_state.relay_parent]))
|
||||
NetworkBridgeEvent::OurViewChange(view![test_state.relay_parent])
|
||||
)
|
||||
).await;
|
||||
|
||||
@@ -1133,7 +1134,7 @@ mod tests {
|
||||
overseer_send(
|
||||
&mut virtual_overseer,
|
||||
CollatorProtocolMessage::NetworkBridgeUpdateV1(
|
||||
NetworkBridgeEvent::OurViewChange(View(vec![test_state.relay_parent]))
|
||||
NetworkBridgeEvent::OurViewChange(view![test_state.relay_parent])
|
||||
)
|
||||
).await;
|
||||
|
||||
|
||||
@@ -197,7 +197,7 @@ async fn handle_signal(
|
||||
|
||||
Ok(false)
|
||||
}
|
||||
OverseerSignal::BlockFinalized(_) => Ok(false),
|
||||
OverseerSignal::BlockFinalized(..) => Ok(false),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -499,7 +499,7 @@ async fn handle_awaiting(
|
||||
relay_parent: Hash,
|
||||
pov_hashes: Vec<Hash>,
|
||||
) {
|
||||
if !state.our_view.0.contains(&relay_parent) {
|
||||
if !state.our_view.contains(&relay_parent) {
|
||||
report_peer(ctx, peer, COST_AWAITED_NOT_IN_VIEW).await;
|
||||
return;
|
||||
}
|
||||
@@ -635,10 +635,10 @@ async fn handle_network_update(
|
||||
NetworkBridgeEvent::PeerViewChange(peer_id, view) => {
|
||||
if let Some(peer_state) = state.peer_state.get_mut(&peer_id) {
|
||||
// prune anything not in the new view.
|
||||
peer_state.awaited.retain(|relay_parent, _| view.0.contains(&relay_parent));
|
||||
peer_state.awaited.retain(|relay_parent, _| view.contains(&relay_parent));
|
||||
|
||||
// introduce things from the new view.
|
||||
for relay_parent in view.0.iter() {
|
||||
for relay_parent in view.heads.iter() {
|
||||
if let Entry::Vacant(entry) = peer_state.awaited.entry(*relay_parent) {
|
||||
entry.insert(HashSet::new());
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ use polkadot_primitives::v1::{
|
||||
use polkadot_subsystem::messages::{RuntimeApiMessage, RuntimeApiRequest};
|
||||
use polkadot_node_subsystem_test_helpers as test_helpers;
|
||||
use polkadot_node_subsystem_util::TimeoutExt;
|
||||
use polkadot_node_network_protocol::view;
|
||||
|
||||
fn make_pov(data: Vec<u8>) -> PoV {
|
||||
PoV { block_data: BlockData(data) }
|
||||
@@ -358,7 +359,7 @@ fn ask_validators_for_povs() {
|
||||
PoVDistributionMessage::NetworkBridgeUpdateV1(
|
||||
NetworkBridgeEvent::PeerViewChange(
|
||||
test_state.validator_peer_id[i].clone(),
|
||||
View(vec![current]),
|
||||
view![current],
|
||||
)
|
||||
)
|
||||
).await;
|
||||
@@ -405,7 +406,7 @@ fn ask_validators_for_povs() {
|
||||
PoVDistributionMessage::NetworkBridgeUpdateV1(
|
||||
NetworkBridgeEvent::PeerViewChange(
|
||||
test_state.validator_peer_id[2].clone(),
|
||||
View(vec![next_leaf]),
|
||||
view![next_leaf],
|
||||
)
|
||||
)
|
||||
).await;
|
||||
@@ -582,7 +583,7 @@ fn distributes_to_those_awaiting_and_completes_local() {
|
||||
|
||||
s
|
||||
},
|
||||
our_view: View(vec![hash_a, hash_b]),
|
||||
our_view: view![hash_a, hash_b],
|
||||
metrics: Default::default(),
|
||||
connection_requests: Default::default(),
|
||||
};
|
||||
@@ -665,7 +666,7 @@ fn we_inform_peers_with_same_view_we_are_awaiting() {
|
||||
|
||||
s
|
||||
},
|
||||
our_view: View(vec![hash_a]),
|
||||
our_view: view![hash_a],
|
||||
metrics: Default::default(),
|
||||
connection_requests: Default::default(),
|
||||
};
|
||||
@@ -839,7 +840,7 @@ fn peer_view_change_leads_to_us_informing() {
|
||||
|
||||
s
|
||||
},
|
||||
our_view: View(vec![hash_a]),
|
||||
our_view: view![hash_a],
|
||||
metrics: Default::default(),
|
||||
connection_requests: Default::default(),
|
||||
};
|
||||
@@ -851,7 +852,7 @@ fn peer_view_change_leads_to_us_informing() {
|
||||
handle_network_update(
|
||||
&mut state,
|
||||
&mut ctx,
|
||||
NetworkBridgeEvent::PeerViewChange(peer_a.clone(), View(vec![hash_a, hash_b])),
|
||||
NetworkBridgeEvent::PeerViewChange(peer_a.clone(), view![hash_a, hash_b]),
|
||||
).await;
|
||||
|
||||
assert_matches!(
|
||||
@@ -912,7 +913,7 @@ fn peer_complete_fetch_and_is_rewarded() {
|
||||
|
||||
s
|
||||
},
|
||||
our_view: View(vec![hash_a]),
|
||||
our_view: view![hash_a],
|
||||
metrics: Default::default(),
|
||||
connection_requests: Default::default(),
|
||||
};
|
||||
@@ -1002,7 +1003,7 @@ fn peer_punished_for_sending_bad_pov() {
|
||||
|
||||
s
|
||||
},
|
||||
our_view: View(vec![hash_a]),
|
||||
our_view: view![hash_a],
|
||||
metrics: Default::default(),
|
||||
connection_requests: Default::default(),
|
||||
};
|
||||
@@ -1067,7 +1068,7 @@ fn peer_punished_for_sending_unexpected_pov() {
|
||||
|
||||
s
|
||||
},
|
||||
our_view: View(vec![hash_a]),
|
||||
our_view: view![hash_a],
|
||||
metrics: Default::default(),
|
||||
connection_requests: Default::default(),
|
||||
};
|
||||
@@ -1130,7 +1131,7 @@ fn peer_punished_for_sending_pov_out_of_our_view() {
|
||||
|
||||
s
|
||||
},
|
||||
our_view: View(vec![hash_a]),
|
||||
our_view: view![hash_a],
|
||||
metrics: Default::default(),
|
||||
connection_requests: Default::default(),
|
||||
};
|
||||
@@ -1190,7 +1191,7 @@ fn peer_reported_for_awaiting_too_much() {
|
||||
|
||||
s
|
||||
},
|
||||
our_view: View(vec![hash_a]),
|
||||
our_view: view![hash_a],
|
||||
metrics: Default::default(),
|
||||
connection_requests: Default::default(),
|
||||
};
|
||||
@@ -1277,7 +1278,7 @@ fn peer_reported_for_awaiting_outside_their_view() {
|
||||
|
||||
s
|
||||
},
|
||||
our_view: View(vec![hash_a, hash_b]),
|
||||
our_view: view![hash_a, hash_b],
|
||||
metrics: Default::default(),
|
||||
connection_requests: Default::default(),
|
||||
};
|
||||
@@ -1341,7 +1342,7 @@ fn peer_reported_for_awaiting_outside_our_view() {
|
||||
|
||||
s
|
||||
},
|
||||
our_view: View(vec![hash_a]),
|
||||
our_view: view![hash_a],
|
||||
metrics: Default::default(),
|
||||
connection_requests: Default::default(),
|
||||
};
|
||||
@@ -1420,7 +1421,7 @@ fn peer_complete_fetch_leads_to_us_completing_others() {
|
||||
|
||||
s
|
||||
},
|
||||
our_view: View(vec![hash_a]),
|
||||
our_view: view![hash_a],
|
||||
metrics: Default::default(),
|
||||
connection_requests: Default::default(),
|
||||
};
|
||||
@@ -1504,7 +1505,7 @@ fn peer_completing_request_no_longer_awaiting() {
|
||||
|
||||
s
|
||||
},
|
||||
our_view: View(vec![hash_a]),
|
||||
our_view: view![hash_a],
|
||||
metrics: Default::default(),
|
||||
connection_requests: Default::default(),
|
||||
};
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#![deny(unused_crate_dependencies, unused_results)]
|
||||
#![warn(missing_docs)]
|
||||
|
||||
use polkadot_primitives::v1::Hash;
|
||||
use polkadot_primitives::v1::{Hash, BlockNumber};
|
||||
use parity_scale_codec::{Encode, Decode};
|
||||
use std::convert::TryFrom;
|
||||
use std::fmt;
|
||||
@@ -159,11 +159,32 @@ impl<M> NetworkBridgeEvent<M> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A succinct representation of a peer's view. This consists of a bounded amount of chain heads.
|
||||
/// A succinct representation of a peer's view. This consists of a bounded amount of chain heads
|
||||
/// and the highest known finalized block number.
|
||||
///
|
||||
/// Up to `N` (5?) chain heads.
|
||||
#[derive(Default, Debug, Clone, PartialEq, Eq, Encode, Decode)]
|
||||
pub struct View(pub Vec<Hash>);
|
||||
pub struct View {
|
||||
/// A bounded amount of chain heads.
|
||||
pub heads: Vec<Hash>,
|
||||
/// The highest known finalized block number.
|
||||
pub finalized_number: BlockNumber,
|
||||
}
|
||||
|
||||
|
||||
/// Construct a new view with the given chain heads and finalized number 0.
|
||||
/// NOTE: Use for tests only.
|
||||
/// # Example
|
||||
///
|
||||
/// ```ignore
|
||||
/// view![Hash::repeat_byte(1), Hash::repeat_byte(2)]
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! view {
|
||||
( $( $hash:expr ),* $(,)? ) => {
|
||||
View { heads: vec![ $( $hash.clone() ),* ], finalized_number: 0 }
|
||||
};
|
||||
}
|
||||
|
||||
impl View {
|
||||
/// Replace `self` with `new`.
|
||||
@@ -172,22 +193,22 @@ impl View {
|
||||
pub fn replace_difference(&mut self, new: View) -> impl Iterator<Item = &Hash> {
|
||||
let old = std::mem::replace(self, new);
|
||||
|
||||
self.0.iter().filter(move |h| !old.contains(h))
|
||||
self.heads.iter().filter(move |h| !old.contains(h))
|
||||
}
|
||||
|
||||
/// Returns an iterator of the hashes present in `Self` but not in `other`.
|
||||
pub fn difference<'a>(&'a self, other: &'a View) -> impl Iterator<Item = &'a Hash> + 'a {
|
||||
self.0.iter().filter(move |h| !other.contains(h))
|
||||
self.heads.iter().filter(move |h| !other.contains(h))
|
||||
}
|
||||
|
||||
/// An iterator containing hashes present in both `Self` and in `other`.
|
||||
pub fn intersection<'a>(&'a self, other: &'a View) -> impl Iterator<Item = &'a Hash> + 'a {
|
||||
self.0.iter().filter(move |h| other.contains(h))
|
||||
self.heads.iter().filter(move |h| other.contains(h))
|
||||
}
|
||||
|
||||
/// Whether the view contains a given hash.
|
||||
pub fn contains(&self, hash: &Hash) -> bool {
|
||||
self.0.contains(hash)
|
||||
self.heads.contains(hash)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -938,7 +938,7 @@ impl StatementDistribution {
|
||||
.or_insert(ActiveHeadData::new(validators, session_index));
|
||||
}
|
||||
}
|
||||
FromOverseer::Signal(OverseerSignal::BlockFinalized(_block_hash)) => {
|
||||
FromOverseer::Signal(OverseerSignal::BlockFinalized(..)) => {
|
||||
// do nothing
|
||||
}
|
||||
FromOverseer::Signal(OverseerSignal::Conclude) => break,
|
||||
@@ -1072,6 +1072,7 @@ mod tests {
|
||||
use futures::executor::{self, block_on};
|
||||
use sp_keystore::{CryptoStore, SyncCryptoStorePtr, SyncCryptoStore};
|
||||
use sc_keystore::LocalKeystore;
|
||||
use polkadot_node_network_protocol::view;
|
||||
|
||||
#[test]
|
||||
fn active_head_accepts_only_2_seconded_per_validator() {
|
||||
@@ -1326,9 +1327,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn peer_view_update_sends_messages() {
|
||||
let hash_a = [1; 32].into();
|
||||
let hash_b = [2; 32].into();
|
||||
let hash_c = [3; 32].into();
|
||||
let hash_a = Hash::repeat_byte(1);
|
||||
let hash_b = Hash::repeat_byte(2);
|
||||
let hash_c = Hash::repeat_byte(3);
|
||||
|
||||
let candidate = {
|
||||
let mut c = CommittedCandidateReceipt::default();
|
||||
@@ -1338,8 +1339,8 @@ mod tests {
|
||||
};
|
||||
let candidate_hash = candidate.hash();
|
||||
|
||||
let old_view = View(vec![hash_a, hash_b]);
|
||||
let new_view = View(vec![hash_b, hash_c]);
|
||||
let old_view = view![hash_a, hash_b];
|
||||
let new_view = view![hash_b, hash_c];
|
||||
|
||||
let mut active_heads = HashMap::new();
|
||||
let validators = vec![
|
||||
@@ -1474,9 +1475,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn circulated_statement_goes_to_all_peers_with_view() {
|
||||
let hash_a = [1; 32].into();
|
||||
let hash_b = [2; 32].into();
|
||||
let hash_c = [3; 32].into();
|
||||
let hash_a = Hash::repeat_byte(1);
|
||||
let hash_b = Hash::repeat_byte(2);
|
||||
let hash_c = Hash::repeat_byte(3);
|
||||
|
||||
let candidate = {
|
||||
let mut c = CommittedCandidateReceipt::default();
|
||||
@@ -1489,15 +1490,15 @@ mod tests {
|
||||
let peer_b = PeerId::random();
|
||||
let peer_c = PeerId::random();
|
||||
|
||||
let peer_a_view = View(vec![hash_a]);
|
||||
let peer_b_view = View(vec![hash_a, hash_b]);
|
||||
let peer_c_view = View(vec![hash_b, hash_c]);
|
||||
let peer_a_view = view![hash_a];
|
||||
let peer_b_view = view![hash_a, hash_b];
|
||||
let peer_c_view = view![hash_b, hash_c];
|
||||
|
||||
let session_index = 1;
|
||||
|
||||
let peer_data_from_view = |view: View| PeerData {
|
||||
view: view.clone(),
|
||||
view_knowledge: view.0.iter().map(|v| (v.clone(), Default::default())).collect(),
|
||||
view_knowledge: view.heads.iter().map(|v| (v.clone(), Default::default())).collect(),
|
||||
};
|
||||
|
||||
let mut peer_data: HashMap<_, _> = vec![
|
||||
|
||||
@@ -1415,13 +1415,10 @@ where
|
||||
self.on_head_deactivated(deactivated)
|
||||
}
|
||||
|
||||
// Most of the time we have a leave already closed when it is finalized, so we check here if there are actually
|
||||
// any updates before sending it to the subsystems.
|
||||
if !update.is_empty() {
|
||||
self.broadcast_signal(OverseerSignal::ActiveLeaves(update)).await?;
|
||||
}
|
||||
|
||||
self.broadcast_signal(OverseerSignal::BlockFinalized(block.hash)).await?;
|
||||
self.broadcast_signal(OverseerSignal::BlockFinalized(block.hash, block.number)).await?;
|
||||
// broadcast `ActiveLeavesUpdate` even if empty to issue view updates
|
||||
self.broadcast_signal(OverseerSignal::ActiveLeaves(update)).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -2061,7 +2058,7 @@ mod tests {
|
||||
deactivated: [first_block_hash, second_block_hash].as_ref().into(),
|
||||
..Default::default()
|
||||
}),
|
||||
OverseerSignal::BlockFinalized(third_block_hash),
|
||||
OverseerSignal::BlockFinalized(third_block_hash, 3),
|
||||
];
|
||||
|
||||
loop {
|
||||
|
||||
@@ -808,7 +808,7 @@ where
|
||||
jobs.send_msg(to_job.relay_parent(), to_job).await;
|
||||
}
|
||||
}
|
||||
Ok(Signal(BlockFinalized(_))) => {}
|
||||
Ok(Signal(BlockFinalized(..))) => {}
|
||||
Err(err) => {
|
||||
tracing::error!(
|
||||
job = Job::NAME,
|
||||
|
||||
@@ -28,7 +28,7 @@ use futures::prelude::*;
|
||||
use futures::channel::{mpsc, oneshot};
|
||||
use futures::future::BoxFuture;
|
||||
|
||||
use polkadot_primitives::v1::Hash;
|
||||
use polkadot_primitives::v1::{Hash, BlockNumber};
|
||||
use async_trait::async_trait;
|
||||
use smallvec::SmallVec;
|
||||
|
||||
@@ -89,8 +89,8 @@ impl PartialEq for ActiveLeavesUpdate {
|
||||
pub enum OverseerSignal {
|
||||
/// Subsystems should adjust their jobs to start and stop work on appropriate block hashes.
|
||||
ActiveLeaves(ActiveLeavesUpdate),
|
||||
/// `Subsystem` is informed of a finalized block by its block hash.
|
||||
BlockFinalized(Hash),
|
||||
/// `Subsystem` is informed of a finalized block by its block hash and number.
|
||||
BlockFinalized(Hash, BlockNumber),
|
||||
/// Conclude the work of the `Overseer` and all `Subsystem`s.
|
||||
Conclude,
|
||||
}
|
||||
|
||||
@@ -991,9 +991,9 @@ mod tests {
|
||||
assert_eq!(h.as_ref().len(), 32);
|
||||
|
||||
let _payload = collator_signature_payload(
|
||||
&Hash::from([1; 32]),
|
||||
&Hash::repeat_byte(1),
|
||||
&5u32.into(),
|
||||
&Hash::from([2; 32]),
|
||||
&Hash::repeat_byte(2),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -825,10 +825,10 @@ mod tests {
|
||||
assert_eq!(h.as_ref().len(), 32);
|
||||
|
||||
let _payload = collator_signature_payload(
|
||||
&Hash::from([1; 32]),
|
||||
&Hash::repeat_byte(1),
|
||||
&5u32.into(),
|
||||
&Hash::from([2; 32]),
|
||||
&Hash::from([3; 32]),
|
||||
&Hash::repeat_byte(2),
|
||||
&Hash::repeat_byte(3),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,9 +63,7 @@ If we are connected to the same peer on both peer-sets, we will send the peer tw
|
||||
|
||||
### Overseer Signal: BlockFinalized
|
||||
|
||||
We obtain the number of the block hash in the event by issuing a `ChainApiMessage::BlockNumber` request and then issue a `ProtocolMessage::ViewUpdate` to each connected peer on each peer-set. We also issue a `NetworkBridgeEvent::OurViewChange` to each event handler for each protocol.
|
||||
|
||||
If we are connected to the same peer on both peer-sets, we will send the peer two view updates as a result.
|
||||
We update our view's `finalized_number` to the provided one and delay `ProtocolMessage::ViewUpdate` and `NetworkBridgeEvent::OurViewChange` till the next `ActiveLeavesUpdate`.
|
||||
|
||||
### Network Event: Peer Connected
|
||||
|
||||
@@ -98,8 +96,6 @@ Map the message onto the corresponding [Event Handler](#event-handlers) based on
|
||||
|
||||
### ConnectToValidators
|
||||
|
||||
> TODO: Currently, this request is limited to the validators in the current session.
|
||||
|
||||
- Determine the DHT keys to use for each validator based on the relay-chain state and Runtime API.
|
||||
- Recover the Peer IDs of the validators from the DHT. There may be more than one peer ID per validator.
|
||||
- Send all `(ValidatorId, PeerId)` pairs on the response channel.
|
||||
|
||||
@@ -1575,7 +1575,7 @@ mod tests {
|
||||
let mut candidate = TestCandidateBuilder {
|
||||
para_id: chain_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
pov_hash: Hash::repeat_byte(1),
|
||||
persisted_validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
hrmp_watermark: RELAY_PARENT_NUM,
|
||||
..Default::default()
|
||||
@@ -1609,7 +1609,7 @@ mod tests {
|
||||
let mut candidate_a = TestCandidateBuilder {
|
||||
para_id: chain_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
pov_hash: Hash::repeat_byte(1),
|
||||
persisted_validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
hrmp_watermark: RELAY_PARENT_NUM,
|
||||
..Default::default()
|
||||
@@ -1617,7 +1617,7 @@ mod tests {
|
||||
let mut candidate_b = TestCandidateBuilder {
|
||||
para_id: chain_b,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([2; 32]),
|
||||
pov_hash: Hash::repeat_byte(2),
|
||||
persisted_validation_data_hash: make_vdata_hash(chain_b).unwrap(),
|
||||
hrmp_watermark: RELAY_PARENT_NUM,
|
||||
..Default::default()
|
||||
@@ -1667,7 +1667,7 @@ mod tests {
|
||||
let mut candidate = TestCandidateBuilder {
|
||||
para_id: chain_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
pov_hash: Hash::repeat_byte(1),
|
||||
persisted_validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
hrmp_watermark: RELAY_PARENT_NUM,
|
||||
..Default::default()
|
||||
@@ -1698,13 +1698,13 @@ mod tests {
|
||||
|
||||
// candidate not in parent context.
|
||||
{
|
||||
let wrong_parent_hash = Hash::from([222; 32]);
|
||||
let wrong_parent_hash = Hash::repeat_byte(222);
|
||||
assert!(System::parent_hash() != wrong_parent_hash);
|
||||
|
||||
let mut candidate = TestCandidateBuilder {
|
||||
para_id: chain_a,
|
||||
relay_parent: wrong_parent_hash,
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
pov_hash: Hash::repeat_byte(1),
|
||||
persisted_validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
..Default::default()
|
||||
}.build();
|
||||
@@ -1737,7 +1737,7 @@ mod tests {
|
||||
let mut candidate = TestCandidateBuilder {
|
||||
para_id: thread_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
pov_hash: Hash::repeat_byte(1),
|
||||
persisted_validation_data_hash: make_vdata_hash(thread_a).unwrap(),
|
||||
hrmp_watermark: RELAY_PARENT_NUM,
|
||||
..Default::default()
|
||||
@@ -1777,7 +1777,7 @@ mod tests {
|
||||
let mut candidate = TestCandidateBuilder {
|
||||
para_id: thread_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
pov_hash: Hash::repeat_byte(1),
|
||||
persisted_validation_data_hash: make_vdata_hash(thread_a).unwrap(),
|
||||
hrmp_watermark: RELAY_PARENT_NUM,
|
||||
..Default::default()
|
||||
@@ -1790,7 +1790,7 @@ mod tests {
|
||||
);
|
||||
|
||||
// change the candidate after signing.
|
||||
candidate.descriptor.pov_hash = Hash::from([2; 32]);
|
||||
candidate.descriptor.pov_hash = Hash::repeat_byte(2);
|
||||
|
||||
let backed = block_on(back_candidate(
|
||||
candidate,
|
||||
@@ -1816,7 +1816,7 @@ mod tests {
|
||||
let mut candidate = TestCandidateBuilder {
|
||||
para_id: chain_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
pov_hash: Hash::repeat_byte(1),
|
||||
persisted_validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
hrmp_watermark: RELAY_PARENT_NUM,
|
||||
..Default::default()
|
||||
@@ -1865,7 +1865,7 @@ mod tests {
|
||||
let mut candidate = TestCandidateBuilder {
|
||||
para_id: chain_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
pov_hash: Hash::repeat_byte(1),
|
||||
persisted_validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
hrmp_watermark: RELAY_PARENT_NUM,
|
||||
..Default::default()
|
||||
@@ -1905,7 +1905,7 @@ mod tests {
|
||||
let mut candidate = TestCandidateBuilder {
|
||||
para_id: chain_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
pov_hash: Hash::repeat_byte(1),
|
||||
new_validation_code: Some(vec![5, 6, 7, 8].into()),
|
||||
persisted_validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
hrmp_watermark: RELAY_PARENT_NUM,
|
||||
@@ -1949,7 +1949,7 @@ mod tests {
|
||||
let mut candidate = TestCandidateBuilder {
|
||||
para_id: chain_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
pov_hash: Hash::repeat_byte(1),
|
||||
persisted_validation_data_hash: [42u8; 32].into(),
|
||||
hrmp_watermark: RELAY_PARENT_NUM,
|
||||
..Default::default()
|
||||
@@ -2048,7 +2048,7 @@ mod tests {
|
||||
let mut candidate_a = TestCandidateBuilder {
|
||||
para_id: chain_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
pov_hash: Hash::repeat_byte(1),
|
||||
persisted_validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
hrmp_watermark: RELAY_PARENT_NUM,
|
||||
..Default::default()
|
||||
@@ -2061,7 +2061,7 @@ mod tests {
|
||||
let mut candidate_b = TestCandidateBuilder {
|
||||
para_id: chain_b,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([2; 32]),
|
||||
pov_hash: Hash::repeat_byte(2),
|
||||
persisted_validation_data_hash: make_vdata_hash(chain_b).unwrap(),
|
||||
hrmp_watermark: RELAY_PARENT_NUM,
|
||||
..Default::default()
|
||||
@@ -2074,7 +2074,7 @@ mod tests {
|
||||
let mut candidate_c = TestCandidateBuilder {
|
||||
para_id: thread_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([3; 32]),
|
||||
pov_hash: Hash::repeat_byte(3),
|
||||
persisted_validation_data_hash: make_vdata_hash(thread_a).unwrap(),
|
||||
hrmp_watermark: RELAY_PARENT_NUM,
|
||||
..Default::default()
|
||||
@@ -2220,7 +2220,7 @@ mod tests {
|
||||
let mut candidate_a = TestCandidateBuilder {
|
||||
para_id: chain_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
pov_hash: Hash::repeat_byte(1),
|
||||
persisted_validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
new_validation_code: Some(vec![1, 2, 3].into()),
|
||||
hrmp_watermark: RELAY_PARENT_NUM,
|
||||
|
||||
Reference in New Issue
Block a user