diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index dac7b66..90fd884 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -18,8 +18,8 @@ use frame_support::{ genesis_builder_helper::{build_config, create_default_config}, parameter_types, traits::{ - AsEnsureOriginWithArg, ConstBool, ConstU32, ConstU64, ConstU8, EitherOfDiverse, Everything, - InstanceFilter, TransformOrigin, + AsEnsureOriginWithArg, ConstU32, ConstU64, EitherOfDiverse, Everything, InstanceFilter, + TransformOrigin, }, weights::{ constants::WEIGHT_REF_TIME_PER_SECOND, ConstantMultiplier, Weight, WeightToFeeCoefficient, @@ -137,16 +137,21 @@ pub type Executive = frame_executive::Executive< /// - Setting it to `1` will cause the literal `#[weight = x]` values to be /// charged. pub struct WeightToFee; + +pub const P_FACTOR: u128 = 10; +pub const Q_FACTOR: u128 = 100; +pub const POLY_DEGREE: u8 = 1; + impl WeightToFeePolynomial for WeightToFee { type Balance = Balance; fn polynomial() -> WeightToFeeCoefficients { // in Rococo, extrinsic base weight (smallest non-zero weight) is mapped to 1 // MILLIUNIT: in our template, we map to 1/10 of that, or 1/10 MILLIUNIT - let p = MILLICENTS / 10; - let q = 100 * Balance::from(ExtrinsicBaseWeight::get().ref_time()); + let p = MILLICENTS / P_FACTOR; + let q = Q_FACTOR * Balance::from(ExtrinsicBaseWeight::get().ref_time()); smallvec![WeightToFeeCoefficient { - degree: 1, + degree: POLY_DEGREE, negative: false, coeff_frac: Perbill::from_rational(p % q, q), coeff_integer: p / q, @@ -214,26 +219,28 @@ pub const DAYS: BlockNumber = HOURS * 24; /// We assume that ~5% of the block weight is consumed by `on_initialize` /// handlers. This is used to limit the maximal weight of a single extrinsic. -const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(5); +pub const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(5); /// 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); +pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); /// We allow for 0.5 of a second of compute with a 12 second average block time. -const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts( +pub const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts( WEIGHT_REF_TIME_PER_SECOND.saturating_div(2), cumulus_primitives_core::relay_chain::MAX_POV_SIZE as u64, ); /// Maximum number of blocks simultaneously accepted by the Runtime, not yet /// included into the relay chain. -const UNINCLUDED_SEGMENT_CAPACITY: u32 = 1; +pub const UNINCLUDED_SEGMENT_CAPACITY: u32 = 1; /// How many parachain blocks are processed by the relay chain per parent. /// Limits the number of blocks authored per slot. -const BLOCK_PROCESSING_VELOCITY: u32 = 1; +pub const BLOCK_PROCESSING_VELOCITY: u32 = 1; /// Relay chain slot duration, in milliseconds. -const RELAY_CHAIN_SLOT_DURATION_MILLIS: u32 = 6000; +pub const RELAY_CHAIN_SLOT_DURATION_MILLIS: u32 = 6000; +/// Maximum length for a block. +pub const MAX_BLOCK_LENGTH: u32 = 5 * 1024 * 1024; /// The version information used to identify this runtime when compiled /// natively. @@ -250,7 +257,7 @@ parameter_types! { // `DeletionWeightLimit` and `DeletionQueueDepth` depend on those to parameterize // the lazy contract deletion. pub RuntimeBlockLength: BlockLength = - BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); + BlockLength::max_with_normal_ratio(MAX_BLOCK_LENGTH, NORMAL_DISPATCH_RATIO); pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder() .base_block(BlockExecutionWeight::get()) .for_class(DispatchClass::all(), |weights| { @@ -273,7 +280,6 @@ parameter_types! { } // Configure FRAME pallets to include in runtime. - impl frame_system::Config for Runtime { /// The data to be stored in an account. type AccountData = pallet_balances::AccountData; @@ -299,7 +305,7 @@ impl frame_system::Config for Runtime { /// The lookup mechanism to get account ID from whatever is passed in /// dispatchers. type Lookup = AccountIdLookup; - type MaxConsumers = frame_support::traits::ConstU32<16>; + type MaxConsumers = ConstU32<16>; /// The index type for storing how many extrinsics an account has signed. type Nonce = Nonce; /// What to do if an account is fully reaped from the system. @@ -409,6 +415,10 @@ impl pallet_proxy::Config for Runtime { parameter_types! { pub const ExistentialDeposit: Balance = EXISTENTIAL_DEPOSIT; + pub const MaxFreezes: u32 = 0; + pub const MaxHolds: u32 = 0; + pub const MaxLocks: u32 = 50; + pub const MaxReserves: u32 = 50; } impl pallet_balances::Config for Runtime { @@ -418,10 +428,10 @@ impl pallet_balances::Config for Runtime { type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; type FreezeIdentifier = (); - type MaxFreezes = ConstU32<0>; - type MaxHolds = ConstU32<0>; - type MaxLocks = ConstU32<50>; - type MaxReserves = ConstU32<50>; + type MaxFreezes = MaxFreezes; + type MaxHolds = MaxHolds; + type MaxLocks = MaxLocks; + type MaxReserves = MaxReserves; type ReserveIdentifier = [u8; 8]; /// The ubiquitous event type. type RuntimeEvent = RuntimeEvent; @@ -437,6 +447,7 @@ parameter_types! { pub const StringLimit: u32 = 50; pub const MetadataDepositBase: Balance = deposit(1, 68); pub const MetadataDepositPerByte: Balance = deposit(0, 1); + pub const RemoveItemsLimit: u32 = 1000; } impl pallet_assets::Config for Runtime { @@ -456,7 +467,7 @@ impl pallet_assets::Config for Runtime { type Freezer = (); type MetadataDepositBase = MetadataDepositBase; type MetadataDepositPerByte = MetadataDepositPerByte; - type RemoveItemsLimit = ConstU32<1000>; + type RemoveItemsLimit = RemoveItemsLimit; type RuntimeEvent = RuntimeEvent; type StringLimit = StringLimit; type WeightInfo = pallet_assets::weights::SubstrateWeight; @@ -465,13 +476,14 @@ impl pallet_assets::Config for Runtime { parameter_types! { /// Relay Chain `TransactionByteFee` / 10 pub const TransactionByteFee: Balance = 10 * MICROCENTS; + pub const OperationalFeeMultiplier: u8 = 5; } impl pallet_transaction_payment::Config for Runtime { type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; type LengthToFee = ConstantMultiplier; type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; - type OperationalFeeMultiplier = ConstU8<5>; + type OperationalFeeMultiplier = OperationalFeeMultiplier; type RuntimeEvent = RuntimeEvent; type WeightToFee = WeightToFee; } @@ -511,11 +523,13 @@ impl parachain_info::Config for Runtime {} parameter_types! { pub MessageQueueServiceWeight: Weight = Perbill::from_percent(35) * RuntimeBlockWeights::get().max_block; + pub const HeapSize: u32 = 64 * 1024; + pub const MaxStale: u32 = 8; } impl pallet_message_queue::Config for Runtime { - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; - type MaxStale = sp_core::ConstU32<8>; + type HeapSize = HeapSize; + type MaxStale = MaxStale; #[cfg(feature = "runtime-benchmarks")] type MessageProcessor = pallet_message_queue::mock_helpers::NoopMessageProcessor< cumulus_primitives_core::AggregateMessageOrigin, @@ -537,11 +551,15 @@ impl pallet_message_queue::Config for Runtime { impl cumulus_pallet_aura_ext::Config for Runtime {} +parameter_types! { + pub const MaxInboundSuspended: u32 = 1000; +} + impl cumulus_pallet_xcmp_queue::Config for Runtime { type ChannelInfo = ParachainSystem; type ControllerOrigin = EnsureRoot; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; - type MaxInboundSuspended = ConstU32<1_000>; + type MaxInboundSuspended = MaxInboundSuspended; type PriceForSiblingDelivery = NoPriceForMessageDelivery; type RuntimeEvent = RuntimeEvent; type VersionWrapper = (); @@ -587,11 +605,16 @@ impl pallet_session::Config for Runtime { type WeightInfo = pallet_session::weights::SubstrateWeight; } +parameter_types! { + pub const AllowMultipleBlocksPerSlot: bool = false; + pub const MaxAuthorities: u32 = 100_000; +} + impl pallet_aura::Config for Runtime { - type AllowMultipleBlocksPerSlot = ConstBool; + type AllowMultipleBlocksPerSlot = AllowMultipleBlocksPerSlot; type AuthorityId = AuraId; type DisabledValidators = (); - type MaxAuthorities = ConstU32<100_000>; + type MaxAuthorities = MaxAuthorities; #[cfg(feature = "experimental")] type SlotDuration = pallet_aura::MinimumPeriodTimesTwo; } @@ -610,13 +633,19 @@ pub type CollatorSelectionUpdateOrigin = EitherOfDiverse< EnsureXcm>, >; +parameter_types! { + pub const MaxCandidates: u32 = 100; + pub const MaxInvulnerables: u32 = 20; + pub const MinEligibleCollators: u32 = 4; +} + impl pallet_collator_selection::Config for Runtime { type Currency = Balances; // should be a multiple of session or things will get inconsistent type KickThreshold = Period; - type MaxCandidates = ConstU32<100>; - type MaxInvulnerables = ConstU32<20>; - type MinEligibleCollators = ConstU32<4>; + type MaxCandidates = MaxCandidates; + type MaxInvulnerables = MaxInvulnerables; + type MinEligibleCollators = MinEligibleCollators; type PotId = PotId; type RuntimeEvent = RuntimeEvent; type UpdateOrigin = CollatorSelectionUpdateOrigin; @@ -922,3 +951,27 @@ cumulus_pallet_parachain_system::register_validate_block! { Runtime = Runtime, BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::, } + +// tests +#[cfg(test)] +mod tests { + use super::*; + + // RUNTIME_API_VERSIONS constant is generated by a macro and is private. + #[test] + fn check_version() { + assert_eq!( + VERSION, + RuntimeVersion { + spec_name: create_runtime_str!("template-parachain"), + impl_name: create_runtime_str!("template-parachain"), + authoring_version: 1, + spec_version: 1, + impl_version: 0, + apis: RUNTIME_API_VERSIONS, + transaction_version: 1, + state_version: 1, + } + ); + } +} diff --git a/runtime/src/xcm_config.rs b/runtime/src/xcm_config.rs index 85d3e95..dca95eb 100644 --- a/runtime/src/xcm_config.rs +++ b/runtime/src/xcm_config.rs @@ -108,7 +108,7 @@ pub type XcmOriginToTransactDispatchOrigin = ( parameter_types! { // One XCM operation is 1_000_000_000 weight - almost certainly a conservative estimate. - pub UnitWeightCost: Weight = Weight::from_parts(1_000_000_000, 64 * 1024); + pub const UnitWeightCost: Weight = Weight::from_parts(1_000_000_000, 64 * 1024); pub const MaxInstructions: u32 = 100; pub const MaxAssetsIntoHolding: u32 = 64; } @@ -186,6 +186,11 @@ parameter_types! { pub ReachableDest: Option = Some(Parent.into()); } +parameter_types! { + pub const MaxLockers: u32 = 8; + pub const MaxRemoteLockConsumers: u32 = 0; +} + impl pallet_xcm::Config for Runtime { type AdminOrigin = EnsureRoot; // ^ Override for AdvertisedXcmVersion default @@ -193,8 +198,8 @@ impl pallet_xcm::Config for Runtime { type Currency = Balances; type CurrencyMatcher = (); type ExecuteXcmOrigin = EnsureXcmOrigin; - type MaxLockers = ConstU32<8>; - type MaxRemoteLockConsumers = ConstU32<0>; + type MaxLockers = MaxLockers; + type MaxRemoteLockConsumers = MaxLockers; #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; type RemoteLockConsumerIdentifier = (); diff --git a/runtime/tests/constants_test.rs b/runtime/tests/constants_test.rs new file mode 100644 index 0000000..3d63a97 --- /dev/null +++ b/runtime/tests/constants_test.rs @@ -0,0 +1,201 @@ +mod constant_tests { + use parachain_template_runtime::constants::currency::*; + + #[test] + fn test_constants() { + assert_eq!(MICROCENTS, 1_000_000); + + assert_eq!(MILLICENTS, 1_000_000_000); + + assert_eq!(CENTS, 1_000 * MILLICENTS); + + assert_eq!(DOLLARS, 100 * CENTS); + + assert_eq!(EXISTENTIAL_DEPOSIT, MILLICENTS); + + // Ensure deposit function behavior remains constant + assert_eq!(deposit(2, 3), 2 * 15 * CENTS + 3 * 6 * CENTS); + } +} + +mod runtime_tests { + use frame_support::{pallet_prelude::Weight, traits::TypedGet, PalletId}; + use parachain_template_runtime::{constants::currency::*, *}; + use xcm::latest::prelude::BodyId; + + #[test] + fn weight_to_fee_constants() { + assert_eq!(P_FACTOR, 10); + + assert_eq!(Q_FACTOR, 100); + + assert_eq!(POLY_DEGREE, 1); + } + + #[test] + fn frame_system_constants() { + assert_eq!( + MAXIMUM_BLOCK_WEIGHT, + Weight::from_parts( + frame_support::weights::constants::WEIGHT_REF_TIME_PER_SECOND.saturating_div(2), + cumulus_primitives_core::relay_chain::MAX_POV_SIZE as u64 + ) + ); + + assert_eq!(AVERAGE_ON_INITIALIZE_RATIO, Perbill::from_percent(5)); + + assert_eq!(NORMAL_DISPATCH_RATIO, Perbill::from_percent(75)); + + assert_eq!(UNINCLUDED_SEGMENT_CAPACITY, 1); + + assert_eq!(BLOCK_PROCESSING_VELOCITY, 1); + + assert_eq!(RELAY_CHAIN_SLOT_DURATION_MILLIS, 6000); + + assert_eq!(MILLISECS_PER_BLOCK, 12000); + + assert_eq!(SLOT_DURATION, MILLISECS_PER_BLOCK); + + assert_eq!(MINUTES, 60_000 / (MILLISECS_PER_BLOCK as BlockNumber)); + + assert_eq!(HOURS, MINUTES * 60); + + assert_eq!(DAYS, HOURS * 24); + + assert_eq!(MAX_BLOCK_LENGTH, 5 * 1024 * 1024); + + assert_eq!(SS58Prefix::get(), 42); + + assert_eq!(::MaxConsumers::get(), 16); + } + + #[test] + fn proxy_constants() { + assert_eq!(MaxProxies::get(), 32); + + assert_eq!(MaxPending::get(), 32); + + assert_eq!(ProxyDepositBase::get(), deposit(1, 40)); + + assert_eq!(AnnouncementDepositBase::get(), deposit(1, 48)); + + assert_eq!(ProxyDepositFactor::get(), deposit(0, 33)); + + assert_eq!(AnnouncementDepositFactor::get(), deposit(0, 66)); + } + + #[test] + fn balances_constants() { + assert_eq!(MaxFreezes::get(), 0); + + assert_eq!(MaxHolds::get(), 0); + + assert_eq!(MaxLocks::get(), 50); + + assert_eq!(MaxReserves::get(), 50); + } + + #[test] + fn assets_constants() { + assert_eq!(AssetDeposit::get(), 10 * CENTS); + + assert_eq!(AssetAccountDeposit::get(), deposit(1, 16)); + + assert_eq!(ApprovalDeposit::get(), EXISTENTIAL_DEPOSIT); + + assert_eq!(StringLimit::get(), 50); + + assert_eq!(MetadataDepositBase::get(), deposit(1, 68)); + + assert_eq!(MetadataDepositPerByte::get(), deposit(0, 1)); + + assert_eq!(RemoveItemsLimit::get(), 1000); + } + + #[test] + fn transaction_payment_constants() { + assert_eq!(TransactionByteFee::get(), 10 * MICROCENTS); + + assert_eq!(OperationalFeeMultiplier::get(), 5); + } + + #[test] + fn cumulus_pallet_parachain_system_constants() { + assert_eq!(ReservedXcmpWeight::get(), MAXIMUM_BLOCK_WEIGHT.saturating_div(4)); + + assert_eq!(ReservedDmpWeight::get(), MAXIMUM_BLOCK_WEIGHT.saturating_div(4)); + } + + #[test] + fn message_queue_constants() { + assert_eq!(HeapSize::get(), 64 * 1024); + assert_eq!(MaxStale::get(), 8); + } + + #[test] + fn cumulus_pallet_xcmp_queue_constants() { + assert_eq!(MaxInboundSuspended::get(), 1000); + } + + #[test] + fn multisig_constants() { + assert_eq!(DepositBase::get(), deposit(1, 88)); + + assert_eq!(DepositFactor::get(), deposit(0, 32)); + + assert_eq!(MaxSignatories::get(), 100); + } + + #[test] + fn session_constants() { + assert_eq!(Period::get(), 6 * HOURS); + + assert_eq!(Offset::get(), 0); + } + + #[test] + #[allow(clippy::assertions_on_constants)] + fn aura_constants() { + assert!(!AllowMultipleBlocksPerSlot::get()); + + assert_eq!(MaxAuthorities::get(), 100_000); + } + + #[test] + fn collator_selection_constants() { + let pallet_id_to_string = |id: PalletId| -> String { + core::str::from_utf8(&id.0).unwrap_or_default().to_string() + }; + + assert_eq!(pallet_id_to_string(PotId::get()), pallet_id_to_string(PalletId(*b"PotStake"))); + + assert_eq!(SessionLength::get(), 6 * HOURS); + + assert_eq!(StakingAdminBodyId::get(), BodyId::Defense); + + assert_eq!(MaxCandidates::get(), 100); + + assert_eq!(MaxInvulnerables::get(), 20); + + assert_eq!(MinEligibleCollators::get(), 4); + } +} + +mod xcm_tests { + use frame_support::weights::Weight; + use parachain_template_runtime::xcm_config::*; + + #[test] + fn xcm_executor_constants() { + assert_eq!(UnitWeightCost::get(), Weight::from_parts(1_000_000_000, 64 * 1024)); + assert_eq!(MaxInstructions::get(), 100); + assert_eq!(MaxAssetsIntoHolding::get(), 64); + } + + #[test] + fn pallet_xcm_constants() { + assert_eq!(MaxLockers::get(), 8); + assert_eq!(MaxRemoteLockConsumers::get(), 0); + assert_eq!(::VERSION_DISCOVERY_QUEUE_SIZE, 100); + } +}