1#![cfg_attr(not(feature = "std"), no_std)]
2#![feature(const_trait_impl, variant_count)]
3#![allow(incomplete_features)]
5#![feature(generic_const_exprs)]
8#![recursion_limit = "256"]
10#![allow(
12 non_camel_case_types,
13 reason = "https://github.com/rust-lang/rust-analyzer/issues/16514"
14)]
15
16mod domains;
17mod fees;
18mod object_mapping;
19mod weights;
20
21extern crate alloc;
22
23#[cfg(feature = "std")]
25include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
26
27use crate::fees::{OnChargeTransaction, TransactionByteFee};
28use crate::object_mapping::extract_block_object_mapping;
29use alloc::borrow::Cow;
30use core::mem;
31use core::num::NonZeroU64;
32use domain_runtime_primitives::opaque::Header as DomainHeader;
33use domain_runtime_primitives::{
34 AccountIdConverter, BlockNumber as DomainNumber, EthereumAccountId, Hash as DomainHash,
35 MAX_OUTGOING_MESSAGES, maximum_domain_block_weight,
36};
37use frame_support::genesis_builder_helper::{build_state, get_preset};
38use frame_support::inherent::ProvideInherent;
39use frame_support::traits::fungible::HoldConsideration;
40use frame_support::traits::{
41 ConstU8, ConstU16, ConstU32, ConstU64, Currency, EitherOfDiverse, EqualPrivilegeOnly,
42 Everything, Get, LinearStoragePrice, OnUnbalanced, VariantCount,
43};
44use frame_support::weights::constants::ParityDbWeight;
45use frame_support::weights::{ConstantMultiplier, Weight};
46use frame_support::{PalletId, construct_runtime, parameter_types};
47use frame_system::EnsureRoot;
48use frame_system::limits::{BlockLength, BlockWeights};
49use frame_system::pallet_prelude::RuntimeCallFor;
50use pallet_collective::{EnsureMember, EnsureProportionAtLeast};
51pub use pallet_rewards::RewardPoint;
52pub use pallet_subspace::{AllowAuthoringBy, EnableRewardsAt};
53use pallet_transporter::EndpointHandler;
54use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
55use scale_info::TypeInfo;
56use sp_api::impl_runtime_apis;
57use sp_consensus_slots::{Slot, SlotDuration};
58use sp_consensus_subspace::{ChainConstants, PotParameters, SignedVote, SolutionRanges, Vote};
59use sp_core::crypto::KeyTypeId;
60use sp_core::{ConstBool, H256, OpaqueMetadata};
61use sp_domains::bundle::BundleVersion;
62use sp_domains::bundle_producer_election::BundleProducerElectionParams;
63use sp_domains::execution_receipt::{
64 ExecutionReceiptFor, ExecutionReceiptVersion, SealedSingletonReceipt,
65};
66use sp_domains::{
67 BundleAndExecutionReceiptVersion, ChannelId, DomainAllowlistUpdates, DomainId,
68 DomainInstanceData, EpochIndex, INITIAL_DOMAIN_TX_RANGE, OperatorId, OperatorPublicKey,
69 PermissionedActionAllowedBy,
70};
71use sp_domains_fraud_proof::fraud_proof::FraudProof;
72use sp_domains_fraud_proof::storage_proof::{
73 FraudProofStorageKeyProvider, FraudProofStorageKeyRequest,
74};
75use sp_messenger::endpoint::{Endpoint, EndpointHandler as EndpointHandlerT, EndpointId};
76use sp_messenger::messages::{
77 BlockMessagesQuery, ChainId, ChannelStateWithNonce, CrossDomainMessage, MessageId, MessageKey,
78 MessagesWithStorageKey, Nonce as XdmNonce,
79};
80use sp_messenger::{ChannelNonce, XdmId};
81use sp_messenger_host_functions::{StorageKeyRequest, get_storage_key};
82use sp_mmr_primitives::EncodableOpaqueLeaf;
83use sp_runtime::traits::{
84 AccountIdConversion, AccountIdLookup, BlakeTwo256, ConstU128, Keccak256, NumberFor,
85};
86use sp_runtime::transaction_validity::{TransactionSource, TransactionValidity};
87use sp_runtime::type_with_default::TypeWithDefault;
88use sp_runtime::{AccountId32, ApplyExtrinsicResult, ExtrinsicInclusionMode, Perbill, generic};
89use sp_std::collections::btree_map::BTreeMap;
90use sp_std::collections::btree_set::BTreeSet;
91use sp_std::marker::PhantomData;
92use sp_std::prelude::*;
93use sp_subspace_mmr::ConsensusChainMmrLeafProof;
94use sp_subspace_mmr::subspace_mmr_runtime_interface::consensus_block_hash;
95use sp_version::RuntimeVersion;
96use static_assertions::const_assert;
97use subspace_core_primitives::objects::BlockObjectMapping;
98use subspace_core_primitives::pieces::Piece;
99use subspace_core_primitives::segments::{
100 HistorySize, SegmentCommitment, SegmentHeader, SegmentIndex,
101};
102use subspace_core_primitives::solutions::{
103 SolutionRange, pieces_to_solution_range, solution_range_to_pieces,
104};
105use subspace_core_primitives::{PublicKey, Randomness, SlotNumber, U256};
106pub use subspace_runtime_primitives::extension::BalanceTransferCheckExtension;
107use subspace_runtime_primitives::extension::{BalanceTransferChecks, MaybeBalancesCall};
108use subspace_runtime_primitives::utility::{
109 DefaultNonceProvider, MaybeMultisigCall, MaybeNestedCall, MaybeUtilityCall,
110};
111use subspace_runtime_primitives::{
112 AI3, AccountId, BLOCK_WEIGHT_FOR_2_SEC, Balance, BlockHashFor, BlockNumber,
113 ConsensusEventSegmentSize, ExtrinsicFor, FindBlockRewardAddress, Hash, HeaderFor,
114 HoldIdentifier, MAX_BLOCK_LENGTH, MIN_REPLICATION_FACTOR, Moment, NORMAL_DISPATCH_RATIO, Nonce,
115 SHANNON, SLOT_PROBABILITY, Signature, SlowAdjustingFeeUpdate, TargetBlockFullness,
116 XdmAdjustedWeightToFee, XdmFeeMultipler, maximum_normal_block_length,
117};
118
119sp_runtime::impl_opaque_keys! {
120 pub struct SessionKeys {
121 }
122}
123
124const MAX_PIECES_IN_SECTOR: u16 = 1000;
126
127#[sp_version::runtime_version]
130pub const VERSION: RuntimeVersion = RuntimeVersion {
131 spec_name: Cow::Borrowed("subspace"),
132 impl_name: Cow::Borrowed("subspace"),
133 authoring_version: 0,
134 spec_version: 7,
135 impl_version: 0,
136 apis: RUNTIME_API_VERSIONS,
137 transaction_version: 1,
138 system_version: 2,
139};
140
141const SLOT_DURATION: u64 = 1000;
146
147const BLOCK_AUTHORING_DELAY: SlotNumber = 4;
149
150const POT_ENTROPY_INJECTION_INTERVAL: BlockNumber = 50;
152
153const POT_ENTROPY_INJECTION_LOOKBACK_DEPTH: u8 = 2;
155
156const POT_ENTROPY_INJECTION_DELAY: SlotNumber = 15;
158
159const_assert!(POT_ENTROPY_INJECTION_INTERVAL as u64 > POT_ENTROPY_INJECTION_DELAY);
162const_assert!(POT_ENTROPY_INJECTION_DELAY > BLOCK_AUTHORING_DELAY + 1);
166
167const ERA_DURATION_IN_BLOCKS: BlockNumber = 2016;
169
170const TX_RANGE_ADJUSTMENT_INTERVAL_BLOCKS: u64 = 100;
172
173const INITIAL_SOLUTION_RANGE: SolutionRange =
175 pieces_to_solution_range(MAX_PIECES_IN_SECTOR as u64, SLOT_PROBABILITY);
176
177const EXPECTED_VOTES_PER_BLOCK: u32 = 9;
181
182const RECENT_SEGMENTS: HistorySize = HistorySize::new(NonZeroU64::new(5).expect("Not zero; qed"));
184const RECENT_HISTORY_FRACTION: (HistorySize, HistorySize) = (
186 HistorySize::new(NonZeroU64::new(1).expect("Not zero; qed")),
187 HistorySize::new(NonZeroU64::new(10).expect("Not zero; qed")),
188);
189const MIN_SECTOR_LIFETIME: HistorySize =
191 HistorySize::new(NonZeroU64::new(4).expect("Not zero; qed"));
192
193parameter_types! {
194 pub const Version: RuntimeVersion = VERSION;
195 pub const BlockHashCount: BlockNumber = 250;
196 pub SubspaceBlockWeights: BlockWeights = BlockWeights::with_sensible_defaults(BLOCK_WEIGHT_FOR_2_SEC, NORMAL_DISPATCH_RATIO);
198 pub SubspaceBlockLength: BlockLength = maximum_normal_block_length();
200}
201
202pub type SS58Prefix = ConstU16<6094>;
203
204impl frame_system::Config for Runtime {
207 type BaseCallFilter = Everything;
212 type BlockWeights = SubspaceBlockWeights;
214 type BlockLength = SubspaceBlockLength;
216 type AccountId = AccountId;
218 type RuntimeCall = RuntimeCall;
220 type RuntimeTask = RuntimeTask;
222 type Lookup = AccountIdLookup<AccountId, ()>;
224 type Nonce = TypeWithDefault<Nonce, DefaultNonceProvider<System, Nonce>>;
226 type Hash = Hash;
228 type Hashing = BlakeTwo256;
230 type Block = Block;
232 type RuntimeEvent = RuntimeEvent;
234 type RuntimeOrigin = RuntimeOrigin;
236 type BlockHashCount = BlockHashCount;
238 type DbWeight = ParityDbWeight;
240 type Version = Version;
242 type PalletInfo = PalletInfo;
246 type OnNewAccount = ();
248 type OnKilledAccount = ();
250 type AccountData = pallet_balances::AccountData<Balance>;
252 type SystemWeightInfo = weights::frame_system::WeightInfo<Runtime>;
254 type SS58Prefix = SS58Prefix;
256 type OnSetCode = subspace_runtime_primitives::SetCode<Runtime, Domains>;
258 type SingleBlockMigrations = ();
259 type MultiBlockMigrator = ();
260 type PreInherents = ();
261 type PostInherents = ();
262 type PostTransactions = ();
263 type MaxConsumers = ConstU32<16>;
264 type ExtensionsWeightInfo = frame_system::ExtensionsWeight<Runtime>;
265 type EventSegmentSize = ConsensusEventSegmentSize;
266}
267
268parameter_types! {
269 pub const BlockAuthoringDelay: SlotNumber = BLOCK_AUTHORING_DELAY;
270 pub const PotEntropyInjectionInterval: BlockNumber = POT_ENTROPY_INJECTION_INTERVAL;
271 pub const PotEntropyInjectionLookbackDepth: u8 = POT_ENTROPY_INJECTION_LOOKBACK_DEPTH;
272 pub const PotEntropyInjectionDelay: SlotNumber = POT_ENTROPY_INJECTION_DELAY;
273 pub const EraDuration: u32 = ERA_DURATION_IN_BLOCKS;
274 pub const SlotProbability: (u64, u64) = SLOT_PROBABILITY;
275 pub const ExpectedVotesPerBlock: u32 = EXPECTED_VOTES_PER_BLOCK;
276 pub const RecentSegments: HistorySize = RECENT_SEGMENTS;
277 pub const RecentHistoryFraction: (HistorySize, HistorySize) = RECENT_HISTORY_FRACTION;
278 pub const MinSectorLifetime: HistorySize = MIN_SECTOR_LIFETIME;
279 pub const ShouldAdjustSolutionRange: bool = false;
282 pub const BlockSlotCount: u32 = 6;
283}
284
285pub struct ConfirmationDepthK;
286
287impl Get<BlockNumber> for ConfirmationDepthK {
288 fn get() -> BlockNumber {
289 pallet_runtime_configs::ConfirmationDepthK::<Runtime>::get()
290 }
291}
292
293impl pallet_subspace::Config for Runtime {
294 type RuntimeEvent = RuntimeEvent;
295 type SubspaceOrigin = pallet_subspace::EnsureSubspaceOrigin;
296 type BlockAuthoringDelay = BlockAuthoringDelay;
297 type PotEntropyInjectionInterval = PotEntropyInjectionInterval;
298 type PotEntropyInjectionLookbackDepth = PotEntropyInjectionLookbackDepth;
299 type PotEntropyInjectionDelay = PotEntropyInjectionDelay;
300 type EraDuration = EraDuration;
301 type InitialSolutionRange = ConstU64<INITIAL_SOLUTION_RANGE>;
302 type SlotProbability = SlotProbability;
303 type ConfirmationDepthK = ConfirmationDepthK;
304 type RecentSegments = RecentSegments;
305 type RecentHistoryFraction = RecentHistoryFraction;
306 type MinSectorLifetime = MinSectorLifetime;
307 type ExpectedVotesPerBlock = ExpectedVotesPerBlock;
308 type MaxPiecesInSector = ConstU16<{ MAX_PIECES_IN_SECTOR }>;
309 type ShouldAdjustSolutionRange = ShouldAdjustSolutionRange;
310 type EraChangeTrigger = pallet_subspace::NormalEraChange;
311 type WeightInfo = weights::pallet_subspace::WeightInfo<Runtime>;
312 type BlockSlotCount = BlockSlotCount;
313 type ExtensionWeightInfo = weights::pallet_subspace_extension::WeightInfo<Runtime>;
314}
315
316impl pallet_timestamp::Config for Runtime {
317 type Moment = Moment;
319 type OnTimestampSet = ();
320 type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>;
321 type WeightInfo = weights::pallet_timestamp::WeightInfo<Runtime>;
322}
323
324parameter_types! {
325 pub const ExistentialDeposit: Balance = 10_000_000_000_000 * SHANNON;
332}
333
334#[derive(
335 PartialEq, Eq, Clone, Encode, Decode, TypeInfo, MaxEncodedLen, Ord, PartialOrd, Copy, Debug,
336)]
337pub struct HoldIdentifierWrapper(HoldIdentifier);
338
339impl pallet_domains::HoldIdentifier<Runtime> for HoldIdentifierWrapper {
340 fn staking_staked() -> Self {
341 Self(HoldIdentifier::DomainStaking)
342 }
343
344 fn domain_instantiation_id() -> Self {
345 Self(HoldIdentifier::DomainInstantiation)
346 }
347
348 fn storage_fund_withdrawal() -> Self {
349 Self(HoldIdentifier::DomainStorageFund)
350 }
351}
352
353impl pallet_messenger::HoldIdentifier<Runtime> for HoldIdentifierWrapper {
354 fn messenger_channel() -> Self {
355 Self(HoldIdentifier::MessengerChannel)
356 }
357}
358
359impl VariantCount for HoldIdentifierWrapper {
360 const VARIANT_COUNT: u32 = mem::variant_count::<HoldIdentifier>() as u32;
361}
362
363impl pallet_balances::Config for Runtime {
364 type RuntimeFreezeReason = RuntimeFreezeReason;
365 type MaxLocks = ConstU32<50>;
366 type MaxReserves = ();
367 type ReserveIdentifier = [u8; 8];
368 type Balance = Balance;
370 type RuntimeEvent = RuntimeEvent;
372 type DustRemoval = ();
373 type ExistentialDeposit = ExistentialDeposit;
374 type AccountStore = System;
375 type WeightInfo = weights::pallet_balances::WeightInfo<Runtime>;
376 type FreezeIdentifier = ();
377 type MaxFreezes = ();
378 type RuntimeHoldReason = HoldIdentifierWrapper;
379 type DoneSlashHandler = ();
380}
381
382parameter_types! {
383 pub CreditSupply: Balance = Balances::total_issuance();
384 pub TotalSpacePledged: u128 = {
385 let pieces = solution_range_to_pieces(Subspace::solution_ranges().current, SLOT_PROBABILITY);
386 pieces as u128 * Piece::SIZE as u128
387 };
388 pub BlockchainHistorySize: u128 = u128::from(Subspace::archived_history_size());
389 pub DynamicCostOfStorage: bool = RuntimeConfigs::enable_dynamic_cost_of_storage();
390 pub TransactionWeightFee: Balance = 100_000 * SHANNON;
391}
392
393impl pallet_transaction_fees::Config for Runtime {
394 type RuntimeEvent = RuntimeEvent;
395 type MinReplicationFactor = ConstU16<MIN_REPLICATION_FACTOR>;
396 type CreditSupply = CreditSupply;
397 type TotalSpacePledged = TotalSpacePledged;
398 type BlockchainHistorySize = BlockchainHistorySize;
399 type Currency = Balances;
400 type FindBlockRewardAddress = Subspace;
401 type DynamicCostOfStorage = DynamicCostOfStorage;
402 type WeightInfo = pallet_transaction_fees::weights::SubstrateWeight<Runtime>;
403}
404
405impl pallet_transaction_payment::Config for Runtime {
406 type RuntimeEvent = RuntimeEvent;
407 type OnChargeTransaction = OnChargeTransaction;
408 type OperationalFeeMultiplier = ConstU8<5>;
409 type WeightToFee = ConstantMultiplier<Balance, TransactionWeightFee>;
410 type LengthToFee = ConstantMultiplier<Balance, TransactionByteFee>;
411 type FeeMultiplierUpdate = SlowAdjustingFeeUpdate<Runtime, TargetBlockFullness>;
412 type WeightInfo = weights::pallet_transaction_payment::WeightInfo<Runtime>;
413}
414
415impl pallet_utility::Config for Runtime {
416 type RuntimeEvent = RuntimeEvent;
417 type RuntimeCall = RuntimeCall;
418 type PalletsOrigin = OriginCaller;
419 type WeightInfo = weights::pallet_utility::WeightInfo<Runtime>;
420}
421
422impl MaybeBalancesCall<Runtime> for RuntimeCall {
423 fn maybe_balance_call(&self) -> Option<&pallet_balances::Call<Runtime>> {
424 match self {
425 RuntimeCall::Balances(call) => Some(call),
426 _ => None,
427 }
428 }
429}
430
431impl BalanceTransferChecks for Runtime {
432 fn is_balance_transferable() -> bool {
433 let enabled = RuntimeConfigs::enable_balance_transfers();
434 if cfg!(feature = "runtime-benchmarks") {
437 false
438 } else {
439 enabled
440 }
441 }
442}
443
444impl MaybeMultisigCall<Runtime> for RuntimeCall {
445 fn maybe_multisig_call(&self) -> Option<&pallet_multisig::Call<Runtime>> {
447 match self {
448 RuntimeCall::Multisig(call) => Some(call),
449 _ => None,
450 }
451 }
452}
453
454impl MaybeUtilityCall<Runtime> for RuntimeCall {
455 fn maybe_utility_call(&self) -> Option<&pallet_utility::Call<Runtime>> {
457 match self {
458 RuntimeCall::Utility(call) => Some(call),
459 _ => None,
460 }
461 }
462}
463
464impl MaybeNestedCall<Runtime> for RuntimeCall {
465 fn maybe_nested_call(&self) -> Option<Vec<&RuntimeCallFor<Runtime>>> {
470 let calls = self.maybe_nested_utility_calls();
476 if calls.is_some() {
477 return calls;
478 }
479
480 let calls = self.maybe_nested_multisig_calls();
481 if calls.is_some() {
482 return calls;
483 }
484
485 None
486 }
487}
488
489impl pallet_sudo::Config for Runtime {
490 type RuntimeEvent = RuntimeEvent;
491 type RuntimeCall = RuntimeCall;
492 type WeightInfo = weights::pallet_sudo::WeightInfo<Runtime>;
493}
494
495pub type CouncilCollective = pallet_collective::Instance1;
496
497macro_rules! impl_get_council_democracy_field_block_number {
499 ($field_type_name:ident, $field:ident) => {
500 pub struct $field_type_name;
501
502 impl Get<BlockNumber> for $field_type_name {
503 fn get() -> BlockNumber {
504 pallet_runtime_configs::CouncilDemocracyConfig::<Runtime>::get().$field
505 }
506 }
507 };
508}
509
510impl_get_council_democracy_field_block_number! {CouncilMotionDuration, council_motion_duration}
511
512parameter_types! {
513 pub MaxProposalWeight: Weight = Perbill::from_percent(50) * SubspaceBlockWeights::get().max_block;
516}
517
518pub type EnsureRootOr<O> = EitherOfDiverse<EnsureRoot<AccountId>, O>;
519pub type AllCouncil = EnsureProportionAtLeast<AccountId, CouncilCollective, 1, 1>;
520pub type TwoThirdsCouncil = EnsureProportionAtLeast<AccountId, CouncilCollective, 2, 3>;
521pub type HalfCouncil = EnsureProportionAtLeast<AccountId, CouncilCollective, 1, 2>;
522
523impl pallet_collective::Config<CouncilCollective> for Runtime {
525 type DefaultVote = pallet_collective::PrimeDefaultVote;
526 type MaxMembers = ConstU32<100>;
527 type MaxProposalWeight = MaxProposalWeight;
528 type MaxProposals = ConstU32<100>;
529 type MotionDuration = CouncilMotionDuration;
531 type Proposal = RuntimeCall;
532 type RuntimeEvent = RuntimeEvent;
533 type RuntimeOrigin = RuntimeOrigin;
534 type SetMembersOrigin = EnsureRootOr<AllCouncil>;
535 type WeightInfo = weights::pallet_collective::WeightInfo<Runtime>;
536 type DisapproveOrigin = TwoThirdsCouncil;
537 type KillOrigin = TwoThirdsCouncil;
538 type Consideration = ();
541}
542
543parameter_types! {
545 pub PreimageBaseDeposit: Balance = 100 * AI3;
546 pub PreimageByteDeposit: Balance = AI3;
547 pub const PreImageHoldReason: HoldIdentifierWrapper = HoldIdentifierWrapper(HoldIdentifier::Preimage);
548}
549
550impl pallet_preimage::Config for Runtime {
551 type Consideration = HoldConsideration<
552 AccountId,
553 Balances,
554 PreImageHoldReason,
555 LinearStoragePrice<PreimageBaseDeposit, PreimageByteDeposit, Balance>,
556 >;
557 type Currency = Balances;
558 type ManagerOrigin = EnsureRoot<AccountId>;
559 type RuntimeEvent = RuntimeEvent;
560 type WeightInfo = weights::pallet_preimage::WeightInfo<Runtime>;
561}
562
563parameter_types! {
564 pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * SubspaceBlockWeights::get().max_block;
565 pub const NoPreimagePostponement: Option<u32> = Some(10);
567}
568
569impl pallet_scheduler::Config for Runtime {
580 type MaxScheduledPerBlock = ConstU32<50>;
581 type MaximumWeight = MaximumSchedulerWeight;
582 type OriginPrivilegeCmp = EqualPrivilegeOnly;
583 type PalletsOrigin = OriginCaller;
584 type Preimages = Preimage;
585 type RuntimeCall = RuntimeCall;
586 type RuntimeEvent = RuntimeEvent;
587 type RuntimeOrigin = RuntimeOrigin;
588 type ScheduleOrigin = EnsureRoot<AccountId>;
589 type WeightInfo = weights::pallet_scheduler::WeightInfo<Runtime>;
590}
591
592type NegativeImbalance = <Balances as Currency<AccountId>>::NegativeImbalance;
593
594pub struct DemocracySlash;
595impl OnUnbalanced<NegativeImbalance> for DemocracySlash {
596 fn on_nonzero_unbalanced(slashed: NegativeImbalance) {
597 Balances::resolve_creating(&TreasuryAccount::get(), slashed);
598 }
599}
600
601impl_get_council_democracy_field_block_number! {CooloffPeriod, democracy_cooloff_period}
602impl_get_council_democracy_field_block_number! {EnactmentPeriod, democracy_enactment_period}
603impl_get_council_democracy_field_block_number! {FastTrackVotingPeriod, democracy_fast_track_voting_period}
604impl_get_council_democracy_field_block_number! {LaunchPeriod, democracy_launch_period}
605impl_get_council_democracy_field_block_number! {VoteLockingPeriod, democracy_vote_locking_period}
606impl_get_council_democracy_field_block_number! {VotingPeriod, democracy_voting_period}
607
608impl pallet_democracy::Config for Runtime {
610 type BlacklistOrigin = EnsureRoot<AccountId>;
611 type CancelProposalOrigin = EnsureRoot<AccountId>;
613 type CancellationOrigin = EnsureRootOr<TwoThirdsCouncil>;
615 type CooloffPeriod = CooloffPeriod;
618 type Currency = Balances;
619 type EnactmentPeriod = EnactmentPeriod;
622 type ExternalDefaultOrigin = AllCouncil;
626 type ExternalMajorityOrigin = HalfCouncil;
630 type ExternalOrigin = HalfCouncil;
633 type FastTrackOrigin = EnsureRootOr<HalfCouncil>;
636 type FastTrackVotingPeriod = FastTrackVotingPeriod;
638 type InstantAllowed = ConstBool<true>;
639 type InstantOrigin = EnsureRootOr<AllCouncil>;
640 type LaunchPeriod = LaunchPeriod;
642 type MaxBlacklisted = ConstU32<100>;
643 type MaxDeposits = ConstU32<100>;
644 type MaxProposals = ConstU32<100>;
645 type MaxVotes = ConstU32<100>;
646 type MinimumDeposit = ConstU128<{ 1000 * AI3 }>;
649 type PalletsOrigin = OriginCaller;
650 type Preimages = Preimage;
651 type RuntimeEvent = RuntimeEvent;
652 type Scheduler = Scheduler;
653 type Slash = DemocracySlash;
655 type SubmitOrigin = EnsureMember<AccountId, CouncilCollective>;
658 type VetoOrigin = EnsureMember<AccountId, CouncilCollective>;
661 type VoteLockingPeriod = VoteLockingPeriod;
662 type VotingPeriod = VotingPeriod;
664 type WeightInfo = pallet_democracy::weights::SubstrateWeight<Runtime>;
665}
666
667parameter_types! {
668 pub const SelfChainId: ChainId = ChainId::Consensus;
669}
670
671pub struct OnXDMRewards;
672
673impl sp_messenger::OnXDMRewards<Balance> for OnXDMRewards {
674 fn on_xdm_rewards(reward: Balance) {
675 if let Some(block_author) = Subspace::find_block_reward_address() {
676 let _ = Balances::deposit_creating(&block_author, reward);
677 }
678 }
679
680 fn on_chain_protocol_fees(chain_id: ChainId, fees: Balance) {
681 if let ChainId::Domain(domain_id) = chain_id {
684 Domains::reward_domain_operators(domain_id, fees)
685 }
686 }
687}
688
689pub struct MmrProofVerifier;
690
691impl sp_subspace_mmr::MmrProofVerifier<mmr::Hash, NumberFor<Block>, Hash> for MmrProofVerifier {
692 fn verify_proof_and_extract_leaf(
693 mmr_leaf_proof: ConsensusChainMmrLeafProof<NumberFor<Block>, Hash, mmr::Hash>,
694 ) -> Option<mmr::Leaf> {
695 let mmr_root = SubspaceMmr::mmr_root_hash(mmr_leaf_proof.consensus_block_number)?;
696 Self::verify_proof_stateless(mmr_root, mmr_leaf_proof)
697 }
698
699 fn verify_proof_stateless(
700 mmr_root: mmr::Hash,
701 mmr_leaf_proof: ConsensusChainMmrLeafProof<NumberFor<Block>, Hash, mmr::Hash>,
702 ) -> Option<mmr::Leaf> {
703 let ConsensusChainMmrLeafProof {
704 opaque_mmr_leaf,
705 proof,
706 ..
707 } = mmr_leaf_proof;
708
709 pallet_mmr::verify_leaves_proof::<mmr::Hashing, _>(
710 mmr_root,
711 vec![mmr::DataOrHash::Data(
712 EncodableOpaqueLeaf(opaque_mmr_leaf.0.clone()).into_opaque_leaf(),
713 )],
714 proof,
715 )
716 .ok()?;
717
718 let leaf: mmr::Leaf = opaque_mmr_leaf.into_opaque_leaf().try_decode()?;
719
720 Some(leaf)
721 }
722}
723
724pub struct StorageKeys;
725
726impl sp_messenger::StorageKeys for StorageKeys {
727 fn confirmed_domain_block_storage_key(domain_id: DomainId) -> Option<Vec<u8>> {
728 Some(Domains::confirmed_domain_block_storage_key(domain_id))
729 }
730
731 fn outbox_storage_key(chain_id: ChainId, message_key: MessageKey) -> Option<Vec<u8>> {
732 get_storage_key(StorageKeyRequest::OutboxStorageKey {
733 chain_id,
734 message_key,
735 })
736 }
737
738 fn inbox_responses_storage_key(chain_id: ChainId, message_key: MessageKey) -> Option<Vec<u8>> {
739 get_storage_key(StorageKeyRequest::InboxResponseStorageKey {
740 chain_id,
741 message_key,
742 })
743 }
744}
745
746parameter_types! {
747 pub const ChannelReserveFee: Balance = 100 * AI3;
749 pub const ChannelInitReservePortion: Perbill = Perbill::from_percent(20);
750 pub const MaxOutgoingMessages: u32 = MAX_OUTGOING_MESSAGES;
751}
752
753const_assert!(MaxOutgoingMessages::get() >= 1);
755
756pub struct DomainRegistration;
757impl sp_messenger::DomainRegistration for DomainRegistration {
758 fn is_domain_registered(domain_id: DomainId) -> bool {
759 Domains::is_domain_registered(domain_id)
760 }
761}
762
763impl pallet_messenger::Config for Runtime {
764 type RuntimeEvent = RuntimeEvent;
765 type SelfChainId = SelfChainId;
766
767 fn get_endpoint_handler(endpoint: &Endpoint) -> Option<Box<dyn EndpointHandlerT<MessageId>>> {
768 if endpoint == &Endpoint::Id(TransporterEndpointId::get()) {
769 Some(Box::new(EndpointHandler(PhantomData::<Runtime>)))
770 } else {
771 None
772 }
773 }
774
775 type Currency = Balances;
776 type WeightInfo = weights::pallet_messenger::WeightInfo<Runtime>;
777 type WeightToFee = ConstantMultiplier<Balance, TransactionWeightFee>;
778 type AdjustedWeightToFee = XdmAdjustedWeightToFee<Runtime>;
779 type FeeMultiplier = XdmFeeMultipler;
780 type OnXDMRewards = OnXDMRewards;
781 type MmrHash = mmr::Hash;
782 type MmrProofVerifier = MmrProofVerifier;
783 #[cfg(feature = "runtime-benchmarks")]
784 type StorageKeys = sp_messenger::BenchmarkStorageKeys;
785 #[cfg(not(feature = "runtime-benchmarks"))]
786 type StorageKeys = StorageKeys;
787 type DomainOwner = Domains;
788 type HoldIdentifier = HoldIdentifierWrapper;
789 type ChannelReserveFee = ChannelReserveFee;
790 type ChannelInitReservePortion = ChannelInitReservePortion;
791 type DomainRegistration = DomainRegistration;
792 type MaxOutgoingMessages = MaxOutgoingMessages;
793 type MessengerOrigin = pallet_messenger::EnsureMessengerOrigin;
794 type NoteChainTransfer = Transporter;
795 type ExtensionWeightInfo = pallet_messenger::extensions::weights::SubstrateWeight<
796 Runtime,
797 (),
800 weights::pallet_messenger_from_domains_extension::WeightInfo<Runtime>,
801 >;
802}
803
804impl<C> frame_system::offchain::CreateTransactionBase<C> for Runtime
805where
806 RuntimeCall: From<C>,
807{
808 type Extrinsic = UncheckedExtrinsic;
809 type RuntimeCall = RuntimeCall;
810}
811
812impl<C> frame_system::offchain::CreateInherent<C> for Runtime
813where
814 RuntimeCall: From<C>,
815{
816 fn create_inherent(call: Self::RuntimeCall) -> Self::Extrinsic {
817 UncheckedExtrinsic::new_bare(call)
818 }
819}
820
821impl<C> subspace_runtime_primitives::CreateUnsigned<C> for Runtime
822where
823 RuntimeCall: From<C>,
824{
825 fn create_unsigned(call: Self::RuntimeCall) -> Self::Extrinsic {
826 create_unsigned_general_extrinsic(call)
827 }
828}
829
830parameter_types! {
831 pub const TransporterEndpointId: EndpointId = 1;
832 pub const MinimumTransfer: Balance = AI3;
833}
834
835impl pallet_transporter::Config for Runtime {
836 type RuntimeEvent = RuntimeEvent;
837 type SelfChainId = SelfChainId;
838 type SelfEndpointId = TransporterEndpointId;
839 type Currency = Balances;
840 type Sender = Messenger;
841 type AccountIdConverter = AccountIdConverter;
842 type WeightInfo = weights::pallet_transporter::WeightInfo<Runtime>;
843 type MinimumTransfer = MinimumTransfer;
844}
845
846pub struct BlockTreePruningDepth;
847impl Get<BlockNumber> for BlockTreePruningDepth {
848 fn get() -> BlockNumber {
849 pallet_runtime_configs::DomainBlockPruningDepth::<Runtime>::get()
850 }
851}
852
853pub struct StakeWithdrawalLockingPeriod;
854impl Get<BlockNumber> for StakeWithdrawalLockingPeriod {
855 fn get() -> BlockNumber {
856 pallet_runtime_configs::StakingWithdrawalPeriod::<Runtime>::get()
857 }
858}
859
860parameter_types! {
861 pub const MaximumReceiptDrift: BlockNumber = 128;
862 pub const InitialDomainTxRange: u64 = INITIAL_DOMAIN_TX_RANGE;
863 pub const DomainTxRangeAdjustmentInterval: u64 = TX_RANGE_ADJUSTMENT_INTERVAL_BLOCKS;
864 pub const MinOperatorStake: Balance = 100 * AI3;
867 pub const MinNominatorStake: Balance = AI3;
870 pub MaxDomainBlockSize: u32 = NORMAL_DISPATCH_RATIO * MAX_BLOCK_LENGTH;
872 pub MaxDomainBlockWeight: Weight = maximum_domain_block_weight();
874 pub const DomainInstantiationDeposit: Balance = 100 * AI3;
875 pub const MaxDomainNameLength: u32 = 32;
876 pub const StakeEpochDuration: DomainNumber = 100;
879 pub TreasuryAccount: AccountId = PalletId(*b"treasury").into_account_truncating();
880 pub const MaxPendingStakingOperation: u32 = 512;
881 pub const DomainsPalletId: PalletId = PalletId(*b"domains_");
882 pub const MaxInitialDomainAccounts: u32 = 10;
883 pub const MinInitialDomainAccountBalance: Balance = AI3;
884 pub const BundleLongevity: u32 = 5;
885 pub const WithdrawalLimit: u32 = 32;
886 pub const CurrentBundleAndExecutionReceiptVersion: BundleAndExecutionReceiptVersion = BundleAndExecutionReceiptVersion{
887 bundle_version: BundleVersion::V0,
888 execution_receipt_version: ExecutionReceiptVersion::V0,
889 };
890 pub const OperatorActivationDelayInEpochs: EpochIndex = 5;
892}
893
894const_assert!(BlockSlotCount::get() >= 2 && BlockSlotCount::get() > BundleLongevity::get());
897
898const_assert!(BlockHashCount::get() > BlockSlotCount::get());
901
902const_assert!(MinOperatorStake::get() >= MinNominatorStake::get());
904
905pub struct BlockSlot;
906
907impl pallet_domains::BlockSlot<Runtime> for BlockSlot {
908 fn future_slot(block_number: BlockNumber) -> Option<sp_consensus_slots::Slot> {
909 let block_slots = Subspace::block_slots();
910 block_slots
911 .get(&block_number)
912 .map(|slot| *slot + Slot::from(BlockAuthoringDelay::get()))
913 }
914
915 fn slot_produced_after(to_check: sp_consensus_slots::Slot) -> Option<BlockNumber> {
916 let block_slots = Subspace::block_slots();
917 for (block_number, slot) in block_slots.into_iter().rev() {
918 if to_check > slot {
919 return Some(block_number);
920 }
921 }
922 None
923 }
924
925 fn current_slot() -> Slot {
926 Subspace::current_slot()
927 }
928}
929
930pub struct OnChainRewards;
931
932impl sp_domains::OnChainRewards<Balance> for OnChainRewards {
933 fn on_chain_rewards(chain_id: ChainId, reward: Balance) {
934 match chain_id {
935 ChainId::Consensus => {
936 if let Some(block_author) = Subspace::find_block_reward_address() {
937 let _ = Balances::deposit_creating(&block_author, reward);
938 }
939 }
940 ChainId::Domain(domain_id) => Domains::reward_domain_operators(domain_id, reward),
941 }
942 }
943}
944
945impl pallet_domains::Config for Runtime {
946 type RuntimeEvent = RuntimeEvent;
947 type DomainOrigin = pallet_domains::EnsureDomainOrigin;
948 type DomainHash = DomainHash;
949 type Balance = Balance;
950 type DomainHeader = sp_runtime::generic::Header<DomainNumber, BlakeTwo256>;
951 type ConfirmationDepthK = ConfirmationDepthK;
952 type Currency = Balances;
953 type Share = Balance;
954 type HoldIdentifier = HoldIdentifierWrapper;
955 type BlockTreePruningDepth = BlockTreePruningDepth;
956 type ConsensusSlotProbability = SlotProbability;
957 type MaxDomainBlockSize = MaxDomainBlockSize;
958 type MaxDomainBlockWeight = MaxDomainBlockWeight;
959 type MaxDomainNameLength = MaxDomainNameLength;
960 type DomainInstantiationDeposit = DomainInstantiationDeposit;
961 type WeightInfo = weights::pallet_domains::WeightInfo<Runtime>;
962 type InitialDomainTxRange = InitialDomainTxRange;
963 type DomainTxRangeAdjustmentInterval = DomainTxRangeAdjustmentInterval;
964 type MinOperatorStake = MinOperatorStake;
965 type MinNominatorStake = MinNominatorStake;
966 type StakeWithdrawalLockingPeriod = StakeWithdrawalLockingPeriod;
967 type StakeEpochDuration = StakeEpochDuration;
968 type TreasuryAccount = TreasuryAccount;
969 type MaxPendingStakingOperation = MaxPendingStakingOperation;
970 type Randomness = Subspace;
971 type PalletId = DomainsPalletId;
972 type StorageFee = TransactionFees;
973 type BlockTimestamp = pallet_timestamp::Pallet<Runtime>;
974 type BlockSlot = BlockSlot;
975 type DomainsTransfersTracker = Transporter;
976 type MaxInitialDomainAccounts = MaxInitialDomainAccounts;
977 type MinInitialDomainAccountBalance = MinInitialDomainAccountBalance;
978 type BundleLongevity = BundleLongevity;
979 type DomainBundleSubmitted = Messenger;
980 type OnDomainInstantiated = Messenger;
981 type MmrHash = mmr::Hash;
982 type MmrProofVerifier = MmrProofVerifier;
983 type FraudProofStorageKeyProvider = StorageKeyProvider;
984 type OnChainRewards = OnChainRewards;
985 type WithdrawalLimit = WithdrawalLimit;
986 type CurrentBundleAndExecutionReceiptVersion = CurrentBundleAndExecutionReceiptVersion;
987 type OperatorActivationDelayInEpochs = OperatorActivationDelayInEpochs;
988}
989
990parameter_types! {
991 pub const AvgBlockspaceUsageNumBlocks: BlockNumber = 100;
992 pub const ProposerTaxOnVotes: (u32, u32) = (1, 10);
993}
994
995impl pallet_rewards::Config for Runtime {
996 type RuntimeEvent = RuntimeEvent;
997 type Currency = Balances;
998 type AvgBlockspaceUsageNumBlocks = AvgBlockspaceUsageNumBlocks;
999 type TransactionByteFee = TransactionByteFee;
1000 type MaxRewardPoints = ConstU32<20>;
1001 type ProposerTaxOnVotes = ProposerTaxOnVotes;
1002 type RewardsEnabled = Subspace;
1003 type FindBlockRewardAddress = Subspace;
1004 type FindVotingRewardAddresses = Subspace;
1005 type WeightInfo = weights::pallet_rewards::WeightInfo<Runtime>;
1006 type OnReward = ();
1007}
1008
1009impl pallet_runtime_configs::Config for Runtime {
1010 type WeightInfo = weights::pallet_runtime_configs::WeightInfo<Runtime>;
1011}
1012
1013impl pallet_domains::extensions::DomainsCheck for Runtime {
1014 fn is_domains_enabled() -> bool {
1015 RuntimeConfigs::enable_domains()
1016 }
1017}
1018
1019mod mmr {
1020 use super::Runtime;
1021 pub use pallet_mmr::primitives::*;
1022
1023 pub type Leaf = <<Runtime as pallet_mmr::Config>::LeafData as LeafDataProvider>::LeafData;
1024 pub type Hashing = <Runtime as pallet_mmr::Config>::Hashing;
1025 pub type Hash = <Hashing as sp_runtime::traits::Hash>::Output;
1026}
1027
1028pub struct BlockHashProvider;
1029
1030impl pallet_mmr::BlockHashProvider<BlockNumber, Hash> for BlockHashProvider {
1031 fn block_hash(block_number: BlockNumber) -> Hash {
1032 consensus_block_hash(block_number).expect("Hash must exist for a given block number.")
1033 }
1034}
1035
1036impl pallet_mmr::Config for Runtime {
1037 const INDEXING_PREFIX: &'static [u8] = mmr::INDEXING_PREFIX;
1038 type Hashing = Keccak256;
1039 type LeafData = SubspaceMmr;
1040 type OnNewRoot = SubspaceMmr;
1041 type BlockHashProvider = BlockHashProvider;
1042 type WeightInfo = weights::pallet_mmr::WeightInfo<Runtime>;
1043 #[cfg(feature = "runtime-benchmarks")]
1044 type BenchmarkHelper = ();
1045}
1046
1047parameter_types! {
1048 pub const MmrRootHashCount: u32 = 1024;
1049}
1050
1051impl pallet_subspace_mmr::Config for Runtime {
1052 type MmrRootHash = mmr::Hash;
1053 type MmrRootHashCount = MmrRootHashCount;
1054}
1055
1056parameter_types! {
1057 pub const MaxSignatories: u32 = 100;
1058}
1059
1060macro_rules! deposit {
1061 ($name:ident, $item_fee:expr, $items:expr, $bytes:expr) => {
1062 pub struct $name;
1063
1064 impl Get<Balance> for $name {
1065 fn get() -> Balance {
1066 $item_fee.saturating_mul($items.into()).saturating_add(
1067 TransactionFees::transaction_byte_fee().saturating_mul($bytes.into()),
1068 )
1069 }
1070 }
1071 };
1072}
1073
1074deposit!(DepositBaseFee, 20 * AI3, 1u32, 88u32);
1077
1078deposit!(DepositFactor, 0u128, 0u32, 32u32);
1080
1081impl pallet_multisig::Config for Runtime {
1082 type RuntimeEvent = RuntimeEvent;
1083 type RuntimeCall = RuntimeCall;
1084 type Currency = Balances;
1085 type DepositBase = DepositBaseFee;
1086 type DepositFactor = DepositFactor;
1087 type MaxSignatories = MaxSignatories;
1088 type WeightInfo = weights::pallet_multisig::WeightInfo<Runtime>;
1089}
1090
1091construct_runtime!(
1092 pub struct Runtime {
1093 System: frame_system = 0,
1094 Timestamp: pallet_timestamp = 1,
1095
1096 Subspace: pallet_subspace = 2,
1097 Rewards: pallet_rewards = 4,
1098
1099 Balances: pallet_balances = 5,
1100 TransactionFees: pallet_transaction_fees = 6,
1101 TransactionPayment: pallet_transaction_payment = 7,
1102 Utility: pallet_utility = 8,
1103
1104 Domains: pallet_domains = 12,
1105 RuntimeConfigs: pallet_runtime_configs = 14,
1106
1107 Mmr: pallet_mmr = 30,
1108 SubspaceMmr: pallet_subspace_mmr = 31,
1109
1110 Messenger: pallet_messenger exclude_parts { Inherent } = 60,
1113 Transporter: pallet_transporter = 61,
1114
1115 Scheduler: pallet_scheduler = 81,
1117 Council: pallet_collective::<Instance1> = 82,
1118 Democracy: pallet_democracy = 83,
1119 Preimage: pallet_preimage = 84,
1120
1121 Multisig: pallet_multisig = 90,
1123
1124 Sudo: pallet_sudo = 100,
1126 }
1127);
1128
1129pub type Address = sp_runtime::MultiAddress<AccountId, ()>;
1131pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
1133pub type Block = generic::Block<Header, UncheckedExtrinsic>;
1135
1136pub type SignedExtra = (
1138 frame_system::CheckNonZeroSender<Runtime>,
1139 frame_system::CheckSpecVersion<Runtime>,
1140 frame_system::CheckTxVersion<Runtime>,
1141 frame_system::CheckGenesis<Runtime>,
1142 frame_system::CheckMortality<Runtime>,
1143 frame_system::CheckNonce<Runtime>,
1144 frame_system::CheckWeight<Runtime>,
1145 pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
1146 BalanceTransferCheckExtension<Runtime>,
1147 pallet_subspace::extensions::SubspaceExtension<Runtime>,
1148 pallet_domains::extensions::DomainsExtension<Runtime>,
1149 pallet_messenger::extensions::MessengerExtension<Runtime>,
1150);
1151pub type UncheckedExtrinsic =
1153 generic::UncheckedExtrinsic<Address, RuntimeCall, Signature, SignedExtra>;
1154
1155pub type Executive = frame_executive::Executive<
1157 Runtime,
1158 Block,
1159 frame_system::ChainContext<Runtime>,
1160 Runtime,
1161 AllPalletsWithSystem,
1162 pallet_domains::migrations::VersionCheckedMigrateDomainsV5ToV6<Runtime>,
1163>;
1164
1165impl pallet_subspace::extensions::MaybeSubspaceCall<Runtime> for RuntimeCall {
1166 fn maybe_subspace_call(&self) -> Option<&pallet_subspace::Call<Runtime>> {
1167 match self {
1168 RuntimeCall::Subspace(call) => Some(call),
1169 _ => None,
1170 }
1171 }
1172}
1173
1174impl pallet_domains::extensions::MaybeDomainsCall<Runtime> for RuntimeCall {
1175 fn maybe_domains_call(&self) -> Option<&pallet_domains::Call<Runtime>> {
1176 match self {
1177 RuntimeCall::Domains(call) => Some(call),
1178 _ => None,
1179 }
1180 }
1181}
1182
1183impl pallet_messenger::extensions::MaybeMessengerCall<Runtime> for RuntimeCall {
1184 fn maybe_messenger_call(&self) -> Option<&pallet_messenger::Call<Runtime>> {
1185 match self {
1186 RuntimeCall::Messenger(call) => Some(call),
1187 _ => None,
1188 }
1189 }
1190}
1191
1192fn extract_segment_headers(ext: &UncheckedExtrinsic) -> Option<Vec<SegmentHeader>> {
1193 match &ext.function {
1194 RuntimeCall::Subspace(pallet_subspace::Call::store_segment_headers { segment_headers }) => {
1195 Some(segment_headers.clone())
1196 }
1197 _ => None,
1198 }
1199}
1200
1201fn is_xdm_mmr_proof_valid(ext: &ExtrinsicFor<Block>) -> Option<bool> {
1202 match &ext.function {
1203 RuntimeCall::Messenger(pallet_messenger::Call::relay_message { msg })
1204 | RuntimeCall::Messenger(pallet_messenger::Call::relay_message_response { msg }) => {
1205 let ConsensusChainMmrLeafProof {
1206 consensus_block_number,
1207 opaque_mmr_leaf,
1208 proof,
1209 ..
1210 } = msg.proof.consensus_mmr_proof();
1211
1212 let mmr_root = SubspaceMmr::mmr_root_hash(consensus_block_number)?;
1213
1214 Some(
1215 pallet_mmr::verify_leaves_proof::<mmr::Hashing, _>(
1216 mmr_root,
1217 vec![mmr::DataOrHash::Data(
1218 EncodableOpaqueLeaf(opaque_mmr_leaf.0.clone()).into_opaque_leaf(),
1219 )],
1220 proof,
1221 )
1222 .is_ok(),
1223 )
1224 }
1225 _ => None,
1226 }
1227}
1228
1229fn create_unsigned_general_extrinsic(call: RuntimeCall) -> UncheckedExtrinsic {
1230 let extra: SignedExtra = (
1231 frame_system::CheckNonZeroSender::<Runtime>::new(),
1232 frame_system::CheckSpecVersion::<Runtime>::new(),
1233 frame_system::CheckTxVersion::<Runtime>::new(),
1234 frame_system::CheckGenesis::<Runtime>::new(),
1235 frame_system::CheckMortality::<Runtime>::from(generic::Era::Immortal),
1236 frame_system::CheckNonce::<Runtime>::from(0u32.into()),
1239 frame_system::CheckWeight::<Runtime>::new(),
1240 pallet_transaction_payment::ChargeTransactionPayment::<Runtime>::from(0u128),
1243 BalanceTransferCheckExtension::<Runtime>::default(),
1244 pallet_subspace::extensions::SubspaceExtension::<Runtime>::new(),
1245 pallet_domains::extensions::DomainsExtension::<Runtime>::new(),
1246 pallet_messenger::extensions::MessengerExtension::<Runtime>::new(),
1247 );
1248
1249 UncheckedExtrinsic::new_transaction(call, extra)
1250}
1251
1252struct RewardAddress([u8; 32]);
1253
1254impl From<PublicKey> for RewardAddress {
1255 #[inline]
1256 fn from(public_key: PublicKey) -> Self {
1257 Self(*public_key)
1258 }
1259}
1260
1261impl From<RewardAddress> for AccountId32 {
1262 #[inline]
1263 fn from(reward_address: RewardAddress) -> Self {
1264 reward_address.0.into()
1265 }
1266}
1267
1268pub struct StorageKeyProvider;
1269impl FraudProofStorageKeyProvider<NumberFor<Block>> for StorageKeyProvider {
1270 fn storage_key(req: FraudProofStorageKeyRequest<NumberFor<Block>>) -> Vec<u8> {
1271 match req {
1272 FraudProofStorageKeyRequest::InvalidInherentExtrinsicData => {
1273 pallet_domains::BlockInherentExtrinsicData::<Runtime>::hashed_key().to_vec()
1274 }
1275 FraudProofStorageKeyRequest::SuccessfulBundles(domain_id) => {
1276 pallet_domains::SuccessfulBundles::<Runtime>::hashed_key_for(domain_id)
1277 }
1278 FraudProofStorageKeyRequest::DomainAllowlistUpdates(domain_id) => {
1279 Messenger::domain_allow_list_update_storage_key(domain_id)
1280 }
1281 FraudProofStorageKeyRequest::DomainRuntimeUpgrades => {
1282 pallet_domains::DomainRuntimeUpgrades::<Runtime>::hashed_key().to_vec()
1283 }
1284 FraudProofStorageKeyRequest::RuntimeRegistry(runtime_id) => {
1285 pallet_domains::RuntimeRegistry::<Runtime>::hashed_key_for(runtime_id)
1286 }
1287 FraudProofStorageKeyRequest::DomainSudoCall(domain_id) => {
1288 pallet_domains::DomainSudoCalls::<Runtime>::hashed_key_for(domain_id)
1289 }
1290 FraudProofStorageKeyRequest::EvmDomainContractCreationAllowedByCall(domain_id) => {
1291 pallet_domains::EvmDomainContractCreationAllowedByCalls::<Runtime>::hashed_key_for(
1292 domain_id,
1293 )
1294 }
1295 FraudProofStorageKeyRequest::MmrRoot(block_number) => {
1296 pallet_subspace_mmr::MmrRootHashes::<Runtime>::hashed_key_for(block_number)
1297 }
1298 }
1299 }
1300}
1301
1302#[cfg(feature = "runtime-benchmarks")]
1303mod benches {
1304 frame_benchmarking::define_benchmarks!(
1305 [frame_benchmarking, BaselineBench::<Runtime>]
1306 [frame_system, SystemBench::<Runtime>]
1307 [pallet_timestamp, Timestamp]
1308 [pallet_subspace, Subspace]
1309 [pallet_subspace_extension, SubspaceExtensionBench::<Runtime>]
1310 [pallet_rewards, Rewards]
1311 [pallet_balances, Balances]
1312 [balance_transfer_check_extension, BalanceTransferCheckBench::<Runtime>]
1313 [pallet_transaction_payment, TransactionPayment]
1315 [pallet_utility, Utility]
1316 [pallet_domains, Domains]
1317 [pallet_runtime_configs, RuntimeConfigs]
1318 [pallet_mmr, Mmr]
1319 [pallet_messenger, Messenger]
1321 [pallet_messenger_from_domains_extension, MessengerFromDomainsExtensionBench::<Runtime>]
1322 [pallet_transporter, Transporter]
1323 [pallet_scheduler, Scheduler]
1324 [pallet_collective, Council]
1325 [pallet_democracy, Democracy]
1326 [pallet_preimage, Preimage]
1327 [pallet_multisig, Multisig]
1328 [pallet_sudo, Sudo]
1329 );
1330}
1331
1332#[cfg(feature = "runtime-benchmarks")]
1333impl frame_system_benchmarking::Config for Runtime {}
1334
1335#[cfg(feature = "runtime-benchmarks")]
1336impl frame_benchmarking::baseline::Config for Runtime {}
1337
1338impl_runtime_apis! {
1339 impl sp_api::Core<Block> for Runtime {
1340 fn version() -> RuntimeVersion {
1341 VERSION
1342 }
1343
1344 fn execute_block(block: Block) {
1345 Executive::execute_block(block);
1346 }
1347
1348 fn initialize_block(header: &HeaderFor<Block>) -> ExtrinsicInclusionMode {
1349 Executive::initialize_block(header)
1350 }
1351 }
1352
1353 impl sp_api::Metadata<Block> for Runtime {
1354 fn metadata() -> OpaqueMetadata {
1355 OpaqueMetadata::new(Runtime::metadata().into())
1356 }
1357
1358 fn metadata_at_version(version: u32) -> Option<OpaqueMetadata> {
1359 Runtime::metadata_at_version(version)
1360 }
1361
1362 fn metadata_versions() -> Vec<u32> {
1363 Runtime::metadata_versions()
1364 }
1365 }
1366
1367 impl sp_block_builder::BlockBuilder<Block> for Runtime {
1368 fn apply_extrinsic(extrinsic: ExtrinsicFor<Block>) -> ApplyExtrinsicResult {
1369 Executive::apply_extrinsic(extrinsic)
1370 }
1371
1372 fn finalize_block() -> HeaderFor<Block> {
1373 Executive::finalize_block()
1374 }
1375
1376 fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<ExtrinsicFor<Block>> {
1377 data.create_extrinsics()
1378 }
1379
1380 fn check_inherents(
1381 block: Block,
1382 data: sp_inherents::InherentData,
1383 ) -> sp_inherents::CheckInherentsResult {
1384 data.check_extrinsics(&block)
1385 }
1386 }
1387
1388 impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
1389 fn validate_transaction(
1390 source: TransactionSource,
1391 tx: ExtrinsicFor<Block>,
1392 block_hash: BlockHashFor<Block>,
1393 ) -> TransactionValidity {
1394 Executive::validate_transaction(source, tx, block_hash)
1395 }
1396 }
1397
1398 impl sp_offchain::OffchainWorkerApi<Block> for Runtime {
1399 fn offchain_worker(header: &HeaderFor<Block>) {
1400 Executive::offchain_worker(header)
1401 }
1402 }
1403
1404 impl sp_objects::ObjectsApi<Block> for Runtime {
1405 fn extract_block_object_mapping(block: Block) -> BlockObjectMapping {
1406 extract_block_object_mapping(block)
1407 }
1408 }
1409
1410 impl sp_consensus_subspace::SubspaceApi<Block, PublicKey> for Runtime {
1411 fn pot_parameters() -> PotParameters {
1412 Subspace::pot_parameters()
1413 }
1414
1415 fn solution_ranges() -> SolutionRanges {
1416 Subspace::solution_ranges()
1417 }
1418
1419 fn submit_vote_extrinsic(
1420 signed_vote: SignedVote<NumberFor<Block>, BlockHashFor<Block>, PublicKey>,
1421 ) {
1422 let SignedVote { vote, signature } = signed_vote;
1423 let Vote::V0 {
1424 height,
1425 parent_hash,
1426 slot,
1427 solution,
1428 proof_of_time,
1429 future_proof_of_time,
1430 } = vote;
1431
1432 Subspace::submit_vote(SignedVote {
1433 vote: Vote::V0 {
1434 height,
1435 parent_hash,
1436 slot,
1437 solution: solution.into_reward_address_format::<RewardAddress, AccountId32>(),
1438 proof_of_time,
1439 future_proof_of_time,
1440 },
1441 signature,
1442 })
1443 }
1444
1445 fn history_size() -> HistorySize {
1446 <pallet_subspace::Pallet<Runtime>>::history_size()
1447 }
1448
1449 fn max_pieces_in_sector() -> u16 {
1450 MAX_PIECES_IN_SECTOR
1451 }
1452
1453 fn segment_commitment(segment_index: SegmentIndex) -> Option<SegmentCommitment> {
1454 Subspace::segment_commitment(segment_index)
1455 }
1456
1457 fn extract_segment_headers(ext: &ExtrinsicFor<Block>) -> Option<Vec<SegmentHeader >> {
1458 extract_segment_headers(ext)
1459 }
1460
1461 fn is_inherent(ext: &ExtrinsicFor<Block>) -> bool {
1462 match &ext.function {
1463 RuntimeCall::Subspace(call) => Subspace::is_inherent(call),
1464 RuntimeCall::Timestamp(call) => Timestamp::is_inherent(call),
1465 _ => false,
1466 }
1467 }
1468
1469 fn root_plot_public_key() -> Option<PublicKey> {
1470 Subspace::root_plot_public_key()
1471 }
1472
1473 fn should_adjust_solution_range() -> bool {
1474 Subspace::should_adjust_solution_range()
1475 }
1476
1477 fn chain_constants() -> ChainConstants {
1478 ChainConstants::V0 {
1479 confirmation_depth_k: ConfirmationDepthK::get(),
1480 block_authoring_delay: Slot::from(BlockAuthoringDelay::get()),
1481 era_duration: EraDuration::get(),
1482 slot_probability: SlotProbability::get(),
1483 slot_duration: SlotDuration::from_millis(SLOT_DURATION),
1484 recent_segments: RecentSegments::get(),
1485 recent_history_fraction: RecentHistoryFraction::get(),
1486 min_sector_lifetime: MinSectorLifetime::get(),
1487 }
1488 }
1489
1490 fn block_weight() -> Weight {
1491 System::block_weight().total()
1492 }
1493 }
1494
1495 impl sp_domains::DomainsApi<Block, DomainHeader> for Runtime {
1496 fn submit_bundle_unsigned(
1497 opaque_bundle: sp_domains::bundle::OpaqueBundle<NumberFor<Block>, BlockHashFor<Block>, DomainHeader, Balance>,
1498 ) {
1499 Domains::submit_bundle_unsigned(opaque_bundle)
1500 }
1501
1502 fn submit_receipt_unsigned(
1503 singleton_receipt: SealedSingletonReceipt<NumberFor<Block>, BlockHashFor<Block>, DomainHeader, Balance>,
1504 ) {
1505 Domains::submit_receipt_unsigned(singleton_receipt)
1506 }
1507
1508 fn extract_successful_bundles(
1509 domain_id: DomainId,
1510 extrinsics: Vec<ExtrinsicFor<Block>>,
1511 ) -> sp_domains::bundle::OpaqueBundles<Block, DomainHeader, Balance> {
1512 crate::domains::extract_successful_bundles(domain_id, extrinsics)
1513 }
1514
1515 fn extrinsics_shuffling_seed() -> Randomness {
1516 Randomness::from(Domains::extrinsics_shuffling_seed().to_fixed_bytes())
1517 }
1518
1519 fn domain_runtime_code(domain_id: DomainId) -> Option<Vec<u8>> {
1520 Domains::domain_runtime_code(domain_id)
1521 }
1522
1523 fn runtime_id(domain_id: DomainId) -> Option<sp_domains::RuntimeId> {
1524 Domains::runtime_id(domain_id)
1525 }
1526
1527 fn runtime_upgrades() -> Vec<sp_domains::RuntimeId> {
1528 Domains::runtime_upgrades()
1529 }
1530
1531 fn domain_instance_data(domain_id: DomainId) -> Option<(DomainInstanceData, NumberFor<Block>)> {
1532 Domains::domain_instance_data(domain_id)
1533 }
1534
1535 fn domain_timestamp() -> Moment {
1536 Domains::timestamp()
1537 }
1538
1539 fn consensus_transaction_byte_fee() -> Balance {
1540 Domains::consensus_transaction_byte_fee()
1541 }
1542
1543 fn domain_tx_range(domain_id: DomainId) -> U256 {
1544 Domains::domain_tx_range(domain_id)
1545 }
1546
1547 fn genesis_state_root(domain_id: DomainId) -> Option<H256> {
1548 Domains::domain_genesis_block_execution_receipt(domain_id)
1549 .map(|er| *er.final_state_root())
1550 }
1551
1552 fn head_receipt_number(domain_id: DomainId) -> DomainNumber {
1553 Domains::head_receipt_number(domain_id)
1554 }
1555
1556 fn oldest_unconfirmed_receipt_number(domain_id: DomainId) -> Option<DomainNumber> {
1557 Domains::oldest_unconfirmed_receipt_number(domain_id)
1558 }
1559
1560 fn domain_bundle_limit(domain_id: DomainId) -> Option<sp_domains::DomainBundleLimit> {
1561 Domains::domain_bundle_limit(domain_id).ok().flatten()
1562 }
1563
1564 fn non_empty_er_exists(domain_id: DomainId) -> bool {
1565 Domains::non_empty_er_exists(domain_id)
1566 }
1567
1568 fn domain_best_number(domain_id: DomainId) -> Option<DomainNumber> {
1569 Domains::domain_best_number(domain_id).ok()
1570 }
1571
1572 fn execution_receipt(receipt_hash: DomainHash) -> Option<ExecutionReceiptFor<DomainHeader, Block, Balance>> {
1573 Domains::execution_receipt(receipt_hash)
1574 }
1575
1576 fn domain_operators(domain_id: DomainId) -> Option<(BTreeMap<OperatorId, Balance>, Vec<OperatorId>)> {
1577 Domains::domain_staking_summary(domain_id).map(|summary| {
1578 let next_operators = summary.next_operators.into_iter().collect();
1579 (summary.current_operators, next_operators)
1580 })
1581 }
1582
1583 fn receipt_hash(domain_id: DomainId, domain_number: DomainNumber) -> Option<DomainHash> {
1584 Domains::receipt_hash(domain_id, domain_number)
1585 }
1586
1587 fn latest_confirmed_domain_block(domain_id: DomainId) -> Option<(DomainNumber, DomainHash)>{
1588 Domains::latest_confirmed_domain_block(domain_id)
1589 }
1590
1591 fn is_bad_er_pending_to_prune(domain_id: DomainId, receipt_hash: DomainHash) -> bool {
1592 Domains::execution_receipt(receipt_hash).map(
1593 |er| Domains::is_bad_er_pending_to_prune(domain_id, *er.domain_block_number())
1594 )
1595 .unwrap_or(false)
1596 }
1597
1598 fn storage_fund_account_balance(operator_id: OperatorId) -> Balance {
1599 Domains::storage_fund_account_balance(operator_id)
1600 }
1601
1602 fn is_domain_runtime_upgraded_since(domain_id: DomainId, at: NumberFor<Block>) -> Option<bool> {
1603 Domains::is_domain_runtime_upgraded_since(domain_id, at)
1604 }
1605
1606 fn domain_sudo_call(domain_id: DomainId) -> Option<Vec<u8>> {
1607 Domains::domain_sudo_call(domain_id)
1608 }
1609
1610 fn evm_domain_contract_creation_allowed_by_call(domain_id: DomainId) -> Option<PermissionedActionAllowedBy<EthereumAccountId>> {
1611 Domains::evm_domain_contract_creation_allowed_by_call(domain_id)
1612 }
1613
1614 fn last_confirmed_domain_block_receipt(domain_id: DomainId) -> Option<ExecutionReceiptFor<DomainHeader, Block, Balance>>{
1615 Domains::latest_confirmed_domain_execution_receipt(domain_id)
1616 }
1617
1618 fn current_bundle_and_execution_receipt_version() -> BundleAndExecutionReceiptVersion {
1619 Domains::current_bundle_and_execution_receipt_version()
1620 }
1621
1622 fn genesis_execution_receipt(domain_id: DomainId) -> Option<ExecutionReceiptFor<DomainHeader, Block, Balance>> {
1623 Domains::domain_genesis_block_execution_receipt(domain_id)
1624 }
1625
1626 fn nominator_position(
1627 operator_id: OperatorId,
1628 nominator_account: sp_runtime::AccountId32,
1629 ) -> Option<sp_domains::NominatorPosition<Balance, DomainNumber, Balance>> {
1630 Domains::nominator_position(operator_id, nominator_account)
1631 }
1632
1633 fn block_pruning_depth() -> NumberFor<Block> {
1634 BlockTreePruningDepth::get()
1635 }
1636 }
1637
1638 impl sp_domains::BundleProducerElectionApi<Block, Balance> for Runtime {
1639 fn bundle_producer_election_params(domain_id: DomainId) -> Option<BundleProducerElectionParams<Balance>> {
1640 Domains::bundle_producer_election_params(domain_id)
1641 }
1642
1643 fn operator(operator_id: OperatorId) -> Option<(OperatorPublicKey, Balance)> {
1644 Domains::operator(operator_id)
1645 }
1646 }
1647
1648 impl sp_session::SessionKeys<Block> for Runtime {
1649 fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
1650 SessionKeys::generate(seed)
1651 }
1652
1653 fn decode_session_keys(
1654 encoded: Vec<u8>,
1655 ) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {
1656 SessionKeys::decode_into_raw_public_keys(&encoded)
1657 }
1658 }
1659
1660 impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Nonce> for Runtime {
1661 fn account_nonce(account: AccountId) -> Nonce {
1662 *System::account_nonce(account)
1663 }
1664 }
1665
1666 impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance> for Runtime {
1667 fn query_info(
1668 uxt: ExtrinsicFor<Block>,
1669 len: u32,
1670 ) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo<Balance> {
1671 TransactionPayment::query_info(uxt, len)
1672 }
1673 fn query_fee_details(
1674 uxt: ExtrinsicFor<Block>,
1675 len: u32,
1676 ) -> pallet_transaction_payment::FeeDetails<Balance> {
1677 TransactionPayment::query_fee_details(uxt, len)
1678 }
1679 fn query_weight_to_fee(weight: Weight) -> Balance {
1680 TransactionPayment::weight_to_fee(weight)
1681 }
1682 fn query_length_to_fee(length: u32) -> Balance {
1683 TransactionPayment::length_to_fee(length)
1684 }
1685 }
1686
1687 impl sp_messenger::MessengerApi<Block, BlockNumber, BlockHashFor<Block>> for Runtime {
1688 fn is_xdm_mmr_proof_valid(
1689 ext: &ExtrinsicFor<Block>
1690 ) -> Option<bool> {
1691 is_xdm_mmr_proof_valid(ext)
1692 }
1693
1694 fn extract_xdm_mmr_proof(ext: &ExtrinsicFor<Block>) -> Option<ConsensusChainMmrLeafProof<BlockNumber, BlockHashFor<Block>, sp_core::H256>> {
1695 match &ext.function {
1696 RuntimeCall::Messenger(pallet_messenger::Call::relay_message { msg })
1697 | RuntimeCall::Messenger(pallet_messenger::Call::relay_message_response { msg }) => {
1698 Some(msg.proof.consensus_mmr_proof())
1699 }
1700 _ => None,
1701 }
1702 }
1703
1704 fn batch_extract_xdm_mmr_proof(extrinsics: &Vec<ExtrinsicFor<Block>>) -> BTreeMap<u32, ConsensusChainMmrLeafProof<BlockNumber, BlockHashFor<Block>, sp_core::H256>> {
1705 let mut mmr_proofs = BTreeMap::new();
1706 for (index, ext) in extrinsics.iter().enumerate() {
1707 match &ext.function {
1708 RuntimeCall::Messenger(pallet_messenger::Call::relay_message { msg })
1709 | RuntimeCall::Messenger(pallet_messenger::Call::relay_message_response { msg }) => {
1710 mmr_proofs.insert(index as u32, msg.proof.consensus_mmr_proof());
1711 }
1712 _ => {},
1713 }
1714 }
1715 mmr_proofs
1716 }
1717
1718 fn confirmed_domain_block_storage_key(domain_id: DomainId) -> Vec<u8> {
1719 Domains::confirmed_domain_block_storage_key(domain_id)
1720 }
1721
1722 fn outbox_storage_key(message_key: MessageKey) -> Vec<u8> {
1723 Messenger::outbox_storage_key(message_key)
1724 }
1725
1726 fn inbox_response_storage_key(message_key: MessageKey) -> Vec<u8> {
1727 Messenger::inbox_response_storage_key(message_key)
1728 }
1729
1730 fn domain_chains_allowlist_update(domain_id: DomainId) -> Option<DomainAllowlistUpdates>{
1731 Messenger::domain_chains_allowlist_update(domain_id)
1732 }
1733
1734 fn xdm_id(ext: &ExtrinsicFor<Block>) -> Option<XdmId> {
1735 match &ext.function {
1736 RuntimeCall::Messenger(pallet_messenger::Call::relay_message { msg })=> {
1737 Some(XdmId::RelayMessage((msg.src_chain_id, msg.channel_id, msg.nonce)))
1738 }
1739 RuntimeCall::Messenger(pallet_messenger::Call::relay_message_response { msg }) => {
1740 Some(XdmId::RelayResponseMessage((msg.src_chain_id, msg.channel_id, msg.nonce)))
1741 }
1742 _ => None,
1743 }
1744 }
1745
1746 fn channel_nonce(chain_id: ChainId, channel_id: ChannelId) -> Option<ChannelNonce> {
1747 Messenger::channel_nonce(chain_id, channel_id)
1748 }
1749 }
1750
1751 impl sp_messenger::RelayerApi<Block, BlockNumber, BlockNumber, BlockHashFor<Block>> for Runtime {
1752 fn outbox_message_unsigned(msg: CrossDomainMessage<NumberFor<Block>, BlockHashFor<Block>, BlockHashFor<Block>>) -> Option<ExtrinsicFor<Block>> {
1753 Messenger::outbox_message_unsigned(msg)
1754 }
1755
1756 fn inbox_response_message_unsigned(msg: CrossDomainMessage<NumberFor<Block>, BlockHashFor<Block>, BlockHashFor<Block>>) -> Option<ExtrinsicFor<Block>> {
1757 Messenger::inbox_response_message_unsigned(msg)
1758 }
1759
1760 fn updated_channels() -> BTreeSet<(ChainId, ChannelId)> {
1761 Messenger::updated_channels()
1762 }
1763
1764 fn channel_storage_key(chain_id: ChainId, channel_id: ChannelId) -> Vec<u8> {
1765 Messenger::channel_storage_key(chain_id, channel_id)
1766 }
1767
1768 fn open_channels() -> BTreeSet<(ChainId, ChannelId)> {
1769 Messenger::open_channels()
1770 }
1771
1772 fn block_messages_with_query(query: BlockMessagesQuery) -> MessagesWithStorageKey {
1773 Messenger::get_block_messages(query)
1774 }
1775
1776 fn channels_and_state() -> Vec<(ChainId, ChannelId, ChannelStateWithNonce)> {
1777 Messenger::channels_and_states()
1778 }
1779
1780 fn first_outbox_message_nonce_to_relay(dst_chain_id: ChainId, channel_id: ChannelId, from_nonce: XdmNonce) -> Option<XdmNonce> {
1781 Messenger::first_outbox_message_nonce_to_relay(dst_chain_id, channel_id, from_nonce)
1782 }
1783
1784 fn first_inbox_message_response_nonce_to_relay(dst_chain_id: ChainId, channel_id: ChannelId, from_nonce: XdmNonce) -> Option<XdmNonce> {
1785 Messenger::first_inbox_message_response_nonce_to_relay(dst_chain_id, channel_id, from_nonce)
1786 }
1787 }
1788
1789 impl sp_domains_fraud_proof::FraudProofApi<Block, DomainHeader> for Runtime {
1790 fn submit_fraud_proof_unsigned(fraud_proof: FraudProof<NumberFor<Block>, BlockHashFor<Block>, DomainHeader, H256>) {
1791 Domains::submit_fraud_proof_unsigned(fraud_proof)
1792 }
1793
1794 fn fraud_proof_storage_key(req: FraudProofStorageKeyRequest<NumberFor<Block>>) -> Vec<u8> {
1795 <StorageKeyProvider as FraudProofStorageKeyProvider<NumberFor<Block>>>::storage_key(req)
1796 }
1797 }
1798
1799 impl mmr::MmrApi<Block, mmr::Hash, BlockNumber> for Runtime {
1800 fn mmr_root() -> Result<mmr::Hash, mmr::Error> {
1801 Ok(Mmr::mmr_root())
1802 }
1803
1804 fn mmr_leaf_count() -> Result<mmr::LeafIndex, mmr::Error> {
1805 Ok(Mmr::mmr_leaves())
1806 }
1807
1808 fn generate_proof(
1809 block_numbers: Vec<BlockNumber>,
1810 best_known_block_number: Option<BlockNumber>,
1811 ) -> Result<(Vec<mmr::EncodableOpaqueLeaf>, mmr::LeafProof<mmr::Hash>), mmr::Error> {
1812 Mmr::generate_proof(block_numbers, best_known_block_number).map(
1813 |(leaves, proof)| {
1814 (
1815 leaves
1816 .into_iter()
1817 .map(|leaf| mmr::EncodableOpaqueLeaf::from_leaf(&leaf))
1818 .collect(),
1819 proof,
1820 )
1821 },
1822 )
1823 }
1824
1825 fn verify_proof(leaves: Vec<mmr::EncodableOpaqueLeaf>, proof: mmr::LeafProof<mmr::Hash>)
1826 -> Result<(), mmr::Error>
1827 {
1828 let leaves = leaves.into_iter().map(|leaf|
1829 leaf.into_opaque_leaf()
1830 .try_decode()
1831 .ok_or(mmr::Error::Verify)).collect::<Result<Vec<mmr::Leaf>, mmr::Error>>()?;
1832 Mmr::verify_leaves(leaves, proof)
1833 }
1834
1835 fn verify_proof_stateless(
1836 root: mmr::Hash,
1837 leaves: Vec<mmr::EncodableOpaqueLeaf>,
1838 proof: mmr::LeafProof<mmr::Hash>
1839 ) -> Result<(), mmr::Error> {
1840 let nodes = leaves.into_iter().map(|leaf|mmr::DataOrHash::Data(leaf.into_opaque_leaf())).collect();
1841 pallet_mmr::verify_leaves_proof::<mmr::Hashing, _>(root, nodes, proof)
1842 }
1843 }
1844
1845 impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
1846 fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
1847 build_state::<RuntimeGenesisConfig>(config)
1848 }
1849
1850 fn get_preset(_id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
1851 get_preset::<RuntimeGenesisConfig>(&None, |_| None)
1853 }
1854
1855 fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
1856 vec![]
1857 }
1858 }
1859
1860 #[cfg(feature = "runtime-benchmarks")]
1861 impl frame_benchmarking::Benchmark<Block> for Runtime {
1862 fn benchmark_metadata(extra: bool) -> (
1863 Vec<frame_benchmarking::BenchmarkList>,
1864 Vec<frame_support::traits::StorageInfo>,
1865 ) {
1866 use frame_benchmarking::{baseline, Benchmarking, BenchmarkList};
1867 use frame_support::traits::StorageInfoTrait;
1868 use frame_system_benchmarking::Pallet as SystemBench;
1869 use baseline::Pallet as BaselineBench;
1870 use pallet_subspace::extensions::benchmarking::Pallet as SubspaceExtensionBench;
1871 use pallet_messenger::extensions::benchmarking_from_domains::Pallet as MessengerFromDomainsExtensionBench;
1872 use subspace_runtime_primitives::extension::benchmarking::Pallet as BalanceTransferCheckBench;
1873
1874 let mut list = Vec::<BenchmarkList>::new();
1875 list_benchmarks!(list, extra);
1876
1877 let storage_info = AllPalletsWithSystem::storage_info();
1878
1879 (list, storage_info)
1880 }
1881
1882 fn dispatch_benchmark(
1883 config: frame_benchmarking::BenchmarkConfig
1884 ) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> {
1885 use frame_benchmarking::{baseline, Benchmarking, BenchmarkBatch};
1886 use sp_core::storage::TrackedStorageKey;
1887
1888 use frame_system_benchmarking::Pallet as SystemBench;
1889 use baseline::Pallet as BaselineBench;
1890 use pallet_subspace::extensions::benchmarking::Pallet as SubspaceExtensionBench;
1891 use pallet_messenger::extensions::benchmarking_from_domains::Pallet as MessengerFromDomainsExtensionBench;
1892 use subspace_runtime_primitives::extension::benchmarking::Pallet as BalanceTransferCheckBench;
1893
1894 use frame_support::traits::WhitelistedStorageKeys;
1895 let whitelist: Vec<TrackedStorageKey> = AllPalletsWithSystem::whitelisted_storage_keys();
1896
1897 let mut batches = Vec::<BenchmarkBatch>::new();
1898 let params = (&config, &whitelist);
1899 add_benchmarks!(params, batches);
1900
1901 Ok(batches)
1902 }
1903 }
1904}
1905
1906#[cfg(test)]
1907mod tests {
1908 use crate::{Runtime, SubspaceBlockWeights as BlockWeights};
1909 use pallet_domains::bundle_storage_fund::AccountType;
1910 use sp_domains::OperatorId;
1911 use sp_runtime::traits::AccountIdConversion;
1912 use subspace_runtime_primitives::tests_utils::FeeMultiplierUtils;
1913
1914 #[test]
1915 fn multiplier_can_grow_from_zero() {
1916 FeeMultiplierUtils::<Runtime, BlockWeights>::multiplier_can_grow_from_zero()
1917 }
1918
1919 #[test]
1920 fn test_bundle_storage_fund_account_uniqueness() {
1921 let _: <Runtime as frame_system::Config>::AccountId = <Runtime as pallet_domains::Config>::PalletId::get()
1922 .try_into_sub_account((AccountType::StorageFund, OperatorId::MAX))
1923 .expect(
1924 "The `AccountId` type must be large enough to fit the seed of the bundle storage fund account",
1925 );
1926 }
1927}