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
pub mod xcm_config;
26

            
27
use polkadot_runtime_common::SlowAdjustingFeeUpdate;
28
#[cfg(feature = "std")]
29
use sp_version::NativeVersion;
30

            
31
#[cfg(any(feature = "std", test))]
32
pub use sp_runtime::BuildStorage;
33

            
34
pub mod weights;
35

            
36
use {
37
    cumulus_pallet_parachain_system::{
38
        RelayChainStateProof, RelayNumberMonotonicallyIncreases, RelaychainDataProvider,
39
        RelaychainStateProvider,
40
    },
41
    cumulus_primitives_core::{
42
        relay_chain::{self, SessionIndex},
43
        AggregateMessageOrigin, BodyId, ParaId,
44
    },
45
    frame_support::{
46
        construct_runtime,
47
        dispatch::{DispatchClass, DispatchErrorWithPostInfo},
48
        genesis_builder_helper::{build_state, get_preset},
49
        pallet_prelude::DispatchResult,
50
        parameter_types,
51
        traits::{
52
            fungible::{Balanced, Credit, Inspect, InspectHold, Mutate, MutateHold},
53
            tokens::{
54
                imbalance::ResolveTo, PayFromAccount, Precision, Preservation,
55
                UnityAssetBalanceConversion,
56
            },
57
            ConstBool, ConstU128, ConstU32, ConstU64, ConstU8, Contains, EitherOfDiverse,
58
            Imbalance, InsideBoth, InstanceFilter, OnUnbalanced, ValidatorRegistration,
59
        },
60
        weights::{
61
            constants::{
62
                BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight,
63
                WEIGHT_REF_TIME_PER_SECOND,
64
            },
65
            ConstantMultiplier, Weight, WeightToFeeCoefficient, WeightToFeeCoefficients,
66
            WeightToFeePolynomial,
67
        },
68
        PalletId,
69
    },
70
    frame_system::{
71
        limits::{BlockLength, BlockWeights},
72
        EnsureRoot, EnsureSigned,
73
    },
74
    nimbus_primitives::{NimbusId, SlotBeacon},
75
    pallet_balances::NegativeImbalance,
76
    pallet_collator_assignment::{GetRandomnessForNextBlock, RotateCollatorsEveryNSessions},
77
    pallet_invulnerables::InvulnerableRewardDistribution,
78
    pallet_pooled_staking::traits::{IsCandidateEligible, Timer},
79
    pallet_registrar::RegistrarHooks,
80
    pallet_registrar_runtime_api::ContainerChainGenesisData,
81
    pallet_services_payment::{ProvideBlockProductionCost, ProvideCollatorAssignmentCost},
82
    pallet_session::{SessionManager, ShouldEndSession},
83
    pallet_stream_payment_runtime_api::{StreamPaymentApiError, StreamPaymentApiStatus},
84
    pallet_transaction_payment::FungibleAdapter,
85
    pallet_xcm_core_buyer::BuyingError,
86
    polkadot_runtime_common::BlockHashCount,
87
    scale_info::{prelude::format, TypeInfo},
88
    smallvec::smallvec,
89
    sp_api::impl_runtime_apis,
90
    sp_consensus_aura::{Slot, SlotDuration},
91
    sp_core::{
92
        crypto::KeyTypeId, Decode, Encode, Get, MaxEncodedLen, OpaqueMetadata, RuntimeDebug, H256,
93
    },
94
    sp_runtime::{
95
        create_runtime_str, generic, impl_opaque_keys,
96
        traits::{
97
            AccountIdConversion, AccountIdLookup, BlakeTwo256, Block as BlockT, Hash as HashT,
98
            IdentityLookup, Verify,
99
        },
100
        transaction_validity::{TransactionSource, TransactionValidity},
101
        AccountId32, ApplyExtrinsicResult,
102
    },
103
    sp_std::{collections::btree_set::BTreeSet, marker::PhantomData, prelude::*},
104
    sp_version::RuntimeVersion,
105
    tp_traits::{
106
        GetContainerChainAuthor, GetHostConfiguration, GetSessionContainerChains,
107
        RelayStorageRootProvider, RemoveInvulnerables, RemoveParaIdsWithNoCredits, SlotFrequency,
108
    },
109
};
110
pub use {
111
    dp_core::{AccountId, Address, Balance, BlockNumber, Hash, Header, Index, Signature},
112
    sp_runtime::{MultiAddress, Perbill, Permill},
113
};
114

            
115
/// Block type as expected by this runtime.
116
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
117
/// A Block signed with a Justification
118
pub type SignedBlock = generic::SignedBlock<Block>;
119
/// BlockId type as expected by this runtime.
120
pub type BlockId = generic::BlockId<Block>;
121

            
122
/// CollatorId type expected by this runtime.
123
pub type CollatorId = AccountId;
124

            
125
/// The SignedExtension to the basic transaction logic.
126
pub type SignedExtra = (
127
    frame_system::CheckNonZeroSender<Runtime>,
128
    frame_system::CheckSpecVersion<Runtime>,
129
    frame_system::CheckTxVersion<Runtime>,
130
    frame_system::CheckGenesis<Runtime>,
131
    frame_system::CheckEra<Runtime>,
132
    frame_system::CheckNonce<Runtime>,
133
    frame_system::CheckWeight<Runtime>,
134
    pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
135
);
136

            
137
/// Unchecked extrinsic type as expected by this runtime.
138
pub type UncheckedExtrinsic =
139
    generic::UncheckedExtrinsic<Address, RuntimeCall, Signature, SignedExtra>;
140

            
141
/// Extrinsic type that has already been checked.
142
pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, RuntimeCall, SignedExtra>;
143

            
144
/// Executive: handles dispatch to the various modules.
145
pub type Executive = frame_executive::Executive<
146
    Runtime,
147
    Block,
148
    frame_system::ChainContext<Runtime>,
149
    Runtime,
150
    AllPalletsWithSystem,
