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_native_token_management::Config for Runtime {
300 type TokenTransferHandler = TestHelperPallet;
301 type MainChainScriptsOrigin = EnsureRoot<Self::AccountId>;
302 type WeightInfo = pallet_native_token_management::weights::SubstrateWeight<Runtime>;
303}
304
305impl pallet_aura::Config for Runtime {
306 type AuthorityId = AuraId;
307 type DisabledValidators = ();
308 type MaxAuthorities = MaxValidators;
309 type AllowMultipleBlocksPerSlot = ConstBool<false>;
310 type SlotDuration = ConstU64<SLOT_DURATION>;
311}
312
313pallet_partner_chains_session::impl_pallet_session_config!(Runtime);
314
315impl pallet_grandpa::Config for Runtime {
316 type RuntimeEvent = RuntimeEvent;
317
318 type WeightInfo = ();
319 type MaxAuthorities = MaxValidators;
320 type MaxNominators = ConstU32<0>;
321 type MaxSetIdSessionEntries = ConstU64<0>;
322
323 type KeyOwnerProof = sp_core::Void;
324 type EquivocationReportSystem = ();
325}
326
327impl pallet_timestamp::Config for Runtime {
328 type Moment = u64;
330 type OnTimestampSet = Aura;
331 type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>;
332 type WeightInfo = pallet_timestamp::weights::SubstrateWeight<Runtime>;
333}
334
335pub const EXISTENTIAL_DEPOSIT: u128 = 500;
337
338impl pallet_balances::Config for Runtime {
339 type MaxLocks = ConstU32<50>;
340 type MaxReserves = ();
341 type ReserveIdentifier = [u8; 8];
342 type Balance = Balance;
344 type RuntimeEvent = RuntimeEvent;
346 type DustRemoval = ();
347 type ExistentialDeposit = ConstU128<EXISTENTIAL_DEPOSIT>;
348 type AccountStore = System;
349 type WeightInfo = pallet_balances::weights::SubstrateWeight<Runtime>;
350 type FreezeIdentifier = ();
351 type MaxFreezes = ();
352 type RuntimeHoldReason = RuntimeHoldReason;
353 type RuntimeFreezeReason = RuntimeFreezeReason;
354 type DoneSlashHandler = ();
355}
356
357parameter_types! {
358 pub FeeMultiplier: Multiplier = Multiplier::one();
359}
360
361impl pallet_transaction_payment::Config for Runtime {
362 type RuntimeEvent = RuntimeEvent;
363 type OnChargeTransaction = FungibleAdapter<Balances, ()>;
364 type OperationalFeeMultiplier = ConstU8<5>;
365 type WeightToFee = IdentityFee<Balance>;
366 type LengthToFee = IdentityFee<Balance>;
367 type FeeMultiplierUpdate = ConstFeeMultiplier<FeeMultiplier>;
368 type WeightInfo = pallet_transaction_payment::weights::SubstrateWeight<Runtime>;
369}
370
371impl pallet_sudo::Config for Runtime {
372 type RuntimeEvent = RuntimeEvent;
373 type RuntimeCall = RuntimeCall;
374 type WeightInfo = pallet_sudo::weights::SubstrateWeight<Runtime>;
375}
376
377impl pallet_partner_chains_session::Config for Runtime {
378 type ValidatorId = <Self as frame_system::Config>::AccountId;
379 type ShouldEndSession = ValidatorManagementSessionManager<Runtime>;
380 type NextSessionRotation = ();
381 type SessionManager = ValidatorManagementSessionManager<Runtime>;
382 type SessionHandler = <opaque::SessionKeys as OpaqueKeys>::KeyTypeIdProviders;
383 type Keys = opaque::SessionKeys;
384}
385
386parameter_types! {
387 pub const MaxValidators: u32 = 1024;
388}
389
390impl pallet_session_validator_management::Config for Runtime {
391 type MaxValidators = MaxValidators;
392 type AuthorityId = CrossChainPublic;
393 type AuthorityKeys = SessionKeys;
394 type AuthoritySelectionInputs = AuthoritySelectionInputs;
395 type ScEpochNumber = ScEpochNumber;
396 type WeightInfo = pallet_session_validator_management::weights::SubstrateWeight<Runtime>;
397 type CommitteeMember = CommitteeMember<CrossChainPublic, SessionKeys>;
398 type MainChainScriptsOrigin = EnsureRoot<Self::AccountId>;
399
400 fn select_authorities(
401 input: AuthoritySelectionInputs,
402 sidechain_epoch: ScEpochNumber,
403 ) -> Option<BoundedVec<Self::CommitteeMember, Self::MaxValidators>> {
404 select_authorities::<opaque::cross_chain_app::Public, SessionKeys, MaxValidators>(
405 Sidechain::genesis_utxo(),
406 input,
407 sidechain_epoch,
408 )
409 }
410
411 fn current_epoch_number() -> ScEpochNumber {
412 Sidechain::current_epoch_number()
413 }
414}
415
416parameter_types! {
417 pub const TokenConversionRate: u128 = 1_000_000_000u128;
418 pub const MaxTransactions: u32 = 256u32;
419}
420
421impl pallet_sidechain::Config for Runtime {
422 fn current_slot_number() -> ScSlotNumber {
423 ScSlotNumber(*pallet_aura::CurrentSlot::<Self>::get())
424 }
425 type OnNewEpoch = TestHelperPallet;
426}
427
428pub type BeneficiaryId = sidechain_domain::byte_string::SizedByteString<32>;
429
430#[derive(
431 MaxEncodedLen,
432 Encode,
433 Decode,
434 DecodeWithMemTracking,
435 Clone,
436 TypeInfo,
437 PartialEq,
438 Eq,
439 Debug,
440 Hash,
441 PartialOrd,
442 Ord,
443)]
444pub enum BlockAuthor {
445 Incentivized(CrossChainPublic, StakePoolPublicKey),
446 ProBono(CrossChainPublic),
447}
448impl BlockAuthor {
449 pub fn id(&self) -> &CrossChainPublic {
450 match self {
451 Self::Incentivized(id, _) => id,
452 Self::ProBono(id) => id,
453 }
454 }
455}
456impl From<CommitteeMember<CrossChainPublic, SessionKeys>> for BlockAuthor {
457 fn from(value: CommitteeMember<CrossChainPublic, SessionKeys>) -> Self {
458 match value {
459 CommitteeMember::Permissioned { id, .. } => BlockAuthor::ProBono(id),
460 CommitteeMember::Registered { id, stake_pool_pub_key, .. } => {
461 BlockAuthor::Incentivized(id, stake_pool_pub_key)
462 },
463 }
464 }
465}
466
467impl AsCardanoSPO for BlockAuthor {
468 fn as_cardano_spo(&self) -> Option<MainchainKeyHash> {
469 match self {
470 BlockAuthor::Incentivized(_, key) => Some(key.hash()),
471 BlockAuthor::ProBono(_) => None,
472 }
473 }
474}
475
476pub const MAX_METADATA_URL_LENGTH: u32 = 512;
477
478#[derive(
479 Clone,
480 Debug,
481 MaxEncodedLen,
482 Encode,
483 Decode,
484 DecodeWithMemTracking,
485 Serialize,
486 Deserialize,
487 PartialEq,
488 Eq,
489 TypeInfo,
490)]
491pub struct BlockProducerMetadataType {
492 pub url: BoundedString<ConstU32<MAX_METADATA_URL_LENGTH>>,
493 pub hash: SizedByteString<32>,
494}
495
496#[cfg(feature = "runtime-benchmarks")]
497pub struct PalletBlockProductionLogBenchmarkHelper;
498
499#[cfg(feature = "runtime-benchmarks")]
500impl pallet_block_production_log::benchmarking::BenchmarkHelper<BlockAuthor>
501 for PalletBlockProductionLogBenchmarkHelper
502{
503 fn producer_id() -> BlockAuthor {
504 let id = sp_core::ecdsa::Public::from_slice(&[0u8; 33]).unwrap().into();
505 BlockAuthor::ProBono(id)
506 }
507}
508
509#[cfg(feature = "runtime-benchmarks")]
510pub struct PalletBlockProducerMetadataBenchmarkHelper;
511
512#[cfg(feature = "runtime-benchmarks")]
513impl
514 pallet_block_producer_metadata::benchmarking::BenchmarkHelper<
515 BlockProducerMetadataType,
516 AccountId,
517 > for PalletBlockProducerMetadataBenchmarkHelper
518{
519 fn genesis_utxo() -> UtxoId {
520 Sidechain::genesis_utxo()
521 }
522
523 fn metadata() -> BlockProducerMetadataType {
524 BlockProducerMetadataType {
525 url: "https://cool.stuff/spo.json".try_into().unwrap(),
526 hash: SizedByteString::from([0; 32]),
527 }
528 }
529
530 fn cross_chain_pub_key() -> sidechain_domain::CrossChainPublicKey {
531 sidechain_domain::CrossChainPublicKey(
532 hex_literal::hex!("020a1091341fe5664bfa1782d5e04779689068c916b04cb365ec3153755684d9a1")
533 .to_vec(),
534 )
535 }
536
537 fn cross_chain_sign_key() -> pallet_block_producer_metadata::benchmarking::SecretKey {
538 pallet_block_producer_metadata::benchmarking::SecretKey::from_slice(&hex_literal::hex!(
539 "cb6df9de1efca7a3998a8ead4e02159d5fa99c3e0d4fd6432667390bb4726854"
540 ))
541 .unwrap()
542 }
543
544 fn upsert_valid_before() -> u64 {
545 11751276163
546 }
547
548 fn delete_valid_before() -> u64 {
549 11751276230
550 }
551}
552
553impl pallet_block_production_log::Config for Runtime {
554 type BlockProducerId = BlockAuthor;
555 type WeightInfo = pallet_block_production_log::weights::SubstrateWeight<Runtime>;
556
557 fn current_slot() -> sp_consensus_slots::Slot {
558 let slot: u64 = pallet_aura::CurrentSlot::<Runtime>::get().into();
559 sp_consensus_slots::Slot::from(slot)
560 }
561
562 #[cfg(feature = "runtime-benchmarks")]
563 type BenchmarkHelper = PalletBlockProductionLogBenchmarkHelper;
564}
565
566parameter_types! {
567 pub const AddressAssociationBurnAmount: Balance = 1_000_000;
569}
570
571impl pallet_address_associations::Config for Runtime {
572 type WeightInfo = pallet_address_associations::weights::SubstrateWeight<Runtime>;
573
574 type PartnerChainAddress = AccountId;
575 type Currency = Balances;
576 type BurnAmount = AddressAssociationBurnAmount;
577
578 fn genesis_utxo() -> UtxoId {
579 Sidechain::genesis_utxo()
580 }
581
582 type OnNewAssociation = TestHelperPallet;
583}
584
585#[cfg(feature = "runtime-benchmarks")]
586pub struct PalletBlockProducerFeesBenchmarkHelper;
587
588#[cfg(feature = "runtime-benchmarks")]
589impl pallet_block_producer_fees::benchmarking::BenchmarkHelper<AccountId>
590 for PalletBlockProducerFeesBenchmarkHelper
591{
592 fn account_id(i: u8) -> AccountId {
593 sp_core::sr25519::Public::from_raw([i; 32]).into()
594 }
595}
596
597impl pallet_block_producer_fees::Config for Runtime {
598 type WeightInfo = ();
599
600 type HistoricalChangesPerProducer = ConstU16<5>;
601
602 fn current_slot() -> sp_consensus_slots::Slot {
603 let slot: u64 = pallet_aura::CurrentSlot::<Runtime>::get().into();
604 sp_consensus_slots::Slot::from(slot)
605 }
606
607 #[cfg(feature = "runtime-benchmarks")]
608 type BenchmarkHelper = PalletBlockProducerFeesBenchmarkHelper;
609}
610
611parameter_types! {
612 pub const MetadataHoldAmount: Balance = 1_000_000;
614}
615
616impl pallet_block_producer_metadata::Config for Runtime {
617 type WeightInfo = pallet_block_producer_metadata::weights::SubstrateWeight<Runtime>;
618
619 type BlockProducerMetadata = BlockProducerMetadataType;
620
621 fn genesis_utxo() -> UtxoId {
622 Sidechain::genesis_utxo()
623 }
624
625 fn current_time() -> u64 {
626 pallet_timestamp::Now::<Runtime>::get() / 1000
627 }
628
629 type Currency = Balances;
630 type HoldAmount = MetadataHoldAmount;
631 type RuntimeHoldReason = RuntimeHoldReason;
632
633 #[cfg(feature = "runtime-benchmarks")]
634 type BenchmarkHelper = PalletBlockProducerMetadataBenchmarkHelper;
635}
636
637impl pallet_block_participation::Config for Runtime {
638 type WeightInfo = pallet_block_participation::weights::SubstrateWeight<Runtime>;
639 type BlockAuthor = BlockAuthor;
640 type DelegatorId = DelegatorKey;
641
642 fn should_release_data(slot: sidechain_slots::Slot) -> Option<sidechain_slots::Slot> {
643 TestHelperPallet::should_release_participation_data(slot)
644 }
645
646 fn blocks_produced_up_to_slot(slot: Slot) -> impl Iterator<Item = (Slot, BlockAuthor)> {
647 BlockProductionLog::peek_prefix(slot)
648 }
649
650 fn discard_blocks_produced_up_to_slot(slot: Slot) {
651 BlockProductionLog::drop_prefix(&slot)
652 }
653
654 const TARGET_INHERENT_ID: InherentIdentifier = TestHelperPallet::INHERENT_IDENTIFIER;
655}
656
657parameter_types! {
658 pub const MaxChanges: u32 = 16;
659 pub const MaxKeyLength: u32 = 64;
660 pub const MaxValueLength: u32 = 512;
661}
662
663impl pallet_governed_map::Config for Runtime {
664 type MaxChanges = MaxChanges;
665 type MaxKeyLength = MaxKeyLength;
666 type MaxValueLength = MaxValueLength;
667 type WeightInfo = pallet_governed_map::weights::SubstrateWeight<Runtime>;
668
669 type OnGovernedMappingChange = TestHelperPallet;
670 type MainChainScriptsOrigin = EnsureRoot<Self::AccountId>;
671
672 #[cfg(feature = "runtime-benchmarks")]
673 type BenchmarkHelper = ();
674}
675
676impl crate::test_helper_pallet::Config for Runtime {}
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 NativeTokenManagement: pallet_native_token_management,
719 GovernedMap: pallet_governed_map,
720 Bridge: pallet_partner_chains_bridge,
721 TestHelperPallet: crate::test_helper_pallet,
722 }
723);
724
725pub type Address = sp_runtime::MultiAddress<AccountId, ()>;
727pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
729pub type Block = generic::Block<Header, UncheckedExtrinsic>;
731pub type SignedExtra = (
733 frame_system::CheckNonZeroSender<Runtime>,
734 frame_system::CheckSpecVersion<Runtime>,
735 frame_system::CheckTxVersion<Runtime>,
736 frame_system::CheckGenesis<Runtime>,
737 frame_system::CheckEra<Runtime>,
738 frame_system::CheckNonce<Runtime>,
739 frame_system::CheckWeight<Runtime>,
740 pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
741);
742
743pub type UncheckedExtrinsic =
745 generic::UncheckedExtrinsic<Address, RuntimeCall, Signature, SignedExtra>;
746pub type SignedPayload = generic::SignedPayload<RuntimeCall, SignedExtra>;
748pub type Migrations = (
749 pallet_session_validator_management::migrations::v1::LegacyToV1Migration<Runtime>,
750 );
752pub type Executive = frame_executive::Executive<
754 Runtime,
755 Block,
756 frame_system::ChainContext<Runtime>,
757 Runtime,
758 AllPalletsWithSystem,
759 Migrations,
760>;
761
762#[cfg(feature = "runtime-benchmarks")]
763mod benches {
764 define_benchmarks!(
765 [frame_benchmarking, BaselineBench::<Runtime>]
766 [frame_system, SystemBench::<Runtime>]
767 [pallet_balances, Balances]
768 [pallet_timestamp, Timestamp]
769 [pallet_sudo, Sudo]
770 [pallet_native_token_management, NativeTokenManagement]
771 [pallet_block_production_log, BlockProductionLog]
772 [pallet_address_associations, AddressAssociations]
773 [pallet_block_producer_fees, BlockProducerFees]
774 [pallet_block_producer_metadata, BlockProducerMetadata]
775 [pallet_block_participation, BlockParticipation]
776 [pallet_governed_map, GovernedMap]
777 [pallet_partner_chains_bridge, Bridge]
778 );
779}
780
781impl_runtime_apis! {
782 impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
783 fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
784 build_state::<RuntimeGenesisConfig>(config)
785 }
786
787 fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
788 get_preset::<RuntimeGenesisConfig>(id, crate::genesis_config_presets::get_preset)
789 }
790
791 fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
792 crate::genesis_config_presets::preset_names()
793 }
794 }
795
796 impl sp_api::Core<Block> for Runtime {
797 fn version() -> RuntimeVersion {
798 VERSION
799 }
800
801 fn execute_block(block: Block) {
802 Executive::execute_block(block);
803 }
804
805 fn initialize_block(header: &<Block as BlockT>::Header) -> sp_runtime::ExtrinsicInclusionMode {
806 Executive::initialize_block(header)
807 }
808 }
809
810 impl sp_api::Metadata<Block> for Runtime {
811 fn metadata() -> OpaqueMetadata {
812 OpaqueMetadata::new(Runtime::metadata().into())
813 }
814
815 fn metadata_at_version(version: u32) -> Option<OpaqueMetadata> {
816 Runtime::metadata_at_version(version)
817 }
818
819 fn metadata_versions() -> sp_std::vec::Vec<u32> {
820 Runtime::metadata_versions()
821 }
822 }
823
824 impl sp_block_builder::BlockBuilder<Block> for Runtime {
825 fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {
826 Executive::apply_extrinsic(extrinsic)
827 }
828
829 fn finalize_block() -> <Block as BlockT>::Header {
830 Executive::finalize_block()
831 }
832
833 fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {
834 data.create_extrinsics()
835 }
836
837 fn check_inherents(
838 block: Block,
839 data: sp_inherents::InherentData,
840 ) -> sp_inherents::CheckInherentsResult {
841 data.check_extrinsics(&block)
842 }
843 }
844
845 impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
846 fn validate_transaction(
847 source: TransactionSource,
848 tx: <Block as BlockT>::Extrinsic,
849 block_hash: <Block as BlockT>::Hash,
850 ) -> TransactionValidity {
851 Executive::validate_transaction(source, tx, block_hash)
852 }
853 }
854
855 impl sp_offchain::OffchainWorkerApi<Block> for Runtime {
856 fn offchain_worker(header: &<Block as BlockT>::Header) {
857 Executive::offchain_worker(header)
858 }
859 }
860
861 impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {
862 fn slot_duration() -> sp_consensus_aura::SlotDuration {
863 sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration())
864 }
865
866 fn authorities() -> Vec<AuraId> {
867 pallet_aura::Authorities::<Runtime>::get().into_inner()
868 }
869 }
870
871 impl sp_session::SessionKeys<Block> for Runtime {
872 fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
873 opaque::CrossChainKey::generate(seed.clone());
875 opaque::SessionKeys::generate(seed)
876 }
877
878 fn decode_session_keys(
879 encoded: Vec<u8>,
880 ) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {
881 opaque::SessionKeys::decode_into_raw_public_keys(&encoded)
882 }
883 }
884
885 impl sp_consensus_grandpa::GrandpaApi<Block> for Runtime {
886 fn grandpa_authorities() -> sp_consensus_grandpa::AuthorityList {
887 Grandpa::grandpa_authorities()
888 }
889
890 fn current_set_id() -> sp_consensus_grandpa::SetId {
891 Grandpa::current_set_id()
892 }
893
894 fn submit_report_equivocation_unsigned_extrinsic(
895 _equivocation_proof: sp_consensus_grandpa::EquivocationProof<
896 <Block as BlockT>::Hash,
897 NumberFor<Block>,
898 >,
899 _key_owner_proof: sp_consensus_grandpa::OpaqueKeyOwnershipProof,
900 ) -> Option<()> {
901 None
902 }
903
904 fn generate_key_ownership_proof(
905 _set_id: sp_consensus_grandpa::SetId,
906 _authority_id: GrandpaId,
907 ) -> Option<sp_consensus_grandpa::OpaqueKeyOwnershipProof> {
908 None
912 }
913 }
914
915
916 impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Nonce> for Runtime {
917 fn account_nonce(account: AccountId) -> Nonce {
918 System::account_nonce(account)
919 }
920 }
921
922 impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance> for Runtime {
923 fn query_info(
924 uxt: <Block as BlockT>::Extrinsic,
925 len: u32,
926 ) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo<Balance> {
927 TransactionPayment::query_info(uxt, len)
928 }
929 fn query_fee_details(
930 uxt: <Block as BlockT>::Extrinsic,
931 len: u32,
932 ) -> pallet_transaction_payment::FeeDetails<Balance> {
933 TransactionPayment::query_fee_details(uxt, len)
934 }
935 fn query_weight_to_fee(weight: sp_weights::Weight) -> Balance {
936 TransactionPayment::weight_to_fee(weight)
937 }
938 fn query_length_to_fee(length: u32) -> Balance {
939 TransactionPayment::length_to_fee(length)
940 }
941 }
942
943 impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentCallApi<Block, Balance, RuntimeCall>
944 for Runtime
945 {
946 fn query_call_info(
947 call: RuntimeCall,
948 len: u32,
949 ) -> pallet_transaction_payment::RuntimeDispatchInfo<Balance> {
950 TransactionPayment::query_call_info(call, len)
951 }
952 fn query_call_fee_details(
953 call: RuntimeCall,
954 len: u32,
955 ) -> pallet_transaction_payment::FeeDetails<Balance> {
956 TransactionPayment::query_call_fee_details(call, len)
957 }
958 fn query_weight_to_fee(weight: sp_weights::Weight) -> Balance {
959 TransactionPayment::weight_to_fee(weight)
960 }
961 fn query_length_to_fee(length: u32) -> Balance {
962 TransactionPayment::length_to_fee(length)
963 }
964 }
965
966 #[cfg(feature = "runtime-benchmarks")]
967 impl frame_benchmarking::Benchmark<Block> for Runtime {
968 fn benchmark_metadata(extra: bool) -> (
969 Vec<frame_benchmarking::BenchmarkList>,
970 Vec<frame_support::traits::StorageInfo>,
971 ) {
972 use frame_benchmarking::{baseline, BenchmarkList};
973 use frame_support::traits::StorageInfoTrait;
974 use frame_system_benchmarking::Pallet as SystemBench;
975 use baseline::Pallet as BaselineBench;
976
977 let mut list = Vec::<BenchmarkList>::new();
978 list_benchmarks!(list, extra);
979
980 let storage_info = AllPalletsWithSystem::storage_info();
981
982 (list, storage_info)
983 }
984
985 fn dispatch_benchmark(
986 config: frame_benchmarking::BenchmarkConfig
987 ) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> {
988 use frame_benchmarking::{baseline, BenchmarkBatch};
989 use sp_storage::TrackedStorageKey;
990 use frame_system_benchmarking::Pallet as SystemBench;
991 use baseline::Pallet as BaselineBench;
992 use frame_support::traits::WhitelistedStorageKeys;
993
994 #[allow(non_local_definitions)]
995 impl frame_system_benchmarking::Config for Runtime {}
996 #[allow(non_local_definitions)]
997 impl frame_benchmarking::baseline::Config for Runtime {}
998
999 let whitelist: Vec<TrackedStorageKey> = AllPalletsWithSystem::whitelisted_storage_keys();
1000
1001 let mut batches = Vec::<BenchmarkBatch>::new();
1002 let params = (&config, &whitelist);
1003 add_benchmarks!(params, batches);
1004
1005 Ok(batches)
1006 }
1007 }
1008
1009 #[cfg(feature = "try-runtime")]
1010 impl frame_try_runtime::TryRuntime<Block> for Runtime {
1011 fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) {
1012 let weight = Executive::try_runtime_upgrade(checks).unwrap();
1016 (weight, BlockWeights::get().max_block)
1017 }
1018
1019 fn execute_block(
1020 block: Block,
1021 state_root_check: bool,
1022 signature_check: bool,
1023 select: frame_try_runtime::TryStateSelect
1024 ) -> Weight {
1025 Executive::try_execute_block(block, state_root_check, signature_check, select).expect("execute-block failed")
1028 }
1029 }
1030
1031 impl sp_sidechain::GetGenesisUtxo<Block> for Runtime {
1032 fn genesis_utxo() -> UtxoId {
1033 Sidechain::genesis_utxo()
1034 }
1035 }
1036
1037 impl sp_sidechain::GetSidechainStatus<Block> for Runtime {
1038 fn get_sidechain_status() -> SidechainStatus {
1039 SidechainStatus {
1040 epoch: Sidechain::current_epoch_number(),
1041 slot: ScSlotNumber(*pallet_aura::CurrentSlot::<Runtime>::get()),
1042 slots_per_epoch: Sidechain::slots_per_epoch().0,
1043 }
1044 }
1045 }
1046
1047 impl sidechain_slots::SlotApi<Block> for Runtime {
1048 fn slot_config() -> sidechain_slots::ScSlotConfig {
1049 sidechain_slots::ScSlotConfig {
1050 slots_per_epoch: Sidechain::slots_per_epoch(),
1051 slot_duration: <Self as sp_consensus_aura::runtime_decl_for_aura_api::AuraApi<Block, AuraId>>::slot_duration()
1052 }
1053 }
1054 }
1055
1056 impl sp_block_producer_metadata::BlockProducerMetadataApi<Block, BlockProducerMetadataType> for Runtime
1057 {
1058 fn get_metadata_for(
1059 cross_chain_pub_key: &CrossChainPublicKey,
1060 ) -> Option<BlockProducerMetadataType> {
1061 BlockProducerMetadata::get_metadata_for(&cross_chain_pub_key)
1062 }
1063 }
1064
1065 impl sp_block_producer_fees::BlockProducerFeesApi<Block, AccountId> for Runtime
1066 {
1067 fn get_all_fees() -> Vec<(AccountId, sp_block_producer_fees::PerTenThousands)> {
1068 BlockProducerFees::get_all_latest().map(|(account_id, (_slot, fee))| (account_id, fee)).collect()
1069 }
1070 }
1071
1072 #[api_version(2)]
1073 impl sp_session_validator_management::SessionValidatorManagementApi<
1074 Block,
1075 CommitteeMember<CrossChainPublic, SessionKeys>,
1076 AuthoritySelectionInputs,
1077 sidechain_domain::ScEpochNumber
1078 > for Runtime {
1079 fn get_current_committee() -> (ScEpochNumber, Vec<CommitteeMember<CrossChainPublic, SessionKeys>>) {
1080 SessionCommitteeManagement::current_committee_storage().as_pair()
1081 }
1082 fn get_next_committee() -> Option<(ScEpochNumber, Vec<CommitteeMember<CrossChainPublic, SessionKeys>>)> {
1083 Some(SessionCommitteeManagement::next_committee_storage()?.as_pair())
1084 }
1085 fn get_next_unset_epoch_number() -> sidechain_domain::ScEpochNumber {
1086 SessionCommitteeManagement::get_next_unset_epoch_number()
1087 }
1088 fn calculate_committee(authority_selection_inputs: AuthoritySelectionInputs, sidechain_epoch: ScEpochNumber) -> Option<Vec<CommitteeMember<CrossChainPublic, SessionKeys>>> {
1089 SessionCommitteeManagement::calculate_committee(authority_selection_inputs, sidechain_epoch)
1090 }
1091 fn get_main_chain_scripts() -> sp_session_validator_management::MainChainScripts {
1092 SessionCommitteeManagement::get_main_chain_scripts()
1093 }
1094 }
1095
1096 impl authority_selection_inherents::CandidateValidationApi<Block> for Runtime {
1097 fn validate_registered_candidate_data(stake_pool_public_key: &StakePoolPublicKey, registration_data: &RegistrationData) -> Option<RegistrationDataError> {
1098 authority_selection_inherents::validate_registration_data::<SessionKeys>(stake_pool_public_key, registration_data, Sidechain::genesis_utxo()).err()
1099 }
1100 fn validate_stake(stake: Option<StakeDelegation>) -> Option<StakeError> {
1101 authority_selection_inherents::validate_stake(stake).err()
1102 }
1103 fn validate_permissioned_candidate_data(candidate: PermissionedCandidateData) -> Option<PermissionedCandidateDataError> {
1104 validate_permissioned_candidate_data::<SessionKeys>(candidate).err()
1105 }
1106 }
1107
1108 impl sp_native_token_management::NativeTokenManagementApi<Block> for Runtime {
1109 fn get_main_chain_scripts() -> Option<sp_native_token_management::MainChainScripts> {
1110 NativeTokenManagement::get_main_chain_scripts()
1111 }
1112 fn initialized() -> bool {
1113 NativeTokenManagement::initialized()
1114 }
1115 }
1116
1117 impl sp_block_production_log::BlockProductionLogApi<Block, CommitteeMember<CrossChainPublic, SessionKeys>> for Runtime {
1118 fn get_author(slot: Slot) -> Option<CommitteeMember<CrossChainPublic, SessionKeys>> {
1119 SessionCommitteeManagement::get_current_authority_round_robin(*slot as usize)
1120 }
1121 }
1122
1123 impl sp_block_participation::BlockParticipationApi<Block, BlockAuthor> for Runtime {
1124 fn should_release_data(slot: Slot) -> Option<Slot> {
1125 BlockParticipation::should_release_data(slot)
1126 }
1127 fn blocks_produced_up_to_slot(slot: Slot) -> Vec<(Slot, BlockAuthor)> {
1128 <Runtime as pallet_block_participation::Config>::blocks_produced_up_to_slot(slot).collect()
1129 }
1130 fn target_inherent_id() -> InherentIdentifier {
1131 <Runtime as pallet_block_participation::Config>::TARGET_INHERENT_ID
1132 }
1133 }
1134
1135 impl sp_governed_map::GovernedMapIDPApi<Block> for Runtime {
1136 fn is_initialized() -> bool {
1137 GovernedMap::is_initialized()
1138 }
1139 fn get_current_state() -> BTreeMap<String, ByteString> {
1140 GovernedMap::get_all_key_value_pairs_unbounded().collect()
1141 }
1142 fn get_main_chain_scripts() -> Option<MainChainScriptsV1> {
1143 GovernedMap::get_main_chain_scripts()
1144 }
1145 fn get_pallet_version() -> u32 {
1146 GovernedMap::get_version()
1147 }
1148 }
1149
1150 impl sp_partner_chains_bridge::TokenBridgeIDPRuntimeApi<Block> for Runtime {
1151 fn get_pallet_version() -> u32 {
1152 Bridge::get_pallet_version()
1153 }
1154 fn get_main_chain_scripts() -> Option<BridgeMainChainScripts> {
1155 Bridge::get_main_chain_scripts()
1156 }
1157 fn get_max_transfers_per_block() -> u32 {
1158 Bridge::get_max_transfers_per_block()
1159 }
1160 fn get_last_data_checkpoint() -> Option<BridgeDataCheckpoint> {
1161 Bridge::get_data_checkpoint()
1162 }
1163 }
1164}
1165
1166#[cfg(test)]
1167mod tests {
1168 use crate::mock::*;
1169 use frame_support::{
1170 dispatch::PostDispatchInfo,
1171 inherent::ProvideInherent,
1172 traits::{UnfilteredDispatchable, WhitelistedStorageKeys},
1173 };
1174 use sp_core::{Pair, hexdisplay::HexDisplay};
1175 use sp_inherents::InherentData;
1176 use std::collections::HashSet;
1177
1178 #[test]
1179 fn check_whitelist() {
1180 let whitelist: HashSet<String> = super::AllPalletsWithSystem::whitelisted_storage_keys()
1181 .iter()
1182 .map(|e| HexDisplay::from(&e.key).to_string())
1183 .collect();
1184
1185 assert!(
1187 whitelist.contains("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac")
1188 );
1189 assert!(
1191 whitelist.contains("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80")
1192 );
1193 assert!(
1195 whitelist.contains("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a")
1196 );
1197 assert!(
1199 whitelist.contains("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850")
1200 );
1201 assert!(
1203 whitelist.contains("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7")
1204 );
1205 }
1206
1207 #[test]
1209 fn check_grandpa_authorities_rotation() {
1210 new_test_ext().execute_with(|| {
1211 advance_block();
1213 set_committee_through_inherent_data(&[alice()]);
1214 until_epoch_after_finalizing(1, &|| {
1215 assert_current_epoch!(0);
1216 assert_grandpa_weights();
1217 assert_grandpa_authorities!([alice(), bob()]);
1218 });
1219
1220 set_committee_through_inherent_data(&[bob()]);
1221 for_next_n_blocks_after_finalizing(SLOTS_PER_EPOCH, &|| {
1222 assert_current_epoch!(1);
1223 assert_grandpa_weights();
1224 assert_grandpa_authorities!([alice()]);
1225 });
1226
1227 for_next_n_blocks_after_finalizing(SLOTS_PER_EPOCH, &|| {
1228 assert_current_epoch!(2);
1229 assert_grandpa_weights();
1230 assert_grandpa_authorities!([bob()]);
1231 });
1232
1233 set_committee_through_inherent_data(&[alice()]);
1235 advance_block();
1236 assert_current_epoch!(3);
1237 assert_grandpa_authorities!([bob()]);
1238 set_committee_through_inherent_data(&[alice(), bob()]);
1239 for_next_n_blocks_after_finalizing(SLOTS_PER_EPOCH - 1, &|| {
1240 assert_current_epoch!(3);
1241 assert_grandpa_weights();
1242 assert_grandpa_authorities!([alice()]);
1243 });
1244
1245 for_next_n_blocks_after_finalizing(SLOTS_PER_EPOCH * 3, &|| {
1246 assert_grandpa_weights();
1247 assert_grandpa_authorities!([alice(), bob()]);
1248 });
1249 });
1250
1251 fn assert_grandpa_weights() {
1252 Grandpa::grandpa_authorities()
1253 .into_iter()
1254 .for_each(|(_, weight)| assert_eq!(weight, 1))
1255 }
1256 }
1257
1258 #[test]
1260 fn check_aura_authorities_rotation() {
1261 new_test_ext().execute_with(|| {
1262 advance_block();
1263 set_committee_through_inherent_data(&[alice()]);
1264 until_epoch(1, &|| {
1265 assert_current_epoch!(0);
1266 assert_aura_authorities!([alice(), bob()]);
1267 });
1268
1269 for_next_n_blocks(SLOTS_PER_EPOCH, &|| {
1270 assert_current_epoch!(1);
1271 assert_aura_authorities!([alice()]);
1272 });
1273
1274 set_committee_through_inherent_data(&[bob()]);
1276 assert_current_epoch!(2);
1277 assert_aura_authorities!([alice()]);
1278 advance_block();
1279 set_committee_through_inherent_data(&[alice(), bob()]);
1280 for_next_n_blocks(SLOTS_PER_EPOCH - 1, &|| {
1281 assert_current_epoch!(2);
1282 assert_aura_authorities!([bob()]);
1283 });
1284
1285 set_committee_through_inherent_data(&[alice(), bob()]);
1286 for_next_n_blocks(SLOTS_PER_EPOCH * 3, &|| {
1287 assert_aura_authorities!([alice(), bob()]);
1288 });
1289 });
1290 }
1291
1292 #[test]
1294 fn check_cross_chain_committee_rotation() {
1295 new_test_ext().execute_with(|| {
1296 advance_block();
1297 set_committee_through_inherent_data(&[alice()]);
1298 until_epoch(1, &|| {
1299 assert_current_epoch!(0);
1300 assert_next_committee!([alice()]);
1301 });
1302
1303 set_committee_through_inherent_data(&[bob()]);
1304 for_next_n_blocks(SLOTS_PER_EPOCH, &|| {
1305 assert_current_epoch!(1);
1306 assert_next_committee!([bob()]);
1307 });
1308
1309 set_committee_through_inherent_data(&[]);
1310 for_next_n_blocks(SLOTS_PER_EPOCH, &|| {
1311 assert_current_epoch!(2);
1312 assert_next_committee!([bob()]);
1313 });
1314 });
1315 }
1316
1317 pub fn set_committee_through_inherent_data(
1318 expected_authorities: &[TestKeys],
1319 ) -> PostDispatchInfo {
1320 let epoch = Sidechain::current_epoch_number();
1321 let slot = *pallet_aura::CurrentSlot::<Test>::get();
1322 println!(
1323 "(slot {slot}, epoch {epoch}) Setting {} authorities for next epoch",
1324 expected_authorities.len()
1325 );
1326 let inherent_data_struct = create_inherent_data_struct(expected_authorities);
1327 let mut inherent_data = InherentData::new();
1328 inherent_data
1329 .put_data(
1330 SessionCommitteeManagement::INHERENT_IDENTIFIER,
1331 &inherent_data_struct.data.unwrap(),
1332 )
1333 .expect("Setting inherent data should not fail");
1334 let call = <SessionCommitteeManagement as ProvideInherent>::create_inherent(&inherent_data)
1335 .expect("Creating test inherent should not fail");
1336 println!(" inherent: {:?}", call);
1337 call.dispatch_bypass_filter(RuntimeOrigin::none())
1338 .expect("dispatching test call should work")
1339 }
1340}