1
// Copyright (C) Moondance Labs Ltd.
2
// This file is part of Tanssi.
3

            
4
// Tanssi is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8

            
9
// Tanssi is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13

            
14
// You should have received a copy of the GNU General Public License
15
// along with Tanssi.  If not, see <http://www.gnu.org/licenses/>
16

            
17
#![cfg_attr(not(feature = "std"), no_std)]
18
// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.
19
#![recursion_limit = "256"]
20

            
21
// Make the WASM binary available.
22
#[cfg(feature = "std")]
23
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
24

            
25
extern crate alloc;
26

            
27
pub mod xcm_config;
28

            
29
#[cfg(feature = "std")]
30
use sp_version::NativeVersion;
31

            
32
#[cfg(any(feature = "std", test))]
33
pub use sp_runtime::BuildStorage;
34
use sp_runtime::{DispatchError, TransactionOutcome};
35

            
36
pub mod weights;
37

            
38
#[cfg(test)]
39
mod tests;
40

            
41
use {
42
    alloc::{
43
        boxed::Box,
44
        collections::{btree_map::BTreeMap, btree_set::BTreeSet},
45
        vec,
46
        vec::Vec,
47
    },
48
    core::marker::PhantomData,
49
    cumulus_pallet_parachain_system::{
50
        RelayChainStateProof, RelayNumberMonotonicallyIncreases, RelaychainDataProvider,
51
        RelaychainStateProvider,
52
    },
53
    cumulus_primitives_core::{
54
        relay_chain::{self, SessionIndex},
55
        AggregateMessageOrigin, BodyId, ParaId,
56
    },
57
    frame_support::{
58
        construct_runtime,
59
        dispatch::DispatchClass,
60
        genesis_builder_helper::{build_state, get_preset},
61
        pallet_prelude::DispatchResult,
62
        parameter_types,
63
        traits::{
64
            fungible::{Balanced, Credit, Inspect},
65
            tokens::{ConversionToAssetBalance, PayFromAccount, UnityAssetBalanceConversion},
66
            ConstBool, ConstU128, ConstU32, ConstU64, ConstU8, Contains, EitherOfDiverse,
67
            InsideBoth, InstanceFilter, OnUnbalanced, ValidatorRegistration,
68
        },
69
        weights::{
70
            constants::{
71
                BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight,
72
                WEIGHT_REF_TIME_PER_SECOND,
73
            },
74
            ConstantMultiplier, Weight, WeightToFee as _, WeightToFeeCoefficient,
75
            WeightToFeeCoefficients, WeightToFeePolynomial,
76
        },
77
        PalletId,
78
    },
79
    frame_system::{
80
        limits::{BlockLength, BlockWeights},
81
        EnsureRoot, EnsureSigned,
82
    },
83
    nimbus_primitives::{NimbusId, SlotBeacon},
84
    pallet_collator_assignment::{GetRandomnessForNextBlock, RotateCollatorsEveryNSessions},
85
    pallet_invulnerables::InvulnerableRewardDistribution,
86
    pallet_pooled_staking::traits::IsCandidateEligible,
87
    pallet_registrar::RegistrarHooks,
88
    pallet_registrar_runtime_api::ContainerChainGenesisData,
89
    pallet_services_payment::{
90
        BalanceOf, ProvideBlockProductionCost, ProvideCollatorAssignmentCost,
91
    },
92
    pallet_session::{SessionManager, ShouldEndSession},
93
    pallet_stream_payment_runtime_api::{StreamPaymentApiError, StreamPaymentApiStatus},
94
    pallet_transaction_payment::FungibleAdapter,
95
    pallet_xcm_core_buyer::BuyingError,
96
    parity_scale_codec::DecodeWithMemTracking,
97
    polkadot_runtime_common::BlockHashCount,
98
    scale_info::prelude::format,
99
    smallvec::smallvec,
100
    sp_api::impl_runtime_apis,
101
    sp_consensus_aura::SlotDuration,
102
    sp_consensus_slots::Slot,
103
    sp_core::{crypto::KeyTypeId, Get, MaxEncodedLen, OpaqueMetadata, H256},
104
    sp_runtime::{
105
        generic, impl_opaque_keys,
106
        traits::{
107
            AccountIdConversion, AccountIdLookup, BlakeTwo256, Block as BlockT, ConvertInto,
108
            Hash as HashT, IdentityLookup, Verify,
109
        },
110
        transaction_validity::{TransactionSource, TransactionValidity},
111
        AccountId32, ApplyExtrinsicResult, Cow,
112
    },
113
    sp_version::RuntimeVersion,
114
    tanssi_runtime_common::SessionTimer,
115
    tp_stream_payment_common::StreamId,
116
    tp_traits::{
117
        apply, derive_storage_traits, GetContainerChainAuthor, GetHostConfiguration,
118
        GetSessionContainerChains, MaybeSelfChainBlockAuthor, NodeActivityTrackingHelper,
119
        ParaIdAssignmentHooks, RelayStorageRootProvider, RemoveInvulnerables, SlotFrequency,
120
    },
121
    tp_xcm_core_buyer::BuyCoreCollatorProof,
122
    xcm::Version as XcmVersion,
123
    xcm::{IntoVersion, VersionedAssetId, VersionedAssets, VersionedLocation, VersionedXcm},
124
    xcm_runtime_apis::{
125
        dry_run::{CallDryRunEffects, Error as XcmDryRunApiError, XcmDryRunEffects},
126
        fees::Error as XcmPaymentApiError,
127
    },
128
};
129
pub use {
130
    dp_core::{AccountId, Address, Balance, BlockNumber, Hash, Header, Index, Signature},
131
    sp_runtime::{MultiAddress, Perbill, Permill},
132
};
133
use {
134
    frame_support::{
135
        storage::{with_storage_layer, with_transaction},
136
        traits::{ExistenceRequirement, WithdrawReasons},
137
    },
138
    polkadot_runtime_common::SlowAdjustingFeeUpdate,
139
};
140

            
141
/// Block type as expected by this runtime.
142
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
143
/// A Block signed with a Justification
144
pub type SignedBlock = generic::SignedBlock<Block>;
145
/// BlockId type as expected by this runtime.
146
pub type BlockId = generic::BlockId<Block>;
147

            
148
/// CollatorId type expected by this runtime.
149
pub type CollatorId = AccountId;
150

            
151
/// The `TxExtension` to the basic transaction logic.
152
pub type TxExtension = cumulus_pallet_weight_reclaim::StorageWeightReclaim<
153
    Runtime,
154
    (
155
        frame_system::CheckNonZeroSender<Runtime>,
156
        frame_system::CheckSpecVersion<Runtime>,
157
        frame_system::CheckTxVersion<Runtime>,
158
        frame_system::CheckGenesis<Runtime>,
159
        frame_system::CheckEra<Runtime>,
160
        frame_system::CheckNonce<Runtime>,
161
        frame_system::CheckWeight<Runtime>,
162
        pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
163
        frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
164
    ),
165
>;
166

            
167
/// Unchecked extrinsic type as expected by this runtime.
168
pub type UncheckedExtrinsic =
169
    generic::UncheckedExtrinsic<Address, RuntimeCall, Signature, TxExtension>;
170

            
171
/// Extrinsic type that has already been checked.
172
pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, RuntimeCall, TxExtension>;
173

            
174
/// Executive: handles dispatch to the various modules.
175
pub type Executive = frame_executive::Executive<
176
    Runtime,
177
    Block,
178
    frame_system::ChainContext<Runtime>,
179
    Runtime,
180
    AllPalletsWithSystem,
181
>;
182

            
183
/// DANCE, the native token, uses 12 decimals of precision.
184
pub mod currency {
185
    use super::Balance;
186

            
187
    // Provide a common factor between runtimes based on a supply of 10_000_000 tokens.
188
    pub const SUPPLY_FACTOR: Balance = 100;
189

            
190
    pub const MICRODANCE: Balance = 1_000_000;
191
    pub const MILLIDANCE: Balance = 1_000_000_000;
192
    pub const DANCE: Balance = 1_000_000_000_000;
193
    pub const KILODANCE: Balance = 1_000_000_000_000_000;
194

            
195
    pub const STORAGE_BYTE_FEE: Balance = 100 * MICRODANCE * SUPPLY_FACTOR;
196
    pub const STORAGE_ITEM_FEE: Balance = 100 * MILLIDANCE * SUPPLY_FACTOR;
197

            
198
4418
    pub const fn deposit(items: u32, bytes: u32) -> Balance {
199
4418
        items as Balance * STORAGE_ITEM_FEE + (bytes as Balance) * STORAGE_BYTE_FEE
200
4418
    }
201
}
202

            
203
/// Handles converting a weight scalar to a fee value, based on the scale and granularity of the
204
/// node's balance type.
205
///
206
/// This should typically create a mapping between the following ranges:
207
///   - `[0, MAXIMUM_BLOCK_WEIGHT]`
208
///   - `[Balance::min, Balance::max]`
209
///
210
/// Yet, it can be used for any other sort of change to weight-fee. Some examples being:
211
///   - Setting it to `0` will essentially disable the weight fee.
212
///   - Setting it to `1` will cause the literal `#[weight = x]` values to be charged.
213
pub struct WeightToFee;
214
impl WeightToFeePolynomial for WeightToFee {
215
    type Balance = Balance;
216
13557
    fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {
217
13557
        // in Rococo, extrinsic base weight (smallest non-zero weight) is mapped to 1 MILLIUNIT:
218
13557
        // in our template, we map to 1/10 of that, or 1/10 MILLIUNIT
219
13557
        let p = MILLIUNIT / 10;
220
13557
        let q = 100 * Balance::from(ExtrinsicBaseWeight::get().ref_time());
221
13557
        smallvec![WeightToFeeCoefficient {
222
            degree: 1,
223
            negative: false,
224
            coeff_frac: Perbill::from_rational(p % q, q),
225
            coeff_integer: p / q,
226
        }]
227
13557
    }
228
}
229

            
230
/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know
231
/// the specifics of the runtime. They can then be made to be agnostic over specific formats
232
/// of data like extrinsics, allowing for them to continue syncing the network through upgrades
233
/// to even the core data structures.
234
pub mod opaque {
235
    use {
236
        super::*,
237
        sp_runtime::{
238
            generic,
239
            traits::{BlakeTwo256, Hash as HashT},
240
        },
241
    };
242

            
243
    pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;
244
    /// Opaque block header type.
245
    pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
246
    /// Opaque block type.
247
    pub type Block = generic::Block<Header, UncheckedExtrinsic>;
248
    /// Opaque block identifier type.
249
    pub type BlockId = generic::BlockId<Block>;
250
    /// Opaque block hash type.
251
    pub type Hash = <BlakeTwo256 as HashT>::Output;
252
    /// Opaque signature type.
253
    pub use super::Signature;
254
}
255

            
256
impl_opaque_keys! {
257
    pub struct SessionKeys {
258
        pub nimbus: Initializer,
259
    }
260
}
261

            
262
#[sp_version::runtime_version]
263
pub const VERSION: RuntimeVersion = RuntimeVersion {
264
    spec_name: Cow::Borrowed("dancebox"),
265
    impl_name: Cow::Borrowed("dancebox"),
266
    authoring_version: 1,
267
    spec_version: 1500,
268
    impl_version: 0,
269
    apis: RUNTIME_API_VERSIONS,
270
    transaction_version: 1,
271
    system_version: 1,
272
};
273

            
274
/// This determines the average expected block time that we are targeting.
275
/// Blocks will be produced at a minimum duration defined by `SLOT_DURATION`.
276
/// `SLOT_DURATION` is picked up by `pallet_timestamp` which is in turn picked
277
/// up by `pallet_aura` to implement `fn slot_duration()`.
278
///
279
/// Change this to adjust the block time.
280
pub const MILLISECS_PER_BLOCK: u64 = 6000;
281

            
282
// NOTE: Currently it is not possible to change the slot duration after the chain has started.
283
//       Attempting to do so will brick block production.
284
pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;
285

            
286
// Time is measured by number of blocks.
287
pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);
288
pub const HOURS: BlockNumber = MINUTES * 60;
289
pub const DAYS: BlockNumber = HOURS * 24;
290

            
291
// Unit = the base number of indivisible units for balances
292
pub const UNIT: Balance = 1_000_000_000_000;
293
pub const CENTS: Balance = UNIT / 30_000;
294
pub const MILLIUNIT: Balance = 1_000_000_000;
295
pub const MICROUNIT: Balance = 1_000_000;
296
/// The existential deposit. Set to 1/10 of the Connected Relay Chain.
297
pub const EXISTENTIAL_DEPOSIT: Balance = MILLIUNIT;
298

            
299
/// We assume that ~5% of the block weight is consumed by `on_initialize` handlers. This is
300
/// used to limit the maximal weight of a single extrinsic.
301
const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(5);
302

            
303
/// We allow `Normal` extrinsics to fill up the block up to 75%, the rest can be used by
304
/// `Operational` extrinsics.
305
const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);
306

            
307
/// We allow for 2 seconds of compute with a 6 second average block time
308
const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts(
309
    WEIGHT_REF_TIME_PER_SECOND.saturating_mul(2),
310
    cumulus_primitives_core::relay_chain::MAX_POV_SIZE as u64,
311
);
312

            
313
/// The version information used to identify this runtime when compiled natively.
314
#[cfg(feature = "std")]
315
2970
pub fn native_version() -> NativeVersion {
316
2970
    NativeVersion {
317
2970
        runtime_version: VERSION,
318
2970
        can_author_with: Default::default(),
319
2970
    }
320
2970
}
321

            
322
parameter_types! {
323
    pub const Version: RuntimeVersion = VERSION;
324

            
325
    // This part is copied from Substrate's `bin/node/runtime/src/lib.rs`.
326
    //  The `RuntimeBlockLength` and `RuntimeBlockWeights` exist here because the
327
    // `DeletionWeightLimit` and `DeletionQueueDepth` depend on those to parameterize
328
    // the lazy contract deletion.
329
    pub RuntimeBlockLength: BlockLength =
330
        BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);
331
    pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()
332
        .base_block(BlockExecutionWeight::get())
333
1701060
        .for_class(DispatchClass::all(), |weights| {
334
1701060
            weights.base_extrinsic = ExtrinsicBaseWeight::get();
335
1701060
        })
336
567020
        .for_class(DispatchClass::Normal, |weights| {
337
567020
            weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);
338
567020
        })
339
567020
        .for_class(DispatchClass::Operational, |weights| {
340
567020
            weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);
341
567020
            // Operational transactions have some extra reserved space, so that they
342
567020
            // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.
343
567020
            weights.reserved = Some(
344
567020
                MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT
345
567020
            );
346
567020
        })
347
        .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)
348
        .build_or_panic();
349
    pub const SS58Prefix: u16 = 42;
