mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 07:01:03 +00:00
Adds propose parachain pallet (#2243)
* Adds propose parachain pallet * Update runtime/rococo/src/propose_parachain.rs Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com> * Fix runtime benchmarks * Get rid of staking * Fix benchmarking feature.. * Remove accidentally added crate * Bump Rococo spec_version Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>
This commit is contained in:
Generated
+1
@@ -6520,6 +6520,7 @@ dependencies = [
|
|||||||
"frame-support",
|
"frame-support",
|
||||||
"frame-system",
|
"frame-system",
|
||||||
"frame-system-rpc-runtime-api",
|
"frame-system-rpc-runtime-api",
|
||||||
|
"hex-literal",
|
||||||
"pallet-authority-discovery",
|
"pallet-authority-discovery",
|
||||||
"pallet-authorship",
|
"pallet-authorship",
|
||||||
"pallet-babe",
|
"pallet-babe",
|
||||||
|
|||||||
@@ -103,7 +103,14 @@ db = ["service/db"]
|
|||||||
full-node = [
|
full-node = [
|
||||||
"polkadot-node-core-av-store",
|
"polkadot-node-core-av-store",
|
||||||
]
|
]
|
||||||
runtime-benchmarks = ["polkadot-runtime/runtime-benchmarks", "kusama-runtime/runtime-benchmarks", "westend-runtime/runtime-benchmarks"]
|
|
||||||
|
runtime-benchmarks = [
|
||||||
|
"polkadot-runtime/runtime-benchmarks",
|
||||||
|
"kusama-runtime/runtime-benchmarks",
|
||||||
|
"westend-runtime/runtime-benchmarks",
|
||||||
|
"rococo-runtime/runtime-benchmarks"
|
||||||
|
]
|
||||||
|
|
||||||
real-overseer = [
|
real-overseer = [
|
||||||
"polkadot-availability-bitfield-distribution",
|
"polkadot-availability-bitfield-distribution",
|
||||||
"polkadot-availability-distribution",
|
"polkadot-availability-distribution",
|
||||||
|
|||||||
@@ -856,7 +856,6 @@ fn rococo_staging_testnet_config_genesis(wasm_binary: &[u8]) -> rococo_runtime::
|
|||||||
pallet_authority_discovery: Some(rococo_runtime::AuthorityDiscoveryConfig {
|
pallet_authority_discovery: Some(rococo_runtime::AuthorityDiscoveryConfig {
|
||||||
keys: vec![],
|
keys: vec![],
|
||||||
}),
|
}),
|
||||||
pallet_staking: Some(Default::default()),
|
|
||||||
pallet_sudo: Some(rococo_runtime::SudoConfig {
|
pallet_sudo: Some(rococo_runtime::SudoConfig {
|
||||||
key: endowed_accounts[0].clone(),
|
key: endowed_accounts[0].clone(),
|
||||||
}),
|
}),
|
||||||
@@ -1343,7 +1342,6 @@ pub fn rococo_testnet_genesis(
|
|||||||
pallet_authority_discovery: Some(rococo_runtime::AuthorityDiscoveryConfig {
|
pallet_authority_discovery: Some(rococo_runtime::AuthorityDiscoveryConfig {
|
||||||
keys: vec![],
|
keys: vec![],
|
||||||
}),
|
}),
|
||||||
pallet_staking: Some(Default::default()),
|
|
||||||
pallet_sudo: Some(rococo_runtime::SudoConfig { key: root_key }),
|
pallet_sudo: Some(rococo_runtime::SudoConfig { key: root_key }),
|
||||||
parachains_configuration: Some(rococo_runtime::ParachainsConfigurationConfig {
|
parachains_configuration: Some(rococo_runtime::ParachainsConfigurationConfig {
|
||||||
config: polkadot_runtime_parachains::configuration::HostConfiguration {
|
config: polkadot_runtime_parachains::configuration::HostConfiguration {
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ pub type NegativeImbalance<T> = <pallet_balances::Module<T> as Currency<<T as fr
|
|||||||
|
|
||||||
/// The sequence of bytes a valid wasm module binary always starts with. Apart from that it's also a
|
/// The sequence of bytes a valid wasm module binary always starts with. Apart from that it's also a
|
||||||
/// valid wasm module.
|
/// valid wasm module.
|
||||||
const WASM_MAGIC: &[u8] = &[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00];
|
pub const WASM_MAGIC: &[u8] = &[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00];
|
||||||
|
|
||||||
/// We assume that an on-initialize consumes 2.5% of the weight on average, hence a single extrinsic
|
/// We assume that an on-initialize consumes 2.5% of the weight on average, hence a single extrinsic
|
||||||
/// will not be allowed to consume more than `AvailableBlockRatio - 2.5%`.
|
/// will not be allowed to consume more than `AvailableBlockRatio - 2.5%`.
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ decl_storage! {
|
|||||||
|
|
||||||
/// Upcoming paras (chains and threads). These are only updated on session change. Corresponds to an
|
/// Upcoming paras (chains and threads). These are only updated on session change. Corresponds to an
|
||||||
/// entry in the upcoming-genesis map.
|
/// entry in the upcoming-genesis map.
|
||||||
UpcomingParas: Vec<ParaId>;
|
UpcomingParas get(fn upcoming_paras): Vec<ParaId>;
|
||||||
/// Upcoming paras instantiation arguments.
|
/// Upcoming paras instantiation arguments.
|
||||||
UpcomingParasGenesis: map hasher(twox_64_concat) ParaId => Option<ParaGenesisArgs>;
|
UpcomingParasGenesis: map hasher(twox_64_concat) ParaId => Option<ParaGenesisArgs>;
|
||||||
/// Paras that are to be cleaned up at the end of the session.
|
/// Paras that are to be cleaned up at the end of the session.
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ parity-scale-codec = { version = "1.3.6", default-features = false, features = [
|
|||||||
serde = { version = "1.0.118", default-features = false }
|
serde = { version = "1.0.118", default-features = false }
|
||||||
serde_derive = { version = "1.0.117", optional = true }
|
serde_derive = { version = "1.0.117", optional = true }
|
||||||
smallvec = "1.6.1"
|
smallvec = "1.6.1"
|
||||||
|
hex-literal = "0.3.1"
|
||||||
|
|
||||||
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||||
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||||
@@ -113,3 +114,16 @@ std = [
|
|||||||
# runtime without clashing with the runtime api exported functions
|
# runtime without clashing with the runtime api exported functions
|
||||||
# in WASM.
|
# in WASM.
|
||||||
disable-runtime-api = []
|
disable-runtime-api = []
|
||||||
|
runtime-benchmarks = [
|
||||||
|
"runtime-common/runtime-benchmarks",
|
||||||
|
"frame-support/runtime-benchmarks",
|
||||||
|
"frame-system/runtime-benchmarks",
|
||||||
|
"sp-runtime/runtime-benchmarks",
|
||||||
|
"pallet-babe/runtime-benchmarks",
|
||||||
|
"pallet-balances/runtime-benchmarks",
|
||||||
|
"pallet-grandpa/runtime-benchmarks",
|
||||||
|
"pallet-im-online/runtime-benchmarks",
|
||||||
|
"pallet-indices/runtime-benchmarks",
|
||||||
|
"pallet-staking/runtime-benchmarks",
|
||||||
|
"pallet-timestamp/runtime-benchmarks",
|
||||||
|
]
|
||||||
|
|||||||
@@ -32,22 +32,18 @@ use primitives::v1::{
|
|||||||
SessionInfo as SessionInfoData,
|
SessionInfo as SessionInfoData,
|
||||||
};
|
};
|
||||||
use runtime_common::{
|
use runtime_common::{
|
||||||
SlowAdjustingFeeUpdate,
|
SlowAdjustingFeeUpdate, impls::ToAuthor, BlockHashCount, BlockWeights, BlockLength, RocksDbWeight,
|
||||||
impls::ToAuthor,
|
|
||||||
BlockHashCount, BlockWeights, BlockLength, RocksDbWeight, OffchainSolutionWeightLimit,
|
|
||||||
};
|
};
|
||||||
use runtime_parachains::{
|
use runtime_parachains::{
|
||||||
self,
|
self,
|
||||||
runtime_api_impl::v1 as runtime_api_impl,
|
runtime_api_impl::v1 as runtime_api_impl,
|
||||||
};
|
};
|
||||||
use frame_support::{
|
use frame_support::{
|
||||||
parameter_types, construct_runtime, debug,
|
parameter_types, construct_runtime, debug, traits::{KeyOwnerProofSystem, Filter, EnsureOrigin}, weights::Weight,
|
||||||
traits::{KeyOwnerProofSystem, Filter},
|
|
||||||
weights::Weight,
|
|
||||||
};
|
};
|
||||||
use sp_runtime::{
|
use sp_runtime::{
|
||||||
create_runtime_str, generic, impl_opaque_keys,
|
create_runtime_str, generic, impl_opaque_keys,
|
||||||
ApplyExtrinsicResult, KeyTypeId, Perbill, curve::PiecewiseLinear,
|
ApplyExtrinsicResult, KeyTypeId, Perbill,
|
||||||
transaction_validity::{TransactionValidity, TransactionSource, TransactionPriority},
|
transaction_validity::{TransactionValidity, TransactionSource, TransactionPriority},
|
||||||
traits::{
|
traits::{
|
||||||
BlakeTwo256, Block as BlockT, OpaqueKeys, IdentityLookup,
|
BlakeTwo256, Block as BlockT, OpaqueKeys, IdentityLookup,
|
||||||
@@ -64,7 +60,7 @@ use pallet_grandpa::{AuthorityId as GrandpaId, fg_primitives};
|
|||||||
use sp_core::OpaqueMetadata;
|
use sp_core::OpaqueMetadata;
|
||||||
use sp_staking::SessionIndex;
|
use sp_staking::SessionIndex;
|
||||||
use pallet_session::historical as session_historical;
|
use pallet_session::historical as session_historical;
|
||||||
use frame_system::EnsureRoot;
|
use frame_system::{EnsureRoot, EnsureOneOf, EnsureSigned};
|
||||||
use runtime_common::{paras_sudo_wrapper, paras_registrar};
|
use runtime_common::{paras_sudo_wrapper, paras_registrar};
|
||||||
|
|
||||||
use runtime_parachains::origin as parachains_origin;
|
use runtime_parachains::origin as parachains_origin;
|
||||||
@@ -78,10 +74,8 @@ use runtime_parachains::dmp as parachains_dmp;
|
|||||||
use runtime_parachains::ump as parachains_ump;
|
use runtime_parachains::ump as parachains_ump;
|
||||||
use runtime_parachains::hrmp as parachains_hrmp;
|
use runtime_parachains::hrmp as parachains_hrmp;
|
||||||
use runtime_parachains::scheduler as parachains_scheduler;
|
use runtime_parachains::scheduler as parachains_scheduler;
|
||||||
use runtime_parachains::reward_points::RewardValidatorsWithEraPoints;
|
|
||||||
|
|
||||||
pub use pallet_balances::Call as BalancesCall;
|
pub use pallet_balances::Call as BalancesCall;
|
||||||
pub use pallet_staking::StakerStatus;
|
|
||||||
|
|
||||||
use polkadot_parachain::primitives::Id as ParaId;
|
use polkadot_parachain::primitives::Id as ParaId;
|
||||||
use xcm::v0::{MultiLocation, NetworkId};
|
use xcm::v0::{MultiLocation, NetworkId};
|
||||||
@@ -91,10 +85,11 @@ use xcm_builder::{
|
|||||||
CurrencyAdapter as XcmCurrencyAdapter, ChildParachainAsNative,
|
CurrencyAdapter as XcmCurrencyAdapter, ChildParachainAsNative,
|
||||||
SignedAccountId32AsNative, ChildSystemParachainAsSuperuser, LocationInverter,
|
SignedAccountId32AsNative, ChildSystemParachainAsSuperuser, LocationInverter,
|
||||||
};
|
};
|
||||||
|
use constants::{time::*, currency::*, fee::*};
|
||||||
|
|
||||||
/// Constant values used within the runtime.
|
/// Constant values used within the runtime.
|
||||||
pub mod constants;
|
pub mod constants;
|
||||||
use constants::{time::*, currency::*, fee::*};
|
mod propose_parachain;
|
||||||
|
|
||||||
// Make the WASM binary available.
|
// Make the WASM binary available.
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
@@ -105,7 +100,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
|
|||||||
spec_name: create_runtime_str!("rococo"),
|
spec_name: create_runtime_str!("rococo"),
|
||||||
impl_name: create_runtime_str!("parity-rococo-v1"),
|
impl_name: create_runtime_str!("parity-rococo-v1"),
|
||||||
authoring_version: 0,
|
authoring_version: 0,
|
||||||
spec_version: 14,
|
spec_version: 15,
|
||||||
impl_version: 0,
|
impl_version: 0,
|
||||||
#[cfg(not(feature = "disable-runtime-api"))]
|
#[cfg(not(feature = "disable-runtime-api"))]
|
||||||
apis: RUNTIME_API_VERSIONS,
|
apis: RUNTIME_API_VERSIONS,
|
||||||
@@ -182,7 +177,6 @@ construct_runtime! {
|
|||||||
|
|
||||||
// Consensus support.
|
// Consensus support.
|
||||||
Authorship: pallet_authorship::{Module, Call, Storage},
|
Authorship: pallet_authorship::{Module, Call, Storage},
|
||||||
Staking: pallet_staking::{Module, Call, Storage, Config<T>, Event<T>, ValidateUnsigned},
|
|
||||||
Offences: pallet_offences::{Module, Call, Storage, Event},
|
Offences: pallet_offences::{Module, Call, Storage, Event},
|
||||||
Historical: session_historical::{Module},
|
Historical: session_historical::{Module},
|
||||||
Session: pallet_session::{Module, Call, Storage, Event, Config<T>},
|
Session: pallet_session::{Module, Call, Storage, Event, Config<T>},
|
||||||
@@ -208,6 +202,9 @@ construct_runtime! {
|
|||||||
|
|
||||||
// Sudo
|
// Sudo
|
||||||
Sudo: pallet_sudo::{Module, Call, Storage, Event<T>, Config<T>},
|
Sudo: pallet_sudo::{Module, Call, Storage, Event<T>, Config<T>},
|
||||||
|
|
||||||
|
// Propose parachain pallet.
|
||||||
|
ProposeParachain: propose_parachain::{Module, Call, Storage, Event},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,35 +301,15 @@ impl frame_system::offchain::SigningTypes for Runtime {
|
|||||||
type Signature = Signature;
|
type Signature = Signature;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Special `FullIdentificationOf` implementation that is returning for every input `Some(Default::default())`.
|
||||||
|
pub struct FullIdentificationOf;
|
||||||
|
impl sp_runtime::traits::Convert<AccountId, Option<()>> for FullIdentificationOf {
|
||||||
|
fn convert(_: AccountId) -> Option<()> { Some(Default::default()) }
|
||||||
|
}
|
||||||
|
|
||||||
impl pallet_session::historical::Config for Runtime {
|
impl pallet_session::historical::Config for Runtime {
|
||||||
type FullIdentification = pallet_staking::Exposure<AccountId, Balance>;
|
type FullIdentification = ();
|
||||||
type FullIdentificationOf = pallet_staking::ExposureOf<Runtime>;
|
type FullIdentificationOf = FullIdentificationOf;
|
||||||
}
|
|
||||||
|
|
||||||
pallet_staking_reward_curve::build! {
|
|
||||||
const REWARD_CURVE: PiecewiseLinear<'static> = curve!(
|
|
||||||
min_inflation: 0_025_000,
|
|
||||||
max_inflation: 0_100_000,
|
|
||||||
ideal_stake: 0_500_000,
|
|
||||||
falloff: 0_050_000,
|
|
||||||
max_piece_count: 40,
|
|
||||||
test_precision: 0_005_000,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
parameter_types! {
|
|
||||||
// Six sessions in an era (6 hours).
|
|
||||||
pub const SessionsPerEra: SessionIndex = 6;
|
|
||||||
// 28 eras for unbonding (7 days).
|
|
||||||
pub const BondingDuration: pallet_staking::EraIndex = 28;
|
|
||||||
// 27 eras in which slashes can be cancelled (~7 days).
|
|
||||||
pub const SlashDeferDuration: pallet_staking::EraIndex = 27;
|
|
||||||
pub const RewardCurve: &'static PiecewiseLinear<'static> = &REWARD_CURVE;
|
|
||||||
pub const MaxNominatorRewardedPerValidator: u32 = 64;
|
|
||||||
// quarter of the last session will be for election.
|
|
||||||
pub ElectionLookahead: BlockNumber = EpochDurationInBlocks::get() / 4;
|
|
||||||
pub const MaxIterations: u32 = 10;
|
|
||||||
pub MinSolutionScoreBump: Perbill = Perbill::from_rational_approximation(5u32, 10_000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
parameter_types! {
|
parameter_types! {
|
||||||
@@ -353,32 +330,6 @@ impl pallet_im_online::Config for Runtime {
|
|||||||
type WeightInfo = ();
|
type WeightInfo = ();
|
||||||
}
|
}
|
||||||
|
|
||||||
impl pallet_staking::Config for Runtime {
|
|
||||||
type Currency = Balances;
|
|
||||||
type UnixTime = Timestamp;
|
|
||||||
type CurrencyToVote = frame_support::traits::U128CurrencyToVote;
|
|
||||||
type RewardRemainder = ();
|
|
||||||
type Event = Event;
|
|
||||||
type Slash = ();
|
|
||||||
type Reward = ();
|
|
||||||
type SessionsPerEra = SessionsPerEra;
|
|
||||||
type BondingDuration = BondingDuration;
|
|
||||||
type SlashDeferDuration = SlashDeferDuration;
|
|
||||||
// A majority of the council can cancel the slash.
|
|
||||||
type SlashCancelOrigin = EnsureRoot<AccountId>;
|
|
||||||
type SessionInterface = Self;
|
|
||||||
type RewardCurve = RewardCurve;
|
|
||||||
type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator;
|
|
||||||
type NextNewSession = Session;
|
|
||||||
type ElectionLookahead = ElectionLookahead;
|
|
||||||
type Call = Call;
|
|
||||||
type UnsignedPriority = StakingUnsignedPriority;
|
|
||||||
type MaxIterations = MaxIterations;
|
|
||||||
type OffchainSolutionWeightLimit = OffchainSolutionWeightLimit;
|
|
||||||
type MinSolutionScoreBump = MinSolutionScoreBump;
|
|
||||||
type WeightInfo = ();
|
|
||||||
}
|
|
||||||
|
|
||||||
parameter_types! {
|
parameter_types! {
|
||||||
pub const ExistentialDeposit: Balance = 1 * CENTS;
|
pub const ExistentialDeposit: Balance = 1 * CENTS;
|
||||||
pub const MaxLocks: u32 = 50;
|
pub const MaxLocks: u32 = 50;
|
||||||
@@ -414,7 +365,7 @@ parameter_types! {
|
|||||||
impl pallet_offences::Config for Runtime {
|
impl pallet_offences::Config for Runtime {
|
||||||
type Event = Event;
|
type Event = Event;
|
||||||
type IdentificationTuple = pallet_session::historical::IdentificationTuple<Self>;
|
type IdentificationTuple = pallet_session::historical::IdentificationTuple<Self>;
|
||||||
type OnOffenceHandler = Staking;
|
type OnOffenceHandler = ();
|
||||||
type WeightSoftLimit = OffencesWeightSoftLimit;
|
type WeightSoftLimit = OffencesWeightSoftLimit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -445,13 +396,19 @@ parameter_types! {
|
|||||||
pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(17);
|
pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(17);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Special `ValidatorIdOf` implementation that is just returning the input as result.
|
||||||
|
pub struct ValidatorIdOf;
|
||||||
|
impl sp_runtime::traits::Convert<AccountId, Option<AccountId>> for ValidatorIdOf {
|
||||||
|
fn convert(a: AccountId) -> Option<AccountId> { Some(a) }
|
||||||
|
}
|
||||||
|
|
||||||
impl pallet_session::Config for Runtime {
|
impl pallet_session::Config for Runtime {
|
||||||
type Event = Event;
|
type Event = Event;
|
||||||
type ValidatorId = AccountId;
|
type ValidatorId = AccountId;
|
||||||
type ValidatorIdOf = pallet_staking::StashOf<Self>;
|
type ValidatorIdOf = ValidatorIdOf;
|
||||||
type ShouldEndSession = Babe;
|
type ShouldEndSession = Babe;
|
||||||
type NextSessionRotation = Babe;
|
type NextSessionRotation = Babe;
|
||||||
type SessionManager = pallet_session::historical::NoteHistoricalRoot<Self, Staking>;
|
type SessionManager = pallet_session::historical::NoteHistoricalRoot<Self, ProposeParachain>;
|
||||||
type SessionHandler = <SessionKeys as OpaqueKeys>::KeyTypeIdProviders;
|
type SessionHandler = <SessionKeys as OpaqueKeys>::KeyTypeIdProviders;
|
||||||
type Keys = SessionKeys;
|
type Keys = SessionKeys;
|
||||||
type DisabledValidatorsThreshold = DisabledValidatorsThreshold;
|
type DisabledValidatorsThreshold = DisabledValidatorsThreshold;
|
||||||
@@ -531,16 +488,23 @@ impl pallet_authorship::Config for Runtime {
|
|||||||
type FindAuthor = pallet_session::FindAccountFromAuthorIndex<Self, Babe>;
|
type FindAuthor = pallet_session::FindAccountFromAuthorIndex<Self, Babe>;
|
||||||
type UncleGenerations = UncleGenerations;
|
type UncleGenerations = UncleGenerations;
|
||||||
type FilterUncle = ();
|
type FilterUncle = ();
|
||||||
type EventHandler = (Staking, ImOnline);
|
type EventHandler = ImOnline;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl parachains_origin::Config for Runtime {}
|
impl parachains_origin::Config for Runtime {}
|
||||||
|
|
||||||
impl parachains_configuration::Config for Runtime {}
|
impl parachains_configuration::Config for Runtime {}
|
||||||
|
|
||||||
|
/// Special `RewardValidators` that does nothing ;)
|
||||||
|
pub struct RewardValidators;
|
||||||
|
impl runtime_parachains::inclusion::RewardValidators for RewardValidators {
|
||||||
|
fn reward_backing(_: impl IntoIterator<Item=ValidatorIndex>) {}
|
||||||
|
fn reward_bitfields(_: impl IntoIterator<Item=ValidatorIndex>) {}
|
||||||
|
}
|
||||||
|
|
||||||
impl parachains_inclusion::Config for Runtime {
|
impl parachains_inclusion::Config for Runtime {
|
||||||
type Event = Event;
|
type Event = Event;
|
||||||
type RewardValidators = RewardValidatorsWithEraPoints<Runtime>;
|
type RewardValidators = RewardValidators;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl parachains_paras::Config for Runtime {
|
impl parachains_paras::Config for Runtime {
|
||||||
@@ -621,6 +585,41 @@ impl pallet_sudo::Config for Runtime {
|
|||||||
type Call = Call;
|
type Call = Call;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Priviledged origin used by propose parachain.
|
||||||
|
pub struct PriviledgedOrigin;
|
||||||
|
|
||||||
|
impl EnsureOrigin<Origin> for PriviledgedOrigin {
|
||||||
|
type Success = ();
|
||||||
|
|
||||||
|
fn try_origin(o: Origin) -> Result<Self::Success, Origin> {
|
||||||
|
let allowed = [
|
||||||
|
hex_literal::hex!("b44c58e50328768ac06ed44b842bfa69d86ea10f60bc36156c9ffc5e00867220"),
|
||||||
|
hex_literal::hex!("762a6a38ba72b139cba285a39a6766e02046fb023f695f5ecf7f48b037c0dd6b")
|
||||||
|
];
|
||||||
|
|
||||||
|
let origin = o.clone();
|
||||||
|
match EnsureSigned::try_origin(o) {
|
||||||
|
Ok(who) if allowed.iter().any(|a| a == &who.as_ref()) => Ok(()),
|
||||||
|
_ => Err(origin),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "runtime-benchmarks")]
|
||||||
|
fn successful_origin() -> Origin { Origin::root() }
|
||||||
|
}
|
||||||
|
|
||||||
|
parameter_types! {
|
||||||
|
pub const ProposeDeposit: Balance = 1000 * DOLLARS;
|
||||||
|
pub const MaxNameLength: u32 = 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl propose_parachain::Config for Runtime {
|
||||||
|
type Event = Event;
|
||||||
|
type MaxNameLength = MaxNameLength;
|
||||||
|
type ProposeDeposit = ProposeDeposit;
|
||||||
|
type PriviledgedOrigin = EnsureOneOf<AccountId, EnsureRoot<AccountId>, PriviledgedOrigin>;
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "disable-runtime-api"))]
|
#[cfg(not(feature = "disable-runtime-api"))]
|
||||||
sp_api::impl_runtime_apis! {
|
sp_api::impl_runtime_apis! {
|
||||||
impl sp_api::Core<Block> for Runtime {
|
impl sp_api::Core<Block> for Runtime {
|
||||||
|
|||||||
@@ -0,0 +1,380 @@
|
|||||||
|
// Copyright 2020 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Polkadot.
|
||||||
|
|
||||||
|
// Polkadot is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Polkadot is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
//! A pallet for proposing a parachain for Rococo.
|
||||||
|
//!
|
||||||
|
//! This pallet works as registration of parachains for Rococo. The idea is to have
|
||||||
|
//! the registration of community provides parachains being handled by this pallet.
|
||||||
|
//! People will be able to propose their parachain for registration. This proposal
|
||||||
|
//! will need to be improved by some priviledged account. After approval the workflow
|
||||||
|
//! is the following:
|
||||||
|
//!
|
||||||
|
//! 1. On start of the next session the pallet announces the new relay chain validators.
|
||||||
|
//!
|
||||||
|
//! 2. The session after announcing the new relay chain validators, they will be active. At the
|
||||||
|
//! switch to this session, the parachain will be registered and is allowed to produce blocks.
|
||||||
|
//!
|
||||||
|
//! When deregistering a parachain, we basically reverse the operations.
|
||||||
|
|
||||||
|
use frame_support::{
|
||||||
|
decl_event, decl_error, decl_module, traits::{Get, ReservableCurrency, EnsureOrigin, Currency},
|
||||||
|
decl_storage, ensure, IterableStorageMap,
|
||||||
|
};
|
||||||
|
use primitives::v1::{Id as ParaId, HeadData, ValidationCode};
|
||||||
|
use polkadot_parachain::primitives::AccountIdConversion;
|
||||||
|
use frame_system::{ensure_signed, EnsureOneOf, EnsureSigned};
|
||||||
|
use sp_runtime::Either;
|
||||||
|
use sp_staking::SessionIndex;
|
||||||
|
use sp_std::vec::Vec;
|
||||||
|
use runtime_parachains::paras::ParaGenesisArgs;
|
||||||
|
|
||||||
|
type EnsurePriviledgedOrSigned<T> = EnsureOneOf<
|
||||||
|
<T as frame_system::Config>::AccountId,
|
||||||
|
<T as Config>::PriviledgedOrigin,
|
||||||
|
EnsureSigned<<T as frame_system::Config>::AccountId>
|
||||||
|
>;
|
||||||
|
|
||||||
|
type Session<T> = pallet_session::Module<T>;
|
||||||
|
|
||||||
|
type BalanceOf<T> = <T as pallet_balances::Config>::Balance;
|
||||||
|
|
||||||
|
/// Configuration for the parachain proposer.
|
||||||
|
pub trait Config: pallet_session::Config
|
||||||
|
+ pallet_balances::Config
|
||||||
|
+ pallet_balances::Config
|
||||||
|
+ runtime_parachains::paras::Config
|
||||||
|
+ runtime_parachains::dmp::Config
|
||||||
|
+ runtime_parachains::ump::Config
|
||||||
|
+ runtime_parachains::hrmp::Config
|
||||||
|
{
|
||||||
|
/// The overreaching event type.
|
||||||
|
type Event: From<Event> + Into<<Self as frame_system::Config>::Event>;
|
||||||
|
|
||||||
|
/// The maximum name length of a parachain.
|
||||||
|
type MaxNameLength: Get<u32>;
|
||||||
|
|
||||||
|
/// The amount that should be deposited when creating a proposal.
|
||||||
|
type ProposeDeposit: Get<BalanceOf<Self>>;
|
||||||
|
|
||||||
|
/// Priviledged origin that can approve/cancel/deregister parachain and proposals.
|
||||||
|
type PriviledgedOrigin: EnsureOrigin<<Self as frame_system::Config>::Origin>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A proposal for adding a parachain to the relay chain.
|
||||||
|
#[derive(parity_scale_codec::Encode, parity_scale_codec::Decode)]
|
||||||
|
struct Proposal<AccountId, ValidatorId, Balance> {
|
||||||
|
/// The account that proposed this parachain.
|
||||||
|
proposer: AccountId,
|
||||||
|
/// The validation WASM code of the parachain.
|
||||||
|
validation_code: ValidationCode,
|
||||||
|
/// The genesis head state of the parachain.
|
||||||
|
genesis_head: HeadData,
|
||||||
|
/// The validators for the relay chain provided by the parachain.
|
||||||
|
validators: Vec<ValidatorId>,
|
||||||
|
/// The name of the parachain.
|
||||||
|
name: Vec<u8>,
|
||||||
|
/// The balance that the parachain should receive.
|
||||||
|
balance: Balance,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Information about the registered parachain.
|
||||||
|
#[derive(parity_scale_codec::Encode, parity_scale_codec::Decode)]
|
||||||
|
struct RegisteredParachainInfo<AccountId, ValidatorId> {
|
||||||
|
/// The validators for the relay chain provided by the parachain.
|
||||||
|
validators: Vec<ValidatorId>,
|
||||||
|
/// The account that proposed the parachain.
|
||||||
|
proposer: AccountId,
|
||||||
|
}
|
||||||
|
|
||||||
|
decl_event! {
|
||||||
|
pub enum Event {
|
||||||
|
/// A parachain was proposed for registration.
|
||||||
|
ParachainProposed(Vec<u8>, ParaId),
|
||||||
|
/// A parachain was approved and is scheduled for being activated.
|
||||||
|
ParachainApproved(ParaId),
|
||||||
|
/// A parachain was registered and is now running.
|
||||||
|
ParachainRegistered(ParaId),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
decl_error! {
|
||||||
|
pub enum Error for Module<T: Config> {
|
||||||
|
/// The name of the parachain is too long.
|
||||||
|
NameTooLong,
|
||||||
|
/// The requested parachain id is already registered.
|
||||||
|
ParachainIdAlreadyTaken,
|
||||||
|
/// The requested parachain id is already proposed for another parachain.
|
||||||
|
ParachainIdAlreadyProposed,
|
||||||
|
/// Could not find the parachain proposal.
|
||||||
|
ProposalNotFound,
|
||||||
|
/// Not authorized to do a certain operation.
|
||||||
|
NotAuthorized,
|
||||||
|
/// A validator is already registered in the active validator set.
|
||||||
|
ValidatorAlreadyRegistered,
|
||||||
|
/// No information about the registered parachain found.
|
||||||
|
ParachainInfoNotFound,
|
||||||
|
/// Parachain is already approved for registration.
|
||||||
|
ParachainAlreadyApproved,
|
||||||
|
/// Parachain is already scheduled for registration.
|
||||||
|
ParachainAlreadyScheduled,
|
||||||
|
/// The given WASM blob is definitley not valid.
|
||||||
|
DefinitelyNotWasm,
|
||||||
|
/// Registration requires at least one validator.
|
||||||
|
AtLeastOneValidatorRequired,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
decl_storage! {
|
||||||
|
trait Store for Module<T: Config> as ParachainProposer {
|
||||||
|
/// All the proposals.
|
||||||
|
Proposals: map hasher(twox_64_concat) ParaId => Option<Proposal<T::AccountId, T::ValidatorId, BalanceOf<T>>>;
|
||||||
|
/// Proposals that are approved.
|
||||||
|
ApprovedProposals: Vec<ParaId>;
|
||||||
|
/// Proposals that are scheduled at for a fixed session to be applied.
|
||||||
|
ScheduledProposals: map hasher(twox_64_concat) SessionIndex => Vec<ParaId>;
|
||||||
|
/// Information about the registered parachains.
|
||||||
|
ParachainInfo: map hasher(twox_64_concat) ParaId => Option<RegisteredParachainInfo<T::AccountId, T::ValidatorId>>;
|
||||||
|
/// Validators that should be retired, because their Parachain was deregistered.
|
||||||
|
ValidatorsToRetire: Vec<T::ValidatorId>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
decl_module! {
|
||||||
|
pub struct Module<T: Config> for enum Call where origin: <T as frame_system::Config>::Origin {
|
||||||
|
type Error = Error<T>;
|
||||||
|
|
||||||
|
/// The maximum name length of a parachain.
|
||||||
|
const MaxNameLength: u32 = T::MaxNameLength::get();
|
||||||
|
|
||||||
|
/// The deposit that will be reserved when proposing a parachain.
|
||||||
|
const ProposeDeposit: BalanceOf<T> = T::ProposeDeposit::get();
|
||||||
|
|
||||||
|
fn deposit_event() = default;
|
||||||
|
|
||||||
|
/// Propose a new parachain
|
||||||
|
///
|
||||||
|
/// This requires:
|
||||||
|
/// - `para_id`: The id of the parachain.
|
||||||
|
/// - `name`: The name of the parachain.
|
||||||
|
/// - `validation_function`: The wasm runtime of the parachain.
|
||||||
|
/// - `initial_head_state`: The genesis state of the parachain.
|
||||||
|
/// - `validators`: Validators that will validate for the relay chain, needs to be at least one.
|
||||||
|
/// - `balance`: The initial balance of the parachain on the relay chain.
|
||||||
|
///
|
||||||
|
/// It will reserve a deposit from the sender account over the lifetime of the chain.
|
||||||
|
#[weight = 1_000_000]
|
||||||
|
fn propose_parachain(
|
||||||
|
origin,
|
||||||
|
para_id: ParaId,
|
||||||
|
name: Vec<u8>,
|
||||||
|
validation_code: ValidationCode,
|
||||||
|
genesis_head: HeadData,
|
||||||
|
validators: Vec<T::ValidatorId>,
|
||||||
|
balance: BalanceOf<T>,
|
||||||
|
) {
|
||||||
|
let who = ensure_signed(origin)?;
|
||||||
|
|
||||||
|
ensure!(name.len() <= T::MaxNameLength::get() as usize, Error::<T>::NameTooLong);
|
||||||
|
ensure!(validators.len() > 0, Error::<T>::AtLeastOneValidatorRequired);
|
||||||
|
ensure!(!Proposals::<T>::contains_key(¶_id), Error::<T>::ParachainIdAlreadyProposed);
|
||||||
|
ensure!(
|
||||||
|
!runtime_parachains::paras::Module::<T>::parachains().contains(¶_id),
|
||||||
|
Error::<T>::ParachainIdAlreadyTaken,
|
||||||
|
);
|
||||||
|
ensure!(
|
||||||
|
!runtime_parachains::paras::Module::<T>::upcoming_paras().contains(¶_id),
|
||||||
|
Error::<T>::ParachainIdAlreadyTaken,
|
||||||
|
);
|
||||||
|
ensure!(validation_code.0.starts_with(runtime_common::WASM_MAGIC), Error::<T>::DefinitelyNotWasm);
|
||||||
|
|
||||||
|
let active_validators = Session::<T>::validators();
|
||||||
|
ensure!(
|
||||||
|
validators.iter().all(|v| !active_validators.contains(v)),
|
||||||
|
Error::<T>::ValidatorAlreadyRegistered,
|
||||||
|
);
|
||||||
|
Proposals::<T>::iter().try_for_each(|(_, prop)|
|
||||||
|
if validators.iter().all(|v| !prop.validators.contains(v)) {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(Error::<T>::ValidatorAlreadyRegistered)
|
||||||
|
}
|
||||||
|
)?;
|
||||||
|
|
||||||
|
pallet_balances::Module::<T>::reserve(&who, T::ProposeDeposit::get())?;
|
||||||
|
|
||||||
|
let proposal = Proposal {
|
||||||
|
name: name.clone(),
|
||||||
|
proposer: who,
|
||||||
|
validators: validators.into(),
|
||||||
|
genesis_head,
|
||||||
|
validation_code,
|
||||||
|
balance,
|
||||||
|
};
|
||||||
|
|
||||||
|
Proposals::<T>::insert(para_id, proposal);
|
||||||
|
|
||||||
|
Self::deposit_event(Event::ParachainProposed(name, para_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Approve a parachain proposal.
|
||||||
|
#[weight = 100_000]
|
||||||
|
fn approve_proposal(
|
||||||
|
origin,
|
||||||
|
para_id: ParaId,
|
||||||
|
) {
|
||||||
|
T::PriviledgedOrigin::ensure_origin(origin)?;
|
||||||
|
|
||||||
|
ensure!(Proposals::<T>::contains_key(¶_id), Error::<T>::ProposalNotFound);
|
||||||
|
|
||||||
|
Self::is_approved_or_scheduled(para_id)?;
|
||||||
|
|
||||||
|
ApprovedProposals::append(para_id);
|
||||||
|
|
||||||
|
Self::deposit_event(Event::ParachainApproved(para_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Cancel a parachain proposal.
|
||||||
|
///
|
||||||
|
/// This also unreserves the deposit.
|
||||||
|
#[weight = 100_000]
|
||||||
|
fn cancel_proposal(origin, para_id: ParaId) {
|
||||||
|
let who = match EnsurePriviledgedOrSigned::<T>::ensure_origin(origin)? {
|
||||||
|
Either::Left(_) => None,
|
||||||
|
Either::Right(who) => Some(who),
|
||||||
|
};
|
||||||
|
|
||||||
|
Self::is_approved_or_scheduled(para_id)?;
|
||||||
|
|
||||||
|
let proposal = Proposals::<T>::get(¶_id).ok_or(Error::<T>::ProposalNotFound)?;
|
||||||
|
|
||||||
|
if let Some(who) = who {
|
||||||
|
ensure!(who == proposal.proposer, Error::<T>::NotAuthorized);
|
||||||
|
}
|
||||||
|
|
||||||
|
Proposals::<T>::remove(¶_id);
|
||||||
|
|
||||||
|
pallet_balances::Module::<T>::unreserve(&proposal.proposer, T::ProposeDeposit::get());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deregister a parachain that was already successfully registered in the relay chain.
|
||||||
|
#[weight = 100_000]
|
||||||
|
fn deregister_parachain(origin, para_id: ParaId) {
|
||||||
|
let who = match EnsurePriviledgedOrSigned::<T>::ensure_origin(origin)? {
|
||||||
|
Either::Left(_) => None,
|
||||||
|
Either::Right(who) => Some(who),
|
||||||
|
};
|
||||||
|
|
||||||
|
let info = ParachainInfo::<T>::get(¶_id).ok_or(Error::<T>::ParachainInfoNotFound)?;
|
||||||
|
|
||||||
|
if let Some(who) = who {
|
||||||
|
ensure!(who == info.proposer, Error::<T>::NotAuthorized);
|
||||||
|
}
|
||||||
|
|
||||||
|
ParachainInfo::<T>::remove(¶_id);
|
||||||
|
info.validators.into_iter().for_each(|v| ValidatorsToRetire::<T>::append(v));
|
||||||
|
runtime_parachains::schedule_para_cleanup::<T>(para_id);
|
||||||
|
|
||||||
|
pallet_balances::Module::<T>::unreserve(&info.proposer, T::ProposeDeposit::get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Config> Module<T> {
|
||||||
|
/// Returns wether the given `para_id` approval is approved or already scheduled.
|
||||||
|
fn is_approved_or_scheduled(para_id: ParaId) -> frame_support::dispatch::DispatchResult {
|
||||||
|
if ApprovedProposals::get().iter().any(|p| *p == para_id) {
|
||||||
|
return Err(Error::<T>::ParachainAlreadyApproved.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
if ScheduledProposals::get(&Session::<T>::current_index() + 1).iter().any(|p| *p == para_id) {
|
||||||
|
return Err(Error::<T>::ParachainAlreadyScheduled.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Config> pallet_session::SessionManager<T::ValidatorId> for Module<T> {
|
||||||
|
fn new_session(new_index: SessionIndex) -> Option<Vec<T::ValidatorId>> {
|
||||||
|
if new_index <= 1 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let proposals = ApprovedProposals::take();
|
||||||
|
|
||||||
|
let mut validators = Session::<T>::validators();
|
||||||
|
|
||||||
|
ValidatorsToRetire::<T>::take().iter().for_each(|v| {
|
||||||
|
if let Some(pos) = validators.iter().position(|r| r == v) {
|
||||||
|
validators.swap_remove(pos);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Schedule all approved proposals
|
||||||
|
for (id, proposal) in proposals.iter().filter_map(|id| Proposals::<T>::get(&id).map(|p| (id, p))) {
|
||||||
|
ScheduledProposals::append(new_index, id);
|
||||||
|
|
||||||
|
let genesis = ParaGenesisArgs {
|
||||||
|
genesis_head: proposal.genesis_head,
|
||||||
|
validation_code: proposal.validation_code,
|
||||||
|
parachain: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
runtime_parachains::schedule_para_initialize::<T>(*id, genesis);
|
||||||
|
|
||||||
|
validators.extend(proposal.validators);
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(validators)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn end_session(_: SessionIndex) {}
|
||||||
|
|
||||||
|
fn start_session(start_index: SessionIndex) {
|
||||||
|
let proposals = ScheduledProposals::take(&start_index);
|
||||||
|
|
||||||
|
// Register all parachains that are allowed to start with the new session.
|
||||||
|
for (id, proposal) in proposals.iter().filter_map(|id| Proposals::<T>::take(&id).map(|p| (id, p))) {
|
||||||
|
Self::deposit_event(Event::ParachainRegistered(*id));
|
||||||
|
|
||||||
|
// Add some funds to the Parachain
|
||||||
|
let _ = pallet_balances::Module::<T>::deposit_creating(&id.into_account(), proposal.balance);
|
||||||
|
|
||||||
|
let info = RegisteredParachainInfo {
|
||||||
|
proposer: proposal.proposer,
|
||||||
|
validators: proposal.validators,
|
||||||
|
};
|
||||||
|
ParachainInfo::<T>::insert(id, info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Config> pallet_session::historical::SessionManager<T::ValidatorId, ()> for Module<T> {
|
||||||
|
fn new_session(
|
||||||
|
new_index: SessionIndex,
|
||||||
|
) -> Option<Vec<(T::ValidatorId, ())>> {
|
||||||
|
<Self as pallet_session::SessionManager<_>>::new_session(new_index)
|
||||||
|
.map(|r| r.into_iter().map(|v| (v, Default::default())).collect())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn start_session(start_index: SessionIndex) {
|
||||||
|
<Self as pallet_session::SessionManager<_>>::start_session(start_index)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn end_session(end_index: SessionIndex) {
|
||||||
|
<Self as pallet_session::SessionManager<_>>::end_session(end_index)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user