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