Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Commit

Permalink
babe, grandpa: set longevity for equivocation report transactions (#8076
Browse files Browse the repository at this point in the history
)

* babe: set longevity for equivocation report transactions

* grandpa: set longevity for equivocation report transaction

* babe, grandpa: fix tests

* node: add ReportLongevity to babe and grandpa modules

* node: bump spec_version
  • Loading branch information
andresilva committed Feb 10, 2021
1 parent 22441aa commit ce018b8
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 23 deletions.
8 changes: 5 additions & 3 deletions bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
// and set impl_version to 0. If only runtime
// implementation changes and behavior does not, then leave spec_version as
// is and increment impl_version.
spec_version: 263,
spec_version: 264,
impl_version: 0,
apis: RUNTIME_API_VERSIONS,
transaction_version: 2,
Expand Down Expand Up @@ -319,6 +319,8 @@ impl pallet_scheduler::Config for Runtime {
parameter_types! {
pub const EpochDuration: u64 = EPOCH_DURATION_IN_SLOTS;
pub const ExpectedBlockTime: Moment = MILLISECS_PER_BLOCK;
pub const ReportLongevity: u64 =
BondingDuration::get() as u64 * SessionsPerEra::get() as u64 * EpochDuration::get();
}

impl pallet_babe::Config for Runtime {
Expand All @@ -339,7 +341,7 @@ impl pallet_babe::Config for Runtime {
)>>::IdentificationTuple;

type HandleEquivocation =
pallet_babe::EquivocationHandler<Self::KeyOwnerIdentification, Offences>;
pallet_babe::EquivocationHandler<Self::KeyOwnerIdentification, Offences, ReportLongevity>;

type WeightInfo = ();
}
Expand Down Expand Up @@ -866,7 +868,7 @@ impl pallet_grandpa::Config for Runtime {
)>>::IdentificationTuple;

type HandleEquivocation =
pallet_grandpa::EquivocationHandler<Self::KeyOwnerIdentification, Offences>;
pallet_grandpa::EquivocationHandler<Self::KeyOwnerIdentification, Offences, ReportLongevity>;

type WeightInfo = ();
}
Expand Down
27 changes: 22 additions & 5 deletions frame/babe/src/equivocation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@
//! definition.
//!

