mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-19 22:51:03 +00:00
Offences report system rework (#13425)
* Experiments with common equivocation trait * Improved equivocation trait * Fix grandpa equivocation implementation * Remove some cruft * Remove some more cruft * More generic naming * Simplification of offences manipilation * More refactory * Some prograss with the encapsulation of offence report system * Finally unit type works as a universal null report system * Align substrate node code * Further simplification * Fix test utils * Remove not required associated type * Fix benches * Rollback to prev field name * Box big params * Fix typo * Remove new tag computation * Remove default implementations * Better docs * Return 'Result' instead of bool * Change offence report system return types * Some renaming and documentation * Improve documentation * More abstract offence report system * Rename 'consume_evidence' to 'process_evidence' * Further docs refinements * Doc for dummy offence report * Fix rustdoc * Fix after master merge * Apply code review suggestions * Improve docs
This commit is contained in:
@@ -28,29 +28,29 @@
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
// re-export since this is necessary for `impl_apis` in runtime.
|
||||
pub use sp_consensus_grandpa as fg_primitives;
|
||||
|
||||
use sp_std::prelude::*;
|
||||
// Re-export since this is necessary for `impl_apis` in runtime.
|
||||
pub use sp_consensus_grandpa::{
|
||||
self as fg_primitives, AuthorityId, AuthorityList, AuthorityWeight, VersionedAuthorityList,
|
||||
};
|
||||
|
||||
use codec::{self as codec, Decode, Encode, MaxEncodedLen};
|
||||
pub use fg_primitives::{AuthorityId, AuthorityList, AuthorityWeight, VersionedAuthorityList};
|
||||
use fg_primitives::{
|
||||
ConsensusLog, EquivocationProof, ScheduledChange, SetId, GRANDPA_AUTHORITIES_KEY,
|
||||
GRANDPA_ENGINE_ID, RUNTIME_LOG_TARGET as LOG_TARGET,
|
||||
};
|
||||
use frame_support::{
|
||||
dispatch::{DispatchResultWithPostInfo, Pays},
|
||||
pallet_prelude::Get,
|
||||
storage,
|
||||
traits::{KeyOwnerProofSystem, OneSessionHandler},
|
||||
traits::OneSessionHandler,
|
||||
weights::Weight,
|
||||
WeakBoundedVec,
|
||||
};
|
||||
use scale_info::TypeInfo;
|
||||
use sp_runtime::{generic::DigestItem, traits::Zero, DispatchResult, KeyTypeId};
|
||||
use sp_consensus_grandpa::{
|
||||
ConsensusLog, EquivocationProof, ScheduledChange, SetId, GRANDPA_AUTHORITIES_KEY,
|
||||
GRANDPA_ENGINE_ID, RUNTIME_LOG_TARGET as LOG_TARGET,
|
||||
};
|
||||
use sp_runtime::{generic::DigestItem, traits::Zero, DispatchResult};
|
||||
use sp_session::{GetSessionNumber, GetValidatorCount};
|
||||
use sp_staking::SessionIndex;
|
||||
use sp_staking::{offence::OffenceReportSystem, SessionIndex};
|
||||
use sp_std::prelude::*;
|
||||
|
||||
mod default_weights;
|
||||
mod equivocation;
|
||||
@@ -63,10 +63,7 @@ mod mock;
|
||||
#[cfg(all(feature = "std", test))]
|
||||
mod tests;
|
||||
|
||||
pub use equivocation::{
|
||||
EquivocationHandler, GrandpaEquivocationOffence, GrandpaOffence, GrandpaTimeSlot,
|
||||
HandleEquivocation,
|
||||
};
|
||||
pub use equivocation::{EquivocationOffence, EquivocationReportSystem, GrandpaTimeSlot};
|
||||
|
||||
pub use pallet::*;
|
||||
|
||||
@@ -91,30 +88,6 @@ pub mod pallet {
|
||||
+ Into<<Self as frame_system::Config>::RuntimeEvent>
|
||||
+ IsType<<Self as frame_system::Config>::RuntimeEvent>;
|
||||
|
||||
/// 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.
|
||||
type KeyOwnerProof: Parameter + GetSessionNumber + GetValidatorCount;
|
||||
|
||||
/// The identification of a key owner, used when reporting equivocations.
|
||||
type KeyOwnerIdentification: Parameter;
|
||||
|
||||
/// A system for proving ownership of keys, i.e. that a given key was part
|
||||
/// of a validator set, needed for validating equivocation reports.
|
||||
type KeyOwnerProofSystem: KeyOwnerProofSystem<
|
||||
(KeyTypeId, AuthorityId),
|
||||
Proof = Self::KeyOwnerProof,
|
||||
IdentificationTuple = Self::KeyOwnerIdentification,
|
||||
>;
|
||||
|
||||
/// The equivocation handling subsystem, defines methods to report an
|
||||
/// offence (after the equivocation has been validated) and for submitting a
|
||||
/// transaction to report an equivocation (from an offchain context).
|
||||
/// NOTE: when enabling equivocation handling (i.e. this type isn't set to
|
||||
/// `()`) you must use this pallet's `ValidateUnsigned` in the runtime
|
||||
/// definition.
|
||||
type HandleEquivocation: HandleEquivocation<Self>;
|
||||
|
||||
/// Weights for this pallet.
|
||||
type WeightInfo: WeightInfo;
|
||||
|
||||
@@ -130,6 +103,19 @@ pub mod pallet {
|
||||
/// can be zero.
|
||||
#[pallet::constant]
|
||||
type MaxSetIdSessionEntries: Get<u64>;
|
||||
|
||||
/// The proof of key ownership, used for validating equivocation reports
|
||||
/// The proof include the session index and validator count of the
|
||||
/// session at which the equivocation occurred.
|
||||
type KeyOwnerProof: Parameter + GetSessionNumber + GetValidatorCount;
|
||||
|
||||
/// The equivocation handling subsystem, defines methods to check/report an
|
||||
/// offence and for submitting a transaction to report an equivocation
|
||||
/// (from an offchain context).
|
||||
type EquivocationReportSystem: OffenceReportSystem<
|
||||
Option<Self::AccountId>,
|
||||
(EquivocationProof<Self::Hash, Self::BlockNumber>, Self::KeyOwnerProof),
|
||||
>;
|
||||
}
|
||||
|
||||
#[pallet::hooks]
|
||||
@@ -211,7 +197,12 @@ pub mod pallet {
|
||||
) -> DispatchResultWithPostInfo {
|
||||
let reporter = ensure_signed(origin)?;
|
||||
|
||||
Self::do_report_equivocation(Some(reporter), *equivocation_proof, key_owner_proof)
|
||||
T::EquivocationReportSystem::process_evidence(
|
||||
Some(reporter),
|
||||
(*equivocation_proof, key_owner_proof),
|
||||
)?;
|
||||
// Waive the fee since the report is valid and beneficial
|
||||
Ok(Pays::No.into())
|
||||
}
|
||||
|
||||
/// Report voter equivocation/misbehavior. This method will verify the
|
||||
@@ -232,11 +223,11 @@ pub mod pallet {
|
||||
) -> DispatchResultWithPostInfo {
|
||||
ensure_none(origin)?;
|
||||
|
||||
Self::do_report_equivocation(
|
||||
T::HandleEquivocation::block_author(),
|
||||
*equivocation_proof,
|
||||
key_owner_proof,
|
||||
)
|
||||
T::EquivocationReportSystem::process_evidence(
|
||||
None,
|
||||
(*equivocation_proof, key_owner_proof),
|
||||
)?;
|
||||
Ok(Pays::No.into())
|
||||
}
|
||||
|
||||
/// Note that the current authority set of the GRANDPA finality gadget has stalled.
|
||||
@@ -352,7 +343,7 @@ pub mod pallet {
|
||||
#[pallet::genesis_build]
|
||||
impl<T: Config> GenesisBuild<T> for GenesisConfig {
|
||||
fn build(&self) {
|
||||
CurrentSetId::<T>::put(fg_primitives::SetId::default());
|
||||
CurrentSetId::<T>::put(SetId::default());
|
||||
Pallet::<T>::initialize(&self.authorities)
|
||||
}
|
||||
}
|
||||
@@ -532,74 +523,6 @@ impl<T: Config> Pallet<T> {
|
||||
SetIdSession::<T>::insert(0, 0);
|
||||
}
|
||||
|
||||
fn do_report_equivocation(
|
||||
reporter: Option<T::AccountId>,
|
||||
equivocation_proof: EquivocationProof<T::Hash, T::BlockNumber>,
|
||||
key_owner_proof: T::KeyOwnerProof,
|
||||
) -> DispatchResultWithPostInfo {
|
||||
// we check the equivocation within the context of its set id (and
|
||||
// associated session) and round. we also need to know the validator
|
||||
// set count when the offence since it is required to calculate the
|
||||
// slash amount.
|
||||
let set_id = equivocation_proof.set_id();
|
||||
let round = equivocation_proof.round();
|
||||
let session_index = key_owner_proof.session();
|
||||
let validator_count = key_owner_proof.validator_count();
|
||||
|
||||
// validate the key ownership proof extracting the id of the offender.
|
||||
let offender = T::KeyOwnerProofSystem::check_proof(
|
||||
(fg_primitives::KEY_TYPE, equivocation_proof.offender().clone()),
|
||||
key_owner_proof,
|
||||
)
|
||||
.ok_or(Error::<T>::InvalidKeyOwnershipProof)?;
|
||||
|
||||
// validate equivocation proof (check votes are different and
|
||||
// signatures are valid).
|
||||
if !sp_consensus_grandpa::check_equivocation_proof(equivocation_proof) {
|
||||
return Err(Error::<T>::InvalidEquivocationProof.into())
|
||||
}
|
||||
|
||||
// fetch the current and previous sets last session index. on the
|
||||
// genesis set there's no previous set.
|
||||
let previous_set_id_session_index = if set_id == 0 {
|
||||
None
|
||||
} else {
|
||||
let session_index =
|
||||
Self::session_for_set(set_id - 1).ok_or(Error::<T>::InvalidEquivocationProof)?;
|
||||
|
||||
Some(session_index)
|
||||
};
|
||||
|
||||
let set_id_session_index =
|
||||
Self::session_for_set(set_id).ok_or(Error::<T>::InvalidEquivocationProof)?;
|
||||
|
||||
// check that the session id for the membership proof is within the
|
||||
// bounds of the set id reported in the equivocation.
|
||||
if session_index > set_id_session_index ||
|
||||
previous_set_id_session_index
|
||||
.map(|previous_index| session_index <= previous_index)
|
||||
.unwrap_or(false)
|
||||
{
|
||||
return Err(Error::<T>::InvalidEquivocationProof.into())
|
||||
}
|
||||
|
||||
// report to the offences module rewarding the sender.
|
||||
T::HandleEquivocation::report_offence(
|
||||
reporter.into_iter().collect(),
|
||||
<T::HandleEquivocation as HandleEquivocation<T>>::Offence::new(
|
||||
session_index,
|
||||
validator_count,
|
||||
offender,
|
||||
set_id,
|
||||
round,
|
||||
),
|
||||
)
|
||||
.map_err(|_| Error::<T>::DuplicateOffenceReport)?;
|
||||
|
||||
// waive the fee since the report is valid and beneficial
|
||||
Ok(Pays::No.into())
|
||||
}
|
||||
|
||||
/// Submits an extrinsic to report an equivocation. This method will create
|
||||
/// an unsigned extrinsic with a call to `report_equivocation_unsigned` and
|
||||
/// will push the transaction to the pool. Only useful in an offchain
|
||||
@@ -608,11 +531,7 @@ impl<T: Config> Pallet<T> {
|
||||
equivocation_proof: EquivocationProof<T::Hash, T::BlockNumber>,
|
||||
key_owner_proof: T::KeyOwnerProof,
|
||||
) -> Option<()> {
|
||||
T::HandleEquivocation::submit_unsigned_equivocation_report(
|
||||
equivocation_proof,
|
||||
key_owner_proof,
|
||||
)
|
||||
.ok()
|
||||
T::EquivocationReportSystem::publish_evidence((equivocation_proof, key_owner_proof)).ok()
|
||||
}
|
||||
|
||||
fn on_stalled(further_wait: T::BlockNumber, median: T::BlockNumber) {
|
||||
|
||||
Reference in New Issue
Block a user