partner_chains_demo_runtime/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.
3#![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_block_production_log::{FromFindAuthorIndex, FromStorage};
33use pallet_grandpa::AuthorityId as GrandpaId;
34use pallet_session_validator_management::CommitteeMemberOf;
35use pallet_transaction_payment::{ConstFeeMultiplier, FungibleAdapter, Multiplier};
36use parity_scale_codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
37use scale_info::TypeInfo;
38use serde::{Deserialize, Serialize};
39use sidechain_domain::byte_string::{BoundedString, ByteString, SizedByteString};
40use sidechain_domain::{
41	CrossChainPublicKey, DelegatorKey, MainchainKeyHash, PermissionedCandidateData,
42	RegistrationData, ScEpochNumber, StakeDelegation, StakePoolPublicKey, UtxoId,
43};
44use sp_api::impl_runtime_apis;
45use sp_block_participation::AsCardanoSPO;
46use sp_consensus_aura::sr25519::AuthorityId as AuraId;
47use sp_consensus_slots::Slot;
48use sp_core::{OpaqueMetadata, crypto::KeyTypeId};
49use sp_governed_map::MainChainScriptsV1;
50use sp_inherents::InherentIdentifier;
51use sp_partner_chains_bridge::{BridgeDataCheckpoint, MainChainScripts as BridgeMainChainScripts};
52use sp_runtime::traits::ConvertInto;
53use sp_runtime::{
54	ApplyExtrinsicResult, MultiSignature, Perbill, generic, impl_opaque_keys,
55	traits::{
56		AccountIdLookup, BlakeTwo256, Block as BlockT, IdentifyAccount, NumberFor, One, OpaqueKeys,
57		Verify,
58	},
59	transaction_validity::{TransactionSource, TransactionValidity},
60};
61use sp_session_validator_management::{AuthoritySelectionInputs, CommitteeMember};
62use sp_sidechain::SidechainStatus;
63use sp_std::prelude::*;
64use sp_version::RuntimeVersion;
65use sp_weights::Weight;
66
67// Make the WASM binary available.
68#[cfg(feature = "std")]
69include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
70
71pub mod genesis_config_presets;
72
73#[cfg(test)]
74mod mock;
75
76#[cfg(test)]
77mod header_tests;
78
79mod test_helper_pallet;
80
81/// An index to a block.
82pub type BlockNumber = u32;
83
84/// Alias to 512-bit hash when used in the context of a transaction signature on the chain.
85pub type Signature = MultiSignature;
86
87/// Some way of identifying an account on the chain. We intentionally make it equivalent
88/// to the public key of our transaction signing scheme.
89pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;
90
91/// Balance of an account.
92pub type Balance = u128;
93
94/// Index of a transaction in the chain.
95pub type Nonce = u32;
96
97/// A hash of some data used by the chain.
98pub type Hash = sp_core::H256;
99
100/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know
101/// the specifics of the runtime. They can then be made to be agnostic over specific formats
102/// of data like extrinsics, allowing for them to continue syncing the network through upgrades
103/// to even the core data structures.
104pub mod opaque {
105	use super::*;
106	use authority_selection_inherents::MaybeFromCandidateKeys;
107	use parity_scale_codec::MaxEncodedLen;
108	use sp_core::{ed25519, sr25519};
109	pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;
110
111	/// Opaque block header type.
112	pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
113	/// Opaque block type.
114	pub type Block = generic::Block<Header, UncheckedExtrinsic>;
115	/// Opaque block identifier type.
116	pub type BlockId = generic::BlockId<Block>;
117
118	impl_opaque_keys! {
119		#[derive(MaxEncodedLen, PartialOrd, Ord)]
120		pub struct SessionKeys {
121			pub aura: Aura,
122			pub grandpa: Grandpa,
123		}
124	}
125	impl From<(sr25519::Public, ed25519::Public)> for SessionKeys {
126		fn from((aura, grandpa): (sr25519::Public, ed25519::Public)) -> Self {
127			Self { aura: aura.into(), grandpa: grandpa.into() }
128		}
129	}
130
131	impl MaybeFromCandidateKeys for SessionKeys {}
132
133	impl_opaque_keys! {
134		pub struct CrossChainKey {
135			pub account: CrossChainPublic,
136		}
137	}
138}
139
140pub type CrossChainPublic = sidechain_domain::cross_chain_app::Public;
141
142// To learn more about runtime versioning, see:
143// https://docs.substrate.io/main-docs/build/upgrade#runtime-versioning
144#[sp_version::runtime_version]
145pub const VERSION: RuntimeVersion = RuntimeVersion {
146	spec_name: alloc::borrow::Cow::Borrowed("cardano-sidechain"),
147	impl_name: alloc::borrow::Cow::Borrowed("cardano-sidechain"),
148	authoring_version: 1,
149	// The version of the runtime specification. A full node will not attempt to use its native
150	//   runtime in substitute for the on-chain Wasm runtime unless all of `spec_name`,
151	//   `spec_version`, and `authoring_version` are the same between Wasm and native.
152	// This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use
153	//   the compatible custom types.
154	spec_version: 181,
155	impl_version: 1,
156	apis: RUNTIME_API_VERSIONS,
157	transaction_version: 1,
158	system_version: 1,
159};
160
161/// This determines the average expected block time that we are targeting.
162/// Blocks will be produced at a minimum duration defined by `SLOT_DURATION`.
163/// `SLOT_DURATION` is picked up by `pallet_timestamp` which is in turn picked
164/// up by `pallet_aura` to implement `fn slot_duration()`.
165///
166/// Change this to adjust the block time.
167pub const MILLISECS_PER_BLOCK: u64 = 6000;
168
169// NOTE: Currently it is not possible to change the slot duration after the chain has started.
170//       Attempting to do so will brick block production.
171pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;
172
173// Time is measured by number of blocks.
174pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);
175pub const HOURS: BlockNumber = MINUTES * 60;
176pub const DAYS: BlockNumber = HOURS * 24;
177
178const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);
179
180/// We allow for 2 seconds of compute with a 6 second average block time.
181pub const MAXIMUM_BLOCK_WEIGHT: Weight =
182	Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND.saturating_mul(2), u64::MAX);
183pub const MAXIMUM_BLOCK_LENGTH: u32 = 5 * 1024 * 1024;
184
185parameter_types! {
186	pub const BlockHashCount: BlockNumber = 2400;
187	pub const Version: RuntimeVersion = VERSION;
188	pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights
189		::with_sensible_defaults(MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO);
190	pub BlockLength: frame_system::limits::BlockLength = frame_system::limits::BlockLength
191		::max_with_normal_ratio(MAXIMUM_BLOCK_LENGTH, NORMAL_DISPATCH_RATIO);
192	pub const SS58Prefix: u8 = 42;
193}
194
195// Configure FRAME pallets to include in runtime.
196
197impl frame_system::Config for Runtime {
198	/// The basic call filter to use in dispatchable.
199	type BaseCallFilter = frame_support::traits::Everything;
200	/// The block type for the runtime.
201	type Block = Block;
202	/// The type for storing how many extrinsics an account has signed.
203	type Nonce = Nonce;
204	/// Block & extrinsics weights: base values and limits.
205	type BlockWeights = BlockWeights;
206	/// The maximum length of a block (in bytes).
207	type BlockLength = BlockLength;
208	/// The identifier used to distinguish between accounts.
209	type AccountId = AccountId;
210	/// The aggregated dispatch type that is available for extrinsics.
211	type RuntimeCall = RuntimeCall;
212	/// The lookup mechanism to get account ID from whatever is passed in dispatchers.
213	type Lookup = AccountIdLookup<AccountId, ()>;
214	/// The type for hashing blocks and tries.
215	type Hash = Hash;
216	/// The hashing algorithm used.
217	type Hashing = BlakeTwo256;
218	/// The ubiquitous event type.
219	type RuntimeEvent = RuntimeEvent;
220	/// The ubiquitous origin type.
221	type RuntimeOrigin = RuntimeOrigin;
222	/// Maximum number of block number to block hash mappings to keep (oldest pruned first).
223	type BlockHashCount = BlockHashCount;
224	/// The weight of database operations that the runtime can invoke.
225	type DbWeight = RuntimeDbWeight;
226	/// Version of the runtime.
227	type Version = Version;
228	/// Converts a module to the index of the module in `construct_runtime!`.
229	///
230	/// This type is being generated by `construct_runtime!`.
231	type PalletInfo = PalletInfo;
232	/// What to do if a new account is created.
233	type OnNewAccount = ();
234	/// What to do if an account is fully reaped from the system.
235	type OnKilledAccount = ();
236	/// The data to be stored in an account.
237	type AccountData = pallet_balances::AccountData<Balance>;
238	/// Weight information for the extrinsics of this pallet.
239	type SystemWeightInfo = frame_system::weights::SubstrateWeight<Runtime>;
240	// WeightInfo for extensions is present but not accessible in polkadot-stable2412-1, because of that we are using () in our demo runtime
241	type ExtensionsWeightInfo = ();
242	/// This is used as an identifier of the chain. 42 is the generic substrate prefix.
243	type SS58Prefix = SS58Prefix;
244	/// The set code logic, just the default since we're not a parachain.
245	type OnSetCode = ();
246	type MaxConsumers = frame_support::traits::ConstU32<16>;
247	type RuntimeTask = RuntimeTask;
248	type SingleBlockMigrations = ();
249	type MultiBlockMigrator = ();
250	type PreInherents = ();
251	type PostInherents = ();
252	type PostTransactions = ();
253}
254
255impl pallet_aura::Config for Runtime {
256	type AuthorityId = AuraId;
257	type DisabledValidators = ();
258	type MaxAuthorities = MaxValidators;
259	type AllowMultipleBlocksPerSlot = ConstBool<false>;
260	type SlotDuration = ConstU64<SLOT_DURATION>;
261}
262
263impl pallet_session::Config for Runtime {
264	type RuntimeEvent = RuntimeEvent;
265	type ValidatorId = AccountId;
266	type ValidatorIdOf = ConvertInto;
267	type ShouldEndSession = SessionCommitteeManagement;
268	type NextSessionRotation = ();
269	type SessionManager = SessionCommitteeManagement;
270	type SessionHandler = <SessionKeys as OpaqueKeys>::KeyTypeIdProviders;
271	type Keys = SessionKeys;
272	type DisablingStrategy = pallet_session::disabling::UpToLimitWithReEnablingDisablingStrategy;
273	type Currency = Balances;
274	type KeyDeposit = ();
275
276	type WeightInfo = pallet_session::weights::SubstrateWeight<Runtime>;
277}
278
279impl pallet_grandpa::Config for Runtime {
280	type RuntimeEvent = RuntimeEvent;
281
282	type WeightInfo = ();
283	type MaxAuthorities = MaxValidators;
284	type MaxNominators = ConstU32<0>;
285	type MaxSetIdSessionEntries = ConstU64<0>;
286
287	type KeyOwnerProof = sp_core::Void;
288	type EquivocationReportSystem = ();
289}
290
291impl pallet_timestamp::Config for Runtime {
292	/// A timestamp: milliseconds since the unix epoch.
293	type Moment = u64;
294	type OnTimestampSet = Aura;
295	type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>;
296	type WeightInfo = pallet_timestamp::weights::SubstrateWeight<Runtime>;
297}
298
299/// Existential deposit.
300pub const EXISTENTIAL_DEPOSIT: u128 = 500;
301pub const UNITS: Balance = 1_000_000_000_000;
302pub const fn deposit(items: u32, bytes: u32) -> Balance {
303	items as Balance * UNITS + (bytes as Balance) * UNITS / 10
304}
305
306impl pallet_balances::Config for Runtime {
307	type MaxLocks = ConstU32<50>;
308	type MaxReserves = ();
309	type ReserveIdentifier = [u8; 8];
310	/// The type for recording an account's balance.
311	type Balance = Balance;
312	/// The ubiquitous event type.
313	type RuntimeEvent = RuntimeEvent;
314	type DustRemoval = ();
315	type ExistentialDeposit = ConstU128<EXISTENTIAL_DEPOSIT>;
316	type AccountStore = System;
317	type WeightInfo = pallet_balances::weights::SubstrateWeight<Runtime>;
318	type FreezeIdentifier = ();
319	type MaxFreezes = ();
320	type RuntimeHoldReason = RuntimeHoldReason;
321	type RuntimeFreezeReason = RuntimeFreezeReason;
322	type DoneSlashHandler = ();
323}
324
325parameter_types! {
326	pub FeeMultiplier: Multiplier = Multiplier::one();
327}
328
329impl pallet_transaction_payment::Config for Runtime {
330	type RuntimeEvent = RuntimeEvent;
331	type OnChargeTransaction = FungibleAdapter<Balances, ()>;
332	type OperationalFeeMultiplier = ConstU8<5>;
333	type WeightToFee = IdentityFee<Balance>;
334	type LengthToFee = IdentityFee<Balance>;
335	type FeeMultiplierUpdate = ConstFeeMultiplier<FeeMultiplier>;
336	type WeightInfo = pallet_transaction_payment::weights::SubstrateWeight<Runtime>;
337}
338
339impl pallet_sudo::Config for Runtime {
340	type RuntimeEvent = RuntimeEvent;
341	type RuntimeCall = RuntimeCall;
342	type WeightInfo = pallet_sudo::weights::SubstrateWeight<Runtime>;
343}
344
345parameter_types! {
346	pub const MaxValidators: u32 = 1024;
347}
348
349impl pallet_session_validator_management::Config for Runtime {
350	type MaxValidators = MaxValidators;
351	type AuthorityId = CrossChainPublic;
352	type AuthorityKeys = SessionKeys;
353	type WeightInfo = pallet_session_validator_management::weights::SubstrateWeight<Runtime>;
354	type MainChainScriptsOrigin = EnsureRoot<Self::AccountId>;
355
356	fn select_authorities(
357		input: AuthoritySelectionInputs,
358		sidechain_epoch: ScEpochNumber,
359	) -> Option<BoundedVec<CommitteeMemberOf<Self>, Self::MaxValidators>> {
360		select_authorities::<sidechain_domain::cross_chain_app::Public, SessionKeys, MaxValidators>(
361			Sidechain::genesis_utxo(),
362			input,
363			sidechain_epoch,
364		)
365	}
366
367	fn current_epoch_number() -> ScEpochNumber {
368		Sidechain::current_epoch_number()
369	}
370
371	#[cfg(feature = "runtime-benchmarks")]
372	type BenchmarkHelper = ();
373}
374
375parameter_types! {
376	pub const TokenConversionRate: u128 = 1_000_000_000u128;
377	pub const MaxTransactions: u32 = 256u32;
378}
379
380impl pallet_sidechain::Config for Runtime {
381	fn reference_timestamp_millis() -> u64 {
382		*pallet_aura::CurrentSlot::<Runtime>::get() * SLOT_DURATION
383	}
384	type OnNewEpoch = TestHelperPallet;
385}
386
387pub type BeneficiaryId = sidechain_domain::byte_string::SizedByteString<32>;
388
389#[derive(
390	MaxEncodedLen,
391	Encode,
392	Decode,
393	DecodeWithMemTracking,
394	Clone,
395	TypeInfo,
396	PartialEq,
397	Eq,
398	Debug,
399	Hash,
400	PartialOrd,
401	Ord,
402)]
403pub enum BlockAuthor {
404	Incentivized(CrossChainPublic, StakePoolPublicKey),
405	ProBono(CrossChainPublic),
406}
407impl BlockAuthor {
408	pub fn id(&self) -> &CrossChainPublic {
409		match self {
410			Self::Incentivized(id, _) => id,
411			Self::ProBono(id) => id,
412		}
413	}
414}
415impl From<CommitteeMember<CrossChainPublic, SessionKeys>> for BlockAuthor {
416	fn from(value: CommitteeMember<CrossChainPublic, SessionKeys>) -> Self {
417		match value {
418			CommitteeMember::Permissioned { id, .. } => BlockAuthor::ProBono(id),
419			CommitteeMember::Registered { id, stake_pool_pub_key, .. } => {
420				BlockAuthor::Incentivized(id, stake_pool_pub_key)
421			},
422		}
423	}
424}
425
426impl AsCardanoSPO for BlockAuthor {
427	fn as_cardano_spo(&self) -> Option<MainchainKeyHash> {
428		match self {
429			BlockAuthor::Incentivized(_, key) => Some(key.hash()),
430			BlockAuthor::ProBono(_) => None,
431		}
432	}
433}
434
435pub const MAX_METADATA_URL_LENGTH: u32 = 512;
436
437#[derive(
438	Clone,
439	Debug,
440	MaxEncodedLen,
441	Encode,
442	Decode,
443	DecodeWithMemTracking,
444	Serialize,
445	Deserialize,
446	PartialEq,
447	Eq,
448	TypeInfo,
449)]
450pub struct BlockProducerMetadataType {
451	pub url: BoundedString<ConstU32<MAX_METADATA_URL_LENGTH>>,
452	pub hash: SizedByteString<32>,
453}
454
455#[cfg(feature = "runtime-benchmarks")]
456pub struct PalletBlockProducerMetadataBenchmarkHelper;
457
458#[cfg(feature = "runtime-benchmarks")]
459impl
460	pallet_block_producer_metadata::benchmarking::BenchmarkHelper<
461		BlockProducerMetadataType,
462		AccountId,
463	> for PalletBlockProducerMetadataBenchmarkHelper
464{
465	fn genesis_utxo() -> UtxoId {
466		Sidechain::genesis_utxo()
467	}
468
469	fn metadata() -> BlockProducerMetadataType {
470		BlockProducerMetadataType {
471			url: "https://cool.stuff/spo.json".try_into().unwrap(),
472			hash: SizedByteString::from([0; 32]),
473		}
474	}
475
476	fn cross_chain_pub_key() -> sidechain_domain::CrossChainPublicKey {
477		sidechain_domain::CrossChainPublicKey(
478			hex_literal::hex!("020a1091341fe5664bfa1782d5e04779689068c916b04cb365ec3153755684d9a1")
479				.to_vec(),
480		)
481	}
482
483	fn cross_chain_sign_key() -> pallet_block_producer_metadata::benchmarking::SecretKey {
484		pallet_block_producer_metadata::benchmarking::SecretKey::from_slice(&hex_literal::hex!(
485			"cb6df9de1efca7a3998a8ead4e02159d5fa99c3e0d4fd6432667390bb4726854"
486		))
487		.unwrap()
488	}
489
490	fn upsert_valid_before() -> u64 {
491		11751276163
492	}
493
494	fn delete_valid_before() -> u64 {
495		11751276230
496	}
497}
498
499impl pallet_block_production_log::Config for Runtime {
500	type BlockProducerId = BlockAuthor;
501
502	type Moment = Slot;
503
504	type GetMoment = FromStorage<pallet_aura::CurrentSlot<Runtime>>;
505	type GetAuthor = FromFindAuthorIndex<Runtime, Aura, u32>;
506}
507
508parameter_types! {
509	/// Amount of tokens to burn when making irreversible, forever association
510	pub const AddressAssociationBurnAmount: Balance = 1_000_000;
511}
512
513impl pallet_address_associations::Config for Runtime {
514	type WeightInfo = pallet_address_associations::weights::SubstrateWeight<Runtime>;
515
516	type PartnerChainAddress = AccountId;
517	type Currency = Balances;
518	type BurnAmount = AddressAssociationBurnAmount;
519
520	fn genesis_utxo() -> UtxoId {
521		Sidechain::genesis_utxo()
522	}
523
524	type OnNewAssociation = TestHelperPallet;
525}
526
527#[cfg(feature = "runtime-benchmarks")]
528pub struct PalletBlockProducerFeesBenchmarkHelper;
529
530#[cfg(feature = "runtime-benchmarks")]
531impl pallet_block_producer_fees::benchmarking::BenchmarkHelper<AccountId>
532	for PalletBlockProducerFeesBenchmarkHelper
533{
534	fn account_id(i: u8) -> AccountId {
535		sp_core::sr25519::Public::from_raw([i; 32]).into()
536	}
537}
538
539impl pallet_block_producer_fees::Config for Runtime {
540	type WeightInfo = ();
541
542	type HistoricalChangesPerProducer = ConstU16<5>;
543
544	type Moment = Slot;
545
546	fn current_moment() -> Slot {
547		let slot: u64 = pallet_aura::CurrentSlot::<Runtime>::get().into();
548		sp_consensus_slots::Slot::from(slot)
549	}
550
551	#[cfg(feature = "runtime-benchmarks")]
552	type BenchmarkHelper = PalletBlockProducerFeesBenchmarkHelper;
553}
554
555parameter_types! {
556	/// Amount of tokens to hold when upserting block producer metadata.
557	pub const MetadataHoldAmount: Balance = 1_000_000;
558}
559
560impl pallet_block_producer_metadata::Config for Runtime {
561	type WeightInfo = pallet_block_producer_metadata::weights::SubstrateWeight<Runtime>;
562
563	type BlockProducerMetadata = BlockProducerMetadataType;
564
565	fn genesis_utxo() -> UtxoId {
566		Sidechain::genesis_utxo()
567	}
568
569	fn current_time() -> u64 {
570		pallet_timestamp::Now::<Runtime>::get() / 1000
571	}
572
573	type Currency = Balances;
574	type HoldAmount = MetadataHoldAmount;
575	type RuntimeHoldReason = RuntimeHoldReason;
576
577	#[cfg(feature = "runtime-benchmarks")]
578	type BenchmarkHelper = PalletBlockProducerMetadataBenchmarkHelper;
579}
580
581impl pallet_block_participation::Config for Runtime {
582	type WeightInfo = pallet_block_participation::weights::SubstrateWeight<Runtime>;
583	type DelegatorId = DelegatorKey;
584	type BlockAuthor = BlockAuthor;
585
586	type Moment = Slot;
587
588	type BlockParticipationProvider = TestHelperPallet;
589
590	const TARGET_INHERENT_ID: InherentIdentifier = TestHelperPallet::INHERENT_IDENTIFIER;
591}
592
593parameter_types! {
594	pub const MaxChanges: u32 = 16;
595	pub const MaxKeyLength: u32 = 64;
596	pub const MaxValueLength: u32 = 512;
597}
598
599impl pallet_governed_map::Config for Runtime {
600	type MaxChanges = MaxChanges;
601	type MaxKeyLength = MaxKeyLength;
602	type MaxValueLength = MaxValueLength;
603	type WeightInfo = pallet_governed_map::weights::SubstrateWeight<Runtime>;
604
605	type OnGovernedMappingChange = TestHelperPallet;
606	type MainChainScriptsOrigin = EnsureRoot<Self::AccountId>;
607
608	#[cfg(feature = "runtime-benchmarks")]
609	type BenchmarkHelper = ();
610}
611
612parameter_types! {
613	pub const ReserveAccount: AccountId = AccountId::new([1;32]);
614}
615
616impl crate::test_helper_pallet::Config for Runtime {
617	type ReserveAccount = ReserveAccount;
618}
619
620parameter_types! {
621pub const MaxTransfersPerBlock: u32 = 256;}
622
623impl pallet_partner_chains_bridge::Config for Runtime {
624	type GovernanceOrigin = EnsureRoot<Runtime>;
625	type Recipient = AccountId;
626	type TransferHandler = TestHelperPallet;
627	type MaxTransfersPerBlock = MaxTransfersPerBlock;
628	type WeightInfo = ();
629
630	#[cfg(feature = "runtime-benchmarks")]
631	type BenchmarkHelper = ();
632}
633
634impl pallet_parameters::Config for Runtime {
635	type RuntimeEvent = RuntimeEvent;
636	type RuntimeParameters = RuntimeParameters;
637	type AdminOrigin = EnsureRoot<AccountId>;
638	type WeightInfo = ();
639}
640
641parameter_types! {
642	pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) *
643		BlockWeights::get().max_block;
644	pub const MaxScheduledPerBlock: u32 = 50;
645}
646
647impl pallet_scheduler::Config for Runtime {
648	type RuntimeOrigin = RuntimeOrigin;
649	type RuntimeEvent = RuntimeEvent;
650	type PalletsOrigin = OriginCaller;
651	type RuntimeCall = RuntimeCall;
652	type MaximumWeight = MaximumSchedulerWeight;
653	type ScheduleOrigin = EnsureRoot<AccountId>;
654	type MaxScheduledPerBlock = MaxScheduledPerBlock;
655	type WeightInfo = ();
656	type OriginPrivilegeCmp = frame_support::traits::EqualPrivilegeOnly;
657	type Preimages = Preimage;
658	type BlockNumberProvider = frame_system::Pallet<Runtime>;
659}
660
661parameter_types! {
662	pub const PreimageHoldReason: RuntimeHoldReason = RuntimeHoldReason::Preimage(pallet_preimage::HoldReason::Preimage);
663}
664
665impl pallet_preimage::Config for Runtime {
666	type WeightInfo = ();
667	type RuntimeEvent = RuntimeEvent;
668	type Currency = Balances;
669	type ManagerOrigin = EnsureRoot<AccountId>;
670	type Consideration = HoldConsideration<
671		AccountId,
672		Balances,
673		PreimageHoldReason,
674		LinearStoragePrice<
675			dynamic_params::preimage::BaseDeposit,
676			dynamic_params::preimage::ByteDeposit,
677			Balance,
678		>,
679	>;
680}
681
682#[dynamic_params(RuntimeParameters, pallet_parameters::Parameters::<Runtime>)]
683pub mod dynamic_params {
684	use super::*;
685
686	#[dynamic_pallet_params]
687	#[codec(index = 0)]
688	pub mod preimage {
689		use super::*;
690
691		#[codec(index = 0)]
692		pub static BaseDeposit: Balance = deposit(2, 64);
693
694		#[codec(index = 1)]
695		pub static ByteDeposit: Balance = deposit(0, 1);
696	}
697}
698
699// Create the runtime by composing the FRAME pallets that were previously configured.
700construct_runtime!(
701	pub struct Runtime {
702		System: frame_system,
703		Timestamp: pallet_timestamp,
704		Aura: pallet_aura,
705		Grandpa: pallet_grandpa,
706		Balances: pallet_balances,
707		TransactionPayment: pallet_transaction_payment,
708		Sudo: pallet_sudo,
709		// Custom Pallets
710		// Sidechain pallet must come after the Aura pallet, since it gets the slot number from it
711		Sidechain: pallet_sidechain,
712		SessionCommitteeManagement: pallet_session_validator_management,
713		AddressAssociations: pallet_address_associations,
714		BlockProducerFees: pallet_block_producer_fees,
715		BlockProducerMetadata: pallet_block_producer_metadata,
716		BlockProductionLog: pallet_block_production_log,
717		BlockParticipation: pallet_block_participation,
718		// We exclude pallet's extrinsics to make them unavailable to users to submit.
719		// This is to ensure that registrations on Cardano coming in throught the
720		// `SessionCommitteeManagement` pallet are the only source of truth about keys
721		// and accounts of block producers.
722		Session: pallet_session exclude_parts { Call },
723		GovernedMap: pallet_governed_map,
724		Bridge: pallet_partner_chains_bridge,
725		Parameters: pallet_parameters,
726		Preimage: pallet_preimage,
727		Scheduler: pallet_scheduler,
728		TestHelperPallet: crate::test_helper_pallet,
729	}
730);
731
732/// The address format for describing accounts.
733pub type Address = sp_runtime::MultiAddress<AccountId, ()>;
734/// Block header type as expected by this runtime.
735pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
736/// Block type as expected by this runtime.
737pub type Block = generic::Block<Header, UncheckedExtrinsic>;
738/// The SignedExtension to the basic transaction logic.
739pub type SignedExtra = (
740	frame_system::CheckNonZeroSender<Runtime>,
741	frame_system::CheckSpecVersion<Runtime>,
742	frame_system::CheckTxVersion<Runtime>,
743	frame_system::CheckGenesis<Runtime>,
744	frame_system::CheckEra<Runtime>,
745	frame_system::CheckNonce<Runtime>,
746	frame_system::CheckWeight<Runtime>,
747	pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
748);
749
750/// Unchecked extrinsic type as expected by this runtime.
751pub type UncheckedExtrinsic =
752	generic::UncheckedExtrinsic<Address, RuntimeCall, Signature, SignedExtra>;
753/// The payload being signed in transactions.
754pub type SignedPayload = generic::SignedPayload<RuntimeCall, SignedExtra>;
755pub type Migrations = (
756	pallet_session_validator_management::migrations::v1::LegacyToV1Migration<Runtime>,
757	pallet_sidechain::migrations::v1::LegacyToV1Migration<Runtime, SLOT_DURATION>,
758	// More migrations can be added here
759);
760/// Executive: handles dispatch to the various modules.
761pub type Executive = frame_executive::Executive<
762	Runtime,
763	Block,
764	frame_system::ChainContext<Runtime>,
765	Runtime,
766	AllPalletsWithSystem,
767	Migrations,
768>;
769
770#[cfg(feature = "runtime-benchmarks")]
771mod benches {
772	define_benchmarks!(
773		[frame_benchmarking, BaselineBench::<Runtime>]
774		[frame_system, SystemBench::<Runtime>]
775		[pallet_balances, Balances]
776		[pallet_timestamp, Timestamp]
777		[pallet_sudo, Sudo]
778		[pallet_address_associations, AddressAssociations]
779		[pallet_block_producer_fees, BlockProducerFees]
780		[pallet_block_producer_metadata, BlockProducerMetadata]
781		[pallet_block_participation, BlockParticipation]
782		[pallet_governed_map, GovernedMap]
783		[pallet_partner_chains_bridge, Bridge]
784		[pallet_session_validator_management, SessionCommitteeManagement]
785	);
786}
787
788impl_runtime_apis! {
789	impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
790		fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
791			build_state::<RuntimeGenesisConfig>(config)
792		}
793
794		fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
795			get_preset::<RuntimeGenesisConfig>(id, crate::genesis_config_presets::get_preset)
796		}
797
798		fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
799			crate::genesis_config_presets::preset_names()
800		}
801	}
802
803	impl sp_api::Core<Block> for Runtime {
804		fn version() -> RuntimeVersion {
805			VERSION
806		}
807
808		fn execute_block(block: Block) {
809			Executive::execute_block(block);
810		}
811
812		fn initialize_block(header: &<Block as BlockT>::Header) -> sp_runtime::ExtrinsicInclusionMode {
813			Executive::initialize_block(header)
814		}
815	}
816
817	impl sp_api::Metadata<Block> for Runtime {
818		fn metadata() -> OpaqueMetadata {
819			OpaqueMetadata::new(Runtime::metadata().into())
820		}
821
822		fn metadata_at_version(version: u32) -> Option<OpaqueMetadata> {
823			Runtime::metadata_at_version(version)
824		}
825
826		fn metadata_versions() -> sp_std::vec::Vec<u32> {
827			Runtime::metadata_versions()
828		}
829	}
830
831	impl sp_block_builder::BlockBuilder<Block> for Runtime {
832		fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {
833			Executive::apply_extrinsic(extrinsic)
834		}
835
836		fn finalize_block() -> <Block as BlockT>::Header {
837			Executive::finalize_block()
838		}
839
840		fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {
841			data.create_extrinsics()
842		}
843
844		fn check_inherents(
845			block: Block,
846			data: sp_inherents::InherentData,
847		) -> sp_inherents::CheckInherentsResult {
848			data.check_extrinsics(&block)
849		}
850	}
851
852	impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
853		fn validate_transaction(
854			source: TransactionSource,
855			tx: <Block as BlockT>::Extrinsic,
856			block_hash: <Block as BlockT>::Hash,
857		) -> TransactionValidity {
858			Executive::validate_transaction(source, tx, block_hash)
859		}
860	}
861
862	impl sp_offchain::OffchainWorkerApi<Block> for Runtime {
863		fn offchain_worker(header: &<Block as BlockT>::Header) {
864			Executive::offchain_worker(header)
865		}
866	}
867
868	impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {
869		fn slot_duration() -> sp_consensus_aura::SlotDuration {
870			sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration())
871		}
872
873		fn authorities() -> Vec<AuraId> {
874			pallet_aura::Authorities::<Runtime>::get().into_inner()
875		}
876	}
877
878	impl sp_session::SessionKeys<Block> for Runtime {
879		fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
880			// despite being named "generate" this function also adds generated keys to local keystore
881			opaque::CrossChainKey::generate(seed.clone());
882			opaque::SessionKeys::generate(seed)
883		}
884
885		fn decode_session_keys(
886			encoded: Vec<u8>,
887		) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {
888			opaque::SessionKeys::decode_into_raw_public_keys(&encoded)
889		}
890	}
891
892	impl sp_consensus_grandpa::GrandpaApi<Block> for Runtime {
893		fn grandpa_authorities() -> sp_consensus_grandpa::AuthorityList {
894			Grandpa::grandpa_authorities()
895		}
896
897		fn current_set_id() -> sp_consensus_grandpa::SetId {
898			Grandpa::current_set_id()
899		}
900
901		fn submit_report_equivocation_unsigned_extrinsic(
902			_equivocation_proof: sp_consensus_grandpa::EquivocationProof<
903				<Block as BlockT>::Hash,
904				NumberFor<Block>,
905			>,
906			_key_owner_proof: sp_consensus_grandpa::OpaqueKeyOwnershipProof,
907		) -> Option<()> {
908			None
909		}
910
911		fn generate_key_ownership_proof(
912			_set_id: sp_consensus_grandpa::SetId,
913			_authority_id: GrandpaId,
914		) -> Option<sp_consensus_grandpa::OpaqueKeyOwnershipProof> {
915			// NOTE: this is the only implementation possible since we've
916			// defined our key owner proof type as a bottom type (i.e. a type
917			// with no values).
918			None
919		}
920	}
921
922	impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Nonce> for Runtime {
923		fn account_nonce(account: AccountId) -> Nonce {
924			System::account_nonce(account)
925		}
926	}
927
928	impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance> for Runtime {
929		fn query_info(
930			uxt: <Block as BlockT>::Extrinsic,
931			len: u32,
932		) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo<Balance> {
933			TransactionPayment::query_info(uxt, len)
934		}
935		fn query_fee_details(
936			uxt: <Block as BlockT>::Extrinsic,
937			len: u32,
938		) -> pallet_transaction_payment::FeeDetails<Balance> {
939			TransactionPayment::query_fee_details(uxt, len)
940		}
941		fn query_weight_to_fee(weight: sp_weights::Weight) -> Balance {
942			TransactionPayment::weight_to_fee(weight)
943		}
944		fn query_length_to_fee(length: u32) -> Balance {
945			TransactionPayment::length_to_fee(length)
946		}
947	}
948
949	impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentCallApi<Block, Balance, RuntimeCall>
950		for Runtime
951	{
952		fn query_call_info(
953			call: RuntimeCall,
954			len: u32,
955		) -> pallet_transaction_payment::RuntimeDispatchInfo<Balance> {
956			TransactionPayment::query_call_info(call, len)
957		}
958		fn query_call_fee_details(
959			call: RuntimeCall,
960			len: u32,
961		) -> pallet_transaction_payment::FeeDetails<Balance> {
962			TransactionPayment::query_call_fee_details(call, len)
963		}
964		fn query_weight_to_fee(weight: sp_weights::Weight) -> Balance {
965			TransactionPayment::weight_to_fee(weight)
966		}
967		fn query_length_to_fee(length: u32) -> Balance {
968			TransactionPayment::length_to_fee(length)
969		}
970	}
971
972	#[cfg(feature = "runtime-benchmarks")]
973	impl frame_benchmarking::Benchmark<Block> for Runtime {
974		fn benchmark_metadata(extra: bool) -> (
975			Vec<frame_benchmarking::BenchmarkList>,
976			Vec<frame_support::traits::StorageInfo>,
977		) {
978			use frame_benchmarking::{baseline, BenchmarkList};
979			use frame_support::traits::StorageInfoTrait;
980			use frame_system_benchmarking::Pallet as SystemBench;
981			use baseline::Pallet as BaselineBench;
982
983			let mut list = Vec::<BenchmarkList>::new();
984			list_benchmarks!(list, extra);
985
986			let storage_info = AllPalletsWithSystem::storage_info();
987
988			(list, storage_info)
989		}
990
991		fn dispatch_benchmark(
992			config: frame_benchmarking::BenchmarkConfig
993		) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> {
994			use frame_benchmarking::{baseline, BenchmarkBatch};
995			use sp_storage::TrackedStorageKey;
996			use frame_system_benchmarking::Pallet as SystemBench;
997			use baseline::Pallet as BaselineBench;
998			use frame_support::traits::WhitelistedStorageKeys;
999
1000			#[allow(non_local_definitions)]
1001			impl frame_system_benchmarking::Config for Runtime {}
1002			#[allow(non_local_definitions)]
1003			impl frame_benchmarking::baseline::Config for Runtime {}
1004
1005			let whitelist: Vec<TrackedStorageKey> = AllPalletsWithSystem::whitelisted_storage_keys();
1006
1007			let mut batches = Vec::<BenchmarkBatch>::new();
1008			let params = (&config, &whitelist);
1009			add_benchmarks!(params, batches);
1010
1011			Ok(batches)
1012		}
1013	}
1014
1015	#[cfg(feature = "try-runtime")]
1016	impl frame_try_runtime::TryRuntime<Block> for Runtime {
1017		fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) {
1018			// NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to
1019			// have a backtrace here. If any of the pre/post migration checks fail, we shall stop
1020			// right here and right now.
1021			let weight = Executive::try_runtime_upgrade(checks).unwrap();
1022			(weight, BlockWeights::get().max_block)
1023		}
1024
1025		fn execute_block(
1026			block: Block,
1027			state_root_check: bool,
1028			signature_check: bool,
1029			select: frame_try_runtime::TryStateSelect
1030		) -> Weight {
1031			// NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to
1032			// have a backtrace here.
1033			Executive::try_execute_block(block, state_root_check, signature_check, select).expect("execute-block failed")
1034		}
1035	}
1036
1037	impl sp_sidechain::GetGenesisUtxo<Block> for Runtime {
1038		fn genesis_utxo() -> UtxoId {
1039			Sidechain::genesis_utxo()
1040		}
1041	}
1042
1043	impl sp_sidechain::GetSidechainStatus<Block> for Runtime {
1044		fn get_sidechain_status() -> SidechainStatus {
1045			SidechainStatus {
1046				epoch: Sidechain::current_epoch_number(),
1047				slot: *pallet_aura::CurrentSlot::<Runtime>::get(),
1048				slots_per_epoch: (Sidechain::epoch_duration_millis() / SLOT_DURATION) as u32,
1049			}
1050		}
1051	}
1052
1053	impl sp_sidechain::GetEpochDurationApi<Block> for Runtime {
1054		fn get_epoch_duration_millis() -> u64 {
1055			Sidechain::epoch_duration_millis()
1056		}
1057	}
1058
1059	impl sp_block_producer_metadata::BlockProducerMetadataApi<Block, BlockProducerMetadataType> for Runtime
1060	{
1061		fn get_metadata_for(
1062			cross_chain_pub_key: &CrossChainPublicKey,
1063		) -> Option<BlockProducerMetadataType> {
1064			BlockProducerMetadata::get_metadata_for(&cross_chain_pub_key)
1065		}
1066	}
1067
1068	impl sp_block_producer_fees::BlockProducerFeesApi<Block, AccountId> for Runtime
1069	{
1070		fn get_all_fees() -> Vec<(AccountId, sp_block_producer_fees::PerTenThousands)> {
1071			BlockProducerFees::get_all_latest().map(|(account_id, (_slot, fee))| (account_id, fee)).collect()
1072		}
1073	}
1074
1075	#[api_version(3)]
1076	impl sp_session_validator_management::SessionValidatorManagementApi<
1077		Block,
1078		CrossChainPublic,
1079		SessionKeys,
1080		sidechain_domain::ScEpochNumber
1081	> for Runtime {
1082		fn get_current_committee() -> (ScEpochNumber, Vec<CommitteeMember<CrossChainPublic, SessionKeys>>) {
1083			SessionCommitteeManagement::current_committee_storage().as_pair()
1084		}
1085		fn get_next_committee() -> Option<(ScEpochNumber, Vec<CommitteeMember<CrossChainPublic, SessionKeys>>)> {
1086			Some(SessionCommitteeManagement::next_committee_storage()?.as_pair())
1087		}
1088		fn get_next_unset_epoch_number() -> sidechain_domain::ScEpochNumber {
1089			SessionCommitteeManagement::get_next_unset_epoch_number()
1090		}
1091		fn calculate_committee(authority_selection_inputs: AuthoritySelectionInputs, sidechain_epoch: ScEpochNumber) -> Option<Vec<CommitteeMember<CrossChainPublic, SessionKeys>>> {
1092			SessionCommitteeManagement::calculate_committee(authority_selection_inputs, sidechain_epoch)
1093		}
1094		fn get_main_chain_scripts() -> sp_session_validator_management::MainChainScripts {
1095			SessionCommitteeManagement::get_main_chain_scripts()
1096		}
1097	}
1098
1099	impl authority_selection_inherents::CandidateValidationApi<Block> for Runtime {
1100		fn validate_registered_candidate_data(stake_pool_public_key: &StakePoolPublicKey, registration_data: &RegistrationData) -> Option<RegistrationDataError> {
1101			authority_selection_inherents::validate_registration_data::<SessionKeys>(stake_pool_public_key, registration_data, Sidechain::genesis_utxo()).err()
1102		}
1103		fn validate_stake(stake: Option<StakeDelegation>) -> Option<StakeError> {
1104			authority_selection_inherents::validate_stake(stake).err()
1105		}
1106		fn validate_permissioned_candidate_data(candidate: PermissionedCandidateData) -> Option<PermissionedCandidateDataError> {
1107			validate_permissioned_candidate_data::<SessionKeys>(candidate).err()
1108		}
1109	}
1110
1111	impl sp_block_participation::BlockParticipationApi<Block, BlockAuthor, Slot> for Runtime {
1112		fn blocks_to_process(slot: &Slot) -> Vec<(Slot, BlockAuthor)> {
1113			BlockParticipation::blocks_to_process(slot)
1114		}
1115		fn target_inherent_id() -> InherentIdentifier {
1116			BlockParticipation::target_inherent_id()
1117		}
1118		fn moment_to_timestamp_millis(moment: Slot) -> u64 {
1119			let slot_duration_millis = <Self as sp_consensus_aura::runtime_decl_for_aura_api::AuraApi<Block, AuraId>>::slot_duration().as_millis();
1120			*moment * slot_duration_millis
1121		}
1122	}
1123
1124	impl sp_governed_map::GovernedMapIDPApi<Block> for Runtime {
1125		fn is_initialized() -> bool {
1126			GovernedMap::is_initialized()
1127		}
1128		fn get_current_state() -> BTreeMap<String, ByteString> {
1129			GovernedMap::get_all_key_value_pairs_unbounded().collect()
1130		}
1131		fn get_main_chain_scripts() -> Option<MainChainScriptsV1> {
1132			GovernedMap::get_main_chain_scripts()
1133		}
1134		fn get_pallet_version() -> u32 {
1135			GovernedMap::get_version()
1136		}
1137	}
1138
1139	impl sp_partner_chains_bridge::TokenBridgeIDPRuntimeApi<Block> for Runtime {
1140		fn get_pallet_version() -> u32 {
1141			Bridge::get_pallet_version()
1142		}
1143		fn get_main_chain_scripts() -> Option<BridgeMainChainScripts> {
1144			Bridge::get_main_chain_scripts()
1145		}
1146		fn get_max_transfers_per_block() -> u32 {
1147			Bridge::get_max_transfers_per_block()
1148		}
1149		fn get_last_data_checkpoint() -> Option<BridgeDataCheckpoint> {
1150			Bridge::get_data_checkpoint()
1151		}
1152	}
1153}
1154
1155#[cfg(test)]
1156mod tests;