// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
//
// This program 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.
//
// This program 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 this program. If not, see .
#![cfg_attr(not(feature = "std"), no_std)]
#![recursion_limit = "256"]
// Make the WASM binary available.
#[cfg(feature = "std")]
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
pub mod constants;
mod contracts;
mod xcm_config;
use sp_api::impl_runtime_apis;
use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
use sp_runtime::{
create_runtime_str, generic, impl_opaque_keys,
traits::{AccountIdLookup, BlakeTwo256, Block as BlockT},
transaction_validity::{TransactionSource, TransactionValidity},
ApplyExtrinsicResult,
};
use sp_std::prelude::*;
#[cfg(feature = "std")]
use sp_version::NativeVersion;
use sp_version::RuntimeVersion;
use constants::{currency::*, fee::WeightToFee};
use frame_support::{
construct_runtime, parameter_types,
traits::{ConstU128, ConstU16, ConstU32, ConstU64, ConstU8, Everything},
weights::{
constants::{BlockExecutionWeight, ExtrinsicBaseWeight},
DispatchClass,
},
PalletId,
};
use frame_system::limits::{BlockLength, BlockWeights};
pub use parachains_common as common;
use parachains_common::{
impls::DealWithFees, opaque, AccountId, BlockNumber, Hash, Header, Index, Signature,
AVERAGE_ON_INITIALIZE_RATIO, HOURS, MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO, SLOT_DURATION,
};
pub use parachains_common::{AuraId, Balance};
use xcm_config::CollatorSelectionUpdateOrigin;
#[cfg(any(feature = "std", test))]
pub use sp_runtime::BuildStorage;
#[cfg(feature = "try-runtime")]
use frame_support::weights::Weight;
// Polkadot imports
use polkadot_runtime::{BlockHashCount, RocksDbWeight, SlowAdjustingFeeUpdate};
/// The address format for describing accounts.
pub type Address = sp_runtime::MultiAddress;
/// 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::CheckNonZeroSender,
frame_system::CheckSpecVersion,
frame_system::CheckTxVersion,
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,
AllPalletsWithSystem,
contracts::Migrations,
>;
impl_opaque_keys! {
pub struct SessionKeys {
pub aura: Aura,
}
}
#[sp_version::runtime_version]
pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: create_runtime_str!("canvas-kusama"),
impl_name: create_runtime_str!("canvas-kusama"),
authoring_version: 1,
spec_version: 16,
impl_version: 0,
apis: RUNTIME_API_VERSIONS,
transaction_version: 1,
state_version: 1,
};
/// 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() }
}
parameter_types! {
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();
}
// Configure FRAME pallets to include in runtime.
impl frame_system::Config for Runtime {
type BaseCallFilter = Everything;
type BlockWeights = RuntimeBlockWeights;
type BlockLength = RuntimeBlockLength;
type AccountId = AccountId;
type Call = Call;
type Lookup = AccountIdLookup;
type Index = Index;
type BlockNumber = BlockNumber;
type Hash = Hash;
type Hashing = BlakeTwo256;
type Header = Header;
type Event = Event;
type Origin = Origin;
type BlockHashCount = BlockHashCount;
type DbWeight = RocksDbWeight;
type Version = Version;
type PalletInfo = PalletInfo;
type OnNewAccount = ();
type OnKilledAccount = ();
type AccountData = pallet_balances::AccountData;
type SystemWeightInfo = frame_system::weights::SubstrateWeight;
type SS58Prefix = ConstU16<42>;
type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode;
type MaxConsumers = ConstU32<16>;
}
impl pallet_timestamp::Config for Runtime {
/// A timestamp: milliseconds since the unix epoch.
type Moment = u64;
type OnTimestampSet = ();
type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>;
type WeightInfo = pallet_timestamp::weights::SubstrateWeight;
}
impl pallet_authorship::Config for Runtime {
type FindAuthor = pallet_session::FindAccountFromAuthorIndex;
type UncleGenerations = ConstU32<0>;
type FilterUncle = ();
type EventHandler = (CollatorSelection,);
}
impl pallet_balances::Config for Runtime {
type MaxLocks = ConstU32<50>;
/// The type for recording an account's balance.
type Balance = Balance;
/// The ubiquitous event type.
type Event = Event;
type DustRemoval = ();
type ExistentialDeposit = ConstU128;
type AccountStore = System;
type WeightInfo = pallet_balances::weights::SubstrateWeight;
type MaxReserves = ConstU32<50>;
type ReserveIdentifier = [u8; 8];
}
impl pallet_transaction_payment::Config for Runtime {
type OnChargeTransaction =
pallet_transaction_payment::CurrencyAdapter>;
/// Relay Chain `TransactionByteFee` / 10
type TransactionByteFee = ConstU128;
type WeightToFee = WeightToFee;
type FeeMultiplierUpdate = SlowAdjustingFeeUpdate;
type OperationalFeeMultiplier = ConstU8<5>;
}
parameter_types! {
// One storage item; key size is 32; value is size 4+4+16+32 bytes = 56 bytes.
pub const DepositBase: Balance = deposit(1, 88);
// Additional storage item size of 32 bytes.
pub const DepositFactor: Balance = deposit(0, 32);
}
impl pallet_multisig::Config for Runtime {
type Event = Event;
type Call = Call;
type Currency = Balances;
type DepositBase = DepositBase;
type DepositFactor = DepositFactor;
type MaxSignatories = ConstU16<100>;
type WeightInfo = pallet_multisig::weights::SubstrateWeight;
}
impl pallet_utility::Config for Runtime {
type Event = Event;
type Call = Call;
type PalletsOrigin = OriginCaller;
type WeightInfo = pallet_utility::weights::SubstrateWeight;
}
impl cumulus_pallet_parachain_system::Config for Runtime {
type Event = Event;
type OnSystemEvent = ();
type SelfParaId = parachain_info::Pallet;
type DmpMessageHandler = DmpQueue;
type ReservedDmpWeight = ConstU64<{ MAXIMUM_BLOCK_WEIGHT / 4 }>;
type OutboundXcmpMessageSource = XcmpQueue;
type XcmpMessageHandler = XcmpQueue;
type ReservedXcmpWeight = ConstU64<{ MAXIMUM_BLOCK_WEIGHT / 4 }>;
}
impl pallet_randomness_collective_flip::Config for Runtime {}
impl parachain_info::Config for Runtime {}
impl cumulus_pallet_aura_ext::Config for Runtime {}
parameter_types! {
pub const Period: u32 = 6 * HOURS;
pub const Offset: u32 = 0;
}
impl pallet_session::Config for Runtime {
type Event = Event;
type ValidatorId = ::AccountId;
// we don't have stash and controller, thus we don't need the convert as well.
type ValidatorIdOf = pallet_collator_selection::IdentityCollator;
type ShouldEndSession = pallet_session::PeriodicSessions;
type NextSessionRotation = pallet_session::PeriodicSessions;
type SessionManager = CollatorSelection;
// Essentially just Aura, but lets be pedantic.
type SessionHandler = ::KeyTypeIdProviders;
type Keys = SessionKeys;
type WeightInfo = pallet_session::weights::SubstrateWeight;
}
impl pallet_aura::Config for Runtime {
type AuthorityId = AuraId;
type DisabledValidators = ();
type MaxAuthorities = ConstU32<100_000>;
}
parameter_types! {
pub const PotId: PalletId = PalletId(*b"PotStake");
}
impl pallet_collator_selection::Config for Runtime {
type Event = Event;
type Currency = Balances;
type UpdateOrigin = CollatorSelectionUpdateOrigin;
type PotId = PotId;
type MaxCandidates = ConstU32<1000>;
type MinCandidates = ConstU32<5>;
type MaxInvulnerables = ConstU32<100>;
// should be a multiple of session or things will get inconsistent
type KickThreshold = Period;
type ValidatorId = ::AccountId;
type ValidatorIdOf = pallet_collator_selection::IdentityCollator;
type ValidatorRegistration = Session;
type WeightInfo = pallet_collator_selection::weights::SubstrateWeight;
}
impl pallet_sudo::Config for Runtime {
type Call = Call;
type Event = Event;
}
// Create the runtime by composing the FRAME pallets that were previously configured.
construct_runtime!(
pub enum Runtime where
Block = Block,
NodeBlock = opaque::Block,
UncheckedExtrinsic = UncheckedExtrinsic,
{
// System support stuff.
System: frame_system::{Pallet, Call, Config, Storage, Event} = 0,
ParachainSystem: cumulus_pallet_parachain_system::{
Pallet, Call, Config, Storage, Inherent, Event, ValidateUnsigned,
} = 1,
RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage} = 2,
Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent} = 3,
ParachainInfo: parachain_info::{Pallet, Storage, Config} = 4,
// Monetary stuff.
Balances: pallet_balances::{Pallet, Call, Storage, Config, Event} = 10,
TransactionPayment: pallet_transaction_payment::{Pallet, Storage} = 11,
// Collator support. The order of these 5 are important and shall not change.
Authorship: pallet_authorship::{Pallet, Call, Storage} = 20,
CollatorSelection: pallet_collator_selection::{Pallet, Call, Storage, Event, Config} = 21,
Session: pallet_session::{Pallet, Call, Storage, Event, Config} = 22,
Aura: pallet_aura::{Pallet, Storage, Config} = 23,
AuraExt: cumulus_pallet_aura_ext::{Pallet, Storage, Config} = 24,
// XCM helpers.
XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event} = 30,
PolkadotXcm: pallet_xcm::{Pallet, Call, Storage, Event, Origin, Config} = 31,
CumulusXcm: cumulus_pallet_xcm::{Pallet, Event, Origin} = 32,
DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event} = 33,
// Smart Contracts.
Contracts: pallet_contracts::{Pallet, Call, Storage, Event} = 40,
// Handy utilities.
Utility: pallet_utility::{Pallet, Call, Event} = 50,
Multisig: pallet_multisig::{Pallet, Call, Storage, Event} = 51,
// Sudo
Sudo: pallet_sudo::{Pallet, Call, Config, Event, Storage} = 100,
}
);
#[cfg(feature = "runtime-benchmarks")]
#[macro_use]
extern crate frame_benchmarking;
#[cfg(feature = "runtime-benchmarks")]
mod benches {
define_benchmarks!(
[frame_system, SystemBench::]
[pallet_balances, Balances]
[pallet_multisig, Multisig]
[pallet_session, SessionBench::]
[pallet_utility, Utility]
[pallet_timestamp, Timestamp]
[pallet_collator_selection, CollatorSelection]
[pallet_contracts, Contracts]
);
}
impl_runtime_apis! {
impl sp_consensus_aura::AuraApi for Runtime {
fn slot_duration() -> sp_consensus_aura::SlotDuration {
sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration())
}
fn authorities() -> Vec {
Aura::authorities().into_inner()
}
}
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 {
OpaqueMetadata::new(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)
}
}
impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime {
fn validate_transaction(
source: TransactionSource,
tx: ::Extrinsic,
block_hash: ::Hash,
) -> TransactionValidity {
Executive::validate_transaction(source, tx, block_hash)
}
}
impl sp_offchain::OffchainWorkerApi for Runtime {
fn offchain_worker(header: &::Header) {
Executive::offchain_worker(header)
}
}
impl sp_session::SessionKeys for Runtime {
fn generate_session_keys(seed: Option>) -> Vec {
SessionKeys::generate(seed)
}
fn decode_session_keys(
encoded: Vec,
) -> Option, KeyTypeId)>> {
SessionKeys::decode_into_raw_public_keys(&encoded)
}
}
impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime {
fn account_nonce(account: AccountId) -> Index {
System::account_nonce(account)
}
}
impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi for Runtime {
fn query_info(
uxt: ::Extrinsic,
len: u32,
) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo {
TransactionPayment::query_info(uxt, len)
}
fn query_fee_details(
uxt: ::Extrinsic,
len: u32,
) -> pallet_transaction_payment::FeeDetails {
TransactionPayment::query_fee_details(uxt, len)
}
}
impl cumulus_primitives_core::CollectCollationInfo for Runtime {
fn collect_collation_info(header: &::Header) -> cumulus_primitives_core::CollationInfo {
ParachainSystem::collect_collation_info(header)
}
}
impl pallet_contracts_rpc_runtime_api::ContractsApi
for Runtime
{
fn call(
origin: AccountId,
dest: AccountId,
value: Balance,
gas_limit: u64,
storage_deposit_limit: Option,
input_data: Vec,
) -> pallet_contracts_primitives::ContractExecResult {
Contracts::bare_call(
origin,
dest,
value,
gas_limit,
storage_deposit_limit,
input_data,
contracts::CONTRACTS_DEBUG_OUTPUT,
)
}
fn instantiate(
origin: AccountId,
value: Balance,
gas_limit: u64,
storage_deposit_limit: Option,
code: pallet_contracts_primitives::Code,
data: Vec,
salt: Vec,
) -> pallet_contracts_primitives::ContractInstantiateResult {
Contracts::bare_instantiate(
origin,
value,
gas_limit,
storage_deposit_limit,
code,
data,
salt,
contracts::CONTRACTS_DEBUG_OUTPUT,
)
}
fn upload_code(
origin: AccountId,
code: Vec,
storage_deposit_limit: Option,
) -> pallet_contracts_primitives::CodeUploadResult {
Contracts::bare_upload_code(origin, code, storage_deposit_limit)
}
fn get_storage(
address: AccountId,
key: [u8; 32],
) -> pallet_contracts_primitives::GetStorageResult {
Contracts::get_storage(address, key)
}
}
#[cfg(feature = "try-runtime")]
impl frame_try_runtime::TryRuntime for Runtime {
fn on_runtime_upgrade() -> (Weight, Weight) {
log::info!("try-runtime::on_runtime_upgrade canvas");
let weight = Executive::try_runtime_upgrade().unwrap();
(weight, RuntimeBlockWeights::get().max_block)
}
fn execute_block_no_check(block: Block) -> Weight {
Executive::execute_block_no_check(block)
}
}
#[cfg(feature = "runtime-benchmarks")]
impl frame_benchmarking::Benchmark for Runtime {
fn benchmark_metadata(extra: bool) -> (
Vec,
Vec,
) {
use frame_benchmarking::{Benchmarking, BenchmarkList};
use frame_support::traits::StorageInfoTrait;
use frame_system_benchmarking::Pallet as SystemBench;
use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
let mut list = Vec::::new();
list_benchmarks!(list, extra);
let storage_info = AllPalletsWithSystem::storage_info();
return (list, storage_info)
}
fn dispatch_benchmark(
config: frame_benchmarking::BenchmarkConfig
) -> Result, sp_runtime::RuntimeString> {
use frame_benchmarking::{Benchmarking, BenchmarkBatch, TrackedStorageKey};
use frame_system_benchmarking::Pallet as SystemBench;
impl frame_system_benchmarking::Config for Runtime {}
use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
impl cumulus_pallet_session_benchmarking::Config for Runtime {}
let whitelist: Vec = vec![
// Block Number
hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(),
// Total Issuance
hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec().into(),
// Execution Phase
hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(),
// Event Count
hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(),
// System Events
hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(),
];
let mut batches = Vec::::new();
let params = (&config, &whitelist);
add_benchmarks!(params, batches);
if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }
Ok(batches)
}
}
}
struct CheckInherents;
impl cumulus_pallet_parachain_system::CheckInherents for CheckInherents {
fn check_inherents(
block: &Block,
relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof,
) -> sp_inherents::CheckInherentsResult {
let relay_chain_slot = relay_state_proof
.read_slot()
.expect("Could not read the relay chain slot from the proof");
let inherent_data =
cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration(
relay_chain_slot,
sp_std::time::Duration::from_secs(6),
)
.create_inherent_data()
.expect("Could not create the timestamp inherent data");
inherent_data.check_extrinsics(&block)
}
}
cumulus_pallet_parachain_system::register_validate_block! {
Runtime = Runtime,
BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::,
CheckInherents = CheckInherents,
}