@@ -118,6 +118,7 @@ use statement_table::{
118118 } ,
119119 Config as TableConfig , Context as TableContextTrait , Table ,
120120} ;
121+ use util:: vstaging:: get_disabled_validators_with_fallback;
121122
122123mod error;
123124
@@ -383,6 +384,21 @@ struct TableContext {
383384 validator : Option < Validator > ,
384385 groups : HashMap < ParaId , Vec < ValidatorIndex > > ,
385386 validators : Vec < ValidatorId > ,
387+ disabled_validators : Vec < ValidatorIndex > ,
388+ }
389+
390+ impl TableContext {
391+ // Returns `true` if the provided `ValidatorIndex` is in the disabled validators list
392+ pub fn validator_is_disabled ( & self , validator_idx : & ValidatorIndex ) -> bool {
393+ self . disabled_validators
394+ . iter ( )
395+ . any ( |disabled_val_idx| * disabled_val_idx == * validator_idx)
396+ }
397+
398+ // Returns `true` if the local validator is in the disabled validators list
399+ pub fn local_validator_is_disabled ( & self ) -> Option < bool > {
400+ self . validator . as_ref ( ) . map ( |v| v. disabled ( ) )
401+ }
386402}
387403
388404impl TableContextTrait for TableContext {
@@ -1010,21 +1026,33 @@ async fn construct_per_relay_parent_state<Context>(
10101026 let minimum_backing_votes =
10111027 try_runtime_api ! ( request_min_backing_votes( parent, session_index, ctx. sender( ) ) . await ) ;
10121028
1029+ // TODO: https://github.com/paritytech/polkadot-sdk/issues/1940
1030+ // Once runtime ver `DISABLED_VALIDATORS_RUNTIME_REQUIREMENT` is released remove this call to
1031+ // `get_disabled_validators_with_fallback`, add `request_disabled_validators` call to the
1032+ // `try_join!` above and use `try_runtime_api!` to get `disabled_validators`
1033+ let disabled_validators = get_disabled_validators_with_fallback ( ctx. sender ( ) , parent)
1034+ . await
1035+ . map_err ( Error :: UtilError ) ?;
1036+
10131037 let signing_context = SigningContext { parent_hash : parent, session_index } ;
1014- let validator =
1015- match Validator :: construct ( & validators, signing_context. clone ( ) , keystore. clone ( ) ) {
1016- Ok ( v) => Some ( v) ,
1017- Err ( util:: Error :: NotAValidator ) => None ,
1018- Err ( e) => {
1019- gum:: warn!(
1020- target: LOG_TARGET ,
1021- err = ?e,
1022- "Cannot participate in candidate backing" ,
1023- ) ;
1038+ let validator = match Validator :: construct (
1039+ & validators,
1040+ & disabled_validators,
1041+ signing_context. clone ( ) ,
1042+ keystore. clone ( ) ,
1043+ ) {
1044+ Ok ( v) => Some ( v) ,
1045+ Err ( util:: Error :: NotAValidator ) => None ,
1046+ Err ( e) => {
1047+ gum:: warn!(
1048+ target: LOG_TARGET ,
1049+ err = ?e,
1050+ "Cannot participate in candidate backing" ,
1051+ ) ;
10241052
1025- return Ok ( None )
1026- } ,
1027- } ;
1053+ return Ok ( None )
1054+ } ,
1055+ } ;
10281056
10291057 let mut groups = HashMap :: new ( ) ;
10301058 let n_cores = cores. len ( ) ;
@@ -1054,7 +1082,7 @@ async fn construct_per_relay_parent_state<Context>(
10541082 }
10551083 }
10561084
1057- let table_context = TableContext { groups, validators, validator } ;
1085+ let table_context = TableContext { validator , groups, validators, disabled_validators } ;
10581086 let table_config = TableConfig {
10591087 allow_multiple_seconded : match mode {
10601088 ProspectiveParachainsMode :: Enabled { .. } => true ,
@@ -1726,6 +1754,19 @@ async fn kick_off_validation_work<Context>(
17261754 background_validation_tx : & mpsc:: Sender < ( Hash , ValidatedCandidateCommand ) > ,
17271755 attesting : AttestingData ,
17281756) -> Result < ( ) , Error > {
1757+ // Do nothing if the local validator is disabled or not a validator at all
1758+ match rp_state. table_context . local_validator_is_disabled ( ) {
1759+ Some ( true ) => {
1760+ gum:: info!( target: LOG_TARGET , "We are disabled - don't kick off validation" ) ;
1761+ return Ok ( ( ) )
1762+ } ,
1763+ Some ( false ) => { } , // we are not disabled - move on
1764+ None => {
1765+ gum:: debug!( target: LOG_TARGET , "We are not a validator - don't kick off validation" ) ;
1766+ return Ok ( ( ) )
1767+ } ,
1768+ }
1769+
17291770 let candidate_hash = attesting. candidate . hash ( ) ;
17301771 if rp_state. issued_statements . contains ( & candidate_hash) {
17311772 return Ok ( ( ) )
@@ -1783,6 +1824,16 @@ async fn maybe_validate_and_import<Context>(
17831824 } ,
17841825 } ;
17851826
1827+ // Don't import statement if the sender is disabled
1828+ if rp_state. table_context . validator_is_disabled ( & statement. validator_index ( ) ) {
1829+ gum:: debug!(
1830+ target: LOG_TARGET ,
1831+ sender_validator_idx = ?statement. validator_index( ) ,
1832+ "Not importing statement because the sender is disabled"
1833+ ) ;
1834+ return Ok ( ( ) )
1835+ }
1836+
17861837 let res = import_statement ( ctx, rp_state, & mut state. per_candidate , & statement) . await ;
17871838
17881839 // if we get an Error::RejectedByProspectiveParachains,
@@ -1944,6 +1995,13 @@ async fn handle_second_message<Context>(
19441995 Some ( r) => r,
19451996 } ;
19461997
1998+ // Just return if the local validator is disabled. If we are here the local node should be a
1999+ // validator but defensively use `unwrap_or(false)` to continue processing in this case.
2000+ if rp_state. table_context . local_validator_is_disabled ( ) . unwrap_or ( false ) {
2001+ gum:: warn!( target: LOG_TARGET , "Local validator is disabled. Don't validate and second" ) ;
2002+ return Ok ( ( ) )
2003+ }
2004+
19472005 // Sanity check that candidate is from our assignment.
19482006 if Some ( candidate. descriptor ( ) . para_id ) != rp_state. assignment {
19492007 gum:: debug!(
@@ -1990,6 +2048,7 @@ async fn handle_statement_message<Context>(
19902048) -> Result < ( ) , Error > {
19912049 let _timer = metrics. time_process_statement ( ) ;
19922050
2051+ // Validator disabling is handled in `maybe_validate_and_import`
19932052 match maybe_validate_and_import ( ctx, state, relay_parent, statement) . await {
19942053 Err ( Error :: ValidationFailed ( _) ) => Ok ( ( ) ) ,
19952054 Err ( e) => Err ( e) ,
0 commit comments