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