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