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