#![cfg_attr(docsrs, feature(doc_cfg))] #![cfg_attr(docsrs, feature(doc_auto_cfg))] #![cfg_attr(not(feature = "std"), no_std)] #![recursion_limit = "256"] #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); // Re-export all components pub use serai_primitives as primitives; pub use frame_system as system; pub use frame_support as support; pub use pallet_balances as balances; pub use pallet_transaction_payment as transaction_payment; pub use pallet_assets as assets; pub use tokens_pallet as tokens; pub use in_instructions_pallet as in_instructions; pub use validator_sets_pallet as validator_sets; pub use pallet_session as session; pub use pallet_tendermint as tendermint; // Actually used by the runtime use sp_core::OpaqueMetadata; use sp_std::prelude::*; use sp_version::RuntimeVersion; #[cfg(feature = "std")] use sp_version::NativeVersion; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, KeyTypeId, traits::{Convert, OpaqueKeys, BlakeTwo256, Block as BlockT}, transaction_validity::{TransactionSource, TransactionValidity}, ApplyExtrinsicResult, Perbill, }; use primitives::{PublicKey, SeraiAddress, AccountLookup, Signature, SubstrateAmount, Coin}; use support::{ traits::{ConstU8, ConstU32, ConstU64, Contains}, weights::{ constants::{RocksDbWeight, WEIGHT_REF_TIME_PER_SECOND}, IdentityFee, Weight, }, parameter_types, construct_runtime, }; use transaction_payment::CurrencyAdapter; use session::PeriodicSessions; /// An index to a block. pub type BlockNumber = u64; /// Index of a transaction in the chain, for a given account. pub type Index = u32; /// A hash of some data used by the chain. pub type Hash = sp_core::H256; pub mod opaque { use super::*; use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; pub type Header = generic::Header; pub type Block = generic::Block; pub type BlockId = generic::BlockId; impl_opaque_keys! { pub struct SessionKeys { pub tendermint: Tendermint, } } } use opaque::SessionKeys; #[sp_version::runtime_version] pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("serai"), impl_name: create_runtime_str!("core"), authoring_version: 1, // TODO: 1? Do we prefer some level of compatibility or our own path? spec_version: 100, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, state_version: 1, }; // 1 MB pub const BLOCK_SIZE: u32 = 1024 * 1024; // 6 seconds pub const TARGET_BLOCK_TIME: u64 = 6; /// Measured in blocks. pub const MINUTES: BlockNumber = 60 / TARGET_BLOCK_TIME; pub const HOURS: BlockNumber = MINUTES * 60; pub const DAYS: BlockNumber = HOURS * 24; #[cfg(feature = "std")] pub fn native_version() -> NativeVersion { NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } } const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); parameter_types! { pub const BlockHashCount: BlockNumber = 2400; pub const Version: RuntimeVersion = VERSION; pub const SS58Prefix: u8 = 42; // TODO: Remove for Bech32m // 1 MB block size limit pub BlockLength: system::limits::BlockLength = system::limits::BlockLength::max_with_normal_ratio(BLOCK_SIZE, NORMAL_DISPATCH_RATIO); pub BlockWeights: system::limits::BlockWeights = system::limits::BlockWeights::with_sensible_defaults( Weight::from_ref_time(2u64 * WEIGHT_REF_TIME_PER_SECOND).set_proof_size(u64::MAX), NORMAL_DISPATCH_RATIO, ); } pub struct CallFilter; impl Contains for CallFilter { fn contains(call: &RuntimeCall) -> bool { if let RuntimeCall::Balances(call) = call { return matches!(call, balances::Call::transfer { .. } | balances::Call::transfer_all { .. }); } if let RuntimeCall::Assets(call) = call { return matches!( call, assets::Call::approve_transfer { .. } | assets::Call::cancel_approval { .. } | assets::Call::transfer { .. } | assets::Call::transfer_approved { .. } ); } if let RuntimeCall::Tokens(call) = call { return matches!(call, tokens::Call::burn { .. }); } if let RuntimeCall::InInstructions(call) = call { return matches!(call, in_instructions::Call::execute_batch { .. }); } if let RuntimeCall::ValidatorSets(call) = call { return matches!(call, validator_sets::Call::vote { .. }); } false } } impl system::Config for Runtime { type BaseCallFilter = CallFilter; type BlockWeights = BlockWeights; type BlockLength = BlockLength; type AccountId = PublicKey; type RuntimeCall = RuntimeCall; type Lookup = AccountLookup; type Index = Index; type BlockNumber = BlockNumber; type Hash = Hash; type Hashing = BlakeTwo256; type Header = Header; type RuntimeOrigin = RuntimeOrigin; type RuntimeEvent = RuntimeEvent; type BlockHashCount = BlockHashCount; type DbWeight = RocksDbWeight; type Version = Version; type PalletInfo = PalletInfo; type OnNewAccount = (); type OnKilledAccount = (); type OnSetCode = (); type AccountData = balances::AccountData; type SystemWeightInfo = (); type SS58Prefix = SS58Prefix; // TODO: Remove for Bech32m type MaxConsumers = support::traits::ConstU32<16>; } impl balances::Config for Runtime { type MaxLocks = ConstU32<50>; type MaxReserves = (); type ReserveIdentifier = [u8; 8]; type Balance = SubstrateAmount; type RuntimeEvent = RuntimeEvent; type DustRemoval = (); type ExistentialDeposit = ConstU64<500>; type AccountStore = System; type WeightInfo = balances::weights::SubstrateWeight; } impl transaction_payment::Config for Runtime { type RuntimeEvent = RuntimeEvent; type OnChargeTransaction = CurrencyAdapter; type OperationalFeeMultiplier = ConstU8<5>; type WeightToFee = IdentityFee; type LengthToFee = IdentityFee; type FeeMultiplierUpdate = (); } impl assets::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Balance = SubstrateAmount; type Currency = Balances; type AssetId = Coin; type AssetIdParameter = Coin; type StringLimit = ConstU32<32>; // Don't allow anyone to create assets type CreateOrigin = support::traits::AsEnsureOriginWithArg>; type ForceOrigin = system::EnsureRoot; // Don't charge fees nor kill accounts type RemoveItemsLimit = ConstU32<0>; type AssetDeposit = ConstU64<0>; type AssetAccountDeposit = ConstU64<0>; type MetadataDepositBase = ConstU64<0>; type MetadataDepositPerByte = ConstU64<0>; type ApprovalDeposit = ConstU64<0>; // Unused hooks type CallbackHandle = (); type Freezer = (); type Extra = (); type WeightInfo = assets::weights::SubstrateWeight; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = (); } impl tokens::Config for Runtime { type RuntimeEvent = RuntimeEvent; } impl in_instructions::Config for Runtime { type RuntimeEvent = RuntimeEvent; } const SESSION_LENGTH: BlockNumber = 5 * DAYS; type Sessions = PeriodicSessions, ConstU64<{ SESSION_LENGTH }>>; pub struct IdentityValidatorIdOf; impl Convert> for IdentityValidatorIdOf { fn convert(key: PublicKey) -> Option { Some(key) } } impl validator_sets::Config for Runtime { type RuntimeEvent = RuntimeEvent; } impl session::Config for Runtime { type RuntimeEvent = RuntimeEvent; type ValidatorId = PublicKey; type ValidatorIdOf = IdentityValidatorIdOf; type ShouldEndSession = Sessions; type NextSessionRotation = Sessions; type SessionManager = (); type SessionHandler = ::KeyTypeIdProviders; type Keys = SessionKeys; type WeightInfo = session::weights::SubstrateWeight; } impl tendermint::Config for Runtime {} pub type Header = generic::Header; pub type Block = generic::Block; pub type SignedExtra = ( system::CheckNonZeroSender, system::CheckSpecVersion, system::CheckTxVersion, system::CheckGenesis, system::CheckEra, system::CheckNonce, system::CheckWeight, transaction_payment::ChargeTransactionPayment, ); pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; pub type SignedPayload = generic::SignedPayload; pub type Executive = frame_executive::Executive< Runtime, Block, system::ChainContext, Runtime, AllPalletsWithSystem, >; construct_runtime!( pub enum Runtime where Block = Block, NodeBlock = Block, UncheckedExtrinsic = UncheckedExtrinsic { System: system, Balances: balances, TransactionPayment: transaction_payment, Assets: assets, Tokens: tokens, InInstructions: in_instructions, ValidatorSets: validator_sets, Session: session, Tendermint: tendermint, } ); #[cfg(feature = "runtime-benchmarks")] #[macro_use] extern crate frame_benchmarking; #[cfg(feature = "runtime-benchmarks")] mod benches { define_benchmarks!( [frame_benchmarking, BaselineBench::] [system, SystemBench::] [balances, Balances] ); } sp_api::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 { 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 { opaque::SessionKeys::generate(seed) } fn decode_session_keys( encoded: Vec, ) -> Option, KeyTypeId)>> { opaque::SessionKeys::decode_into_raw_public_keys(&encoded) } } impl sp_tendermint::TendermintApi for Runtime { fn current_session() -> u32 { Tendermint::session() } fn validators() -> Vec { Session::validators().drain(..).map(Into::into).collect() } } impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { fn account_nonce(account: PublicKey) -> Index { System::account_nonce(account) } } impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi< Block, SubstrateAmount > 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, ) -> transaction_payment::FeeDetails { TransactionPayment::query_fee_details(uxt, len) } fn query_weight_to_fee(weight: Weight) -> SubstrateAmount { TransactionPayment::weight_to_fee(weight) } fn query_length_to_fee(length: u32) -> SubstrateAmount { TransactionPayment::length_to_fee(length) } } }