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