use frame_support::{debug, traits::KeyOwnerProofSystem};
use frame_support::{
debug,
traits::{Get, KeyOwnerProofSystem},
};
use sp_consensus_babe::{EquivocationProof, Slot};
use sp_runtime::transaction_validity::{
InvalidTransaction, TransactionPriority, TransactionSource, TransactionValidity,
Expand All @@ -56,6 +59,10 @@ use crate::{Call, Module, Config};
/// reporter), and also for creating and submitting equivocation report
/// extrinsics (useful only in offchain context).
pub trait HandleEquivocation<T: Config> {
/// The longevity, in blocks, that the equivocation report is valid for. When using the staking
/// pallet this should be equal to the bonding duration (in blocks, not eras).
type ReportLongevity: Get<u64>;

/// Report an offence proved by the given reporters.
fn report_offence(
reporters: Vec<T::AccountId>,
Expand All @@ -76,6 +83,8 @@ pub trait HandleEquivocation<T: Config> {
}

impl<T: Config> HandleEquivocation<T> for () {
type ReportLongevity = ();

fn report_offence(
_reporters: Vec<T::AccountId>,
_offence: BabeEquivocationOffence<T::KeyOwnerIdentification>,
Expand Down Expand Up @@ -103,19 +112,19 @@ impl<T: Config> HandleEquivocation<T> for () {
/// using existing subsystems that are part of frame (type bounds described
/// below) and will dispatch to them directly, it's only purpose is to wire all
/// subsystems together.
pub struct EquivocationHandler<I, R> {
_phantom: sp_std::marker::PhantomData<(I, R)>,
pub struct EquivocationHandler<I, R, L> {
_phantom: sp_std::marker::PhantomData<(I, R, L)>,
}

impl<I, R> Default for EquivocationHandler<I, R> {
impl<I, R, L> Default for EquivocationHandler<I, R, L> {
fn default() -> Self {
Self {
_phantom: Default::default(),
}
}
}

impl<T, R> HandleEquivocation<T> for EquivocationHandler<T::KeyOwnerIdentification, R>
impl<T, R, L> HandleEquivocation<T> for EquivocationHandler<T::KeyOwnerIdentification, R, L>
where
// We use the authorship pallet to fetch the current block author and use
// `offchain::SendTransactionTypes` for unsigned extrinsic creation and
Expand All @@ -128,7 +137,12 @@ where
T::KeyOwnerIdentification,
BabeEquivocationOffence<T::KeyOwnerIdentification>,
>,
// The longevity (in blocks) that the equivocation report is valid for. When using the staking
// pallet this should be the bonding duration.
L: Get<u64>,
{
type ReportLongevity = L;

fn report_offence(
reporters: Vec<T::AccountId>,
offence: BabeEquivocationOffence<T::KeyOwnerIdentification>,
Expand Down Expand Up @@ -184,6 +198,8 @@ impl<T: Config> frame_support::unsigned::ValidateUnsigned for Module<T> {
// check report staleness
is_known_offence::<T>(equivocation_proof, key_owner_proof)?;

let longevity = <T::HandleEquivocation as HandleEquivocation<T>>::ReportLongevity::get();

ValidTransaction::with_tag_prefix("BabeEquivocation")
// We assign the maximum priority for any equivocation report.
.priority(TransactionPriority::max_value())
Expand All @@ -192,6 +208,7 @@ impl<T: Config> frame_support::unsigned::ValidateUnsigned for Module<T> {
equivocation_proof.offender.clone(),
*equivocation_proof.slot,
))
.longevity(longevity)
// We don't propagate this. This can never be included on a remote node.
.propagate(false)
.build()
Expand Down
13 changes: 10 additions & 3 deletions frame/babe/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,6 @@ frame_support::construct_runtime!(

parameter_types! {
pub const BlockHashCount: u64 = 250;
pub const EpochDuration: u64 = 3;
pub const ExpectedBlockTime: u64 = 1;
pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(16);
pub BlockWeights: frame_system::limits::BlockWeights =
frame_system::limits::BlockWeights::simple_max(1024);
Expand Down Expand Up @@ -222,6 +220,13 @@ impl pallet_offences::Config for Test {
type WeightSoftLimit = OffencesWeightSoftLimit;
}

parameter_types! {
pub const EpochDuration: u64 = 3;
pub const ExpectedBlockTime: u64 = 1;
pub const ReportLongevity: u64 =
BondingDuration::get() as u64 * SessionsPerEra::get() as u64 * EpochDuration::get();
}

impl Config for Test {
type EpochDuration = EpochDuration;
type ExpectedBlockTime = ExpectedBlockTime;
Expand All @@ -237,7 +242,9 @@ impl Config for Test {
AuthorityId,
)>>::IdentificationTuple;

type HandleEquivocation = super::EquivocationHandler<Self::KeyOwnerIdentification, Offences>;
type HandleEquivocation =
super::EquivocationHandler<Self::KeyOwnerIdentification, Offences, ReportLongevity>;

type WeightInfo = ();
}

Expand Down
6 changes: 3 additions & 3 deletions frame/babe/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -611,8 +611,8 @@ fn report_equivocation_invalid_equivocation_proof() {
#[test]
fn report_equivocation_validate_unsigned_prevents_duplicates() {
use sp_runtime::transaction_validity::{
InvalidTransaction, TransactionLongevity, TransactionPriority, TransactionSource,
TransactionValidity, ValidTransaction,
InvalidTransaction, TransactionPriority, TransactionSource, TransactionValidity,
ValidTransaction,
};

let (pairs, mut ext) = new_test_ext_with_pairs(3);
Expand Down Expand Up @@ -664,7 +664,7 @@ fn report_equivocation_validate_unsigned_prevents_duplicates() {
priority: TransactionPriority::max_value(),
requires: vec![],
provides: vec![("BabeEquivocation", tx_tag).encode()],
longevity: TransactionLongevity::max_value(),
longevity: ReportLongevity::get(),
propagate: false,
})
);
Expand Down
25 changes: 20 additions & 5 deletions frame/grandpa/src/equivocation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@
use sp_std::prelude::*;

use codec::{self as codec, Decode, Encode};
use frame_support::{debug, traits::KeyOwnerProofSystem};
use frame_support::{
debug,
traits::{Get, KeyOwnerProofSystem},
};
use sp_finality_grandpa::{EquivocationProof, RoundNumber, SetId};
use sp_runtime::{
transaction_validity::{
Expand All @@ -64,6 +67,10 @@ pub trait HandleEquivocation<T: Config> {
/// The offence type used for reporting offences on valid equivocation reports.
type Offence: GrandpaOffence<T::KeyOwnerIdentification>;

/// The longevity, in blocks, that the equivocation report is valid for. When using the staking
/// pallet this should be equal to the bonding duration (in blocks, not eras).
type ReportLongevity: Get<u64>;

/// Report an offence proved by the given reporters.
fn report_offence(
reporters: Vec<T::AccountId>,
Expand All @@ -88,6 +95,7 @@ pub trait HandleEquivocation<T: Config> {

impl<T: Config> HandleEquivocation<T> for () {
type Offence = GrandpaEquivocationOffence<T::KeyOwnerIdentification>;
type ReportLongevity = ();

fn report_offence(
_reporters: Vec<T::AccountId>,
Expand Down Expand Up @@ -119,19 +127,19 @@ impl<T: Config> HandleEquivocation<T> for () {
/// using existing subsystems that are part of frame (type bounds described
/// below) and will dispatch to them directly, it's only purpose is to wire all
/// subsystems together.
pub struct EquivocationHandler<I, R, O = GrandpaEquivocationOffence<I>> {
_phantom: sp_std::marker::PhantomData<(I, R, O)>,
pub struct EquivocationHandler<I, R, L, O = GrandpaEquivocationOffence<I>> {
_phantom: sp_std::marker::PhantomData<(I, R, L, O)>,
}

impl<I, R, O> Default for EquivocationHandler<I, R, O> {
impl<I, R, L, O> Default for EquivocationHandler<I, R, L, O> {
fn default() -> Self {
Self {
_phantom: Default::default(),
}
}
}

impl<T, R, O> HandleEquivocation<T> for EquivocationHandler<T::KeyOwnerIdentification, R, O>
impl<T, R, L, O> HandleEquivocation<T> for EquivocationHandler<T::KeyOwnerIdentification, R, L, O>
where
// We use the authorship pallet to fetch the current block author and use
// `offchain::SendTransactionTypes` for unsigned extrinsic creation and
Expand All @@ -140,10 +148,14 @@ where
// A system for reporting offences after valid equivocation reports are
// processed.
R: ReportOffence<T::AccountId, T::KeyOwnerIdentification, O>,
// The longevity (in blocks) that the equivocation report is valid for. When using the staking
// pallet this should be the bonding duration.
L: Get<u64>,
// The offence type that should be used when reporting.
O: GrandpaOffence<T::KeyOwnerIdentification>,
{
type Offence = O;
type ReportLongevity = L;

fn report_offence(reporters: Vec<T::AccountId>, offence: O) -> Result<(), OffenceError> {
R::report_offence(reporters, offence)
Expand Down Expand Up @@ -207,6 +219,8 @@ impl<T: Config> frame_support::unsigned::ValidateUnsigned for Module<T> {
// check report staleness
is_known_offence::<T>(equivocation_proof, key_owner_proof)?;

let longevity = <T::HandleEquivocation as HandleEquivocation<T>>::ReportLongevity::get();

ValidTransaction::with_tag_prefix("GrandpaEquivocation")
// We assign the maximum priority for any equivocation report.
.priority(TransactionPriority::max_value())
Expand All @@ -216,6 +230,7 @@ impl<T: Config> frame_support::unsigned::ValidateUnsigned for Module<T> {
equivocation_proof.set_id(),
equivocation_proof.round(),
))
.longevity(longevity)
// We don't propagate this. This can never be included on a remote node.
.propagate(false)
.build()
Expand Down
8 changes: 7 additions & 1 deletion frame/grandpa/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,11 @@ impl pallet_offences::Config for Test {
type WeightSoftLimit = OffencesWeightSoftLimit;
}

parameter_types! {
pub const ReportLongevity: u64 =
BondingDuration::get() as u64 * SessionsPerEra::get() as u64 * Period::get();
}

impl Config for Test {
type Event = Event;
type Call = Call;
Expand All @@ -240,7 +245,8 @@ impl Config for Test {
AuthorityId,
)>>::IdentificationTuple;

type HandleEquivocation = super::EquivocationHandler<Self::KeyOwnerIdentification, Offences>;
type HandleEquivocation =
super::EquivocationHandler<Self::KeyOwnerIdentification, Offences, ReportLongevity>;

type WeightInfo = ();
}
Expand Down
6 changes: 3 additions & 3 deletions frame/grandpa/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -706,8 +706,8 @@ fn report_equivocation_invalid_equivocation_proof() {
#[test]
fn report_equivocation_validate_unsigned_prevents_duplicates() {
use sp_runtime::transaction_validity::{
InvalidTransaction, TransactionLongevity, TransactionPriority, TransactionSource,
TransactionValidity, ValidTransaction,
InvalidTransaction, TransactionPriority, TransactionSource, TransactionValidity,
ValidTransaction,
};

let authorities = test_authorities();
Expand Down Expand Up @@ -762,7 +762,7 @@ fn report_equivocation_validate_unsigned_prevents_duplicates() {
priority: TransactionPriority::max_value(),
requires: vec![],
provides: vec![("GrandpaEquivocation", tx_tag).encode()],
longevity: TransactionLongevity::max_value(),
longevity: ReportLongevity::get(),
propagate: false,
})
);
Expand Down

0 comments on commit ce018b8

Please sign in to comment.