Skip to content

Commit b5c6f07

Browse files
committed
Handling of disabled validators in backing subsystem - initial work
1 parent 1d1f852 commit b5c6f07

File tree

7 files changed

+71
-19
lines changed

7 files changed

+71
-19
lines changed

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

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,7 @@ struct TableContext {
379379
validator: Option<Validator>,
380380
groups: HashMap<ParaId, Vec<ValidatorIndex>>,
381381
validators: Vec<ValidatorId>,
382+
disabled_validators: Vec<ValidatorIndex>,
382383
}
383384

384385
impl TableContextTrait for TableContext {
@@ -983,37 +984,46 @@ async fn construct_per_relay_parent_state<Context>(
983984

984985
let parent = relay_parent;
985986

986-
let (validators, groups, session_index, cores) = futures::try_join!(
987+
let (validators, groups, session_index, cores, disabled_validators) = futures::try_join!(
987988
request_validators(parent, ctx.sender()).await,
988989
request_validator_groups(parent, ctx.sender()).await,
989990
request_session_index_for_child(parent, ctx.sender()).await,
990991
request_from_runtime(parent, ctx.sender(), |tx| {
991992
RuntimeApiRequest::AvailabilityCores(tx)
992993
},)
993994
.await,
995+
request_from_runtime(parent, ctx.sender(), |tx| {
996+
RuntimeApiRequest::DisabledValidators(tx)
997+
},)
998+
.await,
994999
)
9951000
.map_err(Error::JoinMultiple)?;
9961001

9971002
let validators: Vec<_> = try_runtime_api!(validators);
9981003
let (validator_groups, group_rotation_info) = try_runtime_api!(groups);
9991004
let session_index = try_runtime_api!(session_index);
10001005
let cores = try_runtime_api!(cores);
1006+
let disabled_validators = try_runtime_api!(disabled_validators);
10011007

10021008
let signing_context = SigningContext { parent_hash: parent, session_index };
1003-
let validator =
1004-
match Validator::construct(&validators, signing_context.clone(), keystore.clone()) {
1005-
Ok(v) => Some(v),
1006-
Err(util::Error::NotAValidator) => None,
1007-
Err(e) => {
1008-
gum::warn!(
1009-
target: LOG_TARGET,
1010-
err = ?e,
1011-
"Cannot participate in candidate backing",
1012-
);
1009+
let validator = match Validator::construct(
1010+
&validators,
1011+
&disabled_validators,
1012+
signing_context.clone(),
1013+
keystore.clone(),
1014+
) {
1015+
Ok(v) => Some(v),
1016+
Err(util::Error::NotAValidator) => None,
1017+
Err(e) => {
1018+
gum::warn!(
1019+
target: LOG_TARGET,
1020+
err = ?e,
1021+
"Cannot participate in candidate backing",
1022+
);
10131023

1014-
return Ok(None)
1015-
},
1016-
};
1024+
return Ok(None)
1025+
},
1026+
};
10171027

10181028
let mut groups = HashMap::new();
10191029
let n_cores = cores.len();
@@ -1043,7 +1053,7 @@ async fn construct_per_relay_parent_state<Context>(
10431053
}
10441054
}
10451055

1046-
let table_context = TableContext { groups, validators, validator };
1056+
let table_context = TableContext { validator, groups, validators, disabled_validators };
10471057
let table_config = TableConfig {
10481058
allow_multiple_seconded: match mode {
10491059
ProspectiveParachainsMode::Enabled { .. } => true,
@@ -1552,6 +1562,8 @@ async fn import_statement<Context>(
15521562

15531563
let stmt = primitive_statement_to_table(statement);
15541564

1565+
// TODO: check if `stmt.sender` is in disabled validators for the job
1566+
15551567
Ok(rp_state.table.import_statement(&rp_state.table_context, stmt))
15561568
}
15571569

@@ -1943,6 +1955,8 @@ async fn handle_second_message<Context>(
19431955
return Ok(())
19441956
}
19451957

1958+
// TODO: do nothing if we are disabled
1959+
19461960
// If the message is a `CandidateBackingMessage::Second`, sign and dispatch a
19471961
// Seconded statement only if we have not signed a Valid statement for the requested candidate.
19481962
//

polkadot/node/core/backing/src/tests/mod.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,16 @@ async fn test_startup(virtual_overseer: &mut VirtualOverseer, test_state: &TestS
289289
tx.send(Ok(test_state.availability_cores.clone())).unwrap();
290290
}
291291
);
292+
293+
// Check that subsystem job issues a request for the disabled validators.
294+
assert_matches!(
295+
virtual_overseer.recv().await,
296+
AllMessages::RuntimeApi(
297+
RuntimeApiMessage::Request(parent, RuntimeApiRequest::DisabledValidators(tx))
298+
) if parent == test_state.relay_parent => {
299+
tx.send(Ok(Vec::new())).unwrap();
300+
}
301+
);
292302
}
293303

294304
// Test that a `CandidateBackingMessage::Second` issues validation work
@@ -1418,6 +1428,7 @@ fn candidate_backing_reorders_votes() {
14181428

14191429
let table_context = TableContext {
14201430
validator: None,
1431+
disabled_validators: Vec::new(),
14211432
groups: validator_groups,
14221433
validators: validator_public.clone(),
14231434
};

polkadot/node/core/backing/src/tests/prospective_parachains.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,16 @@ async fn activate_leaf(
183183
tx.send(Ok(test_state.availability_cores.clone())).unwrap();
184184
}
185185
);
186+
187+
// Check that the subsystem job issues a request for the disabled validators.
188+
assert_matches!(
189+
virtual_overseer.recv().await,
190+
AllMessages::RuntimeApi(
191+
RuntimeApiMessage::Request(parent, RuntimeApiRequest::DisabledValidators(tx))
192+
) if parent == hash => {
193+
tx.send(Ok(Vec::new())).unwrap();
194+
}
195+
);
186196
}
187197
}
188198

