mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 05:51:02 +00:00
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:
Generated
+1
-1
@@ -5010,7 +5010,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pallet-grandpa"
|
name = "pallet-grandpa"
|
||||||
version = "3.0.0"
|
version = "3.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"finality-grandpa",
|
"finality-grandpa",
|
||||||
"frame-benchmarking",
|
"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-aura = { version = "3.0.0", default-features = false, path = "../../../frame/aura" }
|
||||||
pallet-balances = { version = "3.0.0", default-features = false, path = "../../../frame/balances" }
|
pallet-balances = { version = "3.0.0", default-features = false, path = "../../../frame/balances" }
|
||||||
frame-support = { version = "3.0.0", default-features = false, path = "../../../frame/support" }
|
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-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" }
|
pallet-sudo = { version = "3.0.0", default-features = false, path = "../../../frame/sudo" }
|
||||||
frame-system = { version = "3.0.0", default-features = false, path = "../../../frame/system" }
|
frame-system = { version = "3.0.0", default-features = false, path = "../../../frame/system" }
|
||||||
|
|||||||
@@ -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-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-authority-discovery = { version = "3.0.0", path = "../../../frame/authority-discovery" }
|
||||||
pallet-staking = { version = "3.0.0", path = "../../../frame/staking" }
|
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-specific dependencies
|
||||||
node-runtime = { version = "2.0.0", path = "../runtime" }
|
node-runtime = { version = "2.0.0", path = "../runtime" }
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ frame-system = { version = "3.0.0", path = "../../../frame/system" }
|
|||||||
node-testing = { version = "2.0.0", path = "../testing" }
|
node-testing = { version = "2.0.0", path = "../testing" }
|
||||||
pallet-balances = { version = "3.0.0", path = "../../../frame/balances" }
|
pallet-balances = { version = "3.0.0", path = "../../../frame/balances" }
|
||||||
pallet-contracts = { version = "3.0.0", path = "../../../frame/contracts" }
|
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-im-online = { version = "3.0.0", path = "../../../frame/im-online" }
|
||||||
pallet-indices = { version = "3.0.0", path = "../../../frame/indices" }
|
pallet-indices = { version = "3.0.0", path = "../../../frame/indices" }
|
||||||
pallet-session = { version = "3.0.0", path = "../../../frame/session" }
|
pallet-session = { version = "3.0.0", path = "../../../frame/session" }
|
||||||
|
|||||||
@@ -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-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-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-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-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-indices = { version = "3.0.0", default-features = false, path = "../../../frame/indices" }
|
||||||
pallet-identity = { version = "3.0.0", default-features = false, path = "../../../frame/identity" }
|
pallet-identity = { version = "3.0.0", default-features = false, path = "../../../frame/identity" }
|
||||||
|
|||||||
@@ -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/" }
|
sc-client-api = { version = "3.0.0", path = "../../../client/api/" }
|
||||||
codec = { package = "parity-scale-codec", version = "2.0.0" }
|
codec = { package = "parity-scale-codec", version = "2.0.0" }
|
||||||
pallet-contracts = { version = "3.0.0", path = "../../../frame/contracts" }
|
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" }
|
pallet-indices = { version = "3.0.0", path = "../../../frame/indices" }
|
||||||
sp-keyring = { version = "3.0.0", path = "../../../primitives/keyring" }
|
sp-keyring = { version = "3.0.0", path = "../../../primitives/keyring" }
|
||||||
node-executor = { version = "2.0.0", path = "../executor" }
|
node-executor = { version = "2.0.0", path = "../executor" }
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "pallet-grandpa"
|
name = "pallet-grandpa"
|
||||||
version = "3.0.0"
|
version = "3.1.0"
|
||||||
authors = ["Parity Technologies <admin@parity.io>"]
|
authors = ["Parity Technologies <admin@parity.io>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
license = "Apache-2.0"
|
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-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-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-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-session = { version = "3.0.0", default-features = false, path = "../../primitives/session" }
|
||||||
sp-std = { version = "3.0.0", default-features = false, path = "../../primitives/std" }
|
sp-std = { version = "3.0.0", default-features = false, path = "../../primitives/std" }
|
||||||
sp-runtime = { version = "3.0.0", default-features = false, path = "../../primitives/runtime" }
|
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]
|
[dev-dependencies]
|
||||||
frame-benchmarking = { version = "3.1.0", path = "../benchmarking" }
|
frame-benchmarking = { version = "3.1.0", path = "../benchmarking" }
|
||||||
grandpa = { package = "finality-grandpa", version = "0.14.0", features = ["derive-codec"] }
|
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" }
|
sp-keyring = { version = "3.0.0", path = "../../primitives/keyring" }
|
||||||
pallet-balances = { version = "3.0.0", path = "../balances" }
|
pallet-balances = { version = "3.0.0", path = "../balances" }
|
||||||
pallet-offences = { version = "3.0.0", path = "../offences" }
|
pallet-offences = { version = "3.0.0", path = "../offences" }
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
#![cfg_attr(not(feature = "std"), no_std)]
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
|
|
||||||
use super::{*, Module as Grandpa};
|
use super::{*, Pallet as Grandpa};
|
||||||
use frame_benchmarking::benchmarks;
|
use frame_benchmarking::benchmarks;
|
||||||
use frame_system::RawOrigin;
|
use frame_system::RawOrigin;
|
||||||
use sp_core::H256;
|
use sp_core::H256;
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ use sp_staking::{
|
|||||||
SessionIndex,
|
SessionIndex,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{Call, Module, Config};
|
use super::{Call, Pallet, Config};
|
||||||
|
|
||||||
/// A trait with utility methods for handling equivocation reports in GRANDPA.
|
/// A trait with utility methods for handling equivocation reports in GRANDPA.
|
||||||
/// The offence type is generic, and the trait provides , reporting an offence
|
/// 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`
|
/// 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
|
/// 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.
|
/// 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>;
|
type Call = Call<T>;
|
||||||
fn validate_unsigned(source: TransactionSource, call: &Self::Call) -> TransactionValidity {
|
fn validate_unsigned(source: TransactionSource, call: &Self::Call) -> TransactionValidity {
|
||||||
if let Call::report_equivocation_unsigned(equivocation_proof, key_owner_proof) = call {
|
if let Call::report_equivocation_unsigned(equivocation_proof, key_owner_proof) = call {
|
||||||
|
|||||||
+257
-212
@@ -40,10 +40,9 @@ use fg_primitives::{
|
|||||||
GRANDPA_ENGINE_ID,
|
GRANDPA_ENGINE_ID,
|
||||||
};
|
};
|
||||||
use frame_support::{
|
use frame_support::{
|
||||||
decl_error, decl_event, decl_module, decl_storage, dispatch::DispatchResultWithPostInfo,
|
dispatch::DispatchResultWithPostInfo,
|
||||||
storage, traits::{OneSessionHandler, KeyOwnerProofSystem}, weights::{Pays, Weight}, Parameter,
|
storage, traits::{OneSessionHandler, KeyOwnerProofSystem}, weights::{Pays, Weight},
|
||||||
};
|
};
|
||||||
use frame_system::{ensure_none, ensure_root, ensure_signed};
|
|
||||||
use sp_runtime::{
|
use sp_runtime::{
|
||||||
generic::DigestItem,
|
generic::DigestItem,
|
||||||
traits::Zero,
|
traits::Zero,
|
||||||
@@ -54,6 +53,7 @@ use sp_staking::SessionIndex;
|
|||||||
|
|
||||||
mod equivocation;
|
mod equivocation;
|
||||||
mod default_weights;
|
mod default_weights;
|
||||||
|
pub mod migrations;
|
||||||
|
|
||||||
#[cfg(any(feature = "runtime-benchmarks", test))]
|
#[cfg(any(feature = "runtime-benchmarks", test))]
|
||||||
mod benchmarking;
|
mod benchmarking;
|
||||||
@@ -67,219 +67,58 @@ pub use equivocation::{
|
|||||||
HandleEquivocation,
|
HandleEquivocation,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait Config: frame_system::Config {
|
pub use pallet::*;
|
||||||
/// The event type of this module.
|
|
||||||
type Event: From<Event> + Into<<Self as frame_system::Config>::Event>;
|
|
||||||
|
|
||||||
/// The function call.
|
#[frame_support::pallet]
|
||||||
type Call: From<Call<Self>>;
|
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.
|
#[pallet::pallet]
|
||||||
/// The proof must include the session index and validator count of the
|
#[pallet::generate_store(pub(super) trait Store)]
|
||||||
/// session at which the equivocation occurred.
|
pub struct Pallet<T>(_);
|
||||||
type KeyOwnerProof: Parameter + GetSessionNumber + GetValidatorCount;
|
|
||||||
|
|
||||||
/// The identification of a key owner, used when reporting equivocations.
|
#[pallet::config]
|
||||||
type KeyOwnerIdentification: Parameter;
|
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
|
/// The function call.
|
||||||
/// of a validator set, needed for validating equivocation reports.
|
type Call: From<Call<Self>>;
|
||||||
type KeyOwnerProofSystem: KeyOwnerProofSystem<
|
|
||||||
(KeyTypeId, AuthorityId),
|
|
||||||
Proof = Self::KeyOwnerProof,
|
|
||||||
IdentificationTuple = Self::KeyOwnerIdentification,
|
|
||||||
>;
|
|
||||||
|
|
||||||
/// The equivocation handling subsystem, defines methods to report an
|
/// The proof of key ownership, used for validating equivocation reports
|
||||||
/// offence (after the equivocation has been validated) and for submitting a
|
/// The proof must include the session index and validator count of the
|
||||||
/// transaction to report an equivocation (from an offchain context).
|
/// session at which the equivocation occurred.
|
||||||
/// NOTE: when enabling equivocation handling (i.e. this type isn't set to
|
type KeyOwnerProof: Parameter + GetSessionNumber + GetValidatorCount;
|
||||||
/// `()`) you must use this pallet's `ValidateUnsigned` in the runtime
|
|
||||||
/// definition.
|
|
||||||
type HandleEquivocation: HandleEquivocation<Self>;
|
|
||||||
|
|
||||||
/// Weights for this pallet.
|
/// The identification of a key owner, used when reporting equivocations.
|
||||||
type WeightInfo: WeightInfo;
|
type KeyOwnerIdentification: Parameter;
|
||||||
}
|
|
||||||
|
|
||||||
pub trait WeightInfo {
|
/// A system for proving ownership of keys, i.e. that a given key was part
|
||||||
fn report_equivocation(validator_count: u32) -> Weight;
|
/// of a validator set, needed for validating equivocation reports.
|
||||||
fn note_stalled() -> Weight;
|
type KeyOwnerProofSystem: KeyOwnerProofSystem<
|
||||||
}
|
(KeyTypeId, AuthorityId),
|
||||||
|
Proof = Self::KeyOwnerProof,
|
||||||
|
IdentificationTuple = Self::KeyOwnerIdentification,
|
||||||
|
>;
|
||||||
|
|
||||||
/// A stored pending change.
|
/// The equivocation handling subsystem, defines methods to report an
|
||||||
#[derive(Encode, Decode)]
|
/// offence (after the equivocation has been validated) and for submitting a
|
||||||
pub struct StoredPendingChange<N> {
|
/// transaction to report an equivocation (from an offchain context).
|
||||||
/// The block number this was scheduled at.
|
/// NOTE: when enabling equivocation handling (i.e. this type isn't set to
|
||||||
pub scheduled_at: N,
|
/// `()`) you must use this pallet's `ValidateUnsigned` in the runtime
|
||||||
/// The delay in blocks until it will be applied.
|
/// definition.
|
||||||
pub delay: N,
|
type HandleEquivocation: HandleEquivocation<Self>;
|
||||||
/// 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
|
/// Weights for this pallet.
|
||||||
/// the same order of states defined below, e.g. `Paused` implies a prior
|
type WeightInfo: WeightInfo;
|
||||||
/// `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,
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
fn on_finalize(block_number: T::BlockNumber) {
|
||||||
// check for scheduled pending authority set changes
|
// check for scheduled pending authority set changes
|
||||||
if let Some(pending_change) = <PendingChange<T>>::get() {
|
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.
|
/// Get the current set of authorities, along with their respective weights.
|
||||||
pub fn grandpa_authorities() -> AuthorityList {
|
pub fn grandpa_authorities() -> AuthorityList {
|
||||||
storage::unhashed::get_or_default::<VersionedAuthorityList>(GRANDPA_AUTHORITIES_KEY).into()
|
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
|
// NOTE: initialize first session of first set. this is necessary for
|
||||||
// the genesis set and session since we only update the set -> session
|
// the genesis set and session since we only update the set -> session
|
||||||
// mapping whenever a new session starts, i.e. through `on_new_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(
|
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;
|
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
|
where T: pallet_session::Config
|
||||||
{
|
{
|
||||||
type Key = AuthorityId;
|
type Key = AuthorityId;
|
||||||
@@ -580,7 +625,7 @@ impl<T: Config> OneSessionHandler<T::AccountId> for Module<T>
|
|||||||
};
|
};
|
||||||
|
|
||||||
if res.is_ok() {
|
if res.is_ok() {
|
||||||
CurrentSetId::mutate(|s| {
|
CurrentSetId::<T>::mutate(|s| {
|
||||||
*s += 1;
|
*s += 1;
|
||||||
*s
|
*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
|
// 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).
|
// set corresponds to the latest equivalent session (i.e. now).
|
||||||
let session_index = <pallet_session::Module<T>>::current_index();
|
let session_index = <pallet_session::Pallet<T>>::current_index();
|
||||||
SetIdSession::insert(current_set_id, &session_index);
|
SetIdSession::<T>::insert(current_set_id, &session_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_disabled(i: usize) {
|
fn on_disabled(i: usize) {
|
||||||
|
|||||||
@@ -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))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -64,7 +64,7 @@ frame_support::construct_runtime!(
|
|||||||
|
|
||||||
impl_opaque_keys! {
|
impl_opaque_keys! {
|
||||||
pub struct TestSessionKeys {
|
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" }
|
frame-system = { version = "3.0.0", default-features = false, path = "../../system" }
|
||||||
pallet-babe = { version = "3.0.0", default-features = false, path = "../../babe" }
|
pallet-babe = { version = "3.0.0", default-features = false, path = "../../babe" }
|
||||||
pallet-balances = { version = "3.0.0", default-features = false, path = "../../balances" }
|
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-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-offences = { version = "3.0.0", default-features = false, features = ["runtime-benchmarks"], path = "../../offences" }
|
||||||
pallet-session = { version = "3.0.0", default-features = false, path = "../../session" }
|
pallet-session = { version = "3.0.0", default-features = false, path = "../../session" }
|
||||||
|
|||||||
Reference in New Issue
Block a user