151
>;
152

            
153
/// DANCE, the native token, uses 12 decimals of precision.
154
pub mod currency {
155
    use super::Balance;
156

            
157
    // Provide a common factor between runtimes based on a supply of 10_000_000 tokens.
158
    pub const SUPPLY_FACTOR: Balance = 100;
159

            
160
    pub const MICRODANCE: Balance = 1_000_000;
161
    pub const MILLIDANCE: Balance = 1_000_000_000;
162
    pub const DANCE: Balance = 1_000_000_000_000;
163
    pub const KILODANCE: Balance = 1_000_000_000_000_000;
164

            
165
    pub const STORAGE_BYTE_FEE: Balance = 100 * MICRODANCE * SUPPLY_FACTOR;
166
    pub const STORAGE_ITEM_FEE: Balance = 100 * MILLIDANCE * SUPPLY_FACTOR;
167

            
168
1038
    pub const fn deposit(items: u32, bytes: u32) -> Balance {
169
1038
        items as Balance * STORAGE_ITEM_FEE + (bytes as Balance) * STORAGE_BYTE_FEE
170
1038
    }
171
}
172

            
173
/// Handles converting a weight scalar to a fee value, based on the scale and granularity of the
174
/// node's balance type.
175
///
176
/// This should typically create a mapping between the following ranges:
177
///   - `[0, MAXIMUM_BLOCK_WEIGHT]`
178
///   - `[Balance::min, Balance::max]`
179
///
180
/// Yet, it can be used for any other sort of change to weight-fee. Some examples being:
181
///   - Setting it to `0` will essentially disable the weight fee.
182
///   - Setting it to `1` will cause the literal `#[weight = x]` values to be charged.
183
pub struct WeightToFee;
184
impl WeightToFeePolynomial for WeightToFee {
185
    type Balance = Balance;
186
3820
    fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {
187
3820
        // in Rococo, extrinsic base weight (smallest non-zero weight) is mapped to 1 MILLIUNIT:
188
3820
        // in our template, we map to 1/10 of that, or 1/10 MILLIUNIT
189
3820
        let p = MILLIUNIT / 10;
190
3820
        let q = 100 * Balance::from(ExtrinsicBaseWeight::get().ref_time());
191
3820
        smallvec![WeightToFeeCoefficient {
192
            degree: 1,
193
            negative: false,
194
            coeff_frac: Perbill::from_rational(p % q, q),
195
            coeff_integer: p / q,
196
        }]
197
3820
    }
198
}
199

            
200
/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know
201
/// the specifics of the runtime. They can then be made to be agnostic over specific formats
202
/// of data like extrinsics, allowing for them to continue syncing the network through upgrades
203
/// to even the core data structures.
204
pub mod opaque {
205
    use {
206
        super::*,
207
        sp_runtime::{
208
            generic,
209
            traits::{BlakeTwo256, Hash as HashT},
210
        },
211
    };
212

            
213
    pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;
214
    /// Opaque block header type.
215
    pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
216
    /// Opaque block type.
217
    pub type Block = generic::Block<Header, UncheckedExtrinsic>;
218
    /// Opaque block identifier type.
219
    pub type BlockId = generic::BlockId<Block>;
220
    /// Opaque block hash type.
221
    pub type Hash = <BlakeTwo256 as HashT>::Output;
222
    /// Opaque signature type.
223
    pub use super::Signature;
224
}
225

            
226
impl_opaque_keys! {
227
    pub struct SessionKeys {
228
        pub nimbus: Initializer,
229
    }
230
}
231

            
232
#[sp_version::runtime_version]
233
pub const VERSION: RuntimeVersion = RuntimeVersion {
234
    spec_name: create_runtime_str!("dancebox"),
235
    impl_name: create_runtime_str!("dancebox"),
236
    authoring_version: 1,
237
    spec_version: 700,
238
    impl_version: 0,
239
    apis: RUNTIME_API_VERSIONS,
240
    transaction_version: 1,
241
    state_version: 1,
242
};
243

            
244
/// This determines the average expected block time that we are targeting.
245
/// Blocks will be produced at a minimum duration defined by `SLOT_DURATION`.
246
/// `SLOT_DURATION` is picked up by `pallet_timestamp` which is in turn picked
247
/// up by `pallet_aura` to implement `fn slot_duration()`.
248
///
249
/// Change this to adjust the block time.
250
pub const MILLISECS_PER_BLOCK: u64 = 6000;
251

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

            
256
// Time is measured by number of blocks.
257
pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);
258
pub const HOURS: BlockNumber = MINUTES * 60;
259
pub const DAYS: BlockNumber = HOURS * 24;
260

            
261
// Unit = the base number of indivisible units for balances
262
pub const UNIT: Balance = 1_000_000_000_000;
263
pub const MILLIUNIT: Balance = 1_000_000_000;
264
pub const MICROUNIT: Balance = 1_000_000;
265
/// The existential deposit. Set to 1/10 of the Connected Relay Chain.
266
pub const EXISTENTIAL_DEPOSIT: Balance = MILLIUNIT;
267

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

            
272
/// We allow `Normal` extrinsics to fill up the block up to 75%, the rest can be used by
273
/// `Operational` extrinsics.
274
const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);
275

            
276
/// We allow for 0.5 of a second of compute with a 12 second average block time.
277
const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts(
278
    WEIGHT_REF_TIME_PER_SECOND.saturating_div(2),
279
    cumulus_primitives_core::relay_chain::MAX_POV_SIZE as u64,
280
);
281

            
282
/// The version information used to identify this runtime when compiled natively.
283
#[cfg(feature = "std")]
284
656
pub fn native_version() -> NativeVersion {
285
656
    NativeVersion {
286
656
        runtime_version: VERSION,
287
656
        can_author_with: Default::default(),
288
656
    }
289
656
}
290

            
291
parameter_types! {
292
    pub const Version: RuntimeVersion = VERSION;
293

            
294
    // This part is copied from Substrate's `bin/node/runtime/src/lib.rs`.
295
    //  The `RuntimeBlockLength` and `RuntimeBlockWeights` exist here because the
296
    // `DeletionWeightLimit` and `DeletionQueueDepth` depend on those to parameterize
297
    // the lazy contract deletion.
298
    pub RuntimeBlockLength: BlockLength =
299
        BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);
300
    pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()
301
        .base_block(BlockExecutionWeight::get())
302
411498
        .for_class(DispatchClass::all(), |weights| {
303
411498
            weights.base_extrinsic = ExtrinsicBaseWeight::get();
304
411498
        })
305
137166
        .for_class(DispatchClass::Normal, |weights| {
306
137166
            weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);
307
137166
        })
308
137166
        .for_class(DispatchClass::Operational, |weights| {
309
137166
            weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);
310
137166
            // Operational transactions have some extra reserved space, so that they
311
137166
            // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.
312
137166
            weights.reserved = Some(
313
137166
                MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT
314
137166
            );
315
137166
        })
316
        .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)
317
        .build_or_panic();
318
    pub const SS58Prefix: u16 = 42;
319
}
320

            
321
// Configure FRAME pallets to include in runtime.
322

            
323
impl frame_system::Config for Runtime {
324
    /// The identifier used to distinguish between accounts.
325
    type AccountId = AccountId;
326
    /// The aggregated dispatch type that is available for extrinsics.
327
    type RuntimeCall = RuntimeCall;
328
    /// The lookup mechanism to get account ID from whatever is passed in dispatchers.
329
    type Lookup = AccountIdLookup<AccountId, ()>;
330
    /// The index type for storing how many extrinsics an account has signed.
331
    type Nonce = Index;
332
    /// The index type for blocks.
333
    type Block = Block;
334
    /// The type for hashing blocks and tries.
335
    type Hash = Hash;
336
    /// The hashing algorithm used.
337
    type Hashing = BlakeTwo256;
338
    /// The ubiquitous event type.
339
    type RuntimeEvent = RuntimeEvent;
340
    /// The ubiquitous origin type.
341
    type RuntimeOrigin = RuntimeOrigin;
342
    /// Maximum number of block number to block hash mappings to keep (oldest pruned first).
343
    type BlockHashCount = BlockHashCount;
344
    /// Runtime version.
345
    type Version = Version;
346
    /// Converts a module to an index of this module in the runtime.
347
    type PalletInfo = PalletInfo;
348
    /// The data to be stored in an account.
349
    type AccountData = pallet_balances::AccountData<Balance>;
350
    /// What to do if a new account is created.
351
    type OnNewAccount = ();
352
    /// What to do if an account is fully reaped from the system.
353
    type OnKilledAccount = ();
354
    /// The weight of database operations that the runtime can invoke.
355
    type DbWeight = RocksDbWeight;
356
    /// The basic call filter to use in dispatchable.
357
    type BaseCallFilter = InsideBoth<MaintenanceMode, TxPause>;
358
    /// Weight information for the extrinsics of this pallet.
359
    type SystemWeightInfo = weights::frame_system::SubstrateWeight<Runtime>;
360
    /// Block & extrinsics weights: base values and limits.
361
    type BlockWeights = RuntimeBlockWeights;
362
    /// The maximum length of a block (in bytes).
363
    type BlockLength = RuntimeBlockLength;
364
    /// This is used as an identifier of the chain. 42 is the generic substrate prefix.
365
    type SS58Prefix = SS58Prefix;
366
    /// The action to take on a Runtime Upgrade
367
    type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode<Self>;
368
    type MaxConsumers = frame_support::traits::ConstU32<16>;
369
    type RuntimeTask = RuntimeTask;
370
    type SingleBlockMigrations = ();
371
    type MultiBlockMigrator = ();
372
    type PreInherents = ();
373
    type PostInherents = ();
374
    type PostTransactions = ();
375
}
376

            
377
impl pallet_timestamp::Config for Runtime {
378
    /// A timestamp: milliseconds since the unix epoch.
379
    type Moment = u64;
380
    type OnTimestampSet = dp_consensus::OnTimestampSet<
381
        <Self as pallet_author_inherent::Config>::SlotBeacon,
382
        ConstU64<{ SLOT_DURATION }>,
383
    >;
384
    type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>;
385
    type WeightInfo = weights::pallet_timestamp::SubstrateWeight<Runtime>;
386
}
387

            
388
pub struct CanAuthor;
389
impl nimbus_primitives::CanAuthor<NimbusId> for CanAuthor {
390
11062
    fn can_author(author: &NimbusId, slot: &u32) -> bool {
391
11062
        let authorities = AuthorityAssignment::collator_container_chain(Session::current_index())
392
11062
            .expect("authorities should be set")
393
11062
            .orchestrator_chain;
394
11062

            
395
11062
        if authorities.is_empty() {
396
            return false;
397
11062
        }
398
11062

            
399
11062
        let author_index = (*slot as usize) % authorities.len();
400
11062
        let expected_author = &authorities[author_index];
401
11062

            
402
11062
        expected_author == author
403
11062
    }
404
    #[cfg(feature = "runtime-benchmarks")]
405
    fn get_authors(_slot: &u32) -> Vec<NimbusId> {
406
        AuthorityAssignment::collator_container_chain(Session::current_index())
407
            .expect("authorities should be set")
408
            .orchestrator_chain
409
    }
410
}
411

            
412
impl pallet_author_inherent::Config for Runtime {
413
    type AuthorId = NimbusId;
414
    type AccountLookup = dp_consensus::NimbusLookUp;
415
    type CanAuthor = CanAuthor;
416
    type SlotBeacon = dp_consensus::AuraDigestSlotBeacon<Runtime>;
417
    type WeightInfo = weights::pallet_author_inherent::SubstrateWeight<Runtime>;
418
}
419

            
420
parameter_types! {
421
    pub const ExistentialDeposit: Balance = EXISTENTIAL_DEPOSIT;
422
}
423

            
424
impl pallet_balances::Config for Runtime {
425
    type MaxLocks = ConstU32<50>;
426
    /// The type for recording an account's balance.
427
    type Balance = Balance;
428
    /// The ubiquitous event type.
429
    type RuntimeEvent = RuntimeEvent;
430
    type DustRemoval = ();
431
    type ExistentialDeposit = ExistentialDeposit;
432
    type AccountStore = System;
433
    type MaxReserves = ConstU32<50>;
434
    type ReserveIdentifier = [u8; 8];
435
    type FreezeIdentifier = RuntimeFreezeReason;
436
    type MaxFreezes = ConstU32<10>;
437
    type RuntimeHoldReason = RuntimeHoldReason;
438
    type RuntimeFreezeReason = RuntimeFreezeReason;
439
    type WeightInfo = weights::pallet_balances::SubstrateWeight<Runtime>;
440
}
441

            
442
pub struct DealWithFees<R>(sp_std::marker::PhantomData<R>);
443
impl<R> OnUnbalanced<Credit<R::AccountId, pallet_balances::Pallet<R>>> for DealWithFees<R>
444
where
445
    R: pallet_balances::Config + pallet_treasury::Config + frame_system::Config,