350
}
351

            
352
// Configure FRAME pallets to include in runtime.
353

            
354
impl frame_system::Config for Runtime {
355
    /// The identifier used to distinguish between accounts.
356
    type AccountId = AccountId;
357
    /// The aggregated dispatch type that is available for extrinsics.
358
    type RuntimeCall = RuntimeCall;
359
    /// The lookup mechanism to get account ID from whatever is passed in dispatchers.
360
    type Lookup = AccountIdLookup<AccountId, ()>;
361
    /// The index type for storing how many extrinsics an account has signed.
362
    type Nonce = Index;
363
    /// The index type for blocks.
364
    type Block = Block;
365
    /// The type for hashing blocks and tries.
366
    type Hash = Hash;
367
    /// The hashing algorithm used.
368
    type Hashing = BlakeTwo256;
369
    /// The ubiquitous event type.
370
    type RuntimeEvent = RuntimeEvent;
371
    /// The ubiquitous origin type.
372
    type RuntimeOrigin = RuntimeOrigin;
373
    /// Maximum number of block number to block hash mappings to keep (oldest pruned first).
374
    type BlockHashCount = BlockHashCount;
375
    /// Runtime version.
376
    type Version = Version;
377
    /// Converts a module to an index of this module in the runtime.
378
    type PalletInfo = PalletInfo;
379
    /// The data to be stored in an account.
380
    type AccountData = pallet_balances::AccountData<Balance>;
381
    /// What to do if a new account is created.
382
    type OnNewAccount = ();
383
    /// What to do if an account is fully reaped from the system.
384
    type OnKilledAccount = ();
385
    /// The weight of database operations that the runtime can invoke.
386
    type DbWeight = RocksDbWeight;
387
    /// The basic call filter to use in dispatchable.
388
    type BaseCallFilter = InsideBoth<MaintenanceMode, TxPause>;
389
    /// Weight information for the extrinsics of this pallet.
390
    type SystemWeightInfo = weights::frame_system::SubstrateWeight<Runtime>;
391
    /// Block & extrinsics weights: base values and limits.
392
    type BlockWeights = RuntimeBlockWeights;
393
    /// The maximum length of a block (in bytes).
394
    type BlockLength = RuntimeBlockLength;
395
    /// This is used as an identifier of the chain. 42 is the generic substrate prefix.
396
    type SS58Prefix = SS58Prefix;
397
    /// The action to take on a Runtime Upgrade
398
    type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode<Self>;
399
    type MaxConsumers = frame_support::traits::ConstU32<16>;
400
    type RuntimeTask = RuntimeTask;
401
    type SingleBlockMigrations = ();
402
    type MultiBlockMigrator = MultiBlockMigrations;
403
    type PreInherents = ();
404
    type PostInherents = ();
405
    type PostTransactions = ();
406
    type ExtensionsWeightInfo = weights::frame_system_extensions::SubstrateWeight<Runtime>;
407
}
408

            
409
impl cumulus_pallet_weight_reclaim::Config for Runtime {
410
    type WeightInfo = weights::cumulus_pallet_weight_reclaim::SubstrateWeight<Runtime>;
411
}
412

            
413
impl pallet_timestamp::Config for Runtime {
414
    /// A timestamp: milliseconds since the unix epoch.
415
    type Moment = u64;
416
    type OnTimestampSet = dp_consensus::OnTimestampSet<
417
        <Self as pallet_author_inherent::Config>::SlotBeacon,
418
        ConstU64<{ SLOT_DURATION }>,
419
    >;
420
    type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>;
421
    type WeightInfo = weights::pallet_timestamp::SubstrateWeight<Runtime>;
422
}
423

            
424
pub struct CanAuthor;
425
impl nimbus_primitives::CanAuthor<NimbusId> for CanAuthor {
426
27403
    fn can_author(author: &NimbusId, slot: &u32) -> bool {
427
27403
        let authorities = AuthorityAssignment::collator_container_chain(Session::current_index())
428
27403
            .expect("authorities should be set")
429
27403
            .orchestrator_chain;
430
27403

            
431
27403
        if authorities.is_empty() {
432
            return false;
433
27403
        }
434
27403

            
435
27403
        let author_index = (*slot as usize) % authorities.len();
436
27403
        let expected_author = &authorities[author_index];
437
27403

            
438
27403
        expected_author == author
439
27403
    }
440
    #[cfg(feature = "runtime-benchmarks")]
441
    fn get_authors(_slot: &u32) -> Vec<NimbusId> {
442
        AuthorityAssignment::collator_container_chain(Session::current_index())
443
            .expect("authorities should be set")
444
            .orchestrator_chain
445
    }
446
}
447

            
448
impl pallet_author_inherent::Config for Runtime {
449
    type AuthorId = NimbusId;
450
    type AccountLookup = dp_consensus::NimbusLookUp;
451
    type CanAuthor = CanAuthor;
452
    type SlotBeacon = dp_consensus::AuraDigestSlotBeacon<Runtime>;
453
    type WeightInfo = weights::pallet_author_inherent::SubstrateWeight<Runtime>;
454
}
455

            
456
parameter_types! {
457
    pub const ExistentialDeposit: Balance = EXISTENTIAL_DEPOSIT;
458
}
459

            
460
impl pallet_balances::Config for Runtime {
461
    type MaxLocks = ConstU32<50>;
462
    /// The type for recording an account's balance.
463
    type Balance = Balance;
464
    /// The ubiquitous event type.
465
    type RuntimeEvent = RuntimeEvent;
466
    type DustRemoval = ();
467
    type ExistentialDeposit = ExistentialDeposit;
468
    type AccountStore = System;
469
    type MaxReserves = ConstU32<50>;
470
    type ReserveIdentifier = [u8; 8];
471
    type FreezeIdentifier = RuntimeFreezeReason;
472
    type MaxFreezes = ConstU32<10>;
473
    type RuntimeHoldReason = RuntimeHoldReason;
474
    type RuntimeFreezeReason = RuntimeFreezeReason;
475
    type DoneSlashHandler = ();
476
    type WeightInfo = weights::pallet_balances::SubstrateWeight<Runtime>;
477
}
478

            
479
parameter_types! {
480
    pub const TransactionByteFee: Balance = 1;
481
}
482

            
483
impl pallet_transaction_payment::Config for Runtime {
484
    type RuntimeEvent = RuntimeEvent;
485
    type OnChargeTransaction =
486
        FungibleAdapter<Balances, tanssi_runtime_common::DealWithFees<Runtime>>;
487
    type OperationalFeeMultiplier = ConstU8<5>;
488
    type WeightToFee = WeightToFee;
489
    type LengthToFee = ConstantMultiplier<Balance, TransactionByteFee>;
490
    type FeeMultiplierUpdate = SlowAdjustingFeeUpdate<Self>;
491
    type WeightInfo = weights::pallet_transaction_payment::SubstrateWeight<Runtime>;
492
}
493

            
494
parameter_types! {
495
    pub ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;
496
    pub ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;
497
    pub const RelayOrigin: AggregateMessageOrigin = AggregateMessageOrigin::Parent;
498
}
499

            
500
pub const RELAY_CHAIN_SLOT_DURATION_MILLIS: u32 = 6000;
501
pub const UNINCLUDED_SEGMENT_CAPACITY: u32 = 3;
502
pub const BLOCK_PROCESSING_VELOCITY: u32 = 1;
503

            
504
type ConsensusHook = pallet_async_backing::consensus_hook::FixedVelocityConsensusHook<
505
    Runtime,
506
    BLOCK_PROCESSING_VELOCITY,
507
    UNINCLUDED_SEGMENT_CAPACITY,
