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