diff --git a/node/collation-generation/src/lib.rs b/node/collation-generation/src/lib.rs index 0b2b714c6b2a..7796a967c1e1 100644 --- a/node/collation-generation/src/lib.rs +++ b/node/collation-generation/src/lib.rs @@ -145,7 +145,7 @@ impl CollationGenerationSubsystem { } false } - Ok(Signal(BlockFinalized(_))) => false, + Ok(Signal(BlockFinalized(..))) => false, Err(err) => { tracing::error!( target: LOG_TARGET, diff --git a/node/core/av-store/src/lib.rs b/node/core/av-store/src/lib.rs index 795d89d9ee78..d1d81d031c3b 100644 --- a/node/core/av-store/src/lib.rs +++ b/node/core/av-store/src/lib.rs @@ -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( +#[tracing::instrument(level = "trace", skip(subsystem, db), fields(subsystem = LOG_TARGET))] +async fn process_block_finalized( subsystem: &AvailabilityStoreSubsystem, - ctx: &mut Context, db: &Arc, - hash: Hash, -) -> Result<(), Error> -where - Context: SubsystemContext -{ + 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. diff --git a/node/core/av-store/src/tests.rs b/node/core/av-store/src/tests.rs index f35809a4a729..4e83e3d7f7f3 100644 --- a/node/core/av-store/src/tests.rs +++ b/node/core/av-store/src/tests.rs @@ -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(), diff --git a/node/core/backing/src/lib.rs b/node/core/backing/src/lib.rs index 492e57dc4dfa..c54eef157ba8 100644 --- a/node/core/backing/src/lib.rs +++ b/node/core/backing/src/lib.rs @@ -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, diff --git a/node/core/candidate-validation/src/lib.rs b/node/core/candidate-validation/src/lib.rs index 3c64f962c2af..cf47b9d62ec1 100644 --- a/node/core/candidate-validation/src/lib.rs +++ b/node/core/candidate-validation/src/lib.rs @@ -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( diff --git a/node/core/chain-api/src/lib.rs b/node/core/chain-api/src/lib.rs index aa8b8ae6e951..534c41e3ef85 100644 --- a/node/core/chain-api/src/lib.rs +++ b/node/core/chain-api/src/lib.rs @@ -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(); diff --git a/node/core/runtime-api/src/lib.rs b/node/core/runtime-api/src/lib.rs index b3b809296647..97e645a428a2 100644 --- a/node/core/runtime-api/src/lib.rs +++ b/node/core/runtime-api/src/lib.rs @@ -152,7 +152,7 @@ async fn run( 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); diff --git a/node/network/availability-distribution/src/lib.rs b/node/network/availability-distribution/src/lib.rs index 203e7ef2600e..67d1d4ffa812 100644 --- a/node/network/availability-distribution/src/lib.rs +++ b/node/network/availability-distribution/src/lib.rs @@ -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(()); } diff --git a/node/network/availability-distribution/src/tests.rs b/node/network/availability-distribution/src/tests.rs index b55c7a2241de..3e7f0d83e4da 100644 --- a/node/network/availability-distribution/src/tests.rs +++ b/node/network/availability-distribution/src/tests.rs @@ -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) => { diff --git a/node/network/bitfield-distribution/src/lib.rs b/node/network/bitfield-distribution/src/lib.rs index ccf5e26f43be..5bd08e9e874f 100644 --- a/node/network/bitfield-distribution/src/lib.rs +++ b/node/network/bitfield-distribution/src/lib.rs @@ -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(), diff --git a/node/network/bridge/src/lib.rs b/node/network/bridge/src/lib.rs index 38cbe369ba41..e294b3dc4309 100644 --- a/node/network/bridge/src/lib.rs +++ b/node/network/bridge/src/lib.rs @@ -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) -> 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, live_heads: &[Hash], local_view: &mut View, + finalized_number: BlockNumber, validation_peers: &HashMap, collation_peers: &HashMap, ) -> 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( 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 = 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 = HashMap::new(); let mut collation_peers: HashMap = 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::::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::::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::::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::::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; } diff --git a/node/network/collator-protocol/src/collator_side.rs b/node/network/collator-protocol/src/collator_side.rs index 60208ec8c6a9..ca6b1bfae03e 100644 --- a/node/network/collator-protocol/src/collator_side.rs +++ b/node/network/collator-protocol/src/collator_side.rs @@ -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; diff --git a/node/network/collator-protocol/src/validator_side.rs b/node/network/collator-protocol/src/validator_side.rs index a865dc75ee8a..562bb9ab6080 100644 --- a/node/network/collator-protocol/src/validator_side.rs +++ b/node/network/collator-protocol/src/validator_side.rs @@ -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; diff --git a/node/network/pov-distribution/src/lib.rs b/node/network/pov-distribution/src/lib.rs index 9d8df343b276..6c882c8c0060 100644 --- a/node/network/pov-distribution/src/lib.rs +++ b/node/network/pov-distribution/src/lib.rs @@ -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, ) { - 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()); diff --git a/node/network/pov-distribution/src/tests.rs b/node/network/pov-distribution/src/tests.rs index a6358bedfd8f..f0fec496546f 100644 --- a/node/network/pov-distribution/src/tests.rs +++ b/node/network/pov-distribution/src/tests.rs @@ -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) -> 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(), }; diff --git a/node/network/protocol/src/lib.rs b/node/network/protocol/src/lib.rs index 8409a795ae56..fe40e06be2e8 100644 --- a/node/network/protocol/src/lib.rs +++ b/node/network/protocol/src/lib.rs @@ -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 NetworkBridgeEvent { } } -/// 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); +pub struct View { + /// A bounded amount of chain heads. + pub heads: Vec, + /// 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 { 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 + '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 + '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) } } diff --git a/node/network/statement-distribution/src/lib.rs b/node/network/statement-distribution/src/lib.rs index ac2adf094dbe..02ed1cf7bde6 100644 --- a/node/network/statement-distribution/src/lib.rs +++ b/node/network/statement-distribution/src/lib.rs @@ -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![ diff --git a/node/overseer/src/lib.rs b/node/overseer/src/lib.rs index bbd9f626fe38..c204aa745c98 100644 --- a/node/overseer/src/lib.rs +++ b/node/overseer/src/lib.rs @@ -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 { diff --git a/node/subsystem-util/src/lib.rs b/node/subsystem-util/src/lib.rs index 9cc68834be95..0bc69cb3d125 100644 --- a/node/subsystem-util/src/lib.rs +++ b/node/subsystem-util/src/lib.rs @@ -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, diff --git a/node/subsystem/src/lib.rs b/node/subsystem/src/lib.rs index f726e2a15796..8c0fa1fecf9e 100644 --- a/node/subsystem/src/lib.rs +++ b/node/subsystem/src/lib.rs @@ -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, } diff --git a/primitives/src/v0.rs b/primitives/src/v0.rs index 5f6e3ad544a9..7ce060c528a8 100644 --- a/primitives/src/v0.rs +++ b/primitives/src/v0.rs @@ -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), ); } } diff --git a/primitives/src/v1.rs b/primitives/src/v1.rs index 640b2cd1de11..46ae17444b8d 100644 --- a/primitives/src/v1.rs +++ b/primitives/src/v1.rs @@ -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), ); } } diff --git a/roadmap/implementers-guide/src/node/utility/network-bridge.md b/roadmap/implementers-guide/src/node/utility/network-bridge.md index d89ec7e8fe42..2a47459bd785 100644 --- a/roadmap/implementers-guide/src/node/utility/network-bridge.md +++ b/roadmap/implementers-guide/src/node/utility/network-bridge.md @@ -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. diff --git a/runtime/parachains/src/inclusion.rs b/runtime/parachains/src/inclusion.rs index 47bf111f4c50..08f9ae124cc4 100644 --- a/runtime/parachains/src/inclusion.rs +++ b/runtime/parachains/src/inclusion.rs @@ -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,