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