polkadot/node/network/statement-distribution/src/legacy_v1/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1675,6 +1675,8 @@ async fn handle_incoming_message<'a, Context>(
16751675

16761676
let mut _span = handle_incoming_span.child("notify-backing");
16771677

1678+
// TODO: check if peer is disabled?
1679+
16781680
// When we receive a new message from a peer, we forward it to the
16791681
// candidate backing subsystem.
16801682
ctx.send_message(CandidateBackingMessage::Statement(relay_parent, statement_with_pvd))

polkadot/node/network/statement-distribution/src/vstaging/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1583,6 +1583,8 @@ async fn send_backing_fresh_statements<Context>(
15831583
})
15841584
.expect("statements refer to same candidate; qed");
15851585

1586+
// TODO: check if peer is disabled?
1587+
15861588
ctx.send_message(CandidateBackingMessage::Statement(*relay_parent, carrying_pvd))
15871589
.await;
15881590
}

polkadot/node/subsystem-util/src/lib.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,7 @@ pub struct Validator {
379379
signing_context: SigningContext,
380380
key: ValidatorId,
381381
index: ValidatorIndex,
382+
disabled: bool,
382383
}
383384

384385
impl Validator {
@@ -391,30 +392,37 @@ impl Validator {
391392
// Note: request_validators and request_session_index_for_child do not and cannot
392393
// run concurrently: they both have a mutable handle to the same sender.
393394
// However, each of them returns a oneshot::Receiver, and those are resolved concurrently.
394-
let (validators, session_index) = futures::try_join!(
395+
let (validators, session_index, disabled_validators) = futures::try_join!(
395396
request_validators(parent, sender).await,
396397
request_session_index_for_child(parent, sender).await,
398+
request_disabled_validators(parent, sender).await,
397399
)?;
398400

399401
let signing_context = SigningContext { session_index: session_index?, parent_hash: parent };
400402

401403
let validators = validators?;
402404

403-
Self::construct(&validators, signing_context, keystore)
405+
let disabled_validators = disabled_validators?;
406+
407+
Self::construct(&validators, &disabled_validators, signing_context, keystore)
404408
}
405409

406410
/// Construct a validator instance without performing runtime fetches.
407411
///
408412
/// This can be useful if external code also needs the same data.
409413
pub fn construct(
410414
validators: &[ValidatorId],
415+
disabled_validators: &[ValidatorIndex],
411416
signing_context: SigningContext,
412417
keystore: KeystorePtr,
413418
) -> Result<Self, Error> {
414419
let (key, index) =
415420
signing_key_and_index(validators, &keystore).ok_or(Error::NotAValidator)?;
416421

417-
Ok(Validator { signing_context, key, index })
422+
let disabled =
423+
disabled_validators.iter().find(|d: &&ValidatorIndex| **d == index).is_some();
424+
425+
Ok(Validator { signing_context, key, index, disabled })
418426
}
419427

420428
/// Get this validator's id.
@@ -427,6 +435,11 @@ impl Validator {
427435
self.index
428436
}
429437

438+
/// Get the enabled/disabled state of this validator
439+
pub fn disabled(&self) -> bool {
440+
self.disabled
441+
}
442+
430443
/// Get the current signing context.
431444
pub fn signing_context(&self) -> &SigningContext {
432445
&self.signing_context

polkadot/runtime/parachains/src/session_info.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ impl<T: Config> Pallet<T> {
157157
for idx in old_earliest_stored_session..new_earliest_stored_session {
158158
Sessions::<T>::remove(&idx);
159159
// Idx will be missing for a few sessions after the runtime upgrade.
160-
// But it shouldn'be be a problem.
160+
// But it shouldn't be a problem.
161161
AccountKeys::<T>::remove(&idx);
162162
SessionExecutorParams::<T>::remove(&idx);
163163
}

0 commit comments

Comments
 (0)