aura, babe: don't allow disabled validators to build blocks (#9414)

* frame-support: add trait for checking disabled validators

* pallet-session: implement DisabledValidators trait

* pallet-babe: check for disabled validators

* pallet-babe: add test for disabled validators

* pallet-aura: check for disabled validators

* pallet-aura: add test for disabled validators

* runtime: fix missing DisableValidator

* test-runtime: add missing DisabledValidators

* frame-support: clean up doc

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
This commit is contained in:
André Silva
2021-08-03 11:57:08 +01:00
committed by GitHub
parent c9ffce0f9c
commit 0240efde58
12 changed files with 142 additions and 11 deletions
+15 -1
View File
@@ -24,7 +24,9 @@
use codec::{Decode, Encode};
use frame_support::{
dispatch::DispatchResultWithPostInfo,
traits::{FindAuthor, Get, KeyOwnerProofSystem, OnTimestampSet, OneSessionHandler},
traits::{
DisabledValidators, FindAuthor, Get, KeyOwnerProofSystem, OnTimestampSet, OneSessionHandler,
},
weights::{Pays, Weight},
};
use sp_application_crypto::Public;
@@ -137,6 +139,11 @@ pub mod pallet {
/// when no other module is responsible for changing authority set.
type EpochChangeTrigger: EpochChangeTrigger;
/// A way to check whether a given validator is disabled and should not be authoring blocks.
/// Blocks authored by a disabled validator will lead to a panic as part of this module's
/// initialization.
type DisabledValidators: DisabledValidators;
/// The proof of key ownership, used for validating equivocation reports.
/// The proof must include the session index and validator count of the
/// session at which the equivocation occurred.
@@ -678,6 +685,13 @@ impl<T: Config> Pallet<T> {
let authority_index = digest.authority_index();
if T::DisabledValidators::is_disabled(authority_index) {
panic!(
"Validator with index {:?} is disabled and should not be attempting to author blocks.",
authority_index,
);
}
// Extract out the VRF output if we have it
digest.vrf_output().and_then(|vrf_output| {
// Reconstruct the bytes of VRFInOut using the authority id.
+1
View File
@@ -238,6 +238,7 @@ impl Config for Test {
type EpochDuration = EpochDuration;
type ExpectedBlockTime = ExpectedBlockTime;
type EpochChangeTrigger = crate::ExternalTrigger;
type DisabledValidators = Session;
type KeyOwnerProofSystem = Historical;
+28 -3
View File
@@ -373,6 +373,31 @@ fn tracks_block_numbers_when_current_and_previous_epoch_started() {
});
}
#[test]
#[should_panic(
expected = "Validator with index 0 is disabled and should not be attempting to author blocks."
)]
fn disabled_validators_cannot_author_blocks() {
new_test_ext(4).execute_with(|| {
start_era(1);
// let's disable the validator at index 1
Session::disable_index(1);
// the mocking infrastructure always authors all blocks using authority index 0,
// so we should still be able to author blocks
start_era(2);
assert_eq!(Staking::current_era().unwrap(), 2);
// let's disable the validator at index 0
Session::disable_index(0);
// this should now panic as the validator authoring blocks is disabled
start_era(3);
});
}
#[test]
fn report_equivocation_current_session_works() {
let (pairs, mut ext) = new_test_ext_with_pairs(3);
@@ -394,8 +419,8 @@ fn report_equivocation_current_session_works() {
);
}
// we will use the validator at index 0 as the offending authority
let offending_validator_index = 0;
// we will use the validator at index 1 as the offending authority
let offending_validator_index = 1;
let offending_validator_id = Session::validators()[offending_validator_index];
let offending_authority_pair = pairs
.into_iter()
@@ -456,7 +481,7 @@ fn report_equivocation_old_session_works() {
let authorities = Babe::authorities();
// we will use the validator at index 0 as the offending authority
let offending_validator_index = 0;
let offending_validator_index = 1;
let offending_validator_id = Session::validators()[offending_validator_index];
let offending_authority_pair = pairs
.into_iter()