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