Skip to content

Commit a02b534

Browse files
ordiantdimitrov
andauthored
backport to master: Handling of disabled validators in backing subsystem (#1259) (#2764)
#1259 was merged into a feature branch, but we've decided to merge node-side changes for disabling straight into master. This is a dependency of #1841 and #2637. --------- Co-authored-by: Tsvetomir Dimitrov <[email protected]>
1 parent 4fdab49 commit a02b534

File tree

7 files changed

+574
-73
lines changed

7 files changed

+574
-73
lines changed

polkadot/node/core/backing/src/lib.rs

Lines changed: 73 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -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

122123
mod 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

388404
impl 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

Comments
 (0)