@@ -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 ,
@@ -1728,6 +1756,19 @@ async fn kick_off_validation_work<Context>(
17281756 background_validation_tx : & mpsc:: Sender < ( Hash , ValidatedCandidateCommand ) > ,
17291757 attesting : AttestingData ,
17301758) -> Result < ( ) , Error > {
1759+ // Do nothing if the local validator is disabled or not a validator at all
1760+ match rp_state. table_context . local_validator_is_disabled ( ) {
1761+ Some ( true ) => {
1762+ gum:: info!( target: LOG_TARGET , "We are disabled - don't kick off validation" ) ;
1763+ return Ok ( ( ) )
1764+ } ,
1765+ Some ( false ) => { } , // we are not disabled - move on
1766+ None => {
1767+ gum:: debug!( target: LOG_TARGET , "We are not a validator - don't kick off validation" ) ;
1768+ return Ok ( ( ) )
1769+ } ,
1770+ }
1771+
17311772 let candidate_hash = attesting. candidate . hash ( ) ;
17321773 if rp_state. issued_statements . contains ( & candidate_hash) {
17331774 return Ok ( ( ) )
@@ -1785,6 +1826,16 @@ async fn maybe_validate_and_import<Context>(
17851826 } ,
17861827 } ;
17871828
1829+ // Don't import statement if the sender is disabled
1830+ if rp_state. table_context . validator_is_disabled ( & statement. validator_index ( ) ) {
1831+ gum:: debug!(
1832+ target: LOG_TARGET ,
1833+ sender_validator_idx = ?statement. validator_index( ) ,
1834+ "Not importing statement because the sender is disabled"
1835+ ) ;
1836+ return Ok ( ( ) )
1837+ }
1838+
17881839 let res = import_statement ( ctx, rp_state, & mut state. per_candidate , & statement) . await ;
17891840
17901841 // if we get an Error::RejectedByProspectiveParachains,
@@ -1946,6 +1997,13 @@ async fn handle_second_message<Context>(
19461997 Some ( r) => r,
19471998 } ;
19481999
2000+ // Just return if the local validator is disabled. If we are here the local node should be a
2001+ // validator but defensively use `unwrap_or(false)` to continue processing in this case.
2002+ if rp_state. table_context . local_validator_is_disabled ( ) . unwrap_or ( false ) {
2003+ gum:: warn!( target: LOG_TARGET , "Local validator is disabled. Don't validate and second" ) ;
2004+ return Ok ( ( ) )
2005+ }
2006+
19492007 // Sanity check that candidate is from our assignment.
19502008 if Some ( candidate. descriptor ( ) . para_id ) != rp_state. assignment {
19512009 gum:: debug!(
@@ -1992,6 +2050,7 @@ async fn handle_statement_message<Context>(
19922050) -> Result < ( ) , Error > {
19932051 let _timer = metrics. time_process_statement ( ) ;
19942052
2053+ // Validator disabling is handled in `maybe_validate_and_import`
19952054 match maybe_validate_and_import ( ctx, state, relay_parent, statement) . await {
19962055 Err ( Error :: ValidationFailed ( _) ) => Ok ( ( ) ) ,
19972056 Err ( e) => Err ( e) ,
0 commit comments