446
    pallet_treasury::NegativeImbalanceOf<R>: From<NegativeImbalance<R>>,
447
{
448
    // this seems to be called for substrate-based transactions
449
736
    fn on_unbalanceds<B>(
450
736
        mut fees_then_tips: impl Iterator<Item = Credit<R::AccountId, pallet_balances::Pallet<R>>>,
451
736
    ) {
452
736
        if let Some(fees) = fees_then_tips.next() {
453
            // 80% is burned, 20% goes to the treasury
454
            // Same policy applies for tips as well
455
736
            let burn_percentage = 80;
456
736
            let treasury_percentage = 20;
457
736

            
458
736
            let (_, to_treasury) = fees.ration(burn_percentage, treasury_percentage);
459
736
            ResolveTo::<pallet_treasury::TreasuryAccountId<R>, pallet_balances::Pallet<R>>::on_unbalanced(to_treasury);
460
            // Balances pallet automatically burns dropped Negative Imbalances by decreasing total_supply accordingly
461
            // handle tip if there is one
462
736
            if let Some(tip) = fees_then_tips.next() {
463
736
                let (_, to_treasury) = tip.ration(burn_percentage, treasury_percentage);
464
736
                ResolveTo::<pallet_treasury::TreasuryAccountId<R>, pallet_balances::Pallet<R>>::on_unbalanced(to_treasury);
465
736
            }
466
        }
467
736
    }
468

            
469
    // this is called from pallet_evm for Ethereum-based transactions
470
    // (technically, it calls on_unbalanced, which calls this when non-zero)
471
    fn on_nonzero_unbalanced(amount: Credit<R::AccountId, pallet_balances::Pallet<R>>) {
472
        // 80% is burned, 20% goes to the treasury
473
        let burn_percentage = 80;
474
        let treasury_percentage = 20;
475

            
476
        let (_, to_treasury) = amount.ration(burn_percentage, treasury_percentage);
477
        ResolveTo::<pallet_treasury::TreasuryAccountId<R>, pallet_balances::Pallet<R>>::on_unbalanced(to_treasury);
478
    }
479
}
480

            
481
parameter_types! {
482
    pub const TransactionByteFee: Balance = 1;
483
}
484

            
485
impl pallet_transaction_payment::Config for Runtime {
486
    type RuntimeEvent = RuntimeEvent;
487
    // This will burn 80% from fees & tips and deposit the remainder into the treasury
488
    type OnChargeTransaction = FungibleAdapter<Balances, DealWithFees<Runtime>>;
489
    type OperationalFeeMultiplier = ConstU8<5>;
490
    type WeightToFee = WeightToFee;
491
    type LengthToFee = ConstantMultiplier<Balance, TransactionByteFee>;
492
    type FeeMultiplierUpdate = SlowAdjustingFeeUpdate<Self>;
493
}
494

            
495
parameter_types! {
496
    pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4);
497
    pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4);
498
    pub const RelayOrigin: AggregateMessageOrigin = AggregateMessageOrigin::Parent;
499
}
500

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

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

            
511
impl cumulus_pallet_parachain_system::Config for Runtime {
512
    type WeightInfo = weights::cumulus_pallet_parachain_system::SubstrateWeight<Runtime>;
513
    type RuntimeEvent = RuntimeEvent;
514
    type OnSystemEvent = ();
515
    type SelfParaId = parachain_info::Pallet<Runtime>;
516
    type OutboundXcmpMessageSource = XcmpQueue;
517
    type DmpQueue = frame_support::traits::EnqueueWithOrigin<MessageQueue, RelayOrigin>;
518
    type ReservedDmpWeight = ReservedDmpWeight;
519
    type XcmpMessageHandler = XcmpQueue;
520
    type ReservedXcmpWeight = ReservedXcmpWeight;
521
    type CheckAssociatedRelayNumber = RelayNumberMonotonicallyIncreases;
522
    type ConsensusHook = ConsensusHook;
523
}
524
pub struct ParaSlotProvider;
525
impl Get<(Slot, SlotDuration)> for ParaSlotProvider {
526
7206
    fn get() -> (Slot, SlotDuration) {
527
7206
        let slot = u64::from(<Runtime as pallet_author_inherent::Config>::SlotBeacon::slot());
528
7206
        (Slot::from(slot), SlotDuration::from_millis(SLOT_DURATION))
529
7206
    }
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
1048
fn relay_chain_state_proof() -> RelayChainStateProof {
545
1048
    let relay_storage_root =
546
1048
        RelaychainDataProvider::<Runtime>::current_relay_chain_state().state_root;
547
1048
    let relay_chain_state = RelaychainDataProvider::<Runtime>::current_relay_state_proof()
548
1048
        .expect("set in `set_validation_data`");
549
1048
    RelayChainStateProof::new(ParachainInfo::get(), relay_storage_root, relay_chain_state)
550
1048
        .expect("Invalid relay chain state proof, already constructed in `set_validation_data`")
551
1048
}
552

            
553
pub struct BabeCurrentBlockRandomnessGetter;
554
impl BabeCurrentBlockRandomnessGetter {
555
1048
    fn get_block_randomness() -> Option<Hash> {
556
1048
        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 = RelaychainDataProvider::<Runtime>::current_relay_state_proof();
562
            let benchmarking_babe_output = Hash::default();
563
            return Some(benchmarking_babe_output);
564
1048
        }
565
1048

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

            
575
    /// Return the block randomness from the relay mixed with the provided subject.
576
    /// This ensures that the randomness will be different on different pallets, as long as the subject is different.
577
    // TODO: audit usage of randomness API
578
    // https://github.com/paritytech/polkadot/issues/2601
579
1048
    fn get_block_randomness_mixed(subject: &[u8]) -> Option<Hash> {
580
1048
        Self::get_block_randomness()
581
1048
            .map(|random_hash| mix_randomness::<Runtime>(random_hash, subject))
582
1048
    }
583
}
584

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

            
592
52
    T::Hashing::hash(digest.as_slice())
593
52
}
594

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

            
601
        (randomness, block_number)
602
    }
603
}
604

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

            
620
4917
        let next_collators = queued.iter().map(|(k, _)| k.clone()).collect();
621
1397

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

            
626
1397
        let queued_id_to_nimbus_map = queued.iter().cloned().collect();
627
1397
        AuthorityAssignment::initializer_on_new_session(
628
1397
            &session_index,
629
1397
            &queued_id_to_nimbus_map,
630
1397
            &assignments.next_assignment,
631
1397
        );
632
1397
    }
633
}
634

            
635
impl pallet_initializer::Config for Runtime {
636
    type SessionIndex = u32;
637

            
638
    /// The identifier type for an authority.
639
    type AuthorityId = NimbusId;
640

            
641
    type SessionHandler = OwnApplySession;
642
}
643

            
644
impl parachain_info::Config for Runtime {}
645

            
646
/// Returns a list of collators by combining pallet_invulnerables and pallet_pooled_staking.
647
pub struct CollatorsFromInvulnerablesAndThenFromStaking;
648

            
649
/// Play the role of the session manager.
650
impl SessionManager<CollatorId> for CollatorsFromInvulnerablesAndThenFromStaking {
651
1748
    fn new_session(index: SessionIndex) -> Option<Vec<CollatorId>> {
652
1748
        if <frame_system::Pallet<Runtime>>::block_number() == 0 {
653
            // Do not show this log in genesis
654
702
            log::debug!(
655
                "assembling new collators for new session {} at #{:?}",
656
                index,
657
                <frame_system::Pallet<Runtime>>::block_number(),
658
            );
659
        } else {
660
1046
            log::info!(
661
646
                "assembling new collators for new session {} at #{:?}",
662
646
                index,
663
646
                <frame_system::Pallet<Runtime>>::block_number(),
664
            );
665
        }
666

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

            
689
1748
        // TODO: weight?
690
1748
        /*
691
1748
        frame_system::Pallet::<T>::register_extra_weight_unchecked(
692
1748
            T::WeightInfo::new_session(invulnerables.len() as u32),
693
1748
            DispatchClass::Mandatory,
694
1748
        );
695
1748
        */
696
1748
        Some(collators)
697
1748
    }
698
1397
    fn start_session(_: SessionIndex) {
699
1397
        // we don't care.
700
1397
    }
701
1046
    fn end_session(_: SessionIndex) {
702
1046
        // we don't care.
703
1046
    }
704
}
705

            
706
parameter_types! {
707
    pub const Period: u32 = prod_or_fast!(1 * HOURS, 1 * MINUTES);
708
    pub const Offset: u32 = 0;
709
}
710

            
711
impl pallet_session::Config for Runtime {
712
    type RuntimeEvent = RuntimeEvent;
713
    type ValidatorId = CollatorId;
714
    // we don't have stash and controller, thus we don't need the convert as well.
715
    type ValidatorIdOf = pallet_invulnerables::IdentityCollator;
716
    type ShouldEndSession = pallet_session::PeriodicSessions<Period, Offset>;
717
    type NextSessionRotation = pallet_session::PeriodicSessions<Period, Offset>;
718
    type SessionManager = CollatorsFromInvulnerablesAndThenFromStaking;
719
    // Essentially just Aura, but let's be pedantic.
720
    type SessionHandler = <SessionKeys as sp_runtime::traits::OpaqueKeys>::KeyTypeIdProviders;
721
    type Keys = SessionKeys;
722
    type WeightInfo = weights::pallet_session::SubstrateWeight<Runtime>;
723
}
724

            
725
/// Read full_rotation_period from pallet_configuration
726
pub struct ConfigurationCollatorRotationSessionPeriod;
727

            
728
impl Get<u32> for ConfigurationCollatorRotationSessionPeriod {
729
2726
    fn get() -> u32 {
730
2726
        Configuration::config().full_rotation_period
731
2726
    }
732
}
733

            
734
pub struct BabeGetRandomnessForNextBlock;
735

            
736
impl GetRandomnessForNextBlock<u32> for BabeGetRandomnessForNextBlock {
737
21916
    fn should_end_session(n: u32) -> bool {
738
21916
        <Runtime as pallet_session::Config>::ShouldEndSession::should_end_session(n)
739
21916
    }
740

            
741
1048
    fn get_randomness() -> [u8; 32] {
742
1048
        let block_number = System::block_number();
743
1048
        let random_seed = if block_number != 0 {
744
52
            if let Some(random_hash) =
745
1048
                BabeCurrentBlockRandomnessGetter::get_block_randomness_mixed(b"CollatorAssignment")
746
            {
747
                // Return random_hash as a [u8; 32] instead of a Hash
748
52
                let mut buf = [0u8; 32];
749
52
                let len = sp_std::cmp::min(32, random_hash.as_ref().len());
750
52
                buf[..len].copy_from_slice(&random_hash.as_ref()[..len]);
751
52

            
752
52
                buf
753
            } else {
754
                // If there is no randomness (e.g when running in dev mode), return [0; 32]
755
                // TODO: smoke test to ensure this never happens in a live network
756
996
                [0; 32]
757
            }
758
        } else {
759
            // In block 0 (genesis) there is randomness
760
            [0; 32]
761
        };
762

            
763
1048
        random_seed
764
1048
    }
765
}
766

            
767
pub struct RemoveInvulnerablesImpl;
768

            
769
impl RemoveInvulnerables<CollatorId> for RemoveInvulnerablesImpl {
770
1952
    fn remove_invulnerables(
771
1952
        collators: &mut Vec<CollatorId>,
772
1952
        num_invulnerables: usize,
773
1952
    ) -> Vec<CollatorId> {
774
1952
        if num_invulnerables == 0 {
775
            return vec![];
776
1952
        }
777
1952
        // TODO: check if this works on session changes
778
1952
        let all_invulnerables = pallet_invulnerables::Invulnerables::<Runtime>::get();
779
1952
        if all_invulnerables.is_empty() {
780
48
            return vec![];
781
1904
        }
782
1904
        let mut invulnerables = vec![];
783
1904
        // TODO: use binary_search when invulnerables are sorted
784
2676
        collators.retain(|x| {
785
2676
            if invulnerables.len() < num_invulnerables && all_invulnerables.contains(x) {
786
2044
                invulnerables.push(x.clone());
787
2044
                false
788
            } else {
789
632
                true
790
            }
791
2676
        });
792
1904

            
793
1904
        invulnerables
794
1952
    }
795
}
796

            
797
pub struct RemoveParaIdsWithNoCreditsImpl;
798

            
799
impl RemoveParaIdsWithNoCredits for RemoveParaIdsWithNoCreditsImpl {
800
2794
    fn remove_para_ids_with_no_credits(
801
2794
        para_ids: &mut Vec<ParaId>,
802
2794
        currently_assigned: &BTreeSet<ParaId>,
803
2794
    ) {
804
2794
        let blocks_per_session = Period::get();
805
2794

            
806
2794
        para_ids.retain(|para_id| {
807
            // If the para has been assigned collators for this session it must have enough block credits
808
            // for the current and the next session.
809
2152
            let block_credits_needed = if currently_assigned.contains(para_id) {
810
1752
                blocks_per_session * 2
811
            } else {
812
400
                blocks_per_session
813
            };
814

            
815
            // Check if the container chain has enough credits for producing blocks
816
2152
            let free_block_credits = pallet_services_payment::BlockProductionCredits::<Runtime>::get(para_id)
817
2152
                .unwrap_or_default();
818
2152

            
819
2152
            // Check if the container chain has enough credits for a session assignments
820
2152
            let free_session_credits = pallet_services_payment::CollatorAssignmentCredits::<Runtime>::get(para_id)
821
2152
                .unwrap_or_default();
822
2152

            
823
2152
            // If para's max tip is set it should have enough to pay for one assignment with tip
824
2152
            let max_tip = pallet_services_payment::MaxTip::<Runtime>::get(para_id).unwrap_or_default() ;
825
2152

            
826
2152
            // Return if we can survive with free credits
827
2152
            if free_block_credits >= block_credits_needed && free_session_credits >= 1 {
828
                // Max tip should always be checked, as it can be withdrawn even if free credits were used
829
1972
                return Balances::can_withdraw(&pallet_services_payment::Pallet::<Runtime>::parachain_tank(*para_id), max_tip).into_result(true).is_ok()
830
180
            }
831
180

            
832
180
            let remaining_block_credits = block_credits_needed.saturating_sub(free_block_credits);
833
180
            let remaining_session_credits = 1u32.saturating_sub(free_session_credits);
834
180

            
835
180
            let (block_production_costs, _) = <Runtime as pallet_services_payment::Config>::ProvideBlockProductionCost::block_cost(para_id);
836
180
            let (collator_assignment_costs, _) = <Runtime as pallet_services_payment::Config>::ProvideCollatorAssignmentCost::collator_assignment_cost(para_id);
837
180
            // let's check if we can withdraw
838
180
            let remaining_block_credits_to_pay = u128::from(remaining_block_credits).saturating_mul(block_production_costs);
839
180
            let remaining_session_credits_to_pay = u128::from(remaining_session_credits).saturating_mul(collator_assignment_costs);
840
180

            
841
180
            let remaining_to_pay = remaining_block_credits_to_pay.saturating_add(remaining_session_credits_to_pay).saturating_add(max_tip);
842
180

            
843
180
            // This should take into account whether we tank goes below ED
844
180
            // The true refers to keepAlive
845
180
            Balances::can_withdraw(&pallet_services_payment::Pallet::<Runtime>::parachain_tank(*para_id), remaining_to_pay).into_result(true).is_ok()
846
2794
        });
847
2794
    }
848

            
849
    /// Make those para ids valid by giving them enough credits, for benchmarking.
850
    #[cfg(feature = "runtime-benchmarks")]
851
    fn make_valid_para_ids(para_ids: &[ParaId]) {
852
        use frame_support::assert_ok;
853

            
854
        let blocks_per_session = Period::get();
855
        // Enough credits to run any benchmark
856
        let block_credits = 20 * blocks_per_session;
857
        let session_credits = 20;
858

            
859
        for para_id in para_ids {
860
            assert_ok!(ServicesPayment::set_block_production_credits(
861
                RuntimeOrigin::root(),
862
                *para_id,
863
                block_credits,
864
            ));
865
            assert_ok!(ServicesPayment::set_collator_assignment_credits(
866
                RuntimeOrigin::root(),
867
                *para_id,
868
                session_credits,
869
            ));
870
        }
871
    }
872
}
873

            
874
impl pallet_collator_assignment::Config for Runtime {
875
    type RuntimeEvent = RuntimeEvent;
876
    type HostConfiguration = Configuration;
877
    type ContainerChains = Registrar;
878
    type SessionIndex = u32;
879
    type SelfParaId = ParachainInfo;
880
    type ShouldRotateAllCollators =
881
        RotateCollatorsEveryNSessions<ConfigurationCollatorRotationSessionPeriod>;
882
    type GetRandomnessForNextBlock = BabeGetRandomnessForNextBlock;
883
    type RemoveInvulnerables = RemoveInvulnerablesImpl;
884
    type RemoveParaIdsWithNoCredits = RemoveParaIdsWithNoCreditsImpl;
885
    type CollatorAssignmentHook = ServicesPayment;
886
    type CollatorAssignmentTip = ServicesPayment;
887
    type Currency = Balances;
888
    type WeightInfo = weights::pallet_collator_assignment::SubstrateWeight<Runtime>;
889
}
890

            
891
impl pallet_authority_assignment::Config for Runtime {
892
    type SessionIndex = u32;
893
    type AuthorityId = NimbusId;
894
}
895

            
896
pub const FIXED_BLOCK_PRODUCTION_COST: u128 = 1 * currency::MICRODANCE;
897
pub const FIXED_COLLATOR_ASSIGNMENT_COST: u128 = 100 * currency::MICRODANCE;
898

            
899
pub struct BlockProductionCost<Runtime>(PhantomData<Runtime>);
900
impl ProvideBlockProductionCost<Runtime> for BlockProductionCost<Runtime> {
901
346
    fn block_cost(_para_id: &ParaId) -> (u128, Weight) {
902
346
        (FIXED_BLOCK_PRODUCTION_COST, Weight::zero())
903
346
    }
904
}
905

            
906
pub struct CollatorAssignmentCost<Runtime>(PhantomData<Runtime>);
907
impl ProvideCollatorAssignmentCost<Runtime> for CollatorAssignmentCost<Runtime> {
908
204
    fn collator_assignment_cost(_para_id: &ParaId) -> (u128, Weight) {
909
204
        (FIXED_COLLATOR_ASSIGNMENT_COST, Weight::zero())
910
204
    }
911
}
912

            
913
parameter_types! {
914
    // 60 days worth of blocks
915
    pub const FreeBlockProductionCredits: BlockNumber = 60 * DAYS;
916
    // 60 days worth of blocks
917
    pub const FreeCollatorAssignmentCredits: u32 = FreeBlockProductionCredits::get()/Period::get();
918
}
919

            
920
impl pallet_services_payment::Config for Runtime {
921
    type RuntimeEvent = RuntimeEvent;
922
    /// Handler for fees
923
    type OnChargeForBlock = ();
924
    type OnChargeForCollatorAssignment = ();
925
    type OnChargeForCollatorAssignmentTip = ();
926
    /// Currency type for fee payment
927
    type Currency = Balances;
928
    /// Provider of a block cost which can adjust from block to block
929
    type ProvideBlockProductionCost = BlockProductionCost<Runtime>;
930
    /// Provider of a block cost which can adjust from block to block
931
    type ProvideCollatorAssignmentCost = CollatorAssignmentCost<Runtime>;
932
    /// The maximum number of block credits that can be accumulated
933
    type FreeBlockProductionCredits = FreeBlockProductionCredits;
934
    /// The maximum number of session credits that can be accumulated
935
    type FreeCollatorAssignmentCredits = FreeCollatorAssignmentCredits;
936
    type ManagerOrigin =
937
        EitherOfDiverse<pallet_registrar::EnsureSignedByManager<Runtime>, EnsureRoot<AccountId>>;
938
    type WeightInfo = weights::pallet_services_payment::SubstrateWeight<Runtime>;
939
}
940

            
941
parameter_types! {
942
    pub const ProfileDepositBaseFee: Balance = currency::STORAGE_ITEM_FEE;
943
    pub const ProfileDepositByteFee: Balance = currency::STORAGE_BYTE_FEE;
944
    #[derive(Clone)]
945
    pub const MaxAssignmentsPerParaId: u32 = 10;
946
    #[derive(Clone)]
947
    pub const MaxNodeUrlLen: u32 = 200;
948
}
949

            
950
#[derive(
951
    RuntimeDebug,
952
    PartialEq,
953
    Eq,
954
    Encode,
955
    Decode,
956
    Copy,
957
    Clone,
958
340
    TypeInfo,
959
    serde::Serialize,
960
    serde::Deserialize,
961
)]
962
pub enum PreserversAssignementPaymentRequest {
963
205
    Free,
964
    // TODO: Add Stream Payment (with config)
965
}
966

            
967
#[derive(
968
    RuntimeDebug,
969
    PartialEq,
970
    Eq,
971
    Encode,
972
    Decode,
973
    Copy,
974
    Clone,
975
340
    TypeInfo,
976
    serde::Serialize,
977
    serde::Deserialize,
978
)]
979
pub enum PreserversAssignementPaymentExtra {
980
36
    Free,
981
    // TODO: Add Stream Payment (with deposit)
982
}
983

            
984
#[derive(
985
    RuntimeDebug,
986
    PartialEq,
987
    Eq,
988
    Encode,
989
    Decode,
990
    Copy,
991
    Clone,
992
340
    TypeInfo,
993
    serde::Serialize,
994
    serde::Deserialize,
995
)]
996
pub enum PreserversAssignementPaymentWitness {
997
78
    Free,
998
    // TODO: Add Stream Payment (with stream id)
999
}
pub struct PreserversAssignementPayment;
impl pallet_data_preservers::AssignmentPayment<AccountId> for PreserversAssignementPayment {
    /// Providers requests which kind of payment it accepts.
    type ProviderRequest = PreserversAssignementPaymentRequest;
    /// Extra parameter the assigner provides.
    type AssignerParameter = PreserversAssignementPaymentExtra;
    /// Represents the succesful outcome of the assignment.
    type AssignmentWitness = PreserversAssignementPaymentWitness;
72
    fn try_start_assignment(
72
        _assigner: AccountId,
72
        _provider: AccountId,
72
        request: &Self::ProviderRequest,
72
        extra: Self::AssignerParameter,
72
    ) -> Result<Self::AssignmentWitness, DispatchErrorWithPostInfo> {
72
        let witness = match (request, extra) {
72
            (Self::ProviderRequest::Free, Self::AssignerParameter::Free) => {
72
                Self::AssignmentWitness::Free
72
            }
72
        };
72

            
72
        Ok(witness)
72
    }
4
    fn try_stop_assignment(
4
        _provider: AccountId,
4
        witness: Self::AssignmentWitness,
4
    ) -> Result<(), DispatchErrorWithPostInfo> {
4
        match witness {
4
            Self::AssignmentWitness::Free => (),
4
        }
4

            
4
        Ok(())
4
    }
    /// Return the values for a free assignment if it is supported.
    /// This is required to perform automatic migration from old Bootnodes storage.
2
    fn free_variant_values() -> Option<(
2
        Self::ProviderRequest,
2
        Self::AssignerParameter,
2
        Self::AssignmentWitness,
2
    )> {
2
        Some((
2
            Self::ProviderRequest::Free,
2
            Self::AssignerParameter::Free,
2
            Self::AssignmentWitness::Free,
2
        ))
2
    }
    // The values returned by the following functions should match with each other.
    #[cfg(feature = "runtime-benchmarks")]
    fn benchmark_provider_request() -> Self::ProviderRequest {
        PreserversAssignementPaymentRequest::Free
    }
    #[cfg(feature = "runtime-benchmarks")]
    fn benchmark_assigner_parameter() -> Self::AssignerParameter {
        PreserversAssignementPaymentExtra::Free
    }
    #[cfg(feature = "runtime-benchmarks")]
    fn benchmark_assignment_witness() -> Self::AssignmentWitness {
        PreserversAssignementPaymentWitness::Free
    }
}
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 = u64;
    type ProfileDeposit = tp_traits::BytesDeposit<ProfileDepositBaseFee, ProfileDepositByteFee>;
    type AssignmentPayment = PreserversAssignementPayment;
    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 = Registrar;
    type SelfParaId = parachain_info::Pallet<Runtime>;
    type SlotBeacon = dp_consensus::AuraDigestSlotBeacon<Runtime>;
    type ContainerChainAuthor = CollatorAssignment;
    type RelayChainStateProvider = cumulus_pallet_parachain_system::RelaychainDataProvider<Self>;
    // We benchmark each hook individually, so for runtime-benchmarks this should be empty
    #[cfg(feature = "runtime-benchmarks")]
    type AuthorNotingHook = ();
    #[cfg(not(feature = "runtime-benchmarks"))]
    type AuthorNotingHook = (XcmCoreBuyer, InflationRewards, ServicesPayment);
    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 = pallet_invulnerables::IdentityCollator;
    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.
156
    fn session_index() -> u32 {
156
        Session::current_index()
156
    }
}
impl pallet_configuration::Config for Runtime {
    type SessionDelay = ConstU32<2>;
    type SessionIndex = u32;
    type CurrentSessionIndex = CurrentSessionIndexGetter;
    type AuthorityId = NimbusId;
    type WeightInfo = weights::pallet_configuration::SubstrateWeight<Runtime>;
}
pub struct DanceboxRegistrarHooks;
impl RegistrarHooks for DanceboxRegistrarHooks {
66
    fn para_marked_valid_for_collating(para_id: ParaId) -> Weight {
66
        // Give free credits but only once per para id
66
        ServicesPayment::give_free_credits(&para_id)
66
    }
24
    fn para_deregistered(para_id: ParaId) -> Weight {
        // Clear pallet_author_noting storage
24
        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,
            );
24
        }
        // Remove bootnodes from pallet_data_preservers
24
        DataPreservers::para_deregistered(para_id);
24

            
24
        ServicesPayment::para_deregistered(para_id);
24

            
24
        XcmCoreBuyer::para_deregistered(para_id);
24

            
24
        Weight::default()
24
    }
68
    fn check_valid_for_collating(para_id: ParaId) -> DispatchResult {
68
        // To be able to call mark_valid_for_collating, a container chain must have bootnodes
68
        DataPreservers::check_valid_for_collating(para_id)
68
    }
    #[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: PreserversAssignementPaymentRequest::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,
            PreserversAssignementPaymentExtra::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 {
4
    fn get_relay_storage_root(relay_block_number: u32) -> Option<H256> {
4
        pallet_relay_storage_roots::pallet::RelayStorageRoot::<Runtime>::get(relay_block_number)
4
    }
    #[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,
        );
    }
}
parameter_types! {
    pub const DepositAmount: Balance = 100 * UNIT;
    pub const MaxLengthTokenSymbol: u32 = 255;
}
impl pallet_registrar::Config for Runtime {
    type RuntimeEvent = RuntimeEvent;
    type RegistrarOrigin = EnsureRoot<AccountId>;
    type MarkValidForCollatingOrigin = EnsureRoot<AccountId>;
    type MaxLengthParaIds = MaxLengthParaIds;
    type MaxGenesisDataSize = MaxEncodedGenesisDataSize;
    type MaxLengthTokenSymbol = MaxLengthTokenSymbol;
    type RegisterWithRelayProofOrigin = EnsureSigned<AccountId>;
    type RelayStorageRootProvider = PalletRelayStorageRootProvider;
    type SessionDelay = ConstU32<2>;
    type SessionIndex = u32;
    type CurrentSessionIndex = CurrentSessionIndexGetter;
    type Currency = Balances;
    type DepositAmount = DepositAmount;
    type RegistrarHooks = DanceboxRegistrarHooks;
    type WeightInfo = weights::pallet_registrar::SubstrateWeight<Runtime>;
}
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.
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
#[derive(
1700
    Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, MaxEncodedLen, TypeInfo,
)]
#[allow(clippy::unnecessary_cast)]
pub enum ProxyType {
49
    /// All calls can be proxied. This is the trivial/most permissive filter.
    Any = 0,
16
    /// Only extrinsics that do not transfer funds.
    NonTransfer = 1,
13
    /// Only extrinsics related to governance (democracy and collectives).
    Governance = 2,
11
    /// Only extrinsics related to staking.
    Staking = 3,
27
    /// Allow to veto an announced proxy call.
    CancelProxy = 4,
9
    /// Allow extrinsic related to Balances.
    Balances = 5,
9
    /// Allow extrinsics related to Registrar
    Registrar = 6,
7
    /// Allow extrinsics related to Registrar that needs to be called through Sudo
    SudoRegistrar = 7,
9
    /// 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 {
48
    fn filter(&self, c: &RuntimeCall) -> bool {
48
        // Since proxy filters are respected in all dispatches of the Utility
48
        // pallet, it should never need to be filtered by any proxy.
48
        if let RuntimeCall::Utility(..) = c {
            return true;
48
        }
48

            
48
        match self {
10
            ProxyType::Any => true,
            ProxyType::NonTransfer => {
6
                matches!(
8
                    c,
                    RuntimeCall::System(..)
                        | RuntimeCall::ParachainSystem(..)
                        | RuntimeCall::Timestamp(..)
                        | RuntimeCall::Proxy(..)
                        | RuntimeCall::Registrar(..)
                )
            }
            // We don't have governance yet
2
            ProxyType::Governance => false,
            ProxyType::Staking => {
2
                matches!(c, RuntimeCall::Session(..) | RuntimeCall::PooledStaking(..))
            }
4
            ProxyType::CancelProxy => matches!(
2
                c,
                RuntimeCall::Proxy(pallet_proxy::Call::reject_announcement { .. })
            ),
            ProxyType::Balances => {
6
                matches!(c, RuntimeCall::Balances(..))
            }
            ProxyType::Registrar => {
2
                matches!(
6
                    c,
                    RuntimeCall::Registrar(..) | RuntimeCall::DataPreservers(..)
                )
            }
4
            ProxyType::SudoRegistrar => match c {
4
                RuntimeCall::Sudo(pallet_sudo::Call::sudo { call: ref x }) => {
2
                    matches!(
4
                        x.as_ref(),
                        &RuntimeCall::Registrar(..) | &RuntimeCall::DataPreservers(..)
                    )
                }
                _ => false,
            },
            ProxyType::SessionKeyManagement => {
4
                matches!(c, RuntimeCall::Session(..))
            }
        }
48
    }
    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>;
}
pub struct XcmExecutionManager;
impl xcm_primitives::PauseXcmExecution for XcmExecutionManager {
10
    fn suspend_xcm_execution() -> DispatchResult {
10
        XcmpQueue::suspend_xcm_execution(RuntimeOrigin::root())
10
    }
10
    fn resume_xcm_execution() -> DispatchResult {
10
        XcmpQueue::resume_xcm_execution(RuntimeOrigin::root())
10
    }
}
impl pallet_migrations::Config for Runtime {
    type RuntimeEvent = RuntimeEvent;
    type MigrationsList = (tanssi_runtime_common::migrations::DanceboxMigrations<Runtime>,);
    type XcmExecutionManager = XcmExecutionManager;
}
/// Maintenance mode Call filter
pub struct MaintenanceFilter;
impl Contains<RuntimeCall> for MaintenanceFilter {
216
    fn contains(c: &RuntimeCall) -> bool {
210
        !matches!(
216
            c,
            RuntimeCall::Balances(..)
                | RuntimeCall::Registrar(..)
                | RuntimeCall::Session(..)
                | RuntimeCall::System(..)
                | RuntimeCall::PooledStaking(..)
                | RuntimeCall::Utility(..)
                | RuntimeCall::PolkadotXcm(..)
        )
216
    }
}
/// Normal Call Filter
pub struct NormalFilter;
impl Contains<RuntimeCall> for NormalFilter {
28022
    fn contains(_c: &RuntimeCall) -> bool {
28022
        true
28022
    }
}
impl pallet_maintenance_mode::Config for Runtime {
    type RuntimeEvent = RuntimeEvent;
    type NormalCallFilter = NormalFilter;
    type MaintenanceCallFilter = MaintenanceFilter;
    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 SessionTimer<G>(PhantomData<G>);
impl<G> Timer for SessionTimer<G>
where
    G: Get<u32>,
{
    type Instant = u32;
113
    fn now() -> Self::Instant {
113
        Session::current_index()
113
    }
37
    fn is_elapsed(instant: &Self::Instant) -> bool {
37
        let delay = G::get();
37
        let Some(end) = instant.checked_add(delay) else {
            return false;
        };
37
        end <= Self::now()
37
    }
    #[cfg(feature = "runtime-benchmarks")]
    fn elapsed_instant() -> Self::Instant {
        let delay = G::get();
        Self::now()
            .checked_add(delay)
            .expect("overflow when computing valid elapsed instant")
    }
    #[cfg(feature = "runtime-benchmarks")]
    fn skip_to_elapsed() {
        let session_to_reach = Self::elapsed_instant();
        while Self::now() < session_to_reach {
            Session::rotate_session();
        }
    }
}
pub struct CandidateHasRegisteredKeys;
impl IsCandidateEligible<AccountId> for CandidateHasRegisteredKeys {
114
    fn is_candidate_eligible(a: &AccountId) -> bool {
114
        <Session as ValidatorRegistration<AccountId>>::is_registered(a)
114
    }
    #[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()));
        }
    }
}
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<StakingSessionDelay>;
    type LeavingRequestTimer = SessionTimer<StakingSessionDelay>;
    type EligibleCandidatesBufferSize = ConstU32<100>;
    type EligibleCandidatesFilter = CandidateHasRegisteredKeys;
    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: check if we can put the prod inflation for tests too
    // 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 Get<AccountId32> for GetSelfChainBlockAuthor {
11062
    fn get() -> AccountId32 {
11062
        // TODO: we should do a refactor here, and use either authority-mapping or collator-assignemnt
11062
        // we should also make sure we actually account for the weight of these
11062
        // although most of these should be cached as they are read every block
11062
        let slot = u64::from(<Runtime as pallet_author_inherent::Config>::SlotBeacon::slot());
11062
        let self_para_id = ParachainInfo::get();
11062
        let author = CollatorAssignment::author_for_slot(slot.into(), self_para_id);
11062
        author.expect("author should be set")
11062
    }
}
pub struct OnUnbalancedInflation;
impl frame_support::traits::OnUnbalanced<Credit<AccountId, Balances>> for OnUnbalancedInflation {
11062
    fn on_nonzero_unbalanced(credit: Credit<AccountId, Balances>) {
11062
        let _ = <Balances as Balanced<_>>::resolve(&ParachainBondAccount::get(), credit);
11062
    }
}
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>;
}
340
#[derive(RuntimeDebug, PartialEq, Eq, Encode, Decode, Copy, Clone, TypeInfo, MaxEncodedLen)]
pub enum StreamPaymentAssetId {
57
    Native,
}
pub struct StreamPaymentAssets;
impl pallet_stream_payment::Assets<AccountId, StreamPaymentAssetId, Balance>
    for StreamPaymentAssets
{
12
    fn transfer_deposit(
12
        asset_id: &StreamPaymentAssetId,
12
        from: &AccountId,
12
        to: &AccountId,
12
        amount: Balance,
12
    ) -> frame_support::pallet_prelude::DispatchResult {
12
        match asset_id {
12
            StreamPaymentAssetId::Native => {
12
                // We remove the hold before transfering.
12
                Self::decrease_deposit(asset_id, from, amount)?;
12
                Balances::transfer(from, to, amount, Preservation::Preserve).map(|_| ())
            }
        }
12
    }
10
    fn increase_deposit(
10
        asset_id: &StreamPaymentAssetId,
10
        account: &AccountId,
10
        amount: Balance,
10
    ) -> frame_support::pallet_prelude::DispatchResult {
10
        match asset_id {
10
            StreamPaymentAssetId::Native => Balances::hold(
10
                &pallet_stream_payment::HoldReason::StreamPayment.into(),
10
                account,
10
                amount,
10
            ),
10
        }
10
    }
18
    fn decrease_deposit(
18
        asset_id: &StreamPaymentAssetId,
18
        account: &AccountId,
18
        amount: Balance,
18
    ) -> frame_support::pallet_prelude::DispatchResult {
18
        match asset_id {
18
            StreamPaymentAssetId::Native => Balances::release(
18
                &pallet_stream_payment::HoldReason::StreamPayment.into(),
18
                account,
18
                amount,
18
                Precision::Exact,
18
            )
18
            .map(|_| ()),
18
        }
18
    }
    fn get_deposit(asset_id: &StreamPaymentAssetId, account: &AccountId) -> Balance {
        match asset_id {
            StreamPaymentAssetId::Native => Balances::balance_on_hold(
                &pallet_stream_payment::HoldReason::StreamPayment.into(),
                account,
            ),
        }
    }
    /// Benchmarks: should return the asset id which has the worst performance when interacting
    /// with it.
    #[cfg(feature = "runtime-benchmarks")]
    fn bench_worst_case_asset_id() -> StreamPaymentAssetId {
        StreamPaymentAssetId::Native
    }
    /// Benchmarks: should return the another asset id which has the worst performance when interacting
    /// with it afther `bench_worst_case_asset_id`. This is to benchmark the worst case when changing config
    /// from one asset to another.
    #[cfg(feature = "runtime-benchmarks")]
    fn bench_worst_case_asset_id2() -> StreamPaymentAssetId {
        StreamPaymentAssetId::Native
    }
    /// Benchmarks: should set the balance for the asset id returned by `bench_worst_case_asset_id`.
    #[cfg(feature = "runtime-benchmarks")]
    fn bench_set_balance(asset_id: &StreamPaymentAssetId, account: &AccountId, amount: Balance) {
        // only one asset id
        let StreamPaymentAssetId::Native = asset_id;
        Balances::set_balance(account, amount);
    }
}
510
#[derive(RuntimeDebug, PartialEq, Eq, Encode, Decode, Copy, Clone, TypeInfo, MaxEncodedLen)]
pub enum TimeUnit {
57
    BlockNumber,
    Timestamp,
    // TODO: Container chains/relay block number.
}
pub struct TimeProvider;
impl pallet_stream_payment::TimeProvider<TimeUnit, Balance> for TimeProvider {
36
    fn now(unit: &TimeUnit) -> Option<Balance> {
36
        match *unit {
36
            TimeUnit::BlockNumber => Some(System::block_number().into()),
            TimeUnit::Timestamp => Some(Timestamp::now().into()),
        }
36
    }
    /// Benchmarks: should return the time unit which has the worst performance calling
    /// `TimeProvider::now(unit)` with.
    #[cfg(feature = "runtime-benchmarks")]
    fn bench_worst_case_time_unit() -> TimeUnit {
        // Both BlockNumber and Timestamp cost the same (1 db read), but overriding timestamp
        // doesn't work well in benches, while block number works fine.
        TimeUnit::BlockNumber
    }
    /// Benchmarks: sets the "now" time for time unit returned by `worst_case_time_unit`.
    #[cfg(feature = "runtime-benchmarks")]
    fn bench_set_now(instant: Balance) {
        System::set_block_number(instant as u32)
    }
}
type StreamId = u64;
parameter_types! {
    // 1 entry, storing 173 bytes on-chain
    pub const OpenStreamHoldAmount: Balance = currency::deposit(1, 173);
}
impl pallet_stream_payment::Config for Runtime {
    type RuntimeEvent = RuntimeEvent;
    type StreamId = StreamId;
    type TimeUnit = TimeUnit;
    type Balance = Balance;
    type AssetId = StreamPaymentAssetId;
    type Assets = StreamPaymentAssets;
    type Currency = Balances;
    type OpenStreamHoldAmount = OpenStreamHoldAmount;
    type RuntimeHoldReason = RuntimeHoldReason;
    type TimeProvider = TimeProvider;
    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 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 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 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_value();
}
impl pallet_treasury::Config for Runtime {
    type PalletId = TreasuryId;
    type Currency = Balances;
    type ApproveOrigin = EnsureRoot<AccountId>;
    type RejectOrigin = EnsureRoot<AccountId>;
    type RuntimeEvent = RuntimeEvent;
    // If proposal gets rejected, bond goes to treasury
    type OnSlash = Treasury;
    type ProposalBond = ProposalBond;
    type ProposalBondMinimum = ConstU128<{ 1 * currency::DANCE * currency::SUPPLY_FACTOR }>;
    type SpendPeriod = ConstU32<{ 6 * DAYS }>;
    type Burn = ();
    type BurnDestination = ();
    type MaxApprovals = ConstU32<100>;
    type WeightInfo = weights::pallet_treasury::SubstrateWeight<Runtime>;
    type SpendFunds = ();
    type ProposalBondMaximum = ();
    #[cfg(not(feature = "runtime-benchmarks"))]
    type SpendOrigin = frame_support::traits::NeverEnsureOrigin<Balance>; // Disabled, no spending
    #[cfg(feature = "runtime-benchmarks")]
    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 }>;
    #[cfg(feature = "runtime-benchmarks")]
    type BenchmarkHelper = tanssi_runtime_common::benchmarking::TreasurtBenchmarkHelper<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>;
}
// Create the runtime by composing the FRAME pallets that were previously configured.
3393835
construct_runtime!(
384302
    pub enum Runtime
384302
    {
384302
        // System support stuff.
384302
        System: frame_system = 0,
384302
        ParachainSystem: cumulus_pallet_parachain_system = 1,
384302
        Timestamp: pallet_timestamp = 2,
384302
        ParachainInfo: parachain_info = 3,
384302
        Sudo: pallet_sudo = 4,
384302
        Utility: pallet_utility = 5,
384302
        Proxy: pallet_proxy = 6,
384302
        Migrations: pallet_migrations = 7,
384302
        MaintenanceMode: pallet_maintenance_mode = 8,
384302
        TxPause: pallet_tx_pause = 9,
384302

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

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

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

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

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

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

            
384302
        // More system support stuff
384302
        RelayStorageRoots: pallet_relay_storage_roots = 60,
384302

            
384302
        RootTesting: pallet_root_testing = 100,
384302
        AsyncBacking: pallet_async_backing::{Pallet, Storage} = 110,
384302
    }
3393835
);
#[cfg(feature = "runtime-benchmarks")]
mod benches {
    frame_benchmarking::define_benchmarks!(
        [frame_system, frame_system_benchmarking::Pallet::<Runtime>]
        [cumulus_pallet_parachain_system, ParachainSystem]
        [pallet_timestamp, Timestamp]
        [pallet_sudo, Sudo]
        [pallet_utility, Utility]
        [pallet_proxy, Proxy]
        [pallet_tx_pause, TxPause]
        [pallet_balances, Balances]
        [pallet_stream_payment, StreamPayment]
        [pallet_identity, Identity]
        [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_treasury, Treasury]
        [cumulus_pallet_xcmp_queue, XcmpQueue]
        [cumulus_pallet_dmp_queue, DmpQueue]
        [pallet_xcm, PalletXcmExtrinsicsBenchmark::<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]
    );
}
159200
impl_runtime_apis! {
37626
    impl sp_consensus_aura::AuraApi<Block, NimbusId> for Runtime {
37626
        fn slot_duration() -> sp_consensus_aura::SlotDuration {
6958
            sp_consensus_aura::SlotDuration::from_millis(SLOT_DURATION)
6958
        }
37626

            
37626
        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);
37626

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

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

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

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

            
37626
        fn initialize_block(header: &<Block as BlockT>::Header) -> sp_runtime::ExtrinsicInclusionMode {
6802
            Executive::initialize_block(header)
6802
        }
37626
    }
37626

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

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

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

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

            
37626
        fn finalize_block() -> <Block as BlockT>::Header {
6802
            Executive::finalize_block()
6802
        }
37626

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            
37626
        fn dispatch_benchmark(
37626
            config: frame_benchmarking::BenchmarkConfig,
37626
        ) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, sp_runtime::RuntimeString> {
37626
            use frame_benchmarking::{BenchmarkBatch, Benchmarking, BenchmarkError};
37626
            use sp_core::storage::TrackedStorageKey;
37626
            use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
37626
            impl cumulus_pallet_session_benchmarking::Config for Runtime {}
37626

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

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

            
37626
            use staging_xcm::latest::prelude::*;
37626
            use crate::xcm_config::SelfReserve;
37626
            parameter_types! {
37626
                pub ExistentialDepositAsset: Option<Asset> = Some((
37626
                    SelfReserve::get(),
37626
                    ExistentialDeposit::get()
37626
                ).into());
37626
            }
37626

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            
37626
            add_benchmarks!(params, batches);
37626

            
37626
            Ok(batches)
37626
        }
37626
    }
37626

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

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

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

            
16
            assigned_collators.para_id_of(&account, self_para_id)
16
        }
37626

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

            
12
            match assigned_collators {
37634
                Some(assigned_collators) => {
8
                    let self_para_id = ParachainInfo::get();
8

            
8
                    assigned_collators.para_id_of(&account, self_para_id)
37626
                }
37626
                None => {
37630
                    Self::current_collator_parachain_assignment(account)
37626
                }
37626
            }
37626

            
37638
        }
37626

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

            
28
            if para_id == self_para_id {
37644
                Some(assigned_collators.orchestrator_chain)
37626
            } else {
37636
                assigned_collators.container_chains.get(&para_id).cloned()
37626
            }
37654
        }
37626
    }
37626

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

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

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

            
6812
            para_ids
6812
        }
37626

            
37626
        /// Fetch genesis data for this para id
37640
        fn genesis_data(para_id: ParaId) -> Option<ContainerChainGenesisData<MaxLengthTokenSymbol>> {
14
            Registrar::para_genesis_data(para_id)
14
        }
37626

            
37626
        /// Fetch boot_nodes for this para id
37626
        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()
        }
37626
    }
37626

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

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

            
37628
        fn latest_author(para_id: ParaId) -> Option<AccountId> {
2
            AuthorNoting::latest_author(para_id).map(|info| info.author)
2
        }
37626
    }
37626

            
37626
    impl dp_consensus::TanssiAuthorityAssignmentApi<Block, NimbusId> for Runtime {
37626
        /// Return the current authorities assigned to a given paraId
41918
        fn para_id_authorities(para_id: ParaId) -> Option<Vec<NimbusId>> {
11094
            let parent_number = System::block_number();
11094

            
11094
            let should_end_session = <Runtime as pallet_session::Config>::ShouldEndSession::should_end_session(parent_number + 1);
37626

            
41918
            let session_index = if should_end_session {
38034
                Session::current_index() +1
37626
            }
37626
            else {
41510
                Session::current_index()
37626
            };
37626

            
41918
            let assigned_authorities = AuthorityAssignment::collator_container_chain(session_index)?;
37626

            
41918
            let self_para_id = ParachainInfo::get();
11094

            
11094
            if para_id == self_para_id {
41902
                Some(assigned_authorities.orchestrator_chain)
37626
            } else {
37642
                assigned_authorities.container_chains.get(&para_id).cloned()
37626
            }
41918
        }
37626

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

            
37690
            let session_index = if should_end_session {
37642
                Session::current_index() +1
37626
            }
37626
            else {
37674
                Session::current_index()
37626
            };
37690
            let assigned_authorities = AuthorityAssignment::collator_container_chain(session_index)?;
37690
            let self_para_id = ParachainInfo::get();
64

            
64
            assigned_authorities.para_id_of(&authority, self_para_id)
37690
        }
37626

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

            
24
            assigned_authorities.para_id_of(&authority, self_para_id)
37650
        }
37626
    }
37626

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

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

            
37626
        fn query_weight_to_fee(weight: Weight) -> Balance {
20
            TransactionPayment::weight_to_fee(weight)
20
        }
37626

            
37626
        fn query_length_to_fee(length: u32) -> Balance {
6
            TransactionPayment::length_to_fee(length)
6
        }
37626
    }
37626

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

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

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

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

            
37626
    impl pallet_xcm_core_buyer_runtime_api::XCMCoreBuyerApi<Block, BlockNumber, ParaId> for Runtime {
37626
        fn is_core_buying_allowed(para_id: ParaId) -> Result<(), BuyingError<BlockNumber>> {
            XcmCoreBuyer::is_core_buying_allowed(para_id)
        }
37626
    }
159200
}
#[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,
                sp_std::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
        }
    };
}