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