1#![cfg_attr(not(feature = "std"), no_std)]
2#![recursion_limit = "256"]
4#![allow(deprecated)]
5
6#[cfg(feature = "runtime-benchmarks")]
7#[macro_use]
8extern crate frame_benchmarking;
9
10extern crate alloc;
11
12use alloc::collections::BTreeMap;
13use alloc::string::String;
14use authority_selection_inherents::{
15 AuthoritySelectionInputs, CommitteeMember, PermissionedCandidateDataError,
16 RegistrationDataError, StakeError, select_authorities, validate_permissioned_candidate_data,
17};
18use frame_support::genesis_builder_helper::{build_state, get_preset};
19use frame_support::inherent::ProvideInherent;
20use frame_support::weights::constants::RocksDbWeight as RuntimeDbWeight;
21use frame_support::{
22 BoundedVec, construct_runtime, parameter_types,
23 traits::{ConstBool, ConstU8, ConstU16, ConstU32, ConstU64, ConstU128},
24 weights::{IdentityFee, constants::WEIGHT_REF_TIME_PER_SECOND},
25};
26use frame_system::EnsureRoot;
27use opaque::SessionKeys;
28use pallet_block_producer_metadata;
29use pallet_grandpa::AuthorityId as GrandpaId;
30use pallet_session_validator_management::session_manager::ValidatorManagementSessionManager;
31use pallet_transaction_payment::{ConstFeeMultiplier, FungibleAdapter, Multiplier};
32use parity_scale_codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
33use scale_info::TypeInfo;
34use serde::{Deserialize, Serialize};
35use sidechain_domain::byte_string::{BoundedString, ByteString, SizedByteString};
36use sidechain_domain::{
37 CrossChainPublicKey, DelegatorKey, MainchainKeyHash, PermissionedCandidateData,
38 RegistrationData, ScEpochNumber, ScSlotNumber, StakeDelegation, StakePoolPublicKey, UtxoId,
39};
40use sidechain_slots::Slot;
41use sp_api::impl_runtime_apis;
42use sp_block_participation::AsCardanoSPO;
43use sp_consensus_aura::sr25519::AuthorityId as AuraId;
44#[cfg(feature = "runtime-benchmarks")]
45use sp_core::ByteArray;
46use sp_core::{OpaqueMetadata, crypto::KeyTypeId};
47use sp_governed_map::MainChainScriptsV1;
48use sp_inherents::InherentIdentifier;
49use sp_partner_chains_bridge::{BridgeDataCheckpoint, MainChainScripts as BridgeMainChainScripts};
50use sp_runtime::{
51 ApplyExtrinsicResult, MultiSignature, Perbill, generic, impl_opaque_keys,
52 traits::{
53 AccountIdLookup, BlakeTwo256, Block as BlockT, IdentifyAccount, NumberFor, One, OpaqueKeys,
54 Verify,
55 },
56 transaction_validity::{TransactionSource, TransactionValidity},
57};
58use sp_sidechain::SidechainStatus;
59use sp_std::prelude::*;
60use sp_version::RuntimeVersion;
61use sp_weights::Weight;
62
63#[cfg(feature = "std")]
65include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
66
67pub mod genesis_config_presets;
68
69#[cfg(test)]
70mod mock;
71
72#[cfg(test)]
73mod header_tests;
74
75mod test_helper_pallet;
76
77pub type BlockNumber = u32;
79
80pub type Signature = MultiSignature;
82
83pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;
86
87pub type Balance = u128;
89
90pub type Nonce = u32;
92
93pub type Hash = sp_core::H256;
95
96pub mod opaque {
101 use super::*;
102 use authority_selection_inherents::MaybeFromCandidateKeys;
103 use parity_scale_codec::MaxEncodedLen;
104 use sp_core::{ed25519, sr25519};
105 pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;
106
107 pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
109 pub type Block = generic::Block<Header, UncheckedExtrinsic>;
111 pub type BlockId = generic::BlockId<Block>;
113
114 pub const CROSS_CHAIN: KeyTypeId = KeyTypeId(*b"crch");
115 pub struct CrossChainRuntimeAppPublic;
116
117 pub mod cross_chain_app {
118 use super::CROSS_CHAIN;
119 use parity_scale_codec::MaxEncodedLen;
120 use sidechain_domain::SidechainPublicKey;
121 use sp_core::crypto::AccountId32;
122 use sp_runtime::MultiSigner;
123 use sp_runtime::app_crypto::{app_crypto, ecdsa};
124 use sp_runtime::traits::IdentifyAccount;
125 use sp_std::vec::Vec;
126
127 app_crypto!(ecdsa, CROSS_CHAIN);
128 impl MaxEncodedLen for Signature {
129 fn max_encoded_len() -> usize {
130 ecdsa::Signature::max_encoded_len()
131 }
132 }
133
134 impl From<Signature> for Vec<u8> {
135 fn from(value: Signature) -> Self {
136 value.into_inner().0.to_vec()
137 }
138 }
139
140 impl From<Public> for AccountId32 {
141 fn from(value: Public) -> Self {
142 MultiSigner::from(ecdsa::Public::from(value)).into_account()
143 }
144 }
145
146 impl From<Public> for Vec<u8> {
147 fn from(value: Public) -> Self {
148 value.into_inner().0.to_vec()
149 }
150 }
151
152 impl TryFrom<SidechainPublicKey> for Public {
153 type Error = SidechainPublicKey;
154 fn try_from(pubkey: SidechainPublicKey) -> Result<Self, Self::Error> {
155 let cross_chain_public_key =
156 Public::try_from(pubkey.0.as_slice()).map_err(|_| pubkey)?;
157 Ok(cross_chain_public_key)
158 }
159 }
160 }
161
162 impl_opaque_keys! {
163 #[derive(MaxEncodedLen, PartialOrd, Ord)]
164 pub struct SessionKeys {
165 pub aura: Aura,
166 pub grandpa: Grandpa,
167 }
168 }
169 impl From<(sr25519::Public, ed25519::Public)> for SessionKeys {
170 fn from((aura, grandpa): (sr25519::Public, ed25519::Public)) -> Self {
171 Self { aura: aura.into(), grandpa: grandpa.into() }
172 }
173 }
174
175 impl MaybeFromCandidateKeys for SessionKeys {}
176
177 impl_opaque_keys! {
178 pub struct CrossChainKey {
179 pub account: CrossChainPublic,
180 }
181 }
182}
183
184pub type CrossChainPublic = opaque::cross_chain_app::Public;
185
186#[sp_version::runtime_version]
189pub const VERSION: RuntimeVersion = RuntimeVersion {
190 spec_name: alloc::borrow::Cow::Borrowed("cardano-sidechain"),
191 impl_name: alloc::borrow::Cow::Borrowed("cardano-sidechain"),
192 authoring_version: 1,
193 spec_version: 170,
199 impl_version: 1,
200 apis: RUNTIME_API_VERSIONS,
201 transaction_version: 1,
202 system_version: 1,
203};
204
205pub const MILLISECS_PER_BLOCK: u64 = 6000;
212
213pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;
216
217pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);
219pub const HOURS: BlockNumber = MINUTES * 60;
220pub const DAYS: BlockNumber = HOURS * 24;
221
222const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);
223
224pub const MAXIMUM_BLOCK_WEIGHT: Weight =
226 Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND.saturating_mul(2), u64::MAX);
227pub const MAXIMUM_BLOCK_LENGTH: u32 = 5 * 1024 * 1024;
228
229parameter_types! {
230 pub const BlockHashCount: BlockNumber = 2400;
231 pub const Version: RuntimeVersion = VERSION;
232 pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights
233 ::with_sensible_defaults(MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO);
234 pub BlockLength: frame_system::limits::BlockLength = frame_system::limits::BlockLength
235 ::max_with_normal_ratio(MAXIMUM_BLOCK_LENGTH, NORMAL_DISPATCH_RATIO);
236 pub const SS58Prefix: u8 = 42;
237}
238
239impl frame_system::Config for Runtime {
242 type BaseCallFilter = frame_support::traits::Everything;
244 type Block = Block;
246 type Nonce = Nonce;
248 type BlockWeights = BlockWeights;
250 type BlockLength = BlockLength;
252 type AccountId = AccountId;
254 type RuntimeCall = RuntimeCall;
256 type Lookup = AccountIdLookup<AccountId, ()>;
258 type Hash = Hash;
260 type Hashing = BlakeTwo256;
262 type RuntimeEvent = RuntimeEvent;
264 type RuntimeOrigin = RuntimeOrigin;
266 type BlockHashCount = BlockHashCount;
268 type DbWeight = RuntimeDbWeight;
270 type Version = Version;
272 type PalletInfo = PalletInfo;
276 type OnNewAccount = ();
278 type OnKilledAccount = ();
280 type AccountData = pallet_balances::AccountData<Balance>;
282 type SystemWeightInfo = frame_system::weights::SubstrateWeight<Runtime>;
284 type ExtensionsWeightInfo = ();
286 type SS58Prefix = SS58Prefix;
288 type OnSetCode = ();
290 type MaxConsumers = frame_support::traits::ConstU32<16>;
291 type RuntimeTask = RuntimeTask;
292 type SingleBlockMigrations = ();
293 type MultiBlockMigrator = ();
294 type PreInherents = ();
295 type PostInherents = ();
296 type PostTransactions = ();
297}
298
299impl pallet_aura::Config for Runtime {
300 type AuthorityId = AuraId;
301 type DisabledValidators = ();
302 type MaxAuthorities = MaxValidators;
303 type AllowMultipleBlocksPerSlot = ConstBool<false>;
304 type SlotDuration = ConstU64<SLOT_DURATION>;
305}
306
307pallet_partner_chains_session::impl_pallet_session_config!(Runtime);
308
309impl pallet_grandpa::Config for Runtime {
310 type RuntimeEvent = RuntimeEvent;
311
312 type WeightInfo = ();
313 type MaxAuthorities = MaxValidators;
314 type MaxNominators = ConstU32<0>;
315 type MaxSetIdSessionEntries = ConstU64<0>;
316
317 type KeyOwnerProof = sp_core::Void;
318 type EquivocationReportSystem = ();
319}
320
321impl pallet_timestamp::Config for Runtime {
322 type Moment = u64;
324 type OnTimestampSet = Aura;
325 type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>;
326 type WeightInfo = pallet_timestamp::weights::SubstrateWeight<Runtime>;
327}
328
329pub const EXISTENTIAL_DEPOSIT: u128 = 500;
331
332impl pallet_balances::Config for Runtime {
333 type MaxLocks = ConstU32<50>;
334 type MaxReserves = ();
335 type ReserveIdentifier = [u8; 8];
336 type Balance = Balance;
338 type RuntimeEvent = RuntimeEvent;
340 type DustRemoval = ();
341 type ExistentialDeposit = ConstU128<EXISTENTIAL_DEPOSIT>;
342 type AccountStore = System;
343 type WeightInfo = pallet_balances::weights::SubstrateWeight<Runtime>;
344 type FreezeIdentifier = ();
345 type MaxFreezes = ();
346 type RuntimeHoldReason = RuntimeHoldReason;
347 type RuntimeFreezeReason = RuntimeFreezeReason;
348 type DoneSlashHandler = ();
349}
350
351parameter_types! {
352 pub FeeMultiplier: Multiplier = Multiplier::one();
353}
354
355impl pallet_transaction_payment::Config for Runtime {
356 type RuntimeEvent = RuntimeEvent;
357 type OnChargeTransaction = FungibleAdapter<Balances, ()>;
358 type OperationalFeeMultiplier = ConstU8<5>;
359 type WeightToFee = IdentityFee<Balance>;
360 type LengthToFee = IdentityFee<Balance>;
361 type FeeMultiplierUpdate = ConstFeeMultiplier<FeeMultiplier>;
362 type WeightInfo = pallet_transaction_payment::weights::SubstrateWeight<Runtime>;
363}
364
365impl pallet_sudo::Config for Runtime {
366 type RuntimeEvent = RuntimeEvent;
367 type RuntimeCall = RuntimeCall;
368 type WeightInfo = pallet_sudo::weights::SubstrateWeight<Runtime>;
369}
370
371impl pallet_partner_chains_session::Config for Runtime {
372 type ValidatorId = <Self as frame_system::Config>::AccountId;
373 type ShouldEndSession = ValidatorManagementSessionManager<Runtime>;
374 type NextSessionRotation = ();
375 type SessionManager = ValidatorManagementSessionManager<Runtime>;
376 type SessionHandler = <opaque::SessionKeys as OpaqueKeys>::KeyTypeIdProviders;
377 type Keys = opaque::SessionKeys;
378}
379
380parameter_types! {
381 pub const MaxValidators: u32 = 1024;
382}
383
384impl pallet_session_validator_management::Config for Runtime {
385 type MaxValidators = MaxValidators;
386 type AuthorityId = CrossChainPublic;
387 type AuthorityKeys = SessionKeys;
388 type AuthoritySelectionInputs = AuthoritySelectionInputs;
389 type ScEpochNumber = ScEpochNumber;
390 type WeightInfo = pallet_session_validator_management::weights::SubstrateWeight<Runtime>;
391 type CommitteeMember = CommitteeMember<CrossChainPublic, SessionKeys>;
392 type MainChainScriptsOrigin = EnsureRoot<Self::AccountId>;
393
394 fn select_authorities(
395 input: AuthoritySelectionInputs,
396 sidechain_epoch: ScEpochNumber,
397 ) -> Option<BoundedVec<Self::CommitteeMember, Self::MaxValidators>> {
398 select_authorities::<opaque::cross_chain_app::Public, SessionKeys, MaxValidators>(
399 Sidechain::genesis_utxo(),
400 input,
401 sidechain_epoch,
402 )
403 }
404
405 fn current_epoch_number() -> ScEpochNumber {
406 Sidechain::current_epoch_number()
407 }
408}
409
410parameter_types! {
411 pub const TokenConversionRate: u128 = 1_000_000_000u128;
412 pub const MaxTransactions: u32 = 256u32;
413}
414
415impl pallet_sidechain::Config for Runtime {
416 fn current_slot_number() -> ScSlotNumber {
417 ScSlotNumber(*pallet_aura::CurrentSlot::<Self>::get())
418 }
419 type OnNewEpoch = TestHelperPallet;
420}
421
422pub type BeneficiaryId = sidechain_domain::byte_string::SizedByteString<32>;
423
424#[derive(
425 MaxEncodedLen,
426 Encode,
427 Decode,
428 DecodeWithMemTracking,
429 Clone,
430 TypeInfo,
431 PartialEq,
432 Eq,
433 Debug,
434 Hash,
435 PartialOrd,
436 Ord,
437)]
438pub enum BlockAuthor {
439 Incentivized(CrossChainPublic, StakePoolPublicKey),
440 ProBono(CrossChainPublic),
441}
442impl BlockAuthor {
443 pub fn id(&self) -> &CrossChainPublic {
444 match self {
445 Self::Incentivized(id, _) => id,
446 Self::ProBono(id) => id,
447 }
448 }
449}
450impl From<CommitteeMember<CrossChainPublic, SessionKeys>> for BlockAuthor {
451 fn from(value: CommitteeMember<CrossChainPublic, SessionKeys>) -> Self {
452 match value {
453 CommitteeMember::Permissioned { id, .. } => BlockAuthor::ProBono(id),
454 CommitteeMember::Registered { id, stake_pool_pub_key, .. } => {
455 BlockAuthor::Incentivized(id, stake_pool_pub_key)
456 },
457 }
458 }
459}
460
461impl AsCardanoSPO for BlockAuthor {
462 fn as_cardano_spo(&self) -> Option<MainchainKeyHash> {
463 match self {
464 BlockAuthor::Incentivized(_, key) => Some(key.hash()),
465 BlockAuthor::ProBono(_) => None,
466 }
467 }
468}
469
470pub const MAX_METADATA_URL_LENGTH: u32 = 512;
471
472#[derive(
473 Clone,
474 Debug,
475 MaxEncodedLen,
476 Encode,
477 Decode,
478 DecodeWithMemTracking,
479 Serialize,
480 Deserialize,
481 PartialEq,
482 Eq,
483 TypeInfo,
484)]
485pub struct BlockProducerMetadataType {
486 pub url: BoundedString<ConstU32<MAX_METADATA_URL_LENGTH>>,
487 pub hash: SizedByteString<32>,
488}
489
490#[cfg(feature = "runtime-benchmarks")]
491pub struct PalletBlockProductionLogBenchmarkHelper;
492
493#[cfg(feature = "runtime-benchmarks")]
494impl pallet_block_production_log::benchmarking::BenchmarkHelper<BlockAuthor>
495 for PalletBlockProductionLogBenchmarkHelper
496{
497 fn producer_id() -> BlockAuthor {
498 let id = sp_core::ecdsa::Public::from_slice(&[0u8; 33]).unwrap().into();
499 BlockAuthor::ProBono(id)
500 }
501}
502
503#[cfg(feature = "runtime-benchmarks")]
504pub struct PalletBlockProducerMetadataBenchmarkHelper;
505
506#[cfg(feature = "runtime-benchmarks")]
507impl
508 pallet_block_producer_metadata::benchmarking::BenchmarkHelper<
509 BlockProducerMetadataType,
510 AccountId,
511 > for PalletBlockProducerMetadataBenchmarkHelper
512{
513 fn genesis_utxo() -> UtxoId {
514 Sidechain::genesis_utxo()
515 }
516
517 fn metadata() -> BlockProducerMetadataType {
518 BlockProducerMetadataType {
519 url: "https://cool.stuff/spo.json".try_into().unwrap(),
520 hash: SizedByteString::from([0; 32]),
521 }
522 }
523
524 fn cross_chain_pub_key() -> sidechain_domain::CrossChainPublicKey {
525 sidechain_domain::CrossChainPublicKey(
526 hex_literal::hex!("020a1091341fe5664bfa1782d5e04779689068c916b04cb365ec3153755684d9a1")
527 .to_vec(),
528 )
529 }
530
531 fn cross_chain_sign_key() -> pallet_block_producer_metadata::benchmarking::SecretKey {
532 pallet_block_producer_metadata::benchmarking::SecretKey::from_slice(&hex_literal::hex!(
533 "cb6df9de1efca7a3998a8ead4e02159d5fa99c3e0d4fd6432667390bb4726854"
534 ))
535 .unwrap()
536 }
537
538 fn upsert_valid_before() -> u64 {
539 11751276163
540 }
541
542 fn delete_valid_before() -> u64 {
543 11751276230
544 }
545}
546
547impl pallet_block_production_log::Config for Runtime {
548 type BlockProducerId = BlockAuthor;
549 type WeightInfo = pallet_block_production_log::weights::SubstrateWeight<Runtime>;
550
551 fn current_slot() -> sp_consensus_slots::Slot {
552 let slot: u64 = pallet_aura::CurrentSlot::<Runtime>::get().into();
553 sp_consensus_slots::Slot::from(slot)
554 }
555
556 #[cfg(feature = "runtime-benchmarks")]
557 type BenchmarkHelper = PalletBlockProductionLogBenchmarkHelper;
558}
559
560parameter_types! {
561 pub const AddressAssociationBurnAmount: Balance = 1_000_000;
563}
564
565impl pallet_address_associations::Config for Runtime {
566 type WeightInfo = pallet_address_associations::weights::SubstrateWeight<Runtime>;
567
568 type PartnerChainAddress = AccountId;
569 type Currency = Balances;
570 type BurnAmount = AddressAssociationBurnAmount;
571
572 fn genesis_utxo() -> UtxoId {
573 Sidechain::genesis_utxo()
574 }
575
576 type OnNewAssociation = TestHelperPallet;
577}
578
579#[cfg(feature = "runtime-benchmarks")]
580pub struct PalletBlockProducerFeesBenchmarkHelper;
581
582#[cfg(feature = "runtime-benchmarks")]
583impl pallet_block_producer_fees::benchmarking::BenchmarkHelper<AccountId>
584 for PalletBlockProducerFeesBenchmarkHelper
585{
586 fn account_id(i: u8) -> AccountId {
587 sp_core::sr25519::Public::from_raw([i; 32]).into()
588 }
589}
590
591impl pallet_block_producer_fees::Config for Runtime {
592 type WeightInfo = ();
593
594 type HistoricalChangesPerProducer = ConstU16<5>;
595
596 fn current_slot() -> sp_consensus_slots::Slot {
597 let slot: u64 = pallet_aura::CurrentSlot::<Runtime>::get().into();
598 sp_consensus_slots::Slot::from(slot)
599 }
600
601 #[cfg(feature = "runtime-benchmarks")]
602 type BenchmarkHelper = PalletBlockProducerFeesBenchmarkHelper;
603}
604
605parameter_types! {
606 pub const MetadataHoldAmount: Balance = 1_000_000;
608}
609
610impl pallet_block_producer_metadata::Config for Runtime {
611 type WeightInfo = pallet_block_producer_metadata::weights::SubstrateWeight<Runtime>;
612
613 type BlockProducerMetadata = BlockProducerMetadataType;
614
615 fn genesis_utxo() -> UtxoId {
616 Sidechain::genesis_utxo()
617 }
618
619 fn current_time() -> u64 {
620 pallet_timestamp::Now::<Runtime>::get() / 1000
621 }
622
623 type Currency = Balances;
624 type HoldAmount = MetadataHoldAmount;
625 type RuntimeHoldReason = RuntimeHoldReason;
626
627 #[cfg(feature = "runtime-benchmarks")]
628 type BenchmarkHelper = PalletBlockProducerMetadataBenchmarkHelper;
629}
630
631impl pallet_block_participation::Config for Runtime {
632 type WeightInfo = pallet_block_participation::weights::SubstrateWeight<Runtime>;
633 type BlockAuthor = BlockAuthor;
634 type DelegatorId = DelegatorKey;
635
636 fn should_release_data(slot: sidechain_slots::Slot) -> Option<sidechain_slots::Slot> {
637 TestHelperPallet::should_release_participation_data(slot)
638 }
639
640 fn blocks_produced_up_to_slot(slot: Slot) -> impl Iterator<Item = (Slot, BlockAuthor)> {
641 BlockProductionLog::peek_prefix(slot)
642 }
643
644 fn discard_blocks_produced_up_to_slot(slot: Slot) {
645 BlockProductionLog::drop_prefix(&slot)
646 }
647
648 const TARGET_INHERENT_ID: InherentIdentifier = TestHelperPallet::INHERENT_IDENTIFIER;
649}
650
651parameter_types! {
652 pub const MaxChanges: u32 = 16;
653 pub const MaxKeyLength: u32 = 64;
654 pub const MaxValueLength: u32 = 512;
655}
656
657impl pallet_governed_map::Config for Runtime {
658 type MaxChanges = MaxChanges;
659 type MaxKeyLength = MaxKeyLength;
660 type MaxValueLength = MaxValueLength;
661 type WeightInfo = pallet_governed_map::weights::SubstrateWeight<Runtime>;
662
663 type OnGovernedMappingChange = TestHelperPallet;
664 type MainChainScriptsOrigin = EnsureRoot<Self::AccountId>;
665
666 #[cfg(feature = "runtime-benchmarks")]
667 type BenchmarkHelper = ();
668}
669
670parameter_types! {
671 pub const ReserveAccount: AccountId = AccountId::new([1;32]);
672}
673
674impl crate::test_helper_pallet::Config for Runtime {
675 type ReserveAccount = ReserveAccount;
676}
677
678parameter_types! {
679pub const MaxTransfersPerBlock: u32 = 256;}
680
681impl pallet_partner_chains_bridge::Config for Runtime {
682 type GovernanceOrigin = EnsureRoot<Runtime>;
683 type Recipient = AccountId;
684 type TransferHandler = TestHelperPallet;
685 type MaxTransfersPerBlock = MaxTransfersPerBlock;
686 type WeightInfo = ();
687
688 #[cfg(feature = "runtime-benchmarks")]
689 type BenchmarkHelper = ();
690}
691
692construct_runtime!(
694 pub struct Runtime {
695 System: frame_system,
696 Timestamp: pallet_timestamp,
697 Aura: pallet_aura,
698 Grandpa: pallet_grandpa,
699 Balances: pallet_balances,
700 TransactionPayment: pallet_transaction_payment,
701 Sudo: pallet_sudo,
702 Sidechain: pallet_sidechain,
705 SessionCommitteeManagement: pallet_session_validator_management,
706 AddressAssociations: pallet_address_associations,
707 BlockProducerFees: pallet_block_producer_fees,
708 BlockProducerMetadata: pallet_block_producer_metadata,
709 BlockProductionLog: pallet_block_production_log,
710 BlockParticipation: pallet_block_participation,
711 PalletSession: pallet_session,
716 Session: pallet_partner_chains_session,
718 GovernedMap: pallet_governed_map,
719 Bridge: pallet_partner_chains_bridge,
720 TestHelperPallet: crate::test_helper_pallet,
721 }
722);
723
724pub type Address = sp_runtime::MultiAddress<AccountId, ()>;
726pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
728pub type Block = generic::Block<Header, UncheckedExtrinsic>;
730pub type SignedExtra = (
732 frame_system::CheckNonZeroSender<Runtime>,
733 frame_system::CheckSpecVersion<Runtime>,
734 frame_system::CheckTxVersion<Runtime>,
735 frame_system::CheckGenesis<Runtime>,
736 frame_system::CheckEra<Runtime>,
737 frame_system::CheckNonce<Runtime>,
738 frame_system::CheckWeight<Runtime>,
739 pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
740);
741
742pub type UncheckedExtrinsic =
744 generic::UncheckedExtrinsic<Address, RuntimeCall, Signature, SignedExtra>;
745pub type SignedPayload = generic::SignedPayload<RuntimeCall, SignedExtra>;
747pub type Migrations = (
748 pallet_session_validator_management::migrations::v1::LegacyToV1Migration<Runtime>,
749 );
751pub type Executive = frame_executive::Executive<
753 Runtime,
754 Block,
755 frame_system::ChainContext<Runtime>,
756 Runtime,
757 AllPalletsWithSystem,
758 Migrations,
759>;
760
761#[cfg(feature = "runtime-benchmarks")]
762mod benches {
763 define_benchmarks!(
764 [frame_benchmarking, BaselineBench::<Runtime>]
765 [frame_system, SystemBench::<Runtime>]
766 [pallet_balances, Balances]
767 [pallet_timestamp, Timestamp]
768 [pallet_sudo, Sudo]
769 [pallet_block_production_log, BlockProductionLog]
770 [pallet_address_associations, AddressAssociations]
771 [pallet_block_producer_fees, BlockProducerFees]
772 [pallet_block_producer_metadata, BlockProducerMetadata]
773 [pallet_block_participation, BlockParticipation]
774 [pallet_governed_map, GovernedMap]
775 [pallet_partner_chains_bridge, Bridge]
776 );
777}
778
779impl_runtime_apis! {
780 impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
781 fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
782 build_state::<RuntimeGenesisConfig>(config)
783 }
784
785 fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
786 get_preset::<RuntimeGenesisConfig>(id, crate::genesis_config_presets::get_preset)
787 }
788
789 fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
790 crate::genesis_config_presets::preset_names()
791 }
792 }
793
794 impl sp_api::Core<Block> for Runtime {
795 fn version() -> RuntimeVersion {
796 VERSION
797 }
798
799 fn execute_block(block: Block) {
800 Executive::execute_block(block);
801 }
802
803 fn initialize_block(header: &<Block as BlockT>::Header) -> sp_runtime::ExtrinsicInclusionMode {
804 Executive::initialize_block(header)
805 }
806 }
807
808 impl sp_api::Metadata<Block> for Runtime {
809 fn metadata() -> OpaqueMetadata {
810 OpaqueMetadata::new(Runtime::metadata().into())
811 }
812
813 fn metadata_at_version(version: u32) -> Option<OpaqueMetadata> {
814 Runtime::metadata_at_version(version)
815 }
816
817 fn metadata_versions() -> sp_std::vec::Vec<u32> {
818 Runtime::metadata_versions()
819 }
820 }
821
822 impl sp_block_builder::BlockBuilder<Block> for Runtime {
823 fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {
824 Executive::apply_extrinsic(extrinsic)
825 }
826
827 fn finalize_block() -> <Block as BlockT>::Header {
828 Executive::finalize_block()
829 }
830
831 fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {
832 data.create_extrinsics()
833 }
834
835 fn check_inherents(
836 block: Block,
837 data: sp_inherents::InherentData,
838 ) -> sp_inherents::CheckInherentsResult {
839 data.check_extrinsics(&block)
840 }
841 }
842
843 impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
844 fn validate_transaction(
845 source: TransactionSource,
846 tx: <Block as BlockT>::Extrinsic,
847 block_hash: <Block as BlockT>::Hash,
848 ) -> TransactionValidity {
849 Executive::validate_transaction(source, tx, block_hash)
850 }
851 }
852
853 impl sp_offchain::OffchainWorkerApi<Block> for Runtime {
854 fn offchain_worker(header: &<Block as BlockT>::Header) {
855 Executive::offchain_worker(header)
856 }
857 }
858
859 impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {
860 fn slot_duration() -> sp_consensus_aura::SlotDuration {
861 sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration())
862 }
863
864 fn authorities() -> Vec<AuraId> {
865 pallet_aura::Authorities::<Runtime>::get().into_inner()
866 }
867 }
868
869 impl sp_session::SessionKeys<Block> for Runtime {
870 fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
871 opaque::CrossChainKey::generate(seed.clone());
873 opaque::SessionKeys::generate(seed)
874 }
875
876 fn decode_session_keys(
877 encoded: Vec<u8>,
878 ) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {
879 opaque::SessionKeys::decode_into_raw_public_keys(&encoded)
880 }
881 }
882
883 impl sp_consensus_grandpa::GrandpaApi<Block> for Runtime {
884 fn grandpa_authorities() -> sp_consensus_grandpa::AuthorityList {
885 Grandpa::grandpa_authorities()
886 }
887
888 fn current_set_id() -> sp_consensus_grandpa::SetId {
889 Grandpa::current_set_id()
890 }
891
892 fn submit_report_equivocation_unsigned_extrinsic(
893 _equivocation_proof: sp_consensus_grandpa::EquivocationProof<
894 <Block as BlockT>::Hash,
895 NumberFor<Block>,
896 >,
897 _key_owner_proof: sp_consensus_grandpa::OpaqueKeyOwnershipProof,
898 ) -> Option<()> {
899 None
900 }
901
902 fn generate_key_ownership_proof(
903 _set_id: sp_consensus_grandpa::SetId,
904 _authority_id: GrandpaId,
905 ) -> Option<sp_consensus_grandpa::OpaqueKeyOwnershipProof> {
906 None
910 }
911 }
912
913
914 impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Nonce> for Runtime {
915 fn account_nonce(account: AccountId) -> Nonce {
916 System::account_nonce(account)
917 }
918 }
919
920 impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance> for Runtime {
921 fn query_info(
922 uxt: <Block as BlockT>::Extrinsic,
923 len: u32,
924 ) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo<Balance> {
925 TransactionPayment::query_info(uxt, len)
926 }
927 fn query_fee_details(
928 uxt: <Block as BlockT>::Extrinsic,
929 len: u32,
930 ) -> pallet_transaction_payment::FeeDetails<Balance> {
931 TransactionPayment::query_fee_details(uxt, len)
932 }
933 fn query_weight_to_fee(weight: sp_weights::Weight) -> Balance {
934 TransactionPayment::weight_to_fee(weight)
935 }
936 fn query_length_to_fee(length: u32) -> Balance {
937 TransactionPayment::length_to_fee(length)
938 }
939 }
940
941 impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentCallApi<Block, Balance, RuntimeCall>
942 for Runtime
943 {
944 fn query_call_info(
945 call: RuntimeCall,
946 len: u32,
947 ) -> pallet_transaction_payment::RuntimeDispatchInfo<Balance> {
948 TransactionPayment::query_call_info(call, len)
949 }
950 fn query_call_fee_details(
951 call: RuntimeCall,
952 len: u32,
953 ) -> pallet_transaction_payment::FeeDetails<Balance> {
954 TransactionPayment::query_call_fee_details(call, len)
955 }
956 fn query_weight_to_fee(weight: sp_weights::Weight) -> Balance {
957 TransactionPayment::weight_to_fee(weight)
958 }
959 fn query_length_to_fee(length: u32) -> Balance {
960 TransactionPayment::length_to_fee(length)
961 }
962 }
963
964 #[cfg(feature = "runtime-benchmarks")]
965 impl frame_benchmarking::Benchmark<Block> for Runtime {
966 fn benchmark_metadata(extra: bool) -> (
967 Vec<frame_benchmarking::BenchmarkList>,
968 Vec<frame_support::traits::StorageInfo>,
969 ) {
970 use frame_benchmarking::{baseline, BenchmarkList};
971 use frame_support::traits::StorageInfoTrait;
972 use frame_system_benchmarking::Pallet as SystemBench;
973 use baseline::Pallet as BaselineBench;
974
975 let mut list = Vec::<BenchmarkList>::new();
976 list_benchmarks!(list, extra);
977
978 let storage_info = AllPalletsWithSystem::storage_info();
979
980 (list, storage_info)
981 }
982
983 fn dispatch_benchmark(
984 config: frame_benchmarking::BenchmarkConfig
985 ) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> {
986 use frame_benchmarking::{baseline, BenchmarkBatch};
987 use sp_storage::TrackedStorageKey;
988 use frame_system_benchmarking::Pallet as SystemBench;
989 use baseline::Pallet as BaselineBench;
990 use frame_support::traits::WhitelistedStorageKeys;
991
992 #[allow(non_local_definitions)]
993 impl frame_system_benchmarking::Config for Runtime {}
994 #[allow(non_local_definitions)]
995 impl frame_benchmarking::baseline::Config for Runtime {}
996
997 let whitelist: Vec<TrackedStorageKey> = AllPalletsWithSystem::whitelisted_storage_keys();
998
999 let mut batches = Vec::<BenchmarkBatch>::new();
1000 let params = (&config, &whitelist);
1001 add_benchmarks!(params, batches);
1002
1003 Ok(batches)
1004 }
1005 }
1006
1007 #[cfg(feature = "try-runtime")]
1008 impl frame_try_runtime::TryRuntime<Block> for Runtime {
1009 fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) {
1010 let weight = Executive::try_runtime_upgrade(checks).unwrap();
1014 (weight, BlockWeights::get().max_block)
1015 }
1016
1017 fn execute_block(
1018 block: Block,
1019 state_root_check: bool,
1020 signature_check: bool,
1021 select: frame_try_runtime::TryStateSelect
1022 ) -> Weight {
1023 Executive::try_execute_block(block, state_root_check, signature_check, select).expect("execute-block failed")
1026 }
1027 }
1028
1029 impl sp_sidechain::GetGenesisUtxo<Block> for Runtime {
1030 fn genesis_utxo() -> UtxoId {
1031 Sidechain::genesis_utxo()
1032 }
1033 }
1034
1035 impl sp_sidechain::GetSidechainStatus<Block> for Runtime {
1036 fn get_sidechain_status() -> SidechainStatus {
1037 SidechainStatus {
1038 epoch: Sidechain::current_epoch_number(),
1039 slot: ScSlotNumber(*pallet_aura::CurrentSlot::<Runtime>::get()),
1040 slots_per_epoch: Sidechain::slots_per_epoch().0,
1041 }
1042 }
1043 }
1044
1045 impl sidechain_slots::SlotApi<Block> for Runtime {
1046 fn slot_config() -> sidechain_slots::ScSlotConfig {
1047 sidechain_slots::ScSlotConfig {
1048 slots_per_epoch: Sidechain::slots_per_epoch(),
1049 slot_duration: <Self as sp_consensus_aura::runtime_decl_for_aura_api::AuraApi<Block, AuraId>>::slot_duration()
1050 }
1051 }
1052 }
1053
1054 impl sp_block_producer_metadata::BlockProducerMetadataApi<Block, BlockProducerMetadataType> for Runtime
1055 {
1056 fn get_metadata_for(
1057 cross_chain_pub_key: &CrossChainPublicKey,
1058 ) -> Option<BlockProducerMetadataType> {
1059 BlockProducerMetadata::get_metadata_for(&cross_chain_pub_key)
1060 }
1061 }
1062
1063 impl sp_block_producer_fees::BlockProducerFeesApi<Block, AccountId> for Runtime
1064 {
1065 fn get_all_fees() -> Vec<(AccountId, sp_block_producer_fees::PerTenThousands)> {
1066 BlockProducerFees::get_all_latest().map(|(account_id, (_slot, fee))| (account_id, fee)).collect()
1067 }
1068 }
1069
1070 #[api_version(2)]
1071 impl sp_session_validator_management::SessionValidatorManagementApi<
1072 Block,
1073 CommitteeMember<CrossChainPublic, SessionKeys>,
1074 AuthoritySelectionInputs,
1075 sidechain_domain::ScEpochNumber
1076 > for Runtime {
1077 fn get_current_committee() -> (ScEpochNumber, Vec<CommitteeMember<CrossChainPublic, SessionKeys>>) {
1078 SessionCommitteeManagement::current_committee_storage().as_pair()
1079 }
1080 fn get_next_committee() -> Option<(ScEpochNumber, Vec<CommitteeMember<CrossChainPublic, SessionKeys>>)> {
1081 Some(SessionCommitteeManagement::next_committee_storage()?.as_pair())
1082 }
1083 fn get_next_unset_epoch_number() -> sidechain_domain::ScEpochNumber {
1084 SessionCommitteeManagement::get_next_unset_epoch_number()
1085 }
1086 fn calculate_committee(authority_selection_inputs: AuthoritySelectionInputs, sidechain_epoch: ScEpochNumber) -> Option<Vec<CommitteeMember<CrossChainPublic, SessionKeys>>> {
1087 SessionCommitteeManagement::calculate_committee(authority_selection_inputs, sidechain_epoch)
1088 }
1089 fn get_main_chain_scripts() -> sp_session_validator_management::MainChainScripts {
1090 SessionCommitteeManagement::get_main_chain_scripts()
1091 }
1092 }
1093
1094 impl authority_selection_inherents::CandidateValidationApi<Block> for Runtime {
1095 fn validate_registered_candidate_data(stake_pool_public_key: &StakePoolPublicKey, registration_data: &RegistrationData) -> Option<RegistrationDataError> {
1096 authority_selection_inherents::validate_registration_data::<SessionKeys>(stake_pool_public_key, registration_data, Sidechain::genesis_utxo()).err()
1097 }
1098 fn validate_stake(stake: Option<StakeDelegation>) -> Option<StakeError> {
1099 authority_selection_inherents::validate_stake(stake).err()
1100 }
1101 fn validate_permissioned_candidate_data(candidate: PermissionedCandidateData) -> Option<PermissionedCandidateDataError> {
1102 validate_permissioned_candidate_data::<SessionKeys>(candidate).err()
1103 }
1104 }
1105
1106 impl sp_block_production_log::BlockProductionLogApi<Block, CommitteeMember<CrossChainPublic, SessionKeys>> for Runtime {
1107 fn get_author(slot: Slot) -> Option<CommitteeMember<CrossChainPublic, SessionKeys>> {
1108 SessionCommitteeManagement::get_current_authority_round_robin(*slot as usize)
1109 }
1110 }
1111
1112 impl sp_block_participation::BlockParticipationApi<Block, BlockAuthor> for Runtime {
1113 fn should_release_data(slot: Slot) -> Option<Slot> {
1114 BlockParticipation::should_release_data(slot)
1115 }
1116 fn blocks_produced_up_to_slot(slot: Slot) -> Vec<(Slot, BlockAuthor)> {
1117 <Runtime as pallet_block_participation::Config>::blocks_produced_up_to_slot(slot).collect()
1118 }
1119 fn target_inherent_id() -> InherentIdentifier {
1120 <Runtime as pallet_block_participation::Config>::TARGET_INHERENT_ID
1121 }
1122 }
1123
1124 impl sp_governed_map::GovernedMapIDPApi<Block> for Runtime {
1125 fn is_initialized() -> bool {
1126 GovernedMap::is_initialized()
1127 }
1128 fn get_current_state() -> BTreeMap<String, ByteString> {
1129 GovernedMap::get_all_key_value_pairs_unbounded().collect()
1130 }
1131 fn get_main_chain_scripts() -> Option<MainChainScriptsV1> {
1132 GovernedMap::get_main_chain_scripts()
1133 }
1134 fn get_pallet_version() -> u32 {
1135 GovernedMap::get_version()
1136 }
1137 }
1138
1139 impl sp_partner_chains_bridge::TokenBridgeIDPRuntimeApi<Block> for Runtime {
1140 fn get_pallet_version() -> u32 {
1141 Bridge::get_pallet_version()
1142 }
1143 fn get_main_chain_scripts() -> Option<BridgeMainChainScripts> {
1144 Bridge::get_main_chain_scripts()
1145 }
1146 fn get_max_transfers_per_block() -> u32 {
1147 Bridge::get_max_transfers_per_block()
1148 }
1149 fn get_last_data_checkpoint() -> Option<BridgeDataCheckpoint> {
1150 Bridge::get_data_checkpoint()
1151 }
1152 }
1153}
1154
1155#[cfg(test)]
1156mod tests {
1157 use crate::mock::*;
1158 use frame_support::{
1159 dispatch::PostDispatchInfo,
1160 inherent::ProvideInherent,
1161 traits::{UnfilteredDispatchable, WhitelistedStorageKeys},
1162 };
1163 use sp_core::{Pair, hexdisplay::HexDisplay};
1164 use sp_inherents::InherentData;
1165 use std::collections::HashSet;
1166
1167 #[test]
1168 fn check_whitelist() {
1169 let whitelist: HashSet<String> = super::AllPalletsWithSystem::whitelisted_storage_keys()
1170 .iter()
1171 .map(|e| HexDisplay::from(&e.key).to_string())
1172 .collect();
1173
1174 assert!(
1176 whitelist.contains("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac")
1177 );
1178 assert!(
1180 whitelist.contains("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80")
1181 );
1182 assert!(
1184 whitelist.contains("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a")
1185 );
1186 assert!(
1188 whitelist.contains("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850")
1189 );
1190 assert!(
1192 whitelist.contains("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7")
1193 );
1194 }
1195
1196 #[test]
1198 fn check_grandpa_authorities_rotation() {
1199 new_test_ext().execute_with(|| {
1200 advance_block();
1202 set_committee_through_inherent_data(&[alice()]);
1203 until_epoch_after_finalizing(1, &|| {
1204 assert_current_epoch!(0);
1205 assert_grandpa_weights();
1206 assert_grandpa_authorities!([alice(), bob()]);
1207 });
1208
1209 set_committee_through_inherent_data(&[bob()]);
1210 for_next_n_blocks_after_finalizing(SLOTS_PER_EPOCH, &|| {
1211 assert_current_epoch!(1);
1212 assert_grandpa_weights();
1213 assert_grandpa_authorities!([alice()]);
1214 });
1215
1216 for_next_n_blocks_after_finalizing(SLOTS_PER_EPOCH, &|| {
1217 assert_current_epoch!(2);
1218 assert_grandpa_weights();
1219 assert_grandpa_authorities!([bob()]);
1220 });
1221
1222 set_committee_through_inherent_data(&[alice()]);
1224 advance_block();
1225 assert_current_epoch!(3);
1226 assert_grandpa_authorities!([bob()]);
1227 set_committee_through_inherent_data(&[alice(), bob()]);
1228 for_next_n_blocks_after_finalizing(SLOTS_PER_EPOCH - 1, &|| {
1229 assert_current_epoch!(3);
1230 assert_grandpa_weights();
1231 assert_grandpa_authorities!([alice()]);
1232 });
1233
1234 for_next_n_blocks_after_finalizing(SLOTS_PER_EPOCH * 3, &|| {
1235 assert_grandpa_weights();
1236 assert_grandpa_authorities!([alice(), bob()]);
1237 });
1238 });
1239
1240 fn assert_grandpa_weights() {
1241 Grandpa::grandpa_authorities()
1242 .into_iter()
1243 .for_each(|(_, weight)| assert_eq!(weight, 1))
1244 }
1245 }
1246
1247 #[test]
1249 fn check_aura_authorities_rotation() {
1250 new_test_ext().execute_with(|| {
1251 advance_block();
1252 set_committee_through_inherent_data(&[alice()]);
1253 until_epoch(1, &|| {
1254 assert_current_epoch!(0);
1255 assert_aura_authorities!([alice(), bob()]);
1256 });
1257
1258 for_next_n_blocks(SLOTS_PER_EPOCH, &|| {
1259 assert_current_epoch!(1);
1260 assert_aura_authorities!([alice()]);
1261 });
1262
1263 set_committee_through_inherent_data(&[bob()]);
1265 assert_current_epoch!(2);
1266 assert_aura_authorities!([alice()]);
1267 advance_block();
1268 set_committee_through_inherent_data(&[alice(), bob()]);
1269 for_next_n_blocks(SLOTS_PER_EPOCH - 1, &|| {
1270 assert_current_epoch!(2);
1271 assert_aura_authorities!([bob()]);
1272 });
1273
1274 set_committee_through_inherent_data(&[alice(), bob()]);
1275 for_next_n_blocks(SLOTS_PER_EPOCH * 3, &|| {
1276 assert_aura_authorities!([alice(), bob()]);
1277 });
1278 });
1279 }
1280
1281 #[test]
1283 fn check_cross_chain_committee_rotation() {
1284 new_test_ext().execute_with(|| {
1285 advance_block();
1286 set_committee_through_inherent_data(&[alice()]);
1287 until_epoch(1, &|| {
1288 assert_current_epoch!(0);
1289 assert_next_committee!([alice()]);
1290 });
1291
1292 set_committee_through_inherent_data(&[bob()]);
1293 for_next_n_blocks(SLOTS_PER_EPOCH, &|| {
1294 assert_current_epoch!(1);
1295 assert_next_committee!([bob()]);
1296 });
1297
1298 set_committee_through_inherent_data(&[]);
1299 for_next_n_blocks(SLOTS_PER_EPOCH, &|| {
1300 assert_current_epoch!(2);
1301 assert_next_committee!([bob()]);
1302 });
1303 });
1304 }
1305
1306 pub fn set_committee_through_inherent_data(
1307 expected_authorities: &[TestKeys],
1308 ) -> PostDispatchInfo {
1309 let epoch = Sidechain::current_epoch_number();
1310 let slot = *pallet_aura::CurrentSlot::<Test>::get();
1311 println!(
1312 "(slot {slot}, epoch {epoch}) Setting {} authorities for next epoch",
1313 expected_authorities.len()
1314 );
1315 let inherent_data_struct = create_inherent_data_struct(expected_authorities);
1316 let mut inherent_data = InherentData::new();
1317 inherent_data
1318 .put_data(
1319 SessionCommitteeManagement::INHERENT_IDENTIFIER,
1320 &inherent_data_struct.data.unwrap(),
1321 )
1322 .expect("Setting inherent data should not fail");
1323 let call = <SessionCommitteeManagement as ProvideInherent>::create_inherent(&inherent_data)
1324 .expect("Creating test inherent should not fail");
1325 println!(" inherent: {:?}", call);
1326 call.dispatch_bypass_filter(RuntimeOrigin::none())
1327 .expect("dispatching test call should work")
1328 }
1329}