// Copyright 2019-2021 Parity Technologies (UK) Ltd.
// This file is part of Cumulus.
// Cumulus 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.
// Cumulus 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 Cumulus. If not, see .
#![cfg_attr(not(feature = "std"), no_std)]
// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.
#![recursion_limit = "256"]
// Make the WASM binary available.
#[cfg(feature = "std")]
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
use rococo_parachain_primitives::*;
use sp_api::impl_runtime_apis;
use sp_core::OpaqueMetadata;
use sp_runtime::{
create_runtime_str, generic, impl_opaque_keys,
traits::{BlakeTwo256, Block as BlockT, IdentityLookup},
transaction_validity::{TransactionSource, TransactionValidity},
ApplyExtrinsicResult,
};
use sp_std::prelude::*;
#[cfg(feature = "std")]
use sp_version::NativeVersion;
use sp_version::RuntimeVersion;
// A few exports that help ease life for downstream crates.
pub use frame_support::{
construct_runtime, parameter_types,
traits::{Randomness, IsInVec, All},
weights::{
constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
DispatchClass, IdentityFee, Weight,
},
StorageValue,
};
use frame_system::limits::{BlockLength, BlockWeights};
pub use pallet_balances::Call as BalancesCall;
pub use pallet_timestamp::Call as TimestampCall;
#[cfg(any(feature = "std", test))]
pub use sp_runtime::BuildStorage;
pub use sp_runtime::{Perbill, Permill};
// XCM imports
use polkadot_parachain::primitives::Sibling;
use xcm::v0::{Junction, MultiLocation, NetworkId};
use xcm_builder::{
AccountId32Aliases, CurrencyAdapter, LocationInverter, ParentIsDefault, RelayChainAsNative,
SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative,
SovereignSignedViaLocation, FixedRateOfConcreteFungible, EnsureXcmOrigin,
AllowTopLevelPaidExecutionFrom, TakeWeightCredit, FixedWeightBounds, IsConcrete, NativeAsset,
AllowUnpaidExecutionFrom, ParentAsSuperuser,
};
use xcm_executor::{Config, XcmExecutor};
pub type SessionHandlers = ();
impl_opaque_keys! {
pub struct SessionKeys {}
}
/// This runtime version.
pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: create_runtime_str!("cumulus-test-parachain"),
impl_name: create_runtime_str!("cumulus-test-parachain"),
authoring_version: 1,
spec_version: 18,
impl_version: 0,
apis: RUNTIME_API_VERSIONS,
transaction_version: 1,
};
pub const MILLISECS_PER_BLOCK: u64 = 6000;
pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;
pub const EPOCH_DURATION_IN_BLOCKS: u32 = 10 * MINUTES;
// These time units are defined in number of blocks.
pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);
pub const HOURS: BlockNumber = MINUTES * 60;
pub const DAYS: BlockNumber = HOURS * 24;
// 1 in 4 blocks (on average, not counting collisions) will be primary babe blocks.
pub const PRIMARY_PROBABILITY: (u64, u64) = (1, 4);
#[derive(codec::Encode, codec::Decode)]
pub enum XCMPMessage {
/// Transfer tokens to the given account from the Parachain account.
TransferToken(XAccountId, XBalance),
}
/// The version information used to identify this runtime when compiled natively.
#[cfg(feature = "std")]
pub fn native_version() -> NativeVersion {
NativeVersion {
runtime_version: VERSION,
can_author_with: Default::default(),
}
}
/// We assume that ~10% of the block weight is consumed by `on_initalize` handlers.
/// This is used to limit the maximal weight of a single extrinsic.
const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10);
/// We allow `Normal` extrinsics to fill up the block up to 75%, the rest can be used
/// by Operational extrinsics.
const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);
/// We allow for 2 seconds of compute with a 6 second average block time.
const MAXIMUM_BLOCK_WEIGHT: Weight = 2 * WEIGHT_PER_SECOND;
parameter_types! {
pub const BlockHashCount: BlockNumber = 250;
pub const Version: RuntimeVersion = VERSION;
pub RuntimeBlockLength: BlockLength =
BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);
pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()
.base_block(BlockExecutionWeight::get())
.for_class(DispatchClass::all(), |weights| {
weights.base_extrinsic = ExtrinsicBaseWeight::get();
})
.for_class(DispatchClass::Normal, |weights| {
weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);
})
.for_class(DispatchClass::Operational, |weights| {
weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);
// Operational transactions have some extra reserved space, so that they
// are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.
weights.reserved = Some(
MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT
);
})
.avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)
.build_or_panic();
pub const SS58Prefix: u8 = 42;
}
impl frame_system::Config for Runtime {
/// The identifier used to distinguish between accounts.
type AccountId = AccountId;
/// The aggregated dispatch type that is available for extrinsics.
type Call = Call;
/// The lookup mechanism to get account ID from whatever is passed in dispatchers.
type Lookup = IdentityLookup;
/// The index type for storing how many extrinsics an account has signed.
type Index = Index;
/// The index type for blocks.
type BlockNumber = BlockNumber;
/// The type for hashing blocks and tries.
type Hash = Hash;
/// The hashing algorithm used.
type Hashing = BlakeTwo256;
/// The header type.
type Header = generic::Header;
/// The ubiquitous event type.
type Event = Event;
/// The ubiquitous origin type.
type Origin = Origin;
/// Maximum number of block number to block hash mappings to keep (oldest pruned first).
type BlockHashCount = BlockHashCount;
/// Runtime version.
type Version = Version;
/// Converts a module to an index of this module in the runtime.
type PalletInfo = PalletInfo;
type AccountData = pallet_balances::AccountData;
type OnNewAccount = ();
type OnKilledAccount = ();
type DbWeight = ();
type BaseCallFilter = ();
type SystemWeightInfo = ();
type BlockWeights = RuntimeBlockWeights;
type BlockLength = RuntimeBlockLength;
type SS58Prefix = SS58Prefix;
type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode;
}
parameter_types! {
pub const MinimumPeriod: u64 = SLOT_DURATION / 2;
}
impl pallet_timestamp::Config for Runtime {
/// A timestamp: milliseconds since the unix epoch.
type Moment = u64;
type OnTimestampSet = ();
type MinimumPeriod = MinimumPeriod;
type WeightInfo = ();
}
parameter_types! {
pub const ExistentialDeposit: u128 = 500;
pub const TransferFee: u128 = 0;
pub const CreationFee: u128 = 0;
pub const TransactionByteFee: u128 = 1;
pub const MaxLocks: u32 = 50;
}
impl pallet_balances::Config for Runtime {
/// The type for recording an account's balance.
type Balance = Balance;
/// The ubiquitous event type.
type Event = Event;
type DustRemoval = ();
type ExistentialDeposit = ExistentialDeposit;
type AccountStore = System;
type WeightInfo = ();
type MaxLocks = MaxLocks;
}
impl pallet_transaction_payment::Config for Runtime {
type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter;
type TransactionByteFee = TransactionByteFee;
type WeightToFee = IdentityFee;
type FeeMultiplierUpdate = ();
}
impl pallet_sudo::Config for Runtime {
type Call = Call;
type Event = Event;
}
parameter_types! {
pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;
}
impl cumulus_pallet_parachain_system::Config for Runtime {
type Event = Event;
type OnValidationData = ();
type SelfParaId = parachain_info::Module;
type DownwardMessageHandlers = cumulus_primitives_utility::UnqueuedDmpAsParent<
MaxDownwardMessageWeight,
XcmExecutor,
Call,
>;
type OutboundXcmpMessageSource = XcmpQueue;
type XcmpMessageHandler = XcmpQueue;
type ReservedXcmpWeight = ReservedXcmpWeight;
}
impl parachain_info::Config for Runtime {}
parameter_types! {
pub const RococoLocation: MultiLocation = MultiLocation::X1(Junction::Parent);
pub const RococoNetwork: NetworkId = NetworkId::Polkadot;
pub RelayChainOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into();
pub Ancestry: MultiLocation = Junction::Parachain(
ParachainInfo::parachain_id().into()
).into();
}
/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used
/// when determining ownership of accounts for asset transacting and when attempting to use XCM
/// `Transact` in order to determine the dispatch Origin.
pub type LocationToAccountId = (
// The parent (Relay-chain) origin converts to the default `AccountId`.
ParentIsDefault,
// Sibling parachain origins convert to AccountId via the `ParaId::into`.
SiblingParachainConvertsVia,
// Straight up local `AccountId32` origins just alias directly to `AccountId`.
AccountId32Aliases,
);
/// Means for transacting assets on this chain.
pub type LocalAssetTransactor = CurrencyAdapter<
// Use this currency:
Balances,
// Use this currency when it is a fungible asset matching the given location or name:
IsConcrete,
// Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID:
LocationToAccountId,
// Our chain's account ID type (we can't get away without mentioning it explicitly):
AccountId,
>;
/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,
/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can
/// biases the kind of local `Origin` it will become.
pub type XcmOriginToTransactDispatchOrigin = (
// Sovereign account converter; this attempts to derive an `AccountId` from the origin location
// using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for
// foreign chains who want to have a local sovereign account on this chain which they control.
SovereignSignedViaLocation,
// Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when
// recognised.
RelayChainAsNative,
// Native converter for sibling Parachains; will convert to a `SiblingPara` origin when
// recognised.
SiblingParachainAsNative,
// Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a
// transaction from the Root origin.
ParentAsSuperuser,
// Native signed account converter; this just converts an `AccountId32` origin into a normal
// `Origin::Signed` origin of the same 32-byte value.
SignedAccountId32AsNative,
);
parameter_types! {
pub UnitWeightCost: Weight = 1_000;
}
parameter_types! {
// 1_000_000_000_000 => 1 unit of asset for 1 unit of Weight.
// TODO: Should take the actual weight price. This is just 1_000 ROC per second of weight.
pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::X1(Junction::Parent), 1_000);
pub AllowUnpaidFrom: Vec = vec![ MultiLocation::X1(Junction::Parent) ];
}
pub type Barrier = (
TakeWeightCredit,
AllowTopLevelPaidExecutionFrom>,
AllowUnpaidExecutionFrom>, // <- Parent gets free execution
);
pub struct XcmConfig;
impl Config for XcmConfig {
type Call = Call;
type XcmSender = XcmRouter;
// How to withdraw and deposit an asset.
type AssetTransactor = LocalAssetTransactor;
type OriginConverter = XcmOriginToTransactDispatchOrigin;
type IsReserve = NativeAsset;
type IsTeleporter = NativeAsset; // <- should be enough to allow teleportation of ROC
type LocationInverter = LocationInverter;
type Barrier = Barrier;
type Weigher = FixedWeightBounds;
type Trader = FixedRateOfConcreteFungible;
type ResponseHandler = (); // Don't handle responses for now.
}
parameter_types! {
pub const MaxDownwardMessageWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 10;
}
/// No local origins on this chain are allowed to dispatch XCM sends/executions.
pub type LocalOriginToLocation = ();
/// The means for routing XCM messages which are not for local execution into the right message
/// queues.
pub type XcmRouter = (
// Two routers - use UMP to communicate with the relay chain:
cumulus_primitives_utility::ParentAsUmp,
// ..and XCMP to communicate with the sibling chains.
XcmpQueue,
);
impl pallet_xcm::Config for Runtime {
type Event = Event;
type SendXcmOrigin = EnsureXcmOrigin;
type XcmRouter = XcmRouter;
type ExecuteXcmOrigin = EnsureXcmOrigin;
type XcmExecutor = XcmExecutor;
}
impl cumulus_pallet_xcm::Config for Runtime {}
impl cumulus_pallet_xcmp_queue::Config for Runtime {
type Event = Event;
type XcmExecutor = XcmExecutor;
type ChannelInfo = ParachainSystem;
}
impl cumulus_ping::Config for Runtime {
type Event = Event;
type Origin = Origin;
type Call = Call;
type XcmSender = XcmRouter;
}
construct_runtime! {
pub enum Runtime where
Block = Block,
NodeBlock = rococo_parachain_primitives::Block,
UncheckedExtrinsic = UncheckedExtrinsic,
{
System: frame_system::{Pallet, Call, Storage, Config, Event},
Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent},
Balances: pallet_balances::{Pallet, Call, Storage, Config, Event},
Sudo: pallet_sudo::{Pallet, Call, Storage, Config, Event},
RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Call, Storage},
ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Storage, Inherent, Event},
TransactionPayment: pallet_transaction_payment::{Pallet, Storage},
ParachainInfo: parachain_info::{Pallet, Storage, Config},
// XCM helpers.
XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event},
PolkadotXcm: pallet_xcm::{Pallet, Call, Event, Origin},
CumulusXcm: cumulus_pallet_xcm::{Pallet, Origin},
Spambot: cumulus_ping::{Pallet, Call, Storage, Event} = 99,
}
}
/// The address format for describing accounts.
pub type Address = AccountId;
/// Block header type as expected by this runtime.
pub type Header = generic::Header;
/// Block type as expected by this runtime.
pub type Block = generic::Block;
/// A Block signed with a Justification
pub type SignedBlock = generic::SignedBlock;
/// BlockId type as expected by this runtime.
pub type BlockId = generic::BlockId;
/// The SignedExtension to the basic transaction logic.
pub type SignedExtra = (
frame_system::CheckSpecVersion,
frame_system::CheckGenesis,
frame_system::CheckEra,
frame_system::CheckNonce,
frame_system::CheckWeight,
pallet_transaction_payment::ChargeTransactionPayment,
);
/// Unchecked extrinsic type as expected by this runtime.
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic;
/// Extrinsic type that has already been checked.
pub type CheckedExtrinsic = generic::CheckedExtrinsic;
/// Executive: handles dispatch to the various modules.
pub type Executive = frame_executive::Executive<
Runtime,
Block,
frame_system::ChainContext,
Runtime,
AllPallets,
>;
impl_runtime_apis! {
impl sp_api::Core for Runtime {
fn version() -> RuntimeVersion {
VERSION
}
fn execute_block(block: Block) {
Executive::execute_block(block)
}
fn initialize_block(header: &::Header) {
Executive::initialize_block(header)
}
}
impl sp_api::Metadata for Runtime {
fn metadata() -> OpaqueMetadata {
Runtime::metadata().into()
}
}
impl sp_block_builder::BlockBuilder for Runtime {
fn apply_extrinsic(
extrinsic: ::Extrinsic,
) -> ApplyExtrinsicResult {
Executive::apply_extrinsic(extrinsic)
}
fn finalize_block() -> ::Header {
Executive::finalize_block()
}
fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<::Extrinsic> {
data.create_extrinsics()
}
fn check_inherents(block: Block, data: sp_inherents::InherentData) -> sp_inherents::CheckInherentsResult {
data.check_extrinsics(&block)
}
fn random_seed() -> ::Hash {
RandomnessCollectiveFlip::random_seed().0
}
}
impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime {
fn validate_transaction(
source: TransactionSource,
tx: ::Extrinsic,
) -> TransactionValidity {
Executive::validate_transaction(source, tx)
}
}
impl sp_offchain::OffchainWorkerApi for Runtime {
fn offchain_worker(header: &::Header) {
Executive::offchain_worker(header)
}
}
impl sp_session::SessionKeys for Runtime {
fn decode_session_keys(
encoded: Vec,
) -> Option, sp_core::crypto::KeyTypeId)>> {
SessionKeys::decode_into_raw_public_keys(&encoded)
}
fn generate_session_keys(seed: Option>) -> Vec {
SessionKeys::generate(seed)
}
}
}
cumulus_pallet_parachain_system::register_validate_block!(Runtime, Executive);