508
>;
509

            
510
impl cumulus_pallet_parachain_system::Config for Runtime {
511
    type WeightInfo = weights::cumulus_pallet_parachain_system::SubstrateWeight<Runtime>;
512
    type RuntimeEvent = RuntimeEvent;
513
    type OnSystemEvent = ();
514
    type SelfParaId = parachain_info::Pallet<Runtime>;
515
    type OutboundXcmpMessageSource = XcmpQueue;
516
    type DmpQueue = frame_support::traits::EnqueueWithOrigin<MessageQueue, RelayOrigin>;
517
    type ReservedDmpWeight = ReservedDmpWeight;
518
    type XcmpMessageHandler = XcmpQueue;
519
    type ReservedXcmpWeight = ReservedXcmpWeight;
520
    type CheckAssociatedRelayNumber = RelayNumberMonotonicallyIncreases;
521
    type ConsensusHook = ConsensusHook;
522
    type SelectCore = cumulus_pallet_parachain_system::DefaultCoreSelector<Runtime>;
523
}
524
pub struct ParaSlotProvider;
525
impl Get<(Slot, SlotDuration)> for ParaSlotProvider {
526
24753
    fn get() -> (Slot, SlotDuration) {
527
24753
        let slot = u64::from(<Runtime as pallet_author_inherent::Config>::SlotBeacon::slot());
528
24753
        (Slot::from(slot), SlotDuration::from_millis(SLOT_DURATION))
529
24753
    }
530
}
531

            
532
parameter_types! {
533
    pub const ExpectedBlockTime: u64 = MILLISECS_PER_BLOCK;
534
}
535

            
536
impl pallet_async_backing::Config for Runtime {
537
    type AllowMultipleBlocksPerSlot = ConstBool<true>;
538
    type GetAndVerifySlot =
539
        pallet_async_backing::ParaSlot<RELAY_CHAIN_SLOT_DURATION_MILLIS, ParaSlotProvider>;
540
    type ExpectedBlockTime = ExpectedBlockTime;
541
}
542

            
543
/// Only callable after `set_validation_data` is called which forms this proof the same way
544
2657
fn relay_chain_state_proof() -> RelayChainStateProof {
545
2657
    let relay_storage_root =
546
2657
        RelaychainDataProvider::<Runtime>::current_relay_chain_state().state_root;
547
2657
    let relay_chain_state = cumulus_pallet_parachain_system::RelayStateProof::<Runtime>::get()
548
2657
        .expect("set in `set_validation_data`");
549
2657
    RelayChainStateProof::new(ParachainInfo::get(), relay_storage_root, relay_chain_state)
550
2657
        .expect("Invalid relay chain state proof, already constructed in `set_validation_data`")
551
2657
}
552

            
553
pub struct BabeCurrentBlockRandomnessGetter;
554
impl BabeCurrentBlockRandomnessGetter {
555
2657
    fn get_block_randomness() -> Option<Hash> {
556
2657
        if cfg!(feature = "runtime-benchmarks") {
557
            // storage reads as per actual reads
558
            let _relay_storage_root =
559
                RelaychainDataProvider::<Runtime>::current_relay_chain_state().state_root;
560

            
561
            let _relay_chain_state =
562
                cumulus_pallet_parachain_system::RelayStateProof::<Runtime>::get();
563
            let benchmarking_babe_output = Hash::default();
564
            return Some(benchmarking_babe_output);
565
2657
        }
566
2657

            
567
2657
        relay_chain_state_proof()
568
2657
            .read_optional_entry::<Option<Hash>>(
569
2657
                relay_chain::well_known_keys::CURRENT_BLOCK_RANDOMNESS,
570
2657
            )
571
2657
            .ok()
572
2657
            .flatten()
573
2657
            .flatten()
574
2657
    }
575

            
576
    /// Return the block randomness from the relay mixed with the provided subject.
577
    /// This ensures that the randomness will be different on different pallets, as long as the subject is different.
578
2657
    fn get_block_randomness_mixed(subject: &[u8]) -> Option<Hash> {
579
2657
        Self::get_block_randomness()
580
2657
            .map(|random_hash| mix_randomness::<Runtime>(random_hash, subject))
581
2657
    }
582
}
583

            
584
/// Combines the vrf output of the previous relay block with the provided subject.
585
/// This ensures that the randomness will be different on different pallets, as long as the subject is different.
586
86
fn mix_randomness<T: frame_system::Config>(vrf_output: Hash, subject: &[u8]) -> T::Hash {
587
86
    let mut digest = Vec::new();
588
86
    digest.extend_from_slice(vrf_output.as_ref());
589
86
    digest.extend_from_slice(subject);
590
86

            
591
86
    T::Hashing::hash(digest.as_slice())
592
86
}
593

            
594
// Randomness trait
595
impl frame_support::traits::Randomness<Hash, BlockNumber> for BabeCurrentBlockRandomnessGetter {
596
    fn random(subject: &[u8]) -> (Hash, BlockNumber) {
597
        let block_number = frame_system::Pallet::<Runtime>::block_number();
598
        let randomness = Self::get_block_randomness_mixed(subject).unwrap_or_default();
599

            
600
        (randomness, block_number)
601
    }
602
}
603

            
604
pub struct OwnApplySession;
605
impl pallet_initializer::ApplyNewSession<Runtime> for OwnApplySession {
606
3371
    fn apply_new_session(
607
3371
        _changed: bool,
608
3371
        session_index: u32,
609
3371
        all_validators: Vec<(AccountId, NimbusId)>,
610
3371
        queued: Vec<(AccountId, NimbusId)>,
611
3371
    ) {
612
3371
        // We first initialize Configuration
613
3371
        Configuration::initializer_on_new_session(&session_index);
614
3371
        // Next: Registrar
615
3371
        Registrar::initializer_on_new_session(&session_index);
616
3371
        // Next: AuthorityMapping
617
3371
        AuthorityMapping::initializer_on_new_session(&session_index, &all_validators);
618
3371

            
619
11992
        let next_collators = queued.iter().map(|(k, _)| k.clone()).collect();
620
3371

            
621
3371
        // Next: CollatorAssignment
622
3371
        let assignments =
623
3371
            CollatorAssignment::initializer_on_new_session(&session_index, next_collators);
624
3371

            
625
3371
        let queued_id_to_nimbus_map = queued.iter().cloned().collect();
626
3371
        AuthorityAssignment::initializer_on_new_session(
627
3371
            &session_index,
628
3371
            &queued_id_to_nimbus_map,
629
3371
            &assignments.next_assignment,
630
3371
        );
631
3371

            
632
3371
        // Next: InactivityTracking
633
3371
        InactivityTracking::process_ended_session();
634
3371
    }
635

            
636
2639
    fn on_before_session_ending() {
637
2639
        InactivityTracking::on_before_session_ending();
638
2639
    }
639
}
640

            
641
impl pallet_initializer::Config for Runtime {
642
    type SessionIndex = u32;
643

            
644
    /// The identifier type for an authority.
645
    type AuthorityId = NimbusId;
646

            
647
    type SessionHandler = OwnApplySession;
648
}
649

            
650
impl parachain_info::Config for Runtime {}
651

            
652
/// Returns a list of collators by combining pallet_invulnerables and pallet_pooled_staking.
653
pub struct CollatorsFromInvulnerablesAndThenFromStaking;
654

            
655
/// Play the role of the session manager.
656
impl SessionManager<CollatorId> for CollatorsFromInvulnerablesAndThenFromStaking {
657
4103
    fn new_session(index: SessionIndex) -> Option<Vec<CollatorId>> {
658
4103
        if <frame_system::Pallet<Runtime>>::block_number() == 0 {
659
            // Do not show this log in genesis
660
1464
            log::debug!(
661
                "assembling new collators for new session {} at #{:?}",
662
                index,
663
                <frame_system::Pallet<Runtime>>::block_number(),
664
            );
665
        } else {
666
2639
            log::info!(
667
2256
                "assembling new collators for new session {} at #{:?}",
668
2256
                index,
669
2256
                <frame_system::Pallet<Runtime>>::block_number(),
670
            );
671
        }
672

            
673
4103
        let invulnerables = Invulnerables::invulnerables().to_vec();
674
4103
        let candidates_staking =
675
4103
            pallet_pooled_staking::SortedEligibleCandidates::<Runtime>::get().to_vec();
676
4103
        // Max number of collators is set in pallet_configuration
677
4103
        let target_session_index = index.saturating_add(1);
678
4103
        let max_collators =
679
4103
            <Configuration as GetHostConfiguration<u32>>::max_collators(target_session_index);
680
4103
        let collators = invulnerables
681
4103
            .iter()
682
4103
            .cloned()
683
4103
            .chain(candidates_staking.into_iter().filter_map(|elig| {
684
270
                let cand = elig.candidate;
685
270
                if invulnerables.contains(&cand) {
686
                    // If a candidate is both in pallet_invulnerables and pallet_staking, do not count it twice
687
80
                    None
688
                } else {
689
190
                    Some(cand)
690
                }
691
4103
            }))
692
4103
            .take(max_collators as usize)
693
4103
            .collect();
694
4103

            
695
4103
        // TODO: weight?
696
4103
        /*
697
4103
        frame_system::Pallet::<T>::register_extra_weight_unchecked(
698
4103
            T::WeightInfo::new_session(invulnerables.len() as u32),
699
4103
            DispatchClass::Mandatory,
700
4103
        );
701
4103
        */
702
4103
        Some(collators)
703
4103
    }
704
3371
    fn start_session(_: SessionIndex) {
705
3371
        // we don't care.
706
3371
    }
707
2639
    fn end_session(_: SessionIndex) {
708
2639
        // we don't care.
709
2639
    }
710
}
711

            
712
parameter_types! {
713
    pub const Period: u32 = prod_or_fast!(1 * HOURS, 1 * MINUTES);
714
    pub const Offset: u32 = 0;
715
}
716

            
717
impl pallet_session::Config for Runtime {
718
    type RuntimeEvent = RuntimeEvent;
719
    type ValidatorId = CollatorId;
720
    // we don't have stash and controller, thus we don't need the convert as well.
721
    type ValidatorIdOf = ConvertInto;
722
    type ShouldEndSession = pallet_session::PeriodicSessions<Period, Offset>;
723
    type NextSessionRotation = pallet_session::PeriodicSessions<Period, Offset>;
724
    type SessionManager = CollatorsFromInvulnerablesAndThenFromStaking;
725
    // Essentially just Aura, but let's be pedantic.
726
    type SessionHandler = <SessionKeys as sp_runtime::traits::OpaqueKeys>::KeyTypeIdProviders;
727
    type Keys = SessionKeys;
728
    type WeightInfo = weights::pallet_session::SubstrateWeight<Runtime>;
729
    type DisablingStrategy = ();
730
}
731

            
732
/// Read full_rotation_period from pallet_configuration
733
pub struct ConfigurationCollatorRotationSessionPeriod;
734

            
735
impl Get<u32> for ConfigurationCollatorRotationSessionPeriod {
736
5898
    fn get() -> u32 {
737
5898
        Configuration::config().full_rotation_period
738
5898
    }
739
}
740

            
741
pub struct BabeGetRandomnessForNextBlock;
742

            
743
impl GetRandomnessForNextBlock<u32> for BabeGetRandomnessForNextBlock {
744
56624
    fn should_end_session(n: u32) -> bool {
745
56624
        <Runtime as pallet_session::Config>::ShouldEndSession::should_end_session(n)
746
56624
    }
747

            
748
2657
    fn get_randomness() -> [u8; 32] {
749
2657
        let block_number = System::block_number();
750
2657
        let random_seed = if block_number != 0 {
751
86
            if let Some(random_hash) =
752
2657
                BabeCurrentBlockRandomnessGetter::get_block_randomness_mixed(b"CollatorAssignment")
753
            {
754
                // Return random_hash as a [u8; 32] instead of a Hash
755
86
                let mut buf = [0u8; 32];
756
86
                let len = core::cmp::min(32, random_hash.as_ref().len());
757
86
                buf[..len].copy_from_slice(&random_hash.as_ref()[..len]);
758
86

            
759
86
                buf
760
            } else {
761
                // If there is no randomness (e.g when running in dev mode), return [0; 32]
762
2571
                [0; 32]
763
            }
764
        } else {
765
            // In block 0 (genesis) there is no randomness
766
            [0; 32]
767
        };
768

            
769
2657
        random_seed
770
2657
    }
771
}
772

            
773
pub struct RemoveInvulnerablesImpl;
774

            
775
impl RemoveInvulnerables<CollatorId> for RemoveInvulnerablesImpl {
776
4597
    fn remove_invulnerables(
777
4597
        collators: &mut Vec<CollatorId>,
778
4597
        num_invulnerables: usize,
779
4597
    ) -> Vec<CollatorId> {
780
4597
        if num_invulnerables == 0 {
781
            return vec![];
782
4597
        }
783
4597
        let all_invulnerables = pallet_invulnerables::Invulnerables::<Runtime>::get();
784
4597
        if all_invulnerables.is_empty() {
785
144
            return vec![];
786
4453
        }
787
4453
        let mut invulnerables = vec![];
788
4453
        // TODO: use binary_search when invulnerables are sorted
789
5565
        collators.retain(|x| {
790
5565
            if invulnerables.len() < num_invulnerables && all_invulnerables.contains(x) {
791
3625
                invulnerables.push(x.clone());
792
3625
                false
793
            } else {
794
1940
                true
795
            }
796
5565
        });
797
4453

            
798
4453
        invulnerables
799
4597
    }
800
}
801

            
802
pub struct ParaIdAssignmentHooksImpl;
803

            
804
impl ParaIdAssignmentHooksImpl {
805
7652
    fn charge_para_ids_internal(
806
7652
        blocks_per_session: tp_traits::BlockNumber,
807
7652
        para_id: ParaId,
808
7652
        currently_assigned: &BTreeSet<ParaId>,
809
7652
        maybe_tip: &Option<BalanceOf<Runtime>>,
810
7652
    ) -> Result<Weight, DispatchError> {
811
        use frame_support::traits::Currency;
812
        type ServicePaymentCurrency = <Runtime as pallet_services_payment::Config>::Currency;
813

            
814
        // Check if the container chain has enough credits for a session assignments
815
7489
        let maybe_assignment_imbalance =
816
7652
            if  pallet_services_payment::Pallet::<Runtime>::burn_collator_assignment_free_credit_for_para(&para_id).is_err() {
817
219
                let (amount_to_charge, _weight) =
818
219
                    <Runtime as pallet_services_payment::Config>::ProvideCollatorAssignmentCost::collator_assignment_cost(&para_id);
819
219
                Some(<ServicePaymentCurrency as Currency<AccountId>>::withdraw(
820
219
                    &pallet_services_payment::Pallet::<Runtime>::parachain_tank(para_id),
821
219
                    amount_to_charge,
822
219
                    WithdrawReasons::FEE,
823
219
                    ExistenceRequirement::KeepAlive,
824
219
                )?)
825
            } else {
826
7433
                None
827
            };
828

            
829
7489
        if let Some(tip) = maybe_tip {
830
4920
            if let Err(e) = pallet_services_payment::Pallet::<Runtime>::charge_tip(&para_id, tip) {
831
                // Return assignment imbalance to tank on error
832
13
                if let Some(assignment_imbalance) = maybe_assignment_imbalance {
833
                    <Runtime as pallet_services_payment::Config>::Currency::resolve_creating(
834
                        &pallet_services_payment::Pallet::<Runtime>::parachain_tank(para_id),
835
                        assignment_imbalance,
836
                    );
837
13
                }
838
13
                return Err(e);
839
4907
            }
840
2569
        }
841

            
842
7476
        if let Some(assignment_imbalance) = maybe_assignment_imbalance {
843
56
            <Runtime as pallet_services_payment::Config>::OnChargeForCollatorAssignment::on_unbalanced(assignment_imbalance);
844
7420
        }
845

            
846
        // If the para has been assigned collators for this session it must have enough block credits
847
        // for the current and the next session.
848
7476
        let block_credits_needed = if currently_assigned.contains(&para_id) {
849
6840
            blocks_per_session * 2
850
        } else {
851
636
            blocks_per_session
852
        };
853
        // Check if the container chain has enough credits for producing blocks
854
7476
        let free_block_credits =
855
7476
            pallet_services_payment::BlockProductionCredits::<Runtime>::get(para_id)
856
7476
                .unwrap_or_default();
857
7476
        let remaining_block_credits = block_credits_needed.saturating_sub(free_block_credits);
858
7476
        let (block_production_costs, _) =
859
7476
            <Runtime as pallet_services_payment::Config>::ProvideBlockProductionCost::block_cost(
860
7476
                &para_id,
861
7476
            );
862
7476
        // Check if we can withdraw
863
7476
        let remaining_block_credits_to_pay =
864
7476
            u128::from(remaining_block_credits).saturating_mul(block_production_costs);
865
7476
        let remaining_to_pay = remaining_block_credits_to_pay;
866
7476
        // This should take into account whether we tank goes below ED
867
7476
        // The true refers to keepAlive
868
7476
        Balances::can_withdraw(
869
7476
            &pallet_services_payment::Pallet::<Runtime>::parachain_tank(para_id),
870
7476
            remaining_to_pay,
871
7476
        )
872
7476
        .into_result(true)?;
873
        // TODO: Have proper weight
874
7312
        Ok(Weight::zero())
875
7652
    }
876
}
877

            
878
impl<AC> ParaIdAssignmentHooks<BalanceOf<Runtime>, AC> for ParaIdAssignmentHooksImpl {
879
6742
    fn pre_assignment(para_ids: &mut Vec<ParaId>, currently_assigned: &BTreeSet<ParaId>) {
880
6742
        let blocks_per_session = Period::get();
881
6742
        para_ids.retain(|para_id| {
882
5060
            with_transaction(|| {
883
5060
                let max_tip =
884
5060
                    pallet_services_payment::MaxTip::<Runtime>::get(para_id).unwrap_or_default();
885
5060
                TransactionOutcome::Rollback(Self::charge_para_ids_internal(
886
5060
                    blocks_per_session,
887
5060
                    *para_id,
888
5060
                    currently_assigned,
889
5060
                    &Some(max_tip),
890
5060
                ))
891
5060
            })
892
5060
            .is_ok()
893
6742
        });
894
6742
    }
895

            
896
3371
    fn post_assignment(
897
3371
        current_assigned: &BTreeSet<ParaId>,
898
3371
        new_assigned: &mut BTreeMap<ParaId, Vec<AC>>,
899
3371
        maybe_tip: &Option<BalanceOf<Runtime>>,
900
3371
    ) -> Weight {
901
3371
        let blocks_per_session = Period::get();
902
3371
        let mut total_weight = Weight::zero();
903
5336
        new_assigned.retain(|&para_id, collators| {
904
4720
            // Short-circuit in case collators are empty
905
4720
            if collators.is_empty() {
906
2128
                return true;
907
2592
            }
908
2592
            with_storage_layer(|| {
909
2592
                Self::charge_para_ids_internal(
910
2592
                    blocks_per_session,
911
2592
                    para_id,
912
2592
                    current_assigned,
913
2592
                    maybe_tip,
914
2592
                )
915
2592
            })
916
2592
            .inspect(|weight| {
917
2592
                total_weight += *weight;
918
2592
            })
919
2592
            .is_ok()
920
5336
        });
921
3371
        total_weight
922
3371
    }
923

            
924
    /// Make those para ids valid by giving them enough credits, for benchmarking.
925
    #[cfg(feature = "runtime-benchmarks")]
926
    fn make_valid_para_ids(para_ids: &[ParaId]) {
927
        use frame_support::assert_ok;
928

            
929
        let blocks_per_session = Period::get();
930
        // Enough credits to run any benchmark
931
        let block_credits = 20 * blocks_per_session;
932
        let session_credits = 20;
933

            
934
        for para_id in para_ids {
935
            assert_ok!(ServicesPayment::set_block_production_credits(
936
                RuntimeOrigin::root(),
937
                *para_id,
938
                block_credits,
939
            ));
940
            assert_ok!(ServicesPayment::set_collator_assignment_credits(
941
                RuntimeOrigin::root(),
942
                *para_id,
943
                session_credits,
944
            ));
945
        }
946
    }
947
}
948

            
949
impl pallet_collator_assignment::Config for Runtime {
950
    type RuntimeEvent = RuntimeEvent;
951
    type HostConfiguration = Configuration;
952
    type ContainerChains = Registrar;
953
    type SessionIndex = u32;
954
    type SelfParaId = ParachainInfo;
955
    type ShouldRotateAllCollators =
956
        RotateCollatorsEveryNSessions<ConfigurationCollatorRotationSessionPeriod>;
957
    type Randomness =
958
        pallet_collator_assignment::ParachainRandomness<BabeGetRandomnessForNextBlock, Runtime>;
959
    type RemoveInvulnerables = RemoveInvulnerablesImpl;
960
    type ParaIdAssignmentHooks = ParaIdAssignmentHooksImpl;
961
    type CollatorAssignmentTip = ServicesPayment;
962
    type Currency = Balances;
963
    type ForceEmptyOrchestrator = ConstBool<false>;
964
    type CoreAllocationConfiguration = ();
965
    type WeightInfo = weights::pallet_collator_assignment::SubstrateWeight<Runtime>;
966
}
967

            
968
impl pallet_authority_assignment::Config for Runtime {
969
    type SessionIndex = u32;
970
    type AuthorityId = NimbusId;
971
}
972

            
973
pub const FIXED_BLOCK_PRODUCTION_COST: u128 = 1 * currency::MICRODANCE;
974
pub const FIXED_COLLATOR_ASSIGNMENT_COST: u128 = 100 * currency::MICRODANCE;
975

            
976
pub struct BlockProductionCost<Runtime>(PhantomData<Runtime>);
977
impl ProvideBlockProductionCost<Runtime> for BlockProductionCost<Runtime> {
978
7884
    fn block_cost(_para_id: &ParaId) -> (u128, Weight) {
979
7884
        (FIXED_BLOCK_PRODUCTION_COST, Weight::zero())
980
7884
    }
981
}
982

            
983
pub struct CollatorAssignmentCost<Runtime>(PhantomData<Runtime>);
984
impl ProvideCollatorAssignmentCost<Runtime> for CollatorAssignmentCost<Runtime> {
985
229
    fn collator_assignment_cost(_para_id: &ParaId) -> (u128, Weight) {
986
229
        (FIXED_COLLATOR_ASSIGNMENT_COST, Weight::zero())
987
229
    }
988
}
989

            
990
parameter_types! {
991
    // 60 days worth of blocks
992
    pub const FreeBlockProductionCredits: BlockNumber = 60 * DAYS;
993
    // 60 days worth of blocks
994
    pub const FreeCollatorAssignmentCredits: u32 = FreeBlockProductionCredits::get()/Period::get();
995
}
996

            
997
impl pallet_services_payment::Config for Runtime {
998
    type RuntimeEvent = RuntimeEvent;
999
    /// Handler for fees
    type OnChargeForBlock = ();
    type OnChargeForCollatorAssignment = ();
    type OnChargeForCollatorAssignmentTip = ();
    /// Currency type for fee payment
    type Currency = Balances;
    /// Provider of a block cost which can adjust from block to block
    type ProvideBlockProductionCost = BlockProductionCost<Runtime>;
    /// Provider of a block cost which can adjust from block to block
    type ProvideCollatorAssignmentCost = CollatorAssignmentCost<Runtime>;
    /// The maximum number of block credits that can be accumulated
    type FreeBlockProductionCredits = FreeBlockProductionCredits;
    /// The maximum number of session credits that can be accumulated
    type FreeCollatorAssignmentCredits = FreeCollatorAssignmentCredits;
    type ManagerOrigin =
        EitherOfDiverse<pallet_registrar::EnsureSignedByManager<Runtime>, EnsureRoot<AccountId>>;
    type WeightInfo = weights::pallet_services_payment::SubstrateWeight<Runtime>;
}
parameter_types! {
    pub const ProfileDepositBaseFee: Balance = currency::STORAGE_ITEM_FEE;
    pub const ProfileDepositByteFee: Balance = currency::STORAGE_BYTE_FEE;
    #[derive(Clone)]
    pub const MaxAssignmentsPerParaId: u32 = 10;
    #[derive(Clone)]
    pub const MaxNodeUrlLen: u32 = 200;
}
pub type DataPreserversProfileId = u64;
impl pallet_data_preservers::Config for Runtime {
    type RuntimeEvent = RuntimeEvent;
    type RuntimeHoldReason = RuntimeHoldReason;
    type Currency = Balances;
    type WeightInfo = weights::pallet_data_preservers::SubstrateWeight<Runtime>;
    type ProfileId = DataPreserversProfileId;
    type ProfileDeposit = tp_traits::BytesDeposit<ProfileDepositBaseFee, ProfileDepositByteFee>;
    type AssignmentProcessor = tp_data_preservers_common::AssignmentProcessor<Runtime>;
    type AssignmentOrigin = pallet_registrar::EnsureSignedByManager<Runtime>;
    type ForceSetProfileOrigin = EnsureRoot<AccountId>;
    type MaxAssignmentsPerParaId = MaxAssignmentsPerParaId;
    type MaxNodeUrlLen = MaxNodeUrlLen;
    type MaxParaIdsVecLen = MaxLengthParaIds;
}
impl pallet_author_noting::Config for Runtime {
    type RuntimeEvent = RuntimeEvent;
    type ContainerChains = CollatorAssignment;
    type SlotBeacon = dp_consensus::AuraDigestSlotBeacon<Runtime>;
    type ContainerChainAuthor = CollatorAssignment;
    type AuthorNotingHook = (
        XcmCoreBuyer,
        InflationRewards,
        ServicesPayment,
        InactivityTracking,
    );
    type RelayOrPara = pallet_author_noting::ParaMode<
        cumulus_pallet_parachain_system::RelaychainDataProvider<Self>,
    >;
    type MaxContainerChains = MaxLengthParaIds;
    type WeightInfo = weights::pallet_author_noting::SubstrateWeight<Runtime>;
}
parameter_types! {
    pub const PotId: PalletId = PalletId(*b"PotStake");
    pub const MaxCandidates: u32 = 1000;
    pub const MinCandidates: u32 = 5;
    pub const SessionLength: BlockNumber = 5;
    pub const MaxInvulnerables: u32 = 100;
    pub const ExecutiveBody: BodyId = BodyId::Executive;
}
impl pallet_invulnerables::Config for Runtime {
    type RuntimeEvent = RuntimeEvent;
    type UpdateOrigin = EnsureRoot<AccountId>;
    type MaxInvulnerables = MaxInvulnerables;
    type CollatorId = <Self as frame_system::Config>::AccountId;
    type CollatorIdOf = ConvertInto;
    type CollatorRegistration = Session;
    type WeightInfo = weights::pallet_invulnerables::SubstrateWeight<Runtime>;
    #[cfg(feature = "runtime-benchmarks")]
    type Currency = Balances;
}
parameter_types! {
    #[derive(Clone)]
    pub const MaxLengthParaIds: u32 = 100u32;
    pub const MaxEncodedGenesisDataSize: u32 = 5_000_000u32; // 5MB
}
pub struct CurrentSessionIndexGetter;
impl tp_traits::GetSessionIndex<u32> for CurrentSessionIndexGetter {
    /// Returns current session index.
58661
    fn session_index() -> u32 {
58661
        Session::current_index()
58661
    }
    #[cfg(feature = "runtime-benchmarks")]
    fn skip_to_session(session_index: SessionIndex) {
        while Session::current_index() < session_index {
            Session::rotate_session();
        }
    }
}
impl pallet_configuration::Config for Runtime {
    type SessionDelay = ConstU32<2>;
    type SessionIndex = u32;
    type CurrentSessionIndex = CurrentSessionIndexGetter;
    type ForceEmptyOrchestrator = ConstBool<false>;
    type WeightInfo = weights::pallet_configuration::SubstrateWeight<Runtime>;
}
pub struct DanceboxRegistrarHooks;
impl RegistrarHooks for DanceboxRegistrarHooks {
153
    fn para_marked_valid_for_collating(para_id: ParaId) -> Weight {
153
        // Give free credits but only once per para id
153
        ServicesPayment::give_free_credits(&para_id)
153
    }
72
    fn para_deregistered(para_id: ParaId) -> Weight {
        // Clear pallet_author_noting storage
72
        if let Err(e) = AuthorNoting::kill_author_data(RuntimeOrigin::root(), para_id) {
            log::warn!(
                "Failed to kill_author_data after para id {} deregistered: {:?}",
                u32::from(para_id),
                e,
            );
72
        }
        // Remove bootnodes from pallet_data_preservers
72
        DataPreservers::para_deregistered(para_id);
72

            
72
        ServicesPayment::para_deregistered(para_id);
72

            
72
        XcmCoreBuyer::para_deregistered(para_id);
72

            
72
        Weight::default()
72
    }
154
    fn check_valid_for_collating(para_id: ParaId) -> DispatchResult {
154
        // To be able to call mark_valid_for_collating, a container chain must have bootnodes
154
        DataPreservers::check_valid_for_collating(para_id)
154
    }
    #[cfg(feature = "runtime-benchmarks")]
    fn benchmarks_ensure_valid_for_collating(para_id: ParaId) {
        use {
            frame_support::traits::EnsureOriginWithArg,
            pallet_data_preservers::{ParaIdsFilter, Profile, ProfileMode},
        };
        let profile = Profile {
            url: b"/ip4/127.0.0.1/tcp/33049/ws/p2p/12D3KooWHVMhQDHBpj9vQmssgyfspYecgV6e3hH1dQVDUkUbCYC9"
                    .to_vec()
                    .try_into()
                    .expect("to fit in BoundedVec"),
            para_ids: ParaIdsFilter::AnyParaId,
            mode: ProfileMode::Bootnode,
            assignment_request: tp_data_preservers_common::ProviderRequest::Free,
        };
        let profile_id = pallet_data_preservers::NextProfileId::<Runtime>::get();
        let profile_owner = AccountId::new([1u8; 32]);
        DataPreservers::force_create_profile(RuntimeOrigin::root(), profile, profile_owner)
            .expect("profile create to succeed");
        let para_manager =
            <Runtime as pallet_data_preservers::Config>::AssignmentOrigin::try_successful_origin(
                &para_id,
            )
            .expect("should be able to get para manager");
        DataPreservers::start_assignment(
            para_manager,
            profile_id,
            para_id,
            tp_data_preservers_common::AssignerExtra::Free,
        )
        .expect("assignement to work");
        assert!(
            pallet_data_preservers::Assignments::<Runtime>::get(para_id).contains(&profile_id),
            "profile should be correctly assigned"
        );
    }
}
pub struct PalletRelayStorageRootProvider;
impl RelayStorageRootProvider for PalletRelayStorageRootProvider {
12
    fn get_relay_storage_root(relay_block_number: u32) -> Option<H256> {
12
        pallet_relay_storage_roots::pallet::RelayStorageRoot::<Runtime>::get(relay_block_number)
12
    }
    #[cfg(feature = "runtime-benchmarks")]
    fn set_relay_storage_root(relay_block_number: u32, storage_root: Option<H256>) {
        pallet_relay_storage_roots::pallet::RelayStorageRootKeys::<Runtime>::mutate(|x| {
            if storage_root.is_some() {
                if x.is_full() {
                    let key = x.remove(0);
                    pallet_relay_storage_roots::pallet::RelayStorageRoot::<Runtime>::remove(key);
                }
                let pos = x.iter().position(|x| *x >= relay_block_number);
                if let Some(pos) = pos {
                    if x[pos] != relay_block_number {
                        x.try_insert(pos, relay_block_number).unwrap();
                    }
                } else {
                    // Push at end
                    x.try_push(relay_block_number).unwrap();
                }
            } else {
                let pos = x.iter().position(|x| *x == relay_block_number);
                if let Some(pos) = pos {
                    x.remove(pos);
                }
            }
        });
        pallet_relay_storage_roots::pallet::RelayStorageRoot::<Runtime>::set(
            relay_block_number,
            storage_root,
        );
    }
}
impl pallet_registrar::Config for Runtime {
    type RuntimeEvent = RuntimeEvent;
    type RegistrarOrigin =
        EitherOfDiverse<pallet_registrar::EnsureSignedByManager<Runtime>, EnsureRoot<AccountId>>;
    type MarkValidForCollatingOrigin = EnsureRoot<AccountId>;
    type MaxLengthParaIds = MaxLengthParaIds;
    type MaxGenesisDataSize = MaxEncodedGenesisDataSize;
    type RegisterWithRelayProofOrigin = EnsureSigned<AccountId>;
    type RelayStorageRootProvider = PalletRelayStorageRootProvider;
    type SessionDelay = ConstU32<2>;
    type SessionIndex = u32;
    type CurrentSessionIndex = CurrentSessionIndexGetter;
    type Currency = Balances;
    type RegistrarHooks = DanceboxRegistrarHooks;
    type RuntimeHoldReason = RuntimeHoldReason;
    type InnerRegistrar = ();
    type WeightInfo = weights::pallet_registrar::SubstrateWeight<Runtime>;
    type DataDepositPerByte = DataDepositPerByte;
}
impl pallet_authority_mapping::Config for Runtime {
    type SessionIndex = u32;
    type SessionRemovalBoundary = ConstU32<2>;
    type AuthorityId = NimbusId;
}
impl pallet_sudo::Config for Runtime {
    type RuntimeCall = RuntimeCall;
    type RuntimeEvent = RuntimeEvent;
    type WeightInfo = weights::pallet_sudo::SubstrateWeight<Runtime>;
}
impl pallet_utility::Config for Runtime {
    type RuntimeEvent = RuntimeEvent;
    type RuntimeCall = RuntimeCall;
    type PalletsOrigin = OriginCaller;
    type WeightInfo = weights::pallet_utility::SubstrateWeight<Runtime>;
}
/// The type used to represent the kinds of proxying allowed.
#[apply(derive_storage_traits)]
#[derive(Copy, Ord, PartialOrd, MaxEncodedLen, DecodeWithMemTracking)]
#[allow(clippy::unnecessary_cast)]
pub enum ProxyType {
181
    /// All calls can be proxied. This is the trivial/most permissive filter.
    Any = 0,
56
    /// Only extrinsics that do not transfer funds.
    NonTransfer = 1,
49
    /// Only extrinsics related to governance (democracy and collectives).
    Governance = 2,
43
    /// Only extrinsics related to staking.
    Staking = 3,
103
    /// Allow to veto an announced proxy call.
    CancelProxy = 4,
37
    /// Allow extrinsic related to Balances.
    Balances = 5,
37
    /// Allow extrinsics related to Registrar
    Registrar = 6,
31
    /// Allow extrinsics related to Registrar that needs to be called through Sudo
    SudoRegistrar = 7,
37
    /// Allow extrinsics from the Session pallet for key management.
    SessionKeyManagement = 8,
}
impl Default for ProxyType {
    fn default() -> Self {
        Self::Any
    }
}
impl InstanceFilter<RuntimeCall> for ProxyType {
94
    fn filter(&self, c: &RuntimeCall) -> bool {
94
        // Since proxy filters are respected in all dispatches of the Utility
94
        // pallet, it should never need to be filtered by any proxy.
94
        if let RuntimeCall::Utility(..) = c {
            return true;
94
        }
94

            
94
        match self {
25
            ProxyType::Any => true,
            ProxyType::NonTransfer => {
8
                matches!(
14
                    c,
                    RuntimeCall::System(..)
                        | RuntimeCall::ParachainSystem(..)
                        | RuntimeCall::Timestamp(..)
                        | RuntimeCall::Proxy(..)
                        | RuntimeCall::Registrar(..)
                )
            }
            // We don't have governance yet
1
            ProxyType::Governance => false,
            ProxyType::Staking => {
1
                matches!(c, RuntimeCall::Session(..) | RuntimeCall::PooledStaking(..))
            }
7
            ProxyType::CancelProxy => matches!(
6
                c,
                RuntimeCall::Proxy(pallet_proxy::Call::reject_announcement { .. })
            ),
            ProxyType::Balances => {
13
                matches!(c, RuntimeCall::Balances(..))
            }
            ProxyType::Registrar => {
1
                matches!(
13
                    c,
                    RuntimeCall::Registrar(..) | RuntimeCall::DataPreservers(..)
                )
            }
7
            ProxyType::SudoRegistrar => match c {
7
                RuntimeCall::Sudo(pallet_sudo::Call::sudo { call: ref x }) => {
1
                    matches!(
7
                        x.as_ref(),
                        &RuntimeCall::Registrar(..) | &RuntimeCall::DataPreservers(..)
                    )
                }
                _ => false,
            },
            ProxyType::SessionKeyManagement => {
7
                matches!(c, RuntimeCall::Session(..))
            }
        }
94
    }
    fn is_superset(&self, o: &Self) -> bool {
        match (self, o) {
            (x, y) if x == y => true,
            (ProxyType::Any, _) => true,
            (_, ProxyType::Any) => false,
            _ => false,
        }
    }
}
impl pallet_proxy::Config for Runtime {
    type RuntimeEvent = RuntimeEvent;
    type RuntimeCall = RuntimeCall;
    type Currency = Balances;
    type ProxyType = ProxyType;
    // One storage item; key size 32, value size 8
    type ProxyDepositBase = ConstU128<{ currency::deposit(1, 8) }>;
    // Additional storage item size of 33 bytes (32 bytes AccountId + 1 byte sizeof(ProxyType)).
    type ProxyDepositFactor = ConstU128<{ currency::deposit(0, 33) }>;
    type MaxProxies = ConstU32<32>;
    type MaxPending = ConstU32<32>;
    type CallHasher = BlakeTwo256;
    type AnnouncementDepositBase = ConstU128<{ currency::deposit(1, 8) }>;
    // Additional storage item size of 68 bytes:
    // - 32 bytes AccountId
    // - 32 bytes Hasher (Blake2256)
    // - 4 bytes BlockNumber (u32)
    type AnnouncementDepositFactor = ConstU128<{ currency::deposit(0, 68) }>;
    type WeightInfo = weights::pallet_proxy::SubstrateWeight<Runtime>;
    type BlockNumberProvider = System;
}
pub struct XcmExecutionManager;
impl xcm_primitives::PauseXcmExecution for XcmExecutionManager {
42
    fn suspend_xcm_execution() -> DispatchResult {
42
        XcmpQueue::suspend_xcm_execution(RuntimeOrigin::root())
42
    }
36
    fn resume_xcm_execution() -> DispatchResult {
36
        XcmpQueue::resume_xcm_execution(RuntimeOrigin::root())
36
    }
}
impl pallet_migrations::Config for Runtime {
    type RuntimeEvent = RuntimeEvent;
    type MigrationsList = (tanssi_runtime_common::migrations::DanceboxMigrations<Runtime>,);
    type XcmExecutionManager = XcmExecutionManager;
}
parameter_types! {
    pub MbmServiceWeight: Weight = Perbill::from_percent(80) * RuntimeBlockWeights::get().max_block;
}
impl pallet_multiblock_migrations::Config for Runtime {
    type RuntimeEvent = RuntimeEvent;
    #[cfg(not(feature = "runtime-benchmarks"))]
    type Migrations = ();
    // Benchmarks need mocked migrations to guarantee that they succeed.
    #[cfg(feature = "runtime-benchmarks")]
    type Migrations = pallet_multiblock_migrations::mock_helpers::MockedMigrations;
    type CursorMaxLen = ConstU32<65_536>;
    type IdentifierMaxLen = ConstU32<256>;
    type MigrationStatusHandler = ();
    type FailedMigrationHandler = MaintenanceMode;
    type MaxServiceWeight = MbmServiceWeight;
    type WeightInfo = weights::pallet_multiblock_migrations::SubstrateWeight<Runtime>;
}
/// Maintenance mode Call filter
pub struct MaintenanceFilter;
impl Contains<RuntimeCall> for MaintenanceFilter {
696
    fn contains(c: &RuntimeCall) -> bool {
678
        !matches!(
696
            c,
            RuntimeCall::Balances(..)
                | RuntimeCall::Registrar(..)
                | RuntimeCall::Session(..)
                | RuntimeCall::System(..)
                | RuntimeCall::PooledStaking(..)
                | RuntimeCall::Utility(..)
                | RuntimeCall::PolkadotXcm(..)
        )
696
    }
}
/// Normal Call Filter
pub struct NormalFilter;
impl Contains<RuntimeCall> for NormalFilter {
99547
    fn contains(_c: &RuntimeCall) -> bool {
99547
        true
99547
    }
}
impl pallet_maintenance_mode::Config for Runtime {
    type RuntimeEvent = RuntimeEvent;
    type NormalCallFilter = NormalFilter;
    type MaintenanceCallFilter = InsideBoth<MaintenanceFilter, NormalFilter>;
    type MaintenanceOrigin = EnsureRoot<AccountId>;
    type XcmExecutionManager = XcmExecutionManager;
}
parameter_types! {
    pub const MaxStorageRoots: u32 = 10; // 1 minute of relay blocks
}
impl pallet_relay_storage_roots::Config for Runtime {
    type RelaychainStateProvider = cumulus_pallet_parachain_system::RelaychainDataProvider<Self>;
    type MaxStorageRoots = MaxStorageRoots;
    type WeightInfo = weights::pallet_relay_storage_roots::SubstrateWeight<Runtime>;
}
impl pallet_root_testing::Config for Runtime {
    type RuntimeEvent = RuntimeEvent;
}
parameter_types! {
    pub StakingAccount: AccountId32 = PalletId(*b"POOLSTAK").into_account_truncating();
    pub const InitialManualClaimShareValue: u128 = currency::MILLIDANCE;
    pub const InitialAutoCompoundingShareValue: u128 = currency::MILLIDANCE;
    pub const MinimumSelfDelegation: u128 = 10 * currency::KILODANCE;
    pub const RewardsCollatorCommission: Perbill = Perbill::from_percent(20);
    // Need to wait 2 sessions before being able to join or leave staking pools
    pub const StakingSessionDelay: u32 = 2;
}
pub struct CandidateIsOnlineAndHasRegisteredKeys;
impl IsCandidateEligible<AccountId> for CandidateIsOnlineAndHasRegisteredKeys {
156
    fn is_candidate_eligible(a: &AccountId) -> bool {
156
        <Session as ValidatorRegistration<AccountId>>::is_registered(a)
152
            && !InactivityTracking::is_node_offline(a)
156
    }
    #[cfg(feature = "runtime-benchmarks")]
    fn make_candidate_eligible(a: &AccountId, eligible: bool) {
        use sp_core::crypto::UncheckedFrom;
        if eligible {
            let account_slice: &[u8; 32] = a.as_ref();
            let _ = Session::set_keys(
                RuntimeOrigin::signed(a.clone()),
                SessionKeys {
                    nimbus: NimbusId::unchecked_from(*account_slice),
                },
                vec![],
            );
        } else {
            let _ = Session::purge_keys(RuntimeOrigin::signed(a.clone()));
        }
        if InactivityTracking::is_node_offline(a) {
            InactivityTracking::make_node_online(a);
        }
    }
}
parameter_types! {
    pub const MaxCandidatesBufferSize: u32 = 100;
}
impl pallet_pooled_staking::Config for Runtime {
    type RuntimeEvent = RuntimeEvent;
    type Currency = Balances;
    type Balance = Balance;
    type StakingAccount = StakingAccount;
    type InitialManualClaimShareValue = InitialManualClaimShareValue;
    type InitialAutoCompoundingShareValue = InitialAutoCompoundingShareValue;
    type MinimumSelfDelegation = MinimumSelfDelegation;
    type RuntimeHoldReason = RuntimeHoldReason;
    type RewardsCollatorCommission = RewardsCollatorCommission;
    type JoiningRequestTimer = SessionTimer<Runtime, StakingSessionDelay>;
    type LeavingRequestTimer = SessionTimer<Runtime, StakingSessionDelay>;
    type EligibleCandidatesBufferSize = MaxCandidatesBufferSize;
    type EligibleCandidatesFilter = CandidateIsOnlineAndHasRegisteredKeys;
    type WeightInfo = weights::pallet_pooled_staking::SubstrateWeight<Runtime>;
}
parameter_types! {
    pub ParachainBondAccount: AccountId32 = PalletId(*b"ParaBond").into_account_truncating();
    pub PendingRewardsAccount: AccountId32 = PalletId(*b"PENDREWD").into_account_truncating();
    // The equation to solve is:
    // initial_supply * (1.05) = initial_supply * (1+x)^5_259_600
    // we should solve for x = (1.05)^(1/5_259_600) -1 -> 0.000000009 per block or 9/1_000_000_000
    // 1% in the case of dev mode
    // TODO: better calculus for going from annual to block inflation (if it can be done)
    pub const InflationRate: Perbill = prod_or_fast!(Perbill::from_parts(9), Perbill::from_percent(1));
    // 30% for parachain bond, so 70% for staking
    pub const RewardsPortion: Perbill = Perbill::from_percent(70);
}
pub struct GetSelfChainBlockAuthor;
impl MaybeSelfChainBlockAuthor<AccountId32> for GetSelfChainBlockAuthor {
83695
    fn get_block_author() -> Option<AccountId32> {
83695
        // TODO: we should do a refactor here, and use either authority-mapping or collator-assignemnt
83695
        // we should also make sure we actually account for the weight of these
83695
        // although most of these should be cached as they are read every block
83695
        let slot = u64::from(<Runtime as pallet_author_inherent::Config>::SlotBeacon::slot());
83695
        let self_para_id = ParachainInfo::get();
83695
        CollatorAssignment::author_for_slot(slot.into(), self_para_id)
83695
    }
}
pub struct OnUnbalancedInflation;
impl frame_support::traits::OnUnbalanced<Credit<AccountId, Balances>> for OnUnbalancedInflation {
28369
    fn on_nonzero_unbalanced(credit: Credit<AccountId, Balances>) {
28369
        let _ = <Balances as Balanced<_>>::resolve(&ParachainBondAccount::get(), credit);
28369
    }
}
impl pallet_inflation_rewards::Config for Runtime {
    type RuntimeEvent = RuntimeEvent;
    type Currency = Balances;
    type ContainerChains = Registrar;
    type GetSelfChainBlockAuthor = GetSelfChainBlockAuthor;
    type InflationRate = InflationRate;
    type OnUnbalanced = OnUnbalancedInflation;
    type PendingRewardsAccount = PendingRewardsAccount;
    type StakingRewardsDistributor = InvulnerableRewardDistribution<Self, Balances, PooledStaking>;
    type RewardsPortion = RewardsPortion;
}
impl pallet_tx_pause::Config for Runtime {
    type RuntimeEvent = RuntimeEvent;
    type RuntimeCall = RuntimeCall;
    type PauseOrigin = EnsureRoot<AccountId>;
    type UnpauseOrigin = EnsureRoot<AccountId>;
    type WhitelistedCalls = ();
    type MaxNameLen = ConstU32<256>;
    type WeightInfo = weights::pallet_tx_pause::SubstrateWeight<Runtime>;
}
parameter_types! {
    // 1 entry, storing 253 bytes on-chain in the worst case
    pub const OpenStreamHoldAmount: Balance = currency::deposit(1, 253);
}
impl pallet_stream_payment::Config for Runtime {
    type RuntimeEvent = RuntimeEvent;
    type StreamId = StreamId;
    type TimeUnit = tp_stream_payment_common::TimeUnit;
    type Balance = Balance;
    type AssetId = tp_stream_payment_common::AssetId;
    type AssetsManager = tp_stream_payment_common::AssetsManager<Runtime>;
    type Currency = Balances;
    type OpenStreamHoldAmount = OpenStreamHoldAmount;
    type RuntimeHoldReason = RuntimeHoldReason;
    type TimeProvider = tp_stream_payment_common::TimeProvider<Runtime>;
    type WeightInfo = weights::pallet_stream_payment::SubstrateWeight<Runtime>;
}
parameter_types! {
    // 1 entry, storing 258 bytes on-chain
    pub const BasicDeposit: Balance = currency::deposit(1, 258);
    // 1 entry, storing 53 bytes on-chain
    pub const SubAccountDeposit: Balance = currency::deposit(1, 53);
    // Additional bytes adds 0 entries, storing 1 byte on-chain
    pub const ByteDeposit: Balance = currency::deposit(0, 1);
    pub const UsernameDeposit: Balance = currency::deposit(0, 32);
    pub const MaxSubAccounts: u32 = 100;
    pub const MaxAdditionalFields: u32 = 100;
    pub const MaxRegistrars: u32 = 20;
}
impl pallet_identity::Config for Runtime {
    type RuntimeEvent = RuntimeEvent;
    type Currency = Balances;
    type BasicDeposit = BasicDeposit;
    type ByteDeposit = ByteDeposit;
    type UsernameDeposit = UsernameDeposit;
    type SubAccountDeposit = SubAccountDeposit;
    type MaxSubAccounts = MaxSubAccounts;
    type MaxRegistrars = MaxRegistrars;
    type IdentityInformation = pallet_identity::legacy::IdentityInfo<MaxAdditionalFields>;
    // Slashed balances are burnt
    type Slashed = ();
    type ForceOrigin = EnsureRoot<AccountId>;
    type RegistrarOrigin = EnsureRoot<AccountId>;
    type OffchainSignature = Signature;
    type SigningPublicKey = <Signature as Verify>::Signer;
    type UsernameAuthorityOrigin = EnsureRoot<Self::AccountId>;
    type PendingUsernameExpiration = ConstU32<{ 7 * DAYS }>;
    type UsernameGracePeriod = ConstU32<{ 30 * DAYS }>;
    type MaxSuffixLength = ConstU32<7>;
    type MaxUsernameLength = ConstU32<32>;
    type WeightInfo = weights::pallet_identity::SubstrateWeight<Runtime>;
}
parameter_types! {
    pub const TreasuryId: PalletId = PalletId(*b"tns/tsry");
    pub const ProposalBond: Permill = Permill::from_percent(5);
    pub TreasuryAccount: AccountId = Treasury::account_id();
    pub const MaxBalance: Balance = Balance::MAX;
    // We allow it to be 1 minute in fast mode to be able to test it
    pub const SpendPeriod: BlockNumber = prod_or_fast!(6 * DAYS, 1 * MINUTES);
    pub const DataDepositPerByte: Balance = 1 * CENTS;
}
impl pallet_treasury::Config for Runtime {
    type PalletId = TreasuryId;
    type Currency = Balances;
    type RejectOrigin = EnsureRoot<AccountId>;
    type RuntimeEvent = RuntimeEvent;
    // If proposal gets rejected, bond goes to treasury
    type SpendPeriod = SpendPeriod;
    type Burn = ();
    type BurnDestination = ();
    type MaxApprovals = ConstU32<100>;
    type WeightInfo = weights::pallet_treasury::SubstrateWeight<Runtime>;
    type SpendFunds = ();
    type SpendOrigin =
        frame_system::EnsureWithSuccess<EnsureRoot<AccountId>, AccountId, MaxBalance>;
    type AssetKind = ();
    type Beneficiary = AccountId;
    type BeneficiaryLookup = IdentityLookup<AccountId>;
    type Paymaster = PayFromAccount<Balances, TreasuryAccount>;
    // TODO: implement pallet-asset-rate to allow the treasury to spend other assets
    type BalanceConverter = UnityAssetBalanceConversion;
    type PayoutPeriod = ConstU32<{ 30 * DAYS }>;
    type BlockNumberProvider = System;
    #[cfg(feature = "runtime-benchmarks")]
    type BenchmarkHelper = tanssi_runtime_common::benchmarking::TreasuryBenchmarkHelper<Runtime>;
}
parameter_types! {
    // One storage item; key size 32; value is size 4+4+16+32. Total = 1 * (32 + 56)
    pub const DepositBase: Balance = currency::deposit(1, 88);
    // Additional storage item size of 32 bytes.
    pub const DepositFactor: Balance = currency::deposit(0, 32);
    pub const MaxSignatories: u32 = 100;
}
impl pallet_multisig::Config for Runtime {
    type RuntimeEvent = RuntimeEvent;
    type RuntimeCall = RuntimeCall;
    type Currency = Balances;
    type DepositBase = DepositBase;
    type DepositFactor = DepositFactor;
    type MaxSignatories = MaxSignatories;
    type WeightInfo = weights::pallet_multisig::SubstrateWeight<Runtime>;
    type BlockNumberProvider = System;
}
parameter_types! {
    pub const MaxInactiveSessions: u32 = 5;
}
impl pallet_inactivity_tracking::Config for Runtime {
    type RuntimeEvent = RuntimeEvent;
    type MaxInactiveSessions = MaxInactiveSessions;
    type MaxCollatorsPerSession = MaxCandidatesBufferSize;
    type MaxContainerChains = MaxLengthParaIds;
    type CurrentSessionIndex = CurrentSessionIndexGetter;
    type CurrentCollatorsFetcher = CollatorAssignment;
    type GetSelfChainBlockAuthor = GetSelfChainBlockAuthor;
    type ParaFilter = tp_parathread_filter_common::ExcludeAllParathreadsFilter<Runtime>;
    type InvulnerablesFilter = tp_invulnerables_filter_common::InvulnerablesFilter<Runtime>;
    type CollatorStakeHelper = PooledStaking;
    type WeightInfo = weights::pallet_inactivity_tracking::SubstrateWeight<Runtime>;
}
// Create the runtime by composing the FRAME pallets that were previously configured.
1060682
construct_runtime!(
1060682
    pub enum Runtime
1060682
    {
1060682
        // System support stuff.
1060682
        System: frame_system = 0,
1060682
        ParachainSystem: cumulus_pallet_parachain_system = 1,
1060682
        Timestamp: pallet_timestamp = 2,
1060682
        ParachainInfo: parachain_info = 3,
1060682
        Sudo: pallet_sudo = 4,
1060682
        Utility: pallet_utility = 5,
1060682
        Proxy: pallet_proxy = 6,
1060682
        Migrations: pallet_migrations = 7,
1060682
        MultiBlockMigrations: pallet_multiblock_migrations = 121,
1060682
        MaintenanceMode: pallet_maintenance_mode = 8,
1060682
        TxPause: pallet_tx_pause = 9,
1060682

            
1060682
        // Monetary stuff.
1060682
        Balances: pallet_balances = 10,
1060682
        TransactionPayment: pallet_transaction_payment = 11,
1060682
        StreamPayment: pallet_stream_payment = 12,
1060682

            
1060682
        // Other utilities
1060682
        Identity: pallet_identity = 15,
1060682
        Multisig: pallet_multisig = 16,
1060682

            
1060682
        // ContainerChain management. It should go before Session for Genesis
1060682
        Registrar: pallet_registrar = 20,
1060682
        Configuration: pallet_configuration = 21,
1060682
        CollatorAssignment: pallet_collator_assignment = 22,
1060682
        Initializer: pallet_initializer = 23,
1060682
        AuthorNoting: pallet_author_noting = 24,
1060682
        AuthorityAssignment: pallet_authority_assignment = 25,
1060682
        ServicesPayment: pallet_services_payment = 26,
1060682
        DataPreservers: pallet_data_preservers = 27,
1060682

            
1060682
        // Collator support. The order of these 6 are important and shall not change.
1060682
        Invulnerables: pallet_invulnerables = 30,
1060682
        Session: pallet_session = 31,
1060682
        AuthorityMapping: pallet_authority_mapping = 32,
1060682
        AuthorInherent: pallet_author_inherent = 33,
1060682
        PooledStaking: pallet_pooled_staking = 34,
1060682
        // InflationRewards must be after Session and AuthorInherent
1060682
        InflationRewards: pallet_inflation_rewards = 35,
1060682
        InactivityTracking: pallet_inactivity_tracking = 36,
1060682

            
1060682
        // Treasury stuff.
1060682
        Treasury: pallet_treasury::{Pallet, Storage, Config<T>, Event<T>, Call} = 40,
1060682

            
1060682
        //XCM
1060682
        XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event<T>} = 50,
1060682
        CumulusXcm: cumulus_pallet_xcm::{Pallet, Event<T>, Origin} = 51,
1060682
        PolkadotXcm: pallet_xcm::{Pallet, Call, Storage, Event<T>, Origin, Config<T>} = 53,
1060682
        ForeignAssets: pallet_assets::<Instance1>::{Pallet, Call, Storage, Event<T>} = 54,
1060682
        ForeignAssetsCreator: pallet_foreign_asset_creator::{Pallet, Call, Storage, Event<T>} = 55,
1060682
        AssetRate: pallet_asset_rate::{Pallet, Call, Storage, Event<T>} = 56,
1060682
        MessageQueue: pallet_message_queue::{Pallet, Call, Storage, Event<T>} = 57,
1060682
        XcmCoreBuyer: pallet_xcm_core_buyer = 58,
1060682

            
1060682
        // More system support stuff
1060682
        RelayStorageRoots: pallet_relay_storage_roots = 60,
1060682
        WeightReclaim: cumulus_pallet_weight_reclaim = 61,
1060682

            
1060682
        RootTesting: pallet_root_testing = 100,
1060682
        AsyncBacking: pallet_async_backing::{Pallet, Storage} = 110,
1060682
    }
1060682
);
#[cfg(feature = "runtime-benchmarks")]
mod benches {
    frame_benchmarking::define_benchmarks!(
        [frame_system, frame_system_benchmarking::Pallet::<Runtime>]
        [frame_system_extensions, frame_system_benchmarking::extensions::Pallet::<Runtime>]
        [cumulus_pallet_parachain_system, ParachainSystem]
        [pallet_timestamp, Timestamp]
        [pallet_sudo, Sudo]
        [pallet_utility, Utility]
        [pallet_proxy, Proxy]
        [pallet_transaction_payment, TransactionPayment]
        [pallet_tx_pause, TxPause]
        [pallet_balances, Balances]
        [pallet_stream_payment, StreamPayment]
        [pallet_identity, Identity]
        [pallet_multiblock_migrations, MultiBlockMigrations]
        [pallet_multisig, Multisig]
        [pallet_registrar, Registrar]
        [pallet_configuration, Configuration]
        [pallet_collator_assignment, CollatorAssignment]
        [pallet_author_noting, AuthorNoting]
        [pallet_services_payment, ServicesPayment]
        [pallet_data_preservers, DataPreservers]
        [pallet_invulnerables, Invulnerables]
        [pallet_session, SessionBench::<Runtime>]
        [pallet_author_inherent, AuthorInherent]
        [pallet_pooled_staking, PooledStaking]
        [pallet_inactivity_tracking, InactivityTracking]
        [pallet_treasury, Treasury]
        [cumulus_pallet_xcmp_queue, XcmpQueue]
        // XCM
        [pallet_xcm, PalletXcmExtrinsicsBenchmark::<Runtime>]
        [pallet_xcm_benchmarks::fungible, pallet_xcm_benchmarks::fungible::Pallet::<Runtime>]
        [pallet_xcm_benchmarks::generic, pallet_xcm_benchmarks::generic::Pallet::<Runtime>]
        [pallet_assets, ForeignAssets]
        [pallet_foreign_asset_creator, ForeignAssetsCreator]
        [pallet_asset_rate, AssetRate]
        [pallet_message_queue, MessageQueue]
        [pallet_xcm_core_buyer, XcmCoreBuyer]
        [pallet_relay_storage_roots, RelayStorageRoots]
        [cumulus_pallet_weight_reclaim, WeightReclaim]
    );
}
27485
pub fn get_para_id_authorities(para_id: ParaId) -> Option<Vec<NimbusId>> {
27485
    let parent_number = System::block_number();
27485

            
27485
    let should_end_session =
27485
        <Runtime as pallet_session::Config>::ShouldEndSession::should_end_session(
27485
            parent_number + 1,
27485
        );
27485
    let session_index = if should_end_session {
2643
        Session::current_index() + 1
    } else {
24842
        Session::current_index()
    };
27485
    let assigned_authorities = AuthorityAssignment::collator_container_chain(session_index)?;
27485
    let self_para_id = ParachainInfo::get();
27485

            
27485
    if para_id == self_para_id {
27411
        Some(assigned_authorities.orchestrator_chain)
    } else {
74
        assigned_authorities.container_chains.get(&para_id).cloned()
    }
27485
}
51800
impl_runtime_apis! {
51800
    impl sp_consensus_aura::AuraApi<Block, NimbusId> for Runtime {
67536
        fn slot_duration() -> sp_consensus_aura::SlotDuration {
24228
            sp_consensus_aura::SlotDuration::from_millis(SLOT_DURATION)
24228
        }
51800

            
51800
        fn authorities() -> Vec<NimbusId> {
            // Check whether we need to fetch the next authorities or current ones
            let parent_number = System::block_number();
            let should_end_session = <Runtime as pallet_session::Config>::ShouldEndSession::should_end_session(parent_number + 1);
51800

            
51800
            let session_index = if should_end_session {
51800
                Session::current_index() +1
51800
            }
51800
            else {
51800
                Session::current_index()
51800
            };
51800

            
51800
            pallet_authority_assignment::CollatorContainerChain::<Runtime>::get(session_index)
                .expect("authorities for current session should exist")
                .orchestrator_chain
        }
51800
    }
51800

            
51800
    impl sp_api::Core<Block> for Runtime {
51800
        fn version() -> RuntimeVersion {
            VERSION
        }
51800

            
51800
        fn execute_block(block: Block) {
            Executive::execute_block(block)
        }
51800

            
67164
        fn initialize_block(header: &<Block as BlockT>::Header) -> sp_runtime::ExtrinsicInclusionMode {
23670
            Executive::initialize_block(header)
23670
        }
51800
    }
51800

            
51800
    impl sp_api::Metadata<Block> for Runtime {
51800
        fn metadata() -> OpaqueMetadata {
90
            OpaqueMetadata::new(Runtime::metadata().into())
90
        }
51800

            
51800
        fn metadata_at_version(version: u32) -> Option<OpaqueMetadata> {
534
            Runtime::metadata_at_version(version)
534
        }
51800

            
51800
        fn metadata_versions() -> Vec<u32> {
534
            Runtime::metadata_versions()
534
        }
51800
    }
51800

            
51800
    impl sp_block_builder::BlockBuilder<Block> for Runtime {
116268
        fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {
97326
            Executive::apply_extrinsic(extrinsic)
97326
        }
51800

            
67164
        fn finalize_block() -> <Block as BlockT>::Header {
23670
            Executive::finalize_block()
23670
        }
51800

            
67164
        fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {
23670
            data.create_extrinsics()
23670
        }
51800

            
51800
        fn check_inherents(
            block: Block,
            data: sp_inherents::InherentData,
        ) -> sp_inherents::CheckInherentsResult {
            data.check_extrinsics(&block)
        }
51800
    }
51800

            
51800
    impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
59056
        fn validate_transaction(
11508
            source: TransactionSource,
11508
            tx: <Block as BlockT>::Extrinsic,
11508
            block_hash: <Block as BlockT>::Hash,
11508
        ) -> TransactionValidity {
11508
            Executive::validate_transaction(source, tx, block_hash)
11508
        }
51800
    }
51800

            
51800
    impl sp_offchain::OffchainWorkerApi<Block> for Runtime {
67164
        fn offchain_worker(header: &<Block as BlockT>::Header) {
23670
            Executive::offchain_worker(header)
23670
        }
51800
    }
51800

            
51800
    impl sp_session::SessionKeys<Block> for Runtime {
51824
        fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
660
            SessionKeys::generate(seed)
660
        }
51800

            
51800
        fn decode_session_keys(
            encoded: Vec<u8>,
        ) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {
            SessionKeys::decode_into_raw_public_keys(&encoded)
        }
51800
    }
51800

            
51800
    impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Index> for Runtime {
51800
        fn account_nonce(account: AccountId) -> Index {
108
            System::account_nonce(account)
108
        }
51800
    }
51800

            
51800
    impl cumulus_primitives_core::CollectCollationInfo<Block> for Runtime {
67164
        fn collect_collation_info(header: &<Block as BlockT>::Header) -> cumulus_primitives_core::CollationInfo {
23670
            ParachainSystem::collect_collation_info(header)
23670
        }
51800
    }
51800

            
51800
    impl async_backing_primitives::UnincludedSegmentApi<Block> for Runtime {
51800
        fn can_build_upon(
            included_hash: <Block as BlockT>::Hash,
            slot: async_backing_primitives::Slot,
        ) -> bool {
            ConsensusHook::can_build_upon(included_hash, slot)
        }
51800
    }
51800

            
51800
    impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
51800
        fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
            build_state::<RuntimeGenesisConfig>(config)
        }
51800

            
51800
        fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
            get_preset::<RuntimeGenesisConfig>(id, |_| None)
        }
51800

            
51800
        fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
            vec![]
        }
51800
    }
51800

            
51800
    #[cfg(feature = "runtime-benchmarks")]
51800
    impl frame_benchmarking::Benchmark<Block> for Runtime {
51800
        fn benchmark_metadata(
51800
            extra: bool,
51800
        ) -> (
51800
            Vec<frame_benchmarking::BenchmarkList>,
51800
            Vec<frame_support::traits::StorageInfo>,
51800
        ) {
51800
            use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
51800
            use frame_benchmarking::{BenchmarkList};
51800
            use frame_support::traits::StorageInfoTrait;
51800
            use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark;
51800

            
51800
            let mut list = Vec::<BenchmarkList>::new();
51800
            list_benchmarks!(list, extra);
51800

            
51800
            let storage_info = AllPalletsWithSystem::storage_info();
51800
            (list, storage_info)
51800
        }
51800

            
51800
        #[allow(non_local_definitions)]
51800
        fn dispatch_benchmark(
51800
            config: frame_benchmarking::BenchmarkConfig,
51800
        ) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> {
51800
            use frame_benchmarking::{BenchmarkBatch, BenchmarkError};
51800
            use sp_core::storage::TrackedStorageKey;
51800
            use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
51800
            impl cumulus_pallet_session_benchmarking::Config for Runtime {}
51800

            
51800
            impl frame_system_benchmarking::Config for Runtime {
51800
                fn setup_set_code_requirements(code: &alloc::vec::Vec<u8>) -> Result<(), BenchmarkError> {
51800
                    ParachainSystem::initialize_for_set_code_benchmark(code.len() as u32);
51800
                    Ok(())
51800
                }
51800

            
51800
                fn verify_set_code() {
51800
                    System::assert_last_event(cumulus_pallet_parachain_system::Event::<Runtime>::ValidationFunctionStored.into());
51800
                }
51800
            }
51800

            
51800
            use xcm::latest::prelude::*;
51800
            use crate::xcm_config::SelfReserve;
51800

            
51800
            parameter_types! {
51800
                pub ExistentialDepositAsset: Option<Asset> = Some((
51800
                    SelfReserve::get(),
51800
                    ExistentialDeposit::get()
51800
                ).into());
51800
                pub TrustedReserve: Option<(Location, Asset)> = Some(
51800
                    (
51800
                        Location::parent(),
51800
                        Asset {
51800
                            id: AssetId(Location::parent()),
51800
                            fun: Fungible(ExistentialDeposit::get() * 100),
51800
                        },
51800
                    )
51800
                );
51800
            }
51800

            
51800
            impl pallet_xcm_benchmarks::fungible::Config for Runtime {
51800
                type TransactAsset = Balances;
51800
                type CheckedAccount = ();
51800
                type TrustedTeleporter = ();
51800
                type TrustedReserve = TrustedReserve;
51800

            
51800
                fn get_asset() -> Asset {
51800
                    use frame_support::{assert_ok, traits::tokens::fungible::{Inspect, Mutate}};
51800
                    use xcm::latest::prelude::Junctions::X2;
51800

            
51800
                    let (account, _) = pallet_xcm_benchmarks::account_and_location::<Runtime>(1);
51800

            
51800
                    assert_ok!(<Balances as Mutate<_>>::mint_into(
51800
                        &account,
51800
                        <Balances as Inspect<_>>::minimum_balance(),
51800
                    ));
51800

            
51800
                    let asset_id = 42u16;
51800

            
51800
                    let asset_location = Location {
51800
                        parents: 1,
51800
                        interior: X2([
51800
                            GlobalConsensus(NetworkId::Ethereum { chain_id: 1 }),
51800
                            AccountKey20 {
51800
                                network: Some(NetworkId::Ethereum { chain_id: 1 }),
51800
                                key: [0; 20],
51800
                            },
51800
                        ]
51800
                        .into()),
51800
                    };
51800

            
51800
                    assert_ok!(ForeignAssetsCreator::create_foreign_asset(
51800
                        RuntimeOrigin::root(),
51800
                        asset_location.clone(),
51800
                        asset_id,
51800
                        account.clone(),
51800
                        true,
51800
                        1u128,
51800
                    ));
51800

            
51800
                    Asset {
51800
                        id: AssetId(asset_location),
51800
                        fun: Fungible(ExistentialDeposit::get() * 100),
51800
                    }
51800
                }
51800
            }
51800

            
51800
            impl pallet_xcm_benchmarks::Config for Runtime {
51800
                type XcmConfig = xcm_config::XcmConfig;
51800
                type AccountIdConverter = xcm_config::LocationToAccountId;
51800
                type DeliveryHelper = cumulus_primitives_utility::ToParentDeliveryHelper<
51800
                xcm_config::XcmConfig,
51800
                ExistentialDepositAsset,
51800
                xcm_config::PriceForParentDelivery,
51800
                >;
51800
                fn valid_destination() -> Result<Location, BenchmarkError> {
51800
                    Ok(Location::parent())
51800
                }
51800
                fn worst_case_holding(_depositable_count: u32) -> Assets {
51800
                    // We only care for native asset until we support others
51800
                    // TODO: refactor this case once other assets are supported
51800
                    vec![Asset{
51800
                        id: AssetId(SelfReserve::get()),
51800
                        fun: Fungible(u128::MAX),
51800
                    }].into()
51800
                }
51800
            }
51800

            
51800
            impl pallet_xcm_benchmarks::generic::Config for Runtime {
51800
                type TransactAsset = Balances;
51800
                type RuntimeCall = RuntimeCall;
51800

            
51800
                fn worst_case_response() -> (u64, Response) {
51800
                    (0u64, Response::Version(Default::default()))
51800
                }
51800

            
51800
                fn worst_case_asset_exchange() -> Result<(Assets, Assets), BenchmarkError> {
51800
                    Err(BenchmarkError::Skip)
51800
                }
51800

            
51800
                fn universal_alias() -> Result<(Location, Junction), BenchmarkError> {
51800
                    Err(BenchmarkError::Skip)
51800
                }
51800

            
51800
                fn transact_origin_and_runtime_call() -> Result<(Location, RuntimeCall), BenchmarkError> {
51800
                    Ok((Location::parent(), frame_system::Call::remark_with_event { remark: vec![] }.into()))
51800
                }
51800

            
51800
                fn subscribe_origin() -> Result<Location, BenchmarkError> {
51800
                    Ok(Location::parent())
51800
                }
51800

            
51800
                fn fee_asset() -> Result<Asset, BenchmarkError> {
51800
                    Ok(Asset {
51800
                        id: AssetId(SelfReserve::get()),
51800
                        fun: Fungible(ExistentialDeposit::get()*100),
51800
                    })
51800
                }
51800

            
51800
                fn claimable_asset() -> Result<(Location, Location, Assets), BenchmarkError> {
51800
                    let origin = Location::parent();
51800
                    let assets: Assets = (Location::parent(), 1_000u128).into();
51800
                    let ticket = Location { parents: 0, interior: Here };
51800
                    Ok((origin, ticket, assets))
51800
                }
51800

            
51800
                fn unlockable_asset() -> Result<(Location, Location, Asset), BenchmarkError> {
51800
                    Err(BenchmarkError::Skip)
51800
                }
51800

            
51800
                fn export_message_origin_and_destination(
51800
                ) -> Result<(Location, NetworkId, InteriorLocation), BenchmarkError> {
51800
                    Err(BenchmarkError::Skip)
51800
                }
51800

            
51800
                fn alias_origin() -> Result<(Location, Location), BenchmarkError> {
51800
                    Err(BenchmarkError::Skip)
51800
                }
51800
            }
51800

            
51800
            use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark;
51800
            impl pallet_xcm::benchmarking::Config for Runtime {
51800
                type DeliveryHelper = ();
51800
                fn get_asset() -> Asset {
51800
                    Asset {
51800
                        id: AssetId(SelfReserve::get()),
51800
                        fun: Fungible(ExistentialDeposit::get()),
51800
                    }
51800
                }
51800

            
51800
                fn reachable_dest() -> Option<Location> {
51800
                    Some(Parent.into())
51800
                }
51800

            
51800
                fn teleportable_asset_and_dest() -> Option<(Asset, Location)> {
51800
                    // Relay/native token can be teleported between AH and Relay.
51800
                    Some((
51800
                        Asset {
51800
                            fun: Fungible(EXISTENTIAL_DEPOSIT),
51800
                            id: Parent.into()
51800
                        },
51800
                        Parent.into(),
51800
                    ))
51800
                }
51800

            
51800
                fn reserve_transferable_asset_and_dest() -> Option<(Asset, Location)> {
51800
                    use xcm_config::SelfReserve;
51800
                    // AH can reserve transfer native token to some random parachain.
51800
                    let random_para_id = 43211234;
51800
                    ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests(
51800
                        random_para_id.into()
51800
                    );
51800
                    let who = frame_benchmarking::whitelisted_caller();
51800
                    // Give some multiple of the existential deposit
51800
                    let balance = EXISTENTIAL_DEPOSIT * 1000;
51800
                    let _ = <Balances as frame_support::traits::Currency<_>>::make_free_balance_be(
51800
                        &who, balance,
51800
                    );
51800
                    Some((
51800
                        Asset {
51800
                            fun: Fungible(EXISTENTIAL_DEPOSIT),
51800
                            id: AssetId(SelfReserve::get())
51800
                        },
51800
                        ParentThen(Parachain(random_para_id).into()).into(),
51800
                    ))
51800
                }
51800

            
51800
                fn set_up_complex_asset_transfer(
51800
                ) -> Option<(Assets, u32, Location, Box<dyn FnOnce()>)> {
51800
                    use xcm_config::SelfReserve;
51800
                    // Transfer to Relay some local AH asset (local-reserve-transfer) while paying
51800
                    // fees using teleported native token.
51800
                    // (We don't care that Relay doesn't accept incoming unknown AH local asset)
51800
                    let dest = Parent.into();
51800

            
51800
                    let fee_amount = EXISTENTIAL_DEPOSIT;
51800
                    let fee_asset: Asset = (SelfReserve::get(), fee_amount).into();
51800

            
51800
                    let who = frame_benchmarking::whitelisted_caller();
51800
                    // Give some multiple of the existential deposit
51800
                    let balance = fee_amount + EXISTENTIAL_DEPOSIT * 1000;
51800
                    let _ = <Balances as frame_support::traits::Currency<_>>::make_free_balance_be(
51800
                        &who, balance,
51800
                    );
51800

            
51800
                    // verify initial balance
51800
                    assert_eq!(Balances::free_balance(&who), balance);
51800

            
51800
                    // set up local asset
51800
                    let asset_amount = 10u128;
51800
                    let initial_asset_amount = asset_amount * 10;
51800

            
51800
                    // inject it into pallet-foreign-asset-creator.
51800
                    let (asset_id, asset_location) = pallet_foreign_asset_creator::benchmarks::create_default_minted_asset::<Runtime>(
51800
                        initial_asset_amount,
51800
                        who.clone()
51800
                    );
51800
                    let transfer_asset: Asset = (asset_location, asset_amount).into();
51800

            
51800
                    let assets: Assets = vec![fee_asset.clone(), transfer_asset].into();
51800
                    let fee_index = if assets.get(0).unwrap().eq(&fee_asset) { 0 } else { 1 };
51800

            
51800
                    // verify transferred successfully
51800
                    let verify = Box::new(move || {
51800
                        // verify native balance after transfer, decreased by transferred fee amount
51800
                        // (plus transport fees)
51800
                        assert!(Balances::free_balance(&who) <= balance - fee_amount);
51800
                        // verify asset balance decreased by exactly transferred amount
51800
                        assert_eq!(
51800
                            ForeignAssets::balance(asset_id, &who),
51800
                            initial_asset_amount - asset_amount,
51800
                        );
51800
                    });
51800
                    Some((assets, fee_index, dest, verify))
51800
                }
51800
            }
51800

            
51800
            let whitelist: Vec<TrackedStorageKey> = vec![
51800
                // Block Number
51800
                hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac")
51800
                    .to_vec()
51800
                    .into(),
51800
                // Total Issuance
51800
                hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80")
51800
                    .to_vec()
51800
                    .into(),
51800
                // Execution Phase
51800
                hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a")
51800
                    .to_vec()
51800
                    .into(),
51800
                // Event Count
51800
                hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850")
51800
                    .to_vec()
51800
                    .into(),
51800
                // System Events
51800
                hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7")
51800
                    .to_vec()
51800
                    .into(),
51800
                // The transactional storage limit.
51800
                hex_literal::hex!("3a7472616e73616374696f6e5f6c6576656c3a")
51800
                    .to_vec()
51800
                    .into(),
51800

            
51800
                // ParachainInfo ParachainId
51800
                hex_literal::hex!(  "0d715f2646c8f85767b5d2764bb2782604a74d81251e398fd8a0a4d55023bb3f")
51800
                    .to_vec()
51800
                    .into(),
51800
            ];
51800

            
51800
            let mut batches = Vec::<BenchmarkBatch>::new();
51800
            let params = (&config, &whitelist);
51800

            
51800
            add_benchmarks!(params, batches);
51800

            
51800
            Ok(batches)
51800
        }
51800
    }
51800

            
51800
    #[cfg(feature = "try-runtime")]
51800
    impl frame_try_runtime::TryRuntime<Block> for Runtime {
51800
        fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) {
51800
            let weight = Executive::try_runtime_upgrade(checks).unwrap();
51800
            (weight, RuntimeBlockWeights::get().max_block)
51800
        }
51800

            
51800
        fn execute_block(
51800
            block: Block,
51800
            state_root_check: bool,
51800
            signature_check: bool,
51800
            select: frame_try_runtime::TryStateSelect,
51800
        ) -> Weight {
51800
            // NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to
51800
            // have a backtrace here.
51800
            Executive::try_execute_block(block, state_root_check, signature_check, select).unwrap()
51800
        }
51800
    }
51800

            
51800
    impl pallet_collator_assignment_runtime_api::CollatorAssignmentApi<Block, AccountId, ParaId> for Runtime {
51800
        /// Return the parachain that the given `AccountId` is collating for.
51800
        /// Returns `None` if the `AccountId` is not collating.
51808
        fn current_collator_parachain_assignment(account: AccountId) -> Option<ParaId> {
8
            let assigned_collators = CollatorAssignment::collator_container_chain();
8
            let self_para_id = ParachainInfo::get();
8

            
8
            assigned_collators.para_id_of(&account, self_para_id)
8
        }
51800

            
51800
        /// Return the parachain that the given `AccountId` will be collating for
51800
        /// in the next session change.
51800
        /// Returns `None` if the `AccountId` will not be collating.
51806
        fn future_collator_parachain_assignment(account: AccountId) -> Option<ParaId> {
6
            let assigned_collators = CollatorAssignment::pending_collator_container_chain();
6

            
6
            match assigned_collators {
51804
                Some(assigned_collators) => {
4
                    let self_para_id = ParachainInfo::get();
4

            
4
                    assigned_collators.para_id_of(&account, self_para_id)
51800
                }
51800
                None => {
51802
                    Self::current_collator_parachain_assignment(account)
51800
                }
51800
            }
51800

            
51806
        }
51800

            
51800
        /// Return the list of collators of the given `ParaId`.
51800
        /// Returns `None` if the `ParaId` is not in the registrar.
51814
        fn parachain_collators(para_id: ParaId) -> Option<Vec<AccountId>> {
14
            let assigned_collators = CollatorAssignment::collator_container_chain();
14
            let self_para_id = ParachainInfo::get();
14

            
14
            if para_id == self_para_id {
51809
                Some(assigned_collators.orchestrator_chain)
51800
            } else {
51805
                assigned_collators.container_chains.get(&para_id).cloned()
51800
            }
51814
        }
51800

            
51800
        /// Returns the list of `ParaId` of registered chains with at least some
51800
        /// collators. This filters out parachains with no assigned collators.
51800
        /// Since runtime APIs are called on top of a parent block, we need to be carefull
51800
        /// at session boundaries. If the next block will change session, this function returns
51800
        /// the parachains relevant for the next session.
51800
        fn parachains_with_some_collators() -> Vec<ParaId> {
51800
            use tp_traits::{GetContainerChainsWithCollators, ForSession};
51800

            
51800
            // We should return the container-chains for the session in which we are kicking in
51800
            let parent_number = System::block_number();
            let should_end_session = <Runtime as pallet_session::Config>::ShouldEndSession::should_end_session(parent_number + 1);
51800
            let for_session = if should_end_session { ForSession::Next } else { ForSession::Current };
51800

            
51800
            CollatorAssignment::container_chains_with_collators(for_session)
                .into_iter()
                .filter_map(
                    |(para_id, collators)| (!collators.is_empty()).then_some(para_id)
                ).collect()
        }
51800
    }
51800

            
51800
    impl pallet_registrar_runtime_api::RegistrarApi<Block, ParaId> for Runtime {
51800
        /// Return the registered para ids
67169
        fn registered_paras() -> Vec<ParaId> {
23675
            // We should return the container-chains for the session in which we are kicking in
23675
            let parent_number = System::block_number();
23675
            let should_end_session = <Runtime as pallet_session::Config>::ShouldEndSession::should_end_session(parent_number + 1);
51800

            
67169
            let session_index = if should_end_session {
52888
                Session::current_index() +1
51800
            }
51800
            else {
65665
                Session::current_index()
51800
            };
51800

            
67169
            let container_chains = Registrar::session_container_chains(session_index);
23675
            let mut para_ids = vec![];
23675
            para_ids.extend(container_chains.parachains);
23675
            para_ids.extend(container_chains.parathreads.into_iter().map(|(para_id, _)| para_id));
23675

            
23675
            para_ids
23675
        }
51800

            
51800
        /// Fetch genesis data for this para id
51807
        fn genesis_data(para_id: ParaId) -> Option<ContainerChainGenesisData> {
7
            Registrar::para_genesis_data(para_id)
7
        }
51800

            
51800
        /// Fetch boot_nodes for this para id
51800
        fn boot_nodes(para_id: ParaId) -> Vec<Vec<u8>> {
            DataPreservers::assignments_profiles(para_id)
                .filter(|profile| profile.mode == pallet_data_preservers::ProfileMode::Bootnode)
                .map(|profile| profile.url.into())
                .collect()
        }
51800
    }
51800

            
51800
    impl pallet_registrar_runtime_api::OnDemandBlockProductionApi<Block, ParaId, Slot> for Runtime {
51800
        /// Returns slot frequency for particular para thread. Slot frequency specifies amount of slot
51800
        /// need to be passed between two parathread blocks. It is expressed as `(min, max)` pair where `min`
51800
        /// indicates amount of slot must pass before we produce another block and `max` indicates amount of
51800
        /// blocks before this parathread must produce the block.
51800
        ///
51800
        /// Simply put, parathread must produce a block after `min`  but before `(min+max)` slots.
51800
        ///
51800
        /// # Returns
51800
        ///
51800
        /// * `Some(slot_frequency)`.
51800
        /// * `None` if the `para_id` is not a parathread.
51800
        fn parathread_slot_frequency(para_id: ParaId) -> Option<SlotFrequency> {
            Registrar::parathread_params(para_id).map(|params| {
                params.slot_frequency
            })
        }
51800
    }
51800

            
51800
    impl pallet_author_noting_runtime_api::AuthorNotingApi<Block, AccountId, BlockNumber, ParaId> for Runtime
51800
        where
51800
        AccountId: parity_scale_codec::Codec,
51800
        BlockNumber: parity_scale_codec::Codec,
51800
        ParaId: parity_scale_codec::Codec,
51800
    {
51801
        fn latest_block_number(para_id: ParaId) -> Option<BlockNumber> {
1
            AuthorNoting::latest_author(para_id).map(|info| info.block_number)
1
        }
51800

            
51801
        fn latest_author(para_id: ParaId) -> Option<AccountId> {
1
            AuthorNoting::latest_author(para_id).map(|info| info.author)
1
        }
51800
    }
51800

            
51800
    impl dp_consensus::TanssiAuthorityAssignmentApi<Block, NimbusId> for Runtime {
51800
        /// Return the current authorities assigned to a given paraId
70913
        fn para_id_authorities(para_id: ParaId) -> Option<Vec<NimbusId>> {
27419
            get_para_id_authorities(para_id)
27419
        }
51800

            
51800
        /// Return the paraId assigned to a given authority
51832
        fn check_para_id_assignment(authority: NimbusId) -> Option<ParaId> {
32
            let parent_number = System::block_number();
32
            let should_end_session = <Runtime as pallet_session::Config>::ShouldEndSession::should_end_session(parent_number + 1);
51800

            
51832
            let session_index = if should_end_session {
51808
                Session::current_index() +1
51800
            }
51800
            else {
51824
                Session::current_index()
51800
            };
51832
            let assigned_authorities = AuthorityAssignment::collator_container_chain(session_index)?;
51832
            let self_para_id = ParachainInfo::get();
32

            
32
            assigned_authorities.para_id_of(&authority, self_para_id)
51832
        }
51800

            
51800
        /// Return the paraId assigned to a given authority on the next session.
51800
        /// On session boundary this returns the same as `check_para_id_assignment`.
51812
        fn check_para_id_assignment_next_session(authority: NimbusId) -> Option<ParaId> {
12
            let session_index = Session::current_index() + 1;
51812
            let assigned_authorities = AuthorityAssignment::collator_container_chain(session_index)?;
51812
            let self_para_id = ParachainInfo::get();
12

            
12
            assigned_authorities.para_id_of(&authority, self_para_id)
51812
        }
51800
    }
51800

            
51800
    impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance>
51800
    for Runtime {
51800
        fn query_info(
30
            uxt: <Block as BlockT>::Extrinsic,
30
            len: u32,
30
        ) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo<Balance> {
30
            TransactionPayment::query_info(uxt, len)
30
        }
51800

            
51800
        fn query_fee_details(
12
            uxt: <Block as BlockT>::Extrinsic,
12
            len: u32,
12
        ) -> pallet_transaction_payment::FeeDetails<Balance> {
12
            TransactionPayment::query_fee_details(uxt, len)
12
        }
51800

            
51800
        fn query_weight_to_fee(weight: Weight) -> Balance {
66
            TransactionPayment::weight_to_fee(weight)
66
        }
51800

            
51800
        fn query_length_to_fee(length: u32) -> Balance {
18
            TransactionPayment::length_to_fee(length)
18
        }
51800
    }
51800

            
51800
    impl pallet_stream_payment_runtime_api::StreamPaymentApi<Block, StreamId, Balance, Balance>
51800
    for Runtime {
51800
        fn stream_payment_status(
54
            stream_id: StreamId,
54
            now: Option<Balance>,
54
        ) -> Result<StreamPaymentApiStatus<Balance>, StreamPaymentApiError> {
54
            match StreamPayment::stream_payment_status(stream_id, now) {
51800
                Ok(pallet_stream_payment::StreamPaymentStatus {
51800
                    payment, deposit_left, stalled
42
                }) => Ok(StreamPaymentApiStatus {
42
                    payment, deposit_left, stalled
42
                }),
51800
                Err(pallet_stream_payment::Error::<Runtime>::UnknownStreamId)
51800
                => Err(StreamPaymentApiError::UnknownStreamId),
51800
                Err(e) => Err(StreamPaymentApiError::Other(format!("{e:?}")))
51800
            }
51800
        }
51800
    }
51800

            
51800
    impl pallet_data_preservers_runtime_api::DataPreserversApi<Block, DataPreserversProfileId, ParaId> for Runtime {
51800
        fn get_active_assignment(
            profile_id: DataPreserversProfileId,
        ) -> pallet_data_preservers_runtime_api::Assignment<ParaId> {
51800
            use pallet_data_preservers_runtime_api::Assignment;
51800
            use pallet_stream_payment::StreamPaymentStatus;
51800

            
51800
            let Some((para_id, witness)) = pallet_data_preservers::Profiles::<Runtime>::get(profile_id)
                .and_then(|x| x.assignment) else
51800
            {
51800
                return Assignment::NotAssigned;
51800
            };
51800

            
51800
            match witness {
51800
                tp_data_preservers_common::AssignmentWitness::Free => Assignment::Active(para_id),
51800
                tp_data_preservers_common::AssignmentWitness::StreamPayment { stream_id } => {
51800
                    // Error means no Stream exists with that ID or some issue occured when computing
51800
                    // the status. In that case we cannot consider the assignment as active.
51800
                    let Ok(StreamPaymentStatus { stalled, .. }) = StreamPayment::stream_payment_status( stream_id, None) else {
51800
                        return Assignment::Inactive(para_id);
51800
                    };
51800

            
51800
                    if stalled {
51800
                        Assignment::Inactive(para_id)
51800
                    } else {
51800
                        Assignment::Active(para_id)
51800
                    }
51800
                },
51800
            }
51800
        }
51800
    }
51800

            
51800
    impl dp_slot_duration_runtime_api::TanssiSlotDurationApi<Block> for Runtime {
51800
        fn slot_duration() -> u64 {
            SLOT_DURATION
        }
51800
    }
51800

            
51800
    impl pallet_services_payment_runtime_api::ServicesPaymentApi<Block, Balance, ParaId> for Runtime {
51800
        fn block_cost(para_id: ParaId) -> Balance {
6
            let (block_production_costs, _) = <Runtime as pallet_services_payment::Config>::ProvideBlockProductionCost::block_cost(&para_id);
6
            block_production_costs
6
        }
51800

            
51800
        fn collator_assignment_cost(para_id: ParaId) -> Balance {
6
            let (collator_assignment_costs, _) = <Runtime as pallet_services_payment::Config>::ProvideCollatorAssignmentCost::collator_assignment_cost(&para_id);
6
            collator_assignment_costs
6
        }
51800
    }
51800

            
51800
    impl pallet_xcm_core_buyer_runtime_api::XCMCoreBuyerApi<Block, BlockNumber, ParaId, NimbusId> for Runtime {
51800
        fn is_core_buying_allowed(para_id: ParaId, collator_public_key: NimbusId) -> Result<(), BuyingError<BlockNumber>> {
            XcmCoreBuyer::is_core_buying_allowed(para_id, Some(collator_public_key))
        }
51800

            
51800
        fn create_buy_core_unsigned_extrinsic(para_id: ParaId, proof: BuyCoreCollatorProof<NimbusId>) -> Box<<Block as BlockT>::Extrinsic> {
            let call = RuntimeCall::XcmCoreBuyer(pallet_xcm_core_buyer::Call::buy_core {
                para_id,
                proof
            });
            let unsigned_extrinsic = UncheckedExtrinsic::new_bare(call);
            Box::new(unsigned_extrinsic)
        }
51800

            
51800
        fn get_buy_core_signature_nonce(para_id: ParaId) -> u64 {
            pallet_xcm_core_buyer::CollatorSignatureNonce::<Runtime>::get(para_id)
        }
51800

            
51800
        fn get_buy_core_slot_drift() -> Slot {
            <Runtime as pallet_xcm_core_buyer::Config>::BuyCoreSlotDrift::get()
        }
51800
    }
51800

            
51800
    impl xcm_runtime_apis::fees::XcmPaymentApi<Block> for Runtime {
51800
        fn query_acceptable_payment_assets(xcm_version: xcm::Version) -> Result<Vec<VersionedAssetId>, XcmPaymentApiError> {
51800
            if !matches!(xcm_version, 3..=5) {
51800
                return Err(XcmPaymentApiError::UnhandledXcmVersion);
51800
            }
6

            
6
            Ok([VersionedAssetId::V5(xcm_config::SelfReserve::get().into())]
6
                .into_iter()
6
                .chain(
6
                    pallet_asset_rate::ConversionRateToNative::<Runtime>::iter_keys().filter_map(|asset_id_u16| {
6
                        pallet_foreign_asset_creator::AssetIdToForeignAsset::<Runtime>::get(asset_id_u16).map(|location| {
6
                            VersionedAssetId::V5(location.into())
6
                        }).or_else(|| {
                            log::warn!("Asset `{}` is present in pallet_asset_rate but not in pallet_foreign_asset_creator", asset_id_u16);
51800
                            None
6
                        })
6
                    })
6
                )
12
                .filter_map(|asset| asset.into_version(xcm_version).map_err(|e| {
                    log::warn!("Failed to convert asset to version {}: {:?}", xcm_version, e);
51800
                }).ok())
6
                .collect())
51800
        }
51800

            
51800
        fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result<u128, XcmPaymentApiError> {
12
            let local_asset = VersionedAssetId::V5(xcm_config::SelfReserve::get().into());
51800
            let asset = asset
12
                .into_version(5)
12
                .map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?;
51800

            
51800
            if asset == local_asset {
51800
                Ok(WeightToFee::weight_to_fee(&weight))
51800
            } else {
51800
                let native_fee = WeightToFee::weight_to_fee(&weight);
51800
                let asset_v5: xcm::latest::AssetId = asset.try_into().map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?;
51800
                let location: xcm::latest::Location = asset_v5.0;
51800
                let asset_id = pallet_foreign_asset_creator::ForeignAssetToAssetId::<Runtime>::get(location).ok_or(XcmPaymentApiError::AssetNotFound)?;
51800
                let asset_rate = AssetRate::to_asset_balance(native_fee, asset_id);
51800
                match asset_rate {
51800
                    Ok(x) => Ok(x),
51800
                    Err(pallet_asset_rate::Error::UnknownAssetKind) => Err(XcmPaymentApiError::AssetNotFound),
51800
                    // Error when converting native balance to asset balance, probably overflow
51800
                    Err(_e) => Err(XcmPaymentApiError::WeightNotComputable),
51800
                }
51800
            }
51800
        }
51800

            
51800
        fn query_xcm_weight(message: VersionedXcm<()>) -> Result<Weight, XcmPaymentApiError> {
6
            PolkadotXcm::query_xcm_weight(message)
6
        }
51800

            
51800
        fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>) -> Result<VersionedAssets, XcmPaymentApiError> {
            PolkadotXcm::query_delivery_fees(destination, message)
        }
51800
    }
51800

            
51800
    impl xcm_runtime_apis::dry_run::DryRunApi<Block, RuntimeCall, RuntimeEvent, OriginCaller> for Runtime {
51800
        fn dry_run_call(origin: OriginCaller, call: RuntimeCall, result_xcms_version: XcmVersion) -> Result<CallDryRunEffects<RuntimeEvent>, XcmDryRunApiError> {
6
            PolkadotXcm::dry_run_call::<Runtime, xcm_config::XcmRouter, OriginCaller, RuntimeCall>(origin, call, result_xcms_version)
6
        }
51800

            
51800
        fn dry_run_xcm(origin_location: VersionedLocation, xcm: VersionedXcm<RuntimeCall>) -> Result<XcmDryRunEffects<RuntimeEvent>, XcmDryRunApiError> {
6
            PolkadotXcm::dry_run_xcm::<Runtime, xcm_config::XcmRouter, RuntimeCall, xcm_config::XcmConfig>(origin_location, xcm)
6
        }
51800
    }
51800

            
51800
    impl xcm_runtime_apis::conversions::LocationToAccountApi<Block, AccountId> for Runtime {
51800
        fn convert_location(location: VersionedLocation) -> Result<
6
            AccountId,
6
            xcm_runtime_apis::conversions::Error
6
        > {
6
            xcm_runtime_apis::conversions::LocationToAccountHelper::<
6
                AccountId,
6
                xcm_config::LocationToAccountId,
6
            >::convert_location(location)
6
        }
51800
    }
400834
}
#[allow(dead_code)]
struct CheckInherents;
// TODO: this should be removed but currently if we remove it the relay does not check anything
// related to other inherents that are not parachain-system
#[allow(deprecated)]
impl cumulus_pallet_parachain_system::CheckInherents<Block> for CheckInherents {
    fn check_inherents(
        block: &Block,
        relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof,
    ) -> sp_inherents::CheckInherentsResult {
        let relay_chain_slot = relay_state_proof
            .read_slot()
            .expect("Could not read the relay chain slot from the proof");
        let inherent_data =
            cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration(
                relay_chain_slot,
                core::time::Duration::from_secs(6),
            )
            .create_inherent_data()
            .expect("Could not create the timestamp inherent data");
        inherent_data.check_extrinsics(block)
    }
}
cumulus_pallet_parachain_system::register_validate_block! {
    Runtime = Runtime,
    CheckInherents = CheckInherents,
    BlockExecutor = pallet_author_inherent::BlockExecutor::<Runtime, Executive>,
}
#[macro_export]
macro_rules! prod_or_fast {
    ($prod:expr, $test:expr) => {
        if cfg!(feature = "fast-runtime") {
            $test
        } else {
            $prod
        }
    };
    ($prod:expr, $test:expr, $env:expr) => {
        if cfg!(feature = "fast-runtime") {
            core::option_env!($env)
                .map(|s| s.parse().ok())
                .flatten()
                .unwrap_or($test)
        } else {
            $prod
        }
    };
}