Migrate pallet-grandpa to attribute macros (#8724)

* frame/grandpa: migrate Config

* frame/grandpa: migrate decl_module

* frame/grandpa: migrate decl_event

* frame/grandpa: migrate decl_error

* frame/grandpa: migrate decl_storage

* frame/grandpa: make report_equivocation_unsigned pub(super)

* frame/grandpa: remove unused imports

* frame/grandpa: replace deprecated Module with Pallet

* frame/grandpa: add RawEvent for compatibility

* frame/grandpa: create migration to new storage prefix

* frame/grandpa: bump version to 4.0.0

* frame/grandpa: address review comments

* Try using version 3.1 instead

* frame/grandpa: tweak log text to say cancelled
This commit is contained in:
Jon Häggblad
2021-05-26 18:26:15 +02:00
committed by GitHub
parent 4ee5da2403
commit acef22bbd2
14 changed files with 417 additions and 225 deletions
+1 -1
View File
@@ -5010,7 +5010,7 @@ dependencies = [
[[package]]
name = "pallet-grandpa"
version = "3.0.0"
version = "3.1.0"
dependencies = [
"finality-grandpa",
"frame-benchmarking",
@@ -16,7 +16,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features =
pallet-aura = { version = "3.0.0", default-features = false, path = "../../../frame/aura" }
pallet-balances = { version = "3.0.0", default-features = false, path = "../../../frame/balances" }
frame-support = { version = "3.0.0", default-features = false, path = "../../../frame/support" }
pallet-grandpa = { version = "3.0.0", default-features = false, path = "../../../frame/grandpa" }
pallet-grandpa = { version = "3.1.0", default-features = false, path = "../../../frame/grandpa" }
pallet-randomness-collective-flip = { version = "3.0.0", default-features = false, path = "../../../frame/randomness-collective-flip" }
pallet-sudo = { version = "3.0.0", default-features = false, path = "../../../frame/sudo" }
frame-system = { version = "3.0.0", default-features = false, path = "../../../frame/system" }
+1 -1
View File
@@ -89,7 +89,7 @@ frame-support = { version = "3.0.0", default-features = false, path = "../../../
pallet-im-online = { version = "3.0.0", default-features = false, path = "../../../frame/im-online" }
pallet-authority-discovery = { version = "3.0.0", path = "../../../frame/authority-discovery" }
pallet-staking = { version = "3.0.0", path = "../../../frame/staking" }
pallet-grandpa = { version = "3.0.0", path = "../../../frame/grandpa" }
pallet-grandpa = { version = "3.1.0", path = "../../../frame/grandpa" }
# node-specific dependencies
node-runtime = { version = "2.0.0", path = "../runtime" }
+1 -1
View File
@@ -31,7 +31,7 @@ frame-system = { version = "3.0.0", path = "../../../frame/system" }
node-testing = { version = "2.0.0", path = "../testing" }
pallet-balances = { version = "3.0.0", path = "../../../frame/balances" }
pallet-contracts = { version = "3.0.0", path = "../../../frame/contracts" }
pallet-grandpa = { version = "3.0.0", path = "../../../frame/grandpa" }
pallet-grandpa = { version = "3.1.0", path = "../../../frame/grandpa" }
pallet-im-online = { version = "3.0.0", path = "../../../frame/im-online" }
pallet-indices = { version = "3.0.0", path = "../../../frame/indices" }
pallet-session = { version = "3.0.0", path = "../../../frame/session" }
+1 -1
View File
@@ -59,7 +59,7 @@ pallet-democracy = { version = "3.0.0", default-features = false, path = "../../
pallet-election-provider-multi-phase = { version = "3.0.0", default-features = false, path = "../../../frame/election-provider-multi-phase" }
pallet-elections-phragmen = { version = "4.0.0", default-features = false, path = "../../../frame/elections-phragmen" }
pallet-gilt = { version = "3.0.0", default-features = false, path = "../../../frame/gilt" }
pallet-grandpa = { version = "3.0.0", default-features = false, path = "../../../frame/grandpa" }
pallet-grandpa = { version = "3.1.0", default-features = false, path = "../../../frame/grandpa" }
pallet-im-online = { version = "3.0.0", default-features = false, path = "../../../frame/im-online" }
pallet-indices = { version = "3.0.0", default-features = false, path = "../../../frame/indices" }
pallet-identity = { version = "3.0.0", default-features = false, path = "../../../frame/identity" }
+1 -1
View File
@@ -19,7 +19,7 @@ sc-client-db = { version = "0.9.0", path = "../../../client/db/", features = ["k
sc-client-api = { version = "3.0.0", path = "../../../client/api/" }
codec = { package = "parity-scale-codec", version = "2.0.0" }
pallet-contracts = { version = "3.0.0", path = "../../../frame/contracts" }
pallet-grandpa = { version = "3.0.0", path = "../../../frame/grandpa" }
pallet-grandpa = { version = "3.1.0", path = "../../../frame/grandpa" }
pallet-indices = { version = "3.0.0", path = "../../../frame/indices" }
sp-keyring = { version = "3.0.0", path = "../../../primitives/keyring" }
node-executor = { version = "2.0.0", path = "../executor" }
+2 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "pallet-grandpa"
version = "3.0.0"
version = "3.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2018"
license = "Apache-2.0"
@@ -17,6 +17,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features =
sp-application-crypto = { version = "3.0.0", default-features = false, path = "../../primitives/application-crypto" }
sp-core = { version = "3.0.0", default-features = false, path = "../../primitives/core" }
sp-finality-grandpa = { version = "3.0.0", default-features = false, path = "../../primitives/finality-grandpa" }
sp-io = { version = "3.0.0", default-features = false, path = "../../primitives/io" }
sp-session = { version = "3.0.0", default-features = false, path = "../../primitives/session" }
sp-std = { version = "3.0.0", default-features = false, path = "../../primitives/std" }
sp-runtime = { version = "3.0.0", default-features = false, path = "../../primitives/runtime" }
@@ -31,7 +32,6 @@ log = { version = "0.4.14", default-features = false }
[dev-dependencies]
frame-benchmarking = { version = "3.1.0", path = "../benchmarking" }
grandpa = { package = "finality-grandpa", version = "0.14.0", features = ["derive-codec"] }
sp-io = { version = "3.0.0", path = "../../primitives/io" }
sp-keyring = { version = "3.0.0", path = "../../primitives/keyring" }
pallet-balances = { version = "3.0.0", path = "../balances" }
pallet-offences = { version = "3.0.0", path = "../offences" }
+1 -1
View File
@@ -19,7 +19,7 @@
#![cfg_attr(not(feature = "std"), no_std)]
use super::{*, Module as Grandpa};
use super::{*, Pallet as Grandpa};
use frame_benchmarking::benchmarks;
use frame_system::RawOrigin;
use sp_core::H256;
+2 -2
View File
@@ -54,7 +54,7 @@ use sp_staking::{
SessionIndex,
};
use super::{Call, Module, Config};
use super::{Call, Pallet, Config};
/// A trait with utility methods for handling equivocation reports in GRANDPA.
/// The offence type is generic, and the trait provides , reporting an offence
@@ -203,7 +203,7 @@ pub struct GrandpaTimeSlot {
/// A `ValidateUnsigned` implementation that restricts calls to `report_equivocation_unsigned`
/// to local calls (i.e. extrinsics generated on this node) or that already in a block. This
/// guarantees that only block authors can include unsigned equivocation reports.
impl<T: Config> frame_support::unsigned::ValidateUnsigned for Module<T> {
impl<T: Config> frame_support::unsigned::ValidateUnsigned for Pallet<T> {
type Call = Call<T>;
fn validate_unsigned(source: TransactionSource, call: &Self::Call) -> TransactionValidity {
if let Call::report_equivocation_unsigned(equivocation_proof, key_owner_proof) = call {
+257 -212
View File
@@ -40,10 +40,9 @@ use fg_primitives::{
GRANDPA_ENGINE_ID,
};
use frame_support::{
decl_error, decl_event, decl_module, decl_storage, dispatch::DispatchResultWithPostInfo,
storage, traits::{OneSessionHandler, KeyOwnerProofSystem}, weights::{Pays, Weight}, Parameter,
dispatch::DispatchResultWithPostInfo,
storage, traits::{OneSessionHandler, KeyOwnerProofSystem}, weights::{Pays, Weight},
};
use frame_system::{ensure_none, ensure_root, ensure_signed};
use sp_runtime::{
generic::DigestItem,
traits::Zero,
@@ -54,6 +53,7 @@ use sp_staking::SessionIndex;
mod equivocation;
mod default_weights;
pub mod migrations;
#[cfg(any(feature = "runtime-benchmarks", test))]
mod benchmarking;
@@ -67,219 +67,58 @@ pub use equivocation::{
HandleEquivocation,
};
pub trait Config: frame_system::Config {
/// The event type of this module.
type Event: From<Event> + Into<<Self as frame_system::Config>::Event>;
pub use pallet::*;
/// The function call.
type Call: From<Call<Self>>;
#[frame_support::pallet]
pub mod pallet {
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;
use super::*;
/// 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;
#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
pub struct Pallet<T>(_);
/// The identification of a key owner, used when reporting equivocations.
type KeyOwnerIdentification: Parameter;
#[pallet::config]
pub trait Config: frame_system::Config {
/// The event type of this module.
type Event: From<Event>
+ Into<<Self as frame_system::Config>::Event>
+ IsType<<Self as frame_system::Config>::Event>;
/// 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 function call.
type Call: From<Call<Self>>;
/// 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>;
/// 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;
/// Weights for this pallet.
type WeightInfo: WeightInfo;
}
/// The identification of a key owner, used when reporting equivocations.
type KeyOwnerIdentification: Parameter;
pub trait WeightInfo {
fn report_equivocation(validator_count: u32) -> Weight;
fn note_stalled() -> Weight;
}
/// 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,
>;
/// A stored pending change.
#[derive(Encode, Decode)]
pub struct StoredPendingChange<N> {
/// The block number this was scheduled at.
pub scheduled_at: N,
/// The delay in blocks until it will be applied.
pub delay: N,
/// The next authority set.
pub next_authorities: AuthorityList,
/// If defined it means the change was forced and the given block number
/// indicates the median last finalized block when the change was signaled.
pub forced: Option<N>,
}
/// 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>;
/// Current state of the GRANDPA authority set. State transitions must happen in
/// the same order of states defined below, e.g. `Paused` implies a prior
/// `PendingPause`.
#[derive(Decode, Encode)]
#[cfg_attr(test, derive(Debug, PartialEq))]
pub enum StoredState<N> {
/// The current authority set is live, and GRANDPA is enabled.
Live,
/// There is a pending pause event which will be enacted at the given block
/// height.
PendingPause {
/// Block at which the intention to pause was scheduled.
scheduled_at: N,
/// Number of blocks after which the change will be enacted.
delay: N
},
/// The current GRANDPA authority set is paused.
Paused,
/// There is a pending resume event which will be enacted at the given block
/// height.
PendingResume {
/// Block at which the intention to resume was scheduled.
scheduled_at: N,
/// Number of blocks after which the change will be enacted.
delay: N,
},
}
decl_event! {
pub enum Event {
/// New authority set has been applied. \[authority_set\]
NewAuthorities(AuthorityList),
/// Current authority set has been paused.
Paused,
/// Current authority set has been resumed.
Resumed,
/// Weights for this pallet.
type WeightInfo: WeightInfo;
}
}
decl_error! {
pub enum Error for Module<T: Config> {
/// Attempt to signal GRANDPA pause when the authority set isn't live
/// (either paused or already pending pause).
PauseFailed,
/// Attempt to signal GRANDPA resume when the authority set isn't paused
/// (either live or already pending resume).
ResumeFailed,
/// Attempt to signal GRANDPA change with one already pending.
ChangePending,
/// Cannot signal forced change so soon after last.
TooSoon,
/// A key ownership proof provided as part of an equivocation report is invalid.
InvalidKeyOwnershipProof,
/// An equivocation proof provided as part of an equivocation report is invalid.
InvalidEquivocationProof,
/// A given equivocation report is valid but already previously reported.
DuplicateOffenceReport,
}
}
decl_storage! {
trait Store for Module<T: Config> as GrandpaFinality {
/// State of the current authority set.
State get(fn state): StoredState<T::BlockNumber> = StoredState::Live;
/// Pending change: (signaled at, scheduled change).
PendingChange get(fn pending_change): Option<StoredPendingChange<T::BlockNumber>>;
/// next block number where we can force a change.
NextForced get(fn next_forced): Option<T::BlockNumber>;
/// `true` if we are currently stalled.
Stalled get(fn stalled): Option<(T::BlockNumber, T::BlockNumber)>;
/// The number of changes (both in terms of keys and underlying economic responsibilities)
/// in the "set" of Grandpa validators from genesis.
CurrentSetId get(fn current_set_id) build(|_| fg_primitives::SetId::default()): SetId;
/// A mapping from grandpa set ID to the index of the *most recent* session for which its
/// members were responsible.
///
/// TWOX-NOTE: `SetId` is not under user control.
SetIdSession get(fn session_for_set): map hasher(twox_64_concat) SetId => Option<SessionIndex>;
}
add_extra_genesis {
config(authorities): AuthorityList;
build(|config| {
Module::<T>::initialize(&config.authorities)
})
}
}
decl_module! {
pub struct Module<T: Config> for enum Call where origin: T::Origin {
type Error = Error<T>;
fn deposit_event() = default;
/// Report voter equivocation/misbehavior. This method will verify the
/// equivocation proof and validate the given key ownership proof
/// against the extracted offender. If both are valid, the offence
/// will be reported.
#[weight = T::WeightInfo::report_equivocation(key_owner_proof.validator_count())]
fn report_equivocation(
origin,
equivocation_proof: EquivocationProof<T::Hash, T::BlockNumber>,
key_owner_proof: T::KeyOwnerProof,
) -> DispatchResultWithPostInfo {
let reporter = ensure_signed(origin)?;
Self::do_report_equivocation(
Some(reporter),
equivocation_proof,
key_owner_proof,
)
}
/// Report voter equivocation/misbehavior. This method will verify the
/// equivocation proof and validate the given key ownership proof
/// against the extracted offender. If both are valid, the offence
/// will be reported.
///
/// This extrinsic must be called unsigned and it is expected that only
/// block authors will call it (validated in `ValidateUnsigned`), as such
/// if the block author is defined it will be defined as the equivocation
/// reporter.
#[weight = T::WeightInfo::report_equivocation(key_owner_proof.validator_count())]
fn report_equivocation_unsigned(
origin,
equivocation_proof: EquivocationProof<T::Hash, T::BlockNumber>,
key_owner_proof: T::KeyOwnerProof,
) -> DispatchResultWithPostInfo {
ensure_none(origin)?;
Self::do_report_equivocation(
T::HandleEquivocation::block_author(),
equivocation_proof,
key_owner_proof,
)
}
/// Note that the current authority set of the GRANDPA finality gadget has
/// stalled. This will trigger a forced authority set change at the beginning
/// of the next session, to be enacted `delay` blocks after that. The delay
/// should be high enough to safely assume that the block signalling the
/// forced change will not be re-orged (e.g. 1000 blocks). The GRANDPA voters
/// will start the new authority set using the given finalized block as base.
/// Only callable by root.
#[weight = T::WeightInfo::note_stalled()]
fn note_stalled(
origin,
delay: T::BlockNumber,
best_finalized_block_number: T::BlockNumber,
) {
ensure_root(origin)?;
Self::on_stalled(delay, best_finalized_block_number)
}
#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
fn on_finalize(block_number: T::BlockNumber) {
// check for scheduled pending authority set changes
if let Some(pending_change) = <PendingChange<T>>::get() {
@@ -343,9 +182,215 @@ decl_module! {
}
}
}
#[pallet::call]
impl<T: Config> Pallet<T> {
/// Report voter equivocation/misbehavior. This method will verify the
/// equivocation proof and validate the given key ownership proof
/// against the extracted offender. If both are valid, the offence
/// will be reported.
#[pallet::weight(T::WeightInfo::report_equivocation(key_owner_proof.validator_count()))]
fn report_equivocation(
origin: OriginFor<T>,
equivocation_proof: EquivocationProof<T::Hash, T::BlockNumber>,
key_owner_proof: T::KeyOwnerProof,
) -> DispatchResultWithPostInfo {
let reporter = ensure_signed(origin)?;
Self::do_report_equivocation(
Some(reporter),
equivocation_proof,
key_owner_proof,
)
}
/// Report voter equivocation/misbehavior. This method will verify the
/// equivocation proof and validate the given key ownership proof
/// against the extracted offender. If both are valid, the offence
/// will be reported.
///
/// This extrinsic must be called unsigned and it is expected that only
/// block authors will call it (validated in `ValidateUnsigned`), as such
/// if the block author is defined it will be defined as the equivocation
/// reporter.
#[pallet::weight(T::WeightInfo::report_equivocation(key_owner_proof.validator_count()))]
pub(super) fn report_equivocation_unsigned(
origin: OriginFor<T>,
equivocation_proof: EquivocationProof<T::Hash, T::BlockNumber>,
key_owner_proof: T::KeyOwnerProof,
) -> DispatchResultWithPostInfo {
ensure_none(origin)?;
Self::do_report_equivocation(
T::HandleEquivocation::block_author(),
equivocation_proof,
key_owner_proof,
)
}
/// Note that the current authority set of the GRANDPA finality gadget has
/// stalled. This will trigger a forced authority set change at the beginning
/// of the next session, to be enacted `delay` blocks after that. The delay
/// should be high enough to safely assume that the block signalling the
/// forced change will not be re-orged (e.g. 1000 blocks). The GRANDPA voters
/// will start the new authority set using the given finalized block as base.
/// Only callable by root.
#[pallet::weight(T::WeightInfo::note_stalled())]
fn note_stalled(
origin: OriginFor<T>,
delay: T::BlockNumber,
best_finalized_block_number: T::BlockNumber,
) -> DispatchResultWithPostInfo {
ensure_root(origin)?;
Ok(Self::on_stalled(delay, best_finalized_block_number).into())
}
}
#[pallet::event]
#[pallet::generate_deposit(fn deposit_event)]
pub enum Event {
/// New authority set has been applied. \[authority_set\]
NewAuthorities(AuthorityList),
/// Current authority set has been paused.
Paused,
/// Current authority set has been resumed.
Resumed,
}
#[deprecated(note = "use `Event` instead")]
pub type RawEvent = Event;
#[pallet::error]
pub enum Error<T> {
/// Attempt to signal GRANDPA pause when the authority set isn't live
/// (either paused or already pending pause).
PauseFailed,
/// Attempt to signal GRANDPA resume when the authority set isn't paused
/// (either live or already pending resume).
ResumeFailed,
/// Attempt to signal GRANDPA change with one already pending.
ChangePending,
/// Cannot signal forced change so soon after last.
TooSoon,
/// A key ownership proof provided as part of an equivocation report is invalid.
InvalidKeyOwnershipProof,
/// An equivocation proof provided as part of an equivocation report is invalid.
InvalidEquivocationProof,
/// A given equivocation report is valid but already previously reported.
DuplicateOffenceReport,
}
#[pallet::type_value]
pub(super) fn DefaultForState<T: Config>() -> StoredState<T::BlockNumber> {
StoredState::Live
}
/// State of the current authority set.
#[pallet::storage]
#[pallet::getter(fn state)]
pub(super) type State<T: Config> = StorageValue<_, StoredState<T::BlockNumber>, ValueQuery, DefaultForState<T>>;
/// Pending change: (signaled at, scheduled change).
#[pallet::storage]
#[pallet::getter(fn pending_change)]
pub(super) type PendingChange<T: Config> = StorageValue<_, StoredPendingChange<T::BlockNumber>>;
/// next block number where we can force a change.
#[pallet::storage]
#[pallet::getter(fn next_forced)]
pub(super) type NextForced<T: Config> = StorageValue<_, T::BlockNumber>;
/// `true` if we are currently stalled.
#[pallet::storage]
#[pallet::getter(fn stalled)]
pub(super) type Stalled<T: Config> = StorageValue<_, (T::BlockNumber, T::BlockNumber)>;
/// The number of changes (both in terms of keys and underlying economic responsibilities)
/// in the "set" of Grandpa validators from genesis.
#[pallet::storage]
#[pallet::getter(fn current_set_id)]
pub(super) type CurrentSetId<T: Config> = StorageValue<_, SetId, ValueQuery>;
/// A mapping from grandpa set ID to the index of the *most recent* session for which its
/// members were responsible.
///
/// TWOX-NOTE: `SetId` is not under user control.
#[pallet::storage]
#[pallet::getter(fn session_for_set)]
pub(super) type SetIdSession<T: Config> = StorageMap<_, Twox64Concat, SetId, SessionIndex>;
#[pallet::genesis_config]
pub struct GenesisConfig {
pub authorities: AuthorityList,
}
#[cfg(feature = "std")]
impl Default for GenesisConfig {
fn default() -> Self {
Self {
authorities: Default::default(),
}
}
}
#[pallet::genesis_build]
impl<T: Config> GenesisBuild<T> for GenesisConfig {
fn build(&self) {
CurrentSetId::<T>::put(fg_primitives::SetId::default());
Pallet::<T>::initialize(&self.authorities)
}
}
}
impl<T: Config> Module<T> {
pub trait WeightInfo {
fn report_equivocation(validator_count: u32) -> Weight;
fn note_stalled() -> Weight;
}
/// A stored pending change.
#[derive(Encode, Decode)]
pub struct StoredPendingChange<N> {
/// The block number this was scheduled at.
pub scheduled_at: N,
/// The delay in blocks until it will be applied.
pub delay: N,
/// The next authority set.
pub next_authorities: AuthorityList,
/// If defined it means the change was forced and the given block number
/// indicates the median last finalized block when the change was signaled.
pub forced: Option<N>,
}
/// Current state of the GRANDPA authority set. State transitions must happen in
/// the same order of states defined below, e.g. `Paused` implies a prior
/// `PendingPause`.
#[derive(Decode, Encode)]
#[cfg_attr(test, derive(Debug, PartialEq))]
pub enum StoredState<N> {
/// The current authority set is live, and GRANDPA is enabled.
Live,
/// There is a pending pause event which will be enacted at the given block
/// height.
PendingPause {
/// Block at which the intention to pause was scheduled.
scheduled_at: N,
/// Number of blocks after which the change will be enacted.
delay: N
},
/// The current GRANDPA authority set is paused.
Paused,
/// There is a pending resume event which will be enacted at the given block
/// height.
PendingResume {
/// Block at which the intention to resume was scheduled.
scheduled_at: N,
/// Number of blocks after which the change will be enacted.
delay: N,
},
}
impl<T: Config> Pallet<T> {
/// Get the current set of authorities, along with their respective weights.
pub fn grandpa_authorities() -> AuthorityList {
storage::unhashed::get_or_default::<VersionedAuthorityList>(GRANDPA_AUTHORITIES_KEY).into()
@@ -455,7 +500,7 @@ impl<T: Config> Module<T> {
// NOTE: initialize first session of first set. this is necessary for
// the genesis set and session since we only update the set -> session
// mapping whenever a new session starts, i.e. through `on_new_session`.
SetIdSession::insert(0, 0);
SetIdSession::<T>::insert(0, 0);
}
fn do_report_equivocation(
@@ -548,11 +593,11 @@ impl<T: Config> Module<T> {
}
}
impl<T: Config> sp_runtime::BoundToRuntimeAppPublic for Module<T> {
impl<T: Config> sp_runtime::BoundToRuntimeAppPublic for Pallet<T> {
type Public = AuthorityId;
}
impl<T: Config> OneSessionHandler<T::AccountId> for Module<T>
impl<T: Config> OneSessionHandler<T::AccountId> for Pallet<T>
where T: pallet_session::Config
{
type Key = AuthorityId;
@@ -580,7 +625,7 @@ impl<T: Config> OneSessionHandler<T::AccountId> for Module<T>
};
if res.is_ok() {
CurrentSetId::mutate(|s| {
CurrentSetId::<T>::mutate(|s| {
*s += 1;
*s
})
@@ -598,8 +643,8 @@ impl<T: Config> OneSessionHandler<T::AccountId> for Module<T>
// if we didn't issue a change, we update the mapping to note that the current
// set corresponds to the latest equivalent session (i.e. now).
let session_index = <pallet_session::Module<T>>::current_index();
SetIdSession::insert(current_set_id, &session_index);
let session_index = <pallet_session::Pallet<T>>::current_index();
SetIdSession::<T>::insert(current_set_id, &session_index);
}
fn on_disabled(i: usize) {
+19
View File
@@ -0,0 +1,19 @@
// This file is part of Substrate.
// Copyright (C) 2021 Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Version 3.1.
pub mod v3_1;
@@ -0,0 +1,128 @@
// This file is part of Substrate.
// Copyright (C) 2021 Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use frame_support::{
weights::Weight,
traits::{GetPalletVersion, PalletVersion, Get},
};
use sp_io::hashing::twox_128;
/// The old prefix.
pub const OLD_PREFIX: &[u8] = b"GrandpaFinality";
/// Migrate the entire storage of this pallet to a new prefix.
///
/// This new prefix must be the same as the one set in construct_runtime. For safety, use
/// `PalletInfo` to get it, as:
/// `<Runtime as frame_system::Config>::PalletInfo::name::<GrandpaPallet>`.
///
/// The old storage prefix, `GrandpaFinality` is hardcoded in the migration code.
pub fn migrate<
T: frame_system::Config,
P: GetPalletVersion,
N: AsRef<str>,
>(new_pallet_name: N) -> Weight {
if new_pallet_name.as_ref().as_bytes() == OLD_PREFIX {
log::info!(
target: "runtime::afg",
"New pallet name is equal to the old prefix. No migration needs to be done.",
);
return 0;
}
let maybe_storage_version = <P as GetPalletVersion>::storage_version();
log::info!(
target: "runtime::afg",
"Running migration to v3.1 for grandpa with storage version {:?}",
maybe_storage_version,
);
match maybe_storage_version {
Some(storage_version) if storage_version <= PalletVersion::new(3, 0, 0) => {
log::info!("new prefix: {}", new_pallet_name.as_ref());
frame_support::storage::migration::move_pallet(
OLD_PREFIX,
new_pallet_name.as_ref().as_bytes(),
);
<T as frame_system::Config>::BlockWeights::get().max_block
}
_ => {
log::warn!(
target: "runtime::afg",
"Attempted to apply migration to v3.1 but cancelled because storage version is {:?}",
maybe_storage_version,
);
0
},
}
}
/// Some checks prior to migration. This can be linked to
/// [`frame_support::traits::OnRuntimeUpgrade::pre_upgrade`] for further testing.
///
/// Panics if anything goes wrong.
pub fn pre_migration<
T: frame_system::Config,
P: GetPalletVersion + 'static,
N: AsRef<str>,
>(new: N) {
let new = new.as_ref();
log::info!("pre-migration grandpa test with new = {}", new);
// the next key must exist, and start with the hash of `OLD_PREFIX`.
let next_key = sp_io::storage::next_key(&twox_128(OLD_PREFIX)).unwrap();
assert!(next_key.starts_with(&twox_128(OLD_PREFIX)));
// The pallet version is already stored using the pallet name
let storage_key = PalletVersion::storage_key::<T::PalletInfo, P>().unwrap();
// ensure nothing is stored in the new prefix.
assert!(
sp_io::storage::next_key(&twox_128(new.as_bytes())).map_or(
// either nothing is there
true,
// or we ensure that it has no common prefix with twox_128(new),
// or isn't the pallet version that is already stored using the pallet name
|next_key| {
!next_key.starts_with(&twox_128(new.as_bytes())) || next_key == storage_key
},
),
"unexpected next_key({}) = {:?}",
new,
sp_core::hexdisplay::HexDisplay::from(
&sp_io::storage::next_key(&twox_128(new.as_bytes())).unwrap()
),
);
// ensure storage version is 3.
assert!(<P as GetPalletVersion>::storage_version().unwrap().major == 3);
}
/// Some checks for after migration. This can be linked to
/// [`frame_support::traits::OnRuntimeUpgrade::post_upgrade`] for further testing.
///
/// Panics if anything goes wrong.
pub fn post_migration<P: GetPalletVersion>() {
log::info!("post-migration grandpa");
// Assert that nothing remains at the old prefix
assert!(
sp_io::storage::next_key(&twox_128(OLD_PREFIX)).map_or(
true,
|next_key| !next_key.starts_with(&twox_128(OLD_PREFIX))
)
);
}
+1 -1
View File
@@ -64,7 +64,7 @@ frame_support::construct_runtime!(
impl_opaque_keys! {
pub struct TestSessionKeys {
pub grandpa_authority: super::Module<Test>,
pub grandpa_authority: super::Pallet<Test>,
}
}
@@ -19,7 +19,7 @@ frame-support = { version = "3.0.0", default-features = false, path = "../../sup
frame-system = { version = "3.0.0", default-features = false, path = "../../system" }
pallet-babe = { version = "3.0.0", default-features = false, path = "../../babe" }
pallet-balances = { version = "3.0.0", default-features = false, path = "../../balances" }
pallet-grandpa = { version = "3.0.0", default-features = false, path = "../../grandpa" }
pallet-grandpa = { version = "3.1.0", default-features = false, path = "../../grandpa" }
pallet-im-online = { version = "3.0.0", default-features = false, path = "../../im-online" }
pallet-offences = { version = "3.0.0", default-features = false, features = ["runtime-benchmarks"], path = "../../offences" }
pallet-session = { version = "3.0.0", default-features = false, path = "../../session" }