1717//! Implementation of the v2 statement distribution protocol,
1818//! designed for asynchronous backing.
1919
20+ use bitvec:: prelude:: { BitVec , Lsb0 } ;
2021use polkadot_node_network_protocol:: {
2122 self as net_protocol,
2223 grid_topology:: SessionGridTopology ,
@@ -63,7 +64,7 @@ use futures::{
6364use std:: {
6465 collections:: {
6566 hash_map:: { Entry , HashMap } ,
66- HashSet ,
67+ BTreeSet , HashSet ,
6768 } ,
6869 time:: { Duration , Instant } ,
6970} ;
@@ -162,6 +163,9 @@ struct PerSessionState {
162163 // getting the topology from the gossip-support subsystem
163164 grid_view : Option < grid:: SessionTopologyView > ,
164165 local_validator : Option < ValidatorIndex > ,
166+ // We assume that the validators are never re-enabled per session
167+ // and store the latest state here.
168+ disabled_validators : BTreeSet < ValidatorIndex > ,
165169}
166170
167171impl PerSessionState {
@@ -183,6 +187,7 @@ impl PerSessionState {
183187 authority_lookup,
184188 grid_view : None ,
185189 local_validator : local_validator. map ( |( _key, index) | index) ,
190+ disabled_validators : BTreeSet :: new ( ) ,
186191 }
187192 }
188193
@@ -195,6 +200,34 @@ impl PerSessionState {
195200
196201 self . grid_view = Some ( grid_view) ;
197202 }
203+
204+ /// A convenience function to generate a disabled bitmask for the given backing group.
205+ /// The output bits are set to `true` for validators that are disabled.
206+ /// Returns `None` if the group index is out of bounds.
207+ pub fn disabled_bitmask ( & self , group : GroupIndex ) -> Option < BitVec < u8 , Lsb0 > > {
208+ let group = self . groups . get ( group) ?;
209+ let group_size = group. len ( ) ;
210+ let mut mask = BitVec :: repeat ( false , group_size) ;
211+ for ( i, v) in group. iter ( ) . enumerate ( ) {
212+ if self . is_disabled ( v) {
213+ mask. set ( i, true ) ;
214+ }
215+ }
216+ Some ( mask)
217+ }
218+
219+ /// Returns `true` if the given validator is disabled in the current session.
220+ pub fn is_disabled ( & self , validator_index : & ValidatorIndex ) -> bool {
221+ self . disabled_validators . contains ( validator_index)
222+ }
223+
224+ /// Extend the set of disabled validators for the current session.
225+ pub fn extend_disabled_validators (
226+ & mut self ,
227+ disabled : impl IntoIterator < Item = ValidatorIndex > ,
228+ ) {
229+ self . disabled_validators . extend ( disabled) ;
230+ }
198231}
199232
200233pub ( crate ) struct State {
@@ -483,9 +516,6 @@ pub(crate) async fn handle_active_leaves_update<Context>(
483516 . map_err ( JfyiError :: RuntimeApiUnavailable ) ?
484517 . map_err ( JfyiError :: FetchDisabledValidators ) ?;
485518
486- // deduplicate and order
487- let disabled_validators = disabled_validators. into_iter ( ) . collect ( ) ;
488-
489519 let group_rotation_info =
490520 polkadot_node_subsystem_util:: request_validator_groups ( new_relay_parent, ctx. sender ( ) )
491521 . await
@@ -529,9 +559,11 @@ pub(crate) async fn handle_active_leaves_update<Context>(
529559
530560 let per_session = state
531561 . per_session
532- . get ( & session_index)
562+ . get_mut ( & session_index)
533563 . expect ( "either existed or just inserted; qed" ) ;
534564
565+ per_session. extend_disabled_validators ( disabled_validators) ;
566+
535567 let local_validator = per_session. local_validator . and_then ( |v| {
536568 find_local_validator_state (
537569 v,
@@ -546,7 +578,7 @@ pub(crate) async fn handle_active_leaves_update<Context>(
546578 new_relay_parent,
547579 PerRelayParentState {
548580 local_validator,
549- statement_store : StatementStore :: new ( & per_session. groups , & disabled_validators ) ,
581+ statement_store : StatementStore :: new ( & per_session. groups ) ,
550582 availability_cores,
551583 group_rotation_info,
552584 seconding_limit,
@@ -1313,10 +1345,7 @@ async fn handle_incoming_statement<Context>(
13131345 } ,
13141346 } ;
13151347
1316- if per_relay_parent
1317- . statement_store
1318- . is_disabled ( & statement. unchecked_validator_index ( ) )
1319- {
1348+ if per_session. is_disabled ( & statement. unchecked_validator_index ( ) ) {
13201349 gum:: debug!(
13211350 target: LOG_TARGET ,
13221351 ?relay_parent,
@@ -1450,17 +1479,6 @@ async fn handle_incoming_statement<Context>(
14501479
14511480 return
14521481 } ,
1453- Err ( statement_store:: Error :: ValidatorDisabled ) => {
1454- // sanity: should never happen, checked above.
1455- gum:: warn!(
1456- target: LOG_TARGET ,
1457- ?relay_parent,
1458- validator_index = ?originator_index,
1459- "Error - accepted message from disabled validator."
1460- ) ;
1461-
1462- return
1463- } ,
14641482 Ok ( known) => known,
14651483 } ;
14661484
@@ -2024,11 +2042,7 @@ async fn handle_incoming_manifest_common<'a, Context>(
20242042 let claimed_parent_hash = manifest_summary. claimed_parent_hash ;
20252043
20262044 // Ignore votes from disabled validators when counting towards the threshold.
2027- let disabled_mask = per_session
2028- . groups
2029- . get ( group_index)
2030- . map ( |group| relay_parent_state. statement_store . disabled_bitmask ( group) )
2031- . unwrap_or_default ( ) ;
2045+ let disabled_mask = per_session. disabled_bitmask ( group_index) . unwrap_or_default ( ) ;
20322046 manifest_summary. statement_knowledge . mask_seconded ( & disabled_mask) ;
20332047 manifest_summary. statement_knowledge . mask_valid ( & disabled_mask) ;
20342048
@@ -2622,7 +2636,9 @@ pub(crate) async fn handle_response<Context>(
26222636 Some ( g) => g,
26232637 } ;
26242638
2625- let disabled_mask = relay_parent_state. statement_store . disabled_bitmask ( group) ;
2639+ let disabled_mask = per_session
2640+ . disabled_bitmask ( group_index)
2641+ . expect ( "group_index checked above; qed" ) ;
26262642
26272643 let res = response. validate_response (
26282644 & mut state. request_manager ,
@@ -2800,11 +2816,7 @@ pub(crate) fn answer_request(state: &mut State, message: ResponderMessage) {
28002816 } ;
28012817
28022818 // Ignore disabled validators when sending the response.
2803- let disabled_mask = per_session
2804- . groups
2805- . get ( confirmed. group_index ( ) )
2806- . map ( |group| relay_parent_state. statement_store . disabled_bitmask ( group) )
2807- . unwrap_or_default ( ) ;
2819+ let disabled_mask = per_session. disabled_bitmask ( confirmed. group_index ( ) ) . unwrap_or_default ( ) ;
28082820 and_mask. mask_seconded ( & disabled_mask) ;
28092821 and_mask. mask_valid ( & disabled_mask) ;
28102822
0 commit comments