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
use {
18
    crate::{AuthorInherent, BlockProductionCost, CollatorAssignmentCost, RuntimeOrigin},
19
    cumulus_primitives_core::{ParaId, PersistedValidationData},
20
    cumulus_primitives_parachain_inherent::ParachainInherentData,
21
    dp_consensus::runtime_decl_for_tanssi_authority_assignment_api::TanssiAuthorityAssignmentApi,
22
    frame_support::{
23
        assert_ok,
24
        traits::{OnFinalize, OnInitialize},
25
    },
26
    nimbus_primitives::{NimbusId, NIMBUS_ENGINE_ID},
27
    pallet_collator_assignment_runtime_api::runtime_decl_for_collator_assignment_api::CollatorAssignmentApi,
28
    pallet_registrar_runtime_api::ContainerChainGenesisData,
29
    pallet_services_payment::{ProvideBlockProductionCost, ProvideCollatorAssignmentCost},
30
    parity_scale_codec::{Decode, Encode, MaxEncodedLen},
31
    polkadot_parachain_primitives::primitives::HeadData,
32
    sp_consensus_aura::AURA_ENGINE_ID,
33
    sp_consensus_slots::Slot,
34
    sp_core::{Get, Pair},
35
    sp_runtime::{traits::Dispatchable, BuildStorage, Digest, DigestItem},
36
    sp_std::collections::btree_map::BTreeMap,
37
    test_relay_sproof_builder::ParaHeaderSproofBuilder,
38
};
39

            
40
pub use crate::{
41
    AccountId, AssetRate, AuthorNoting, AuthorityAssignment, AuthorityMapping, Balance, Balances,
42
    CollatorAssignment, Configuration, DataPreservers, ForeignAssets, ForeignAssetsCreator,
43
    InactivityTracking, InflationRewards, Initializer, Invulnerables, MinimumSelfDelegation,
44
    ParachainInfo, PooledStaking, Proxy, ProxyType, Registrar, RewardsPortion, Runtime,
45
    RuntimeCall, ServicesPayment, Session, System, TransactionPayment,
46
};
47

            
48
pub const UNIT: Balance = 1_000_000_000_000;
49

            
50
117
pub fn session_to_block(n: u32) -> u32 {
51
117
    let block_number = crate::Period::get() * n;
52
117

            
53
117
    // Add 1 because the block that emits the NewSession event cannot contain any extrinsics,
54
117
    // so this is the first block of the new session that can actually be used
55
117
    block_number + 1
56
117
}
57

            
58
#[derive(Debug, Clone, Eq, PartialEq)]
59
pub struct RunSummary {
60
    pub author_id: AccountId,
61
    pub inflation: Balance,
62
}
63

            
64
114
pub fn run_to_session(n: u32) {
65
114
    run_to_block(session_to_block(n));
66
114
}
67

            
68
/// Utility function that advances the chain to the desired block number.
69
///
70
/// After this function returns, the current block number will be `n`, and the block will be "open",
71
/// meaning that on_initialize has been executed, but on_finalize has not. To execute on_finalize as
72
/// well, for example to test a runtime api, manually call `end_block` after this, run the test, and
73
/// call `start_block` to ensure that this function keeps working as expected.
74
/// Extrinsics should always be executed before on_finalize.
75
189
pub fn run_to_block(n: u32) -> BTreeMap<u32, RunSummary> {
76
189
    let current_block_number = System::block_number();
77
189
    assert!(
78
189
        current_block_number < n,
79
        "run_to_block called with block {} when current block is {}",
80
        n,
81
        current_block_number
82
    );
83
189
    let mut summaries = BTreeMap::new();
84

            
85
2275
    while System::block_number() < n {
86
2086
        let summary = run_block();
87
2086
        let block_number = System::block_number();
88
2086
        summaries.insert(block_number, summary);
89
2086
    }
90

            
91
189
    summaries
92
189
}
93

            
94
2255
pub fn insert_authorities_and_slot_digests(slot: u64) {
95
2255
    let authorities =
96
2255
        Runtime::para_id_authorities(ParachainInfo::get()).expect("authorities should be set");
97
2255

            
98
2255
    let authority: NimbusId = authorities[slot as usize % authorities.len()].clone();
99
2255

            
100
2255
    let pre_digest = Digest {
101
2255
        logs: vec![
102
2255
            DigestItem::PreRuntime(AURA_ENGINE_ID, slot.encode()),
103
2255
            DigestItem::PreRuntime(NIMBUS_ENGINE_ID, authority.encode()),
104
2255
        ],
105
2255
    };
106
2255

            
107
2255
    System::reset_events();
108
2255
    System::initialize(
109
2255
        &(System::block_number() + 1),
110
2255
        &System::parent_hash(),
111
2255
        &pre_digest,
112
2255
    );
113
2255
}
114

            
115
// Used to create the next block inherent data
116
#[derive(Clone, Encode, Decode, Default, PartialEq, Debug, scale_info::TypeInfo, MaxEncodedLen)]
117
pub struct MockInherentData {
118
    pub random_seed: Option<[u8; 32]>,
119
}
120

            
121
2255
fn take_new_inherent_data() -> Option<MockInherentData> {
122
2255
    let data: Option<MockInherentData> =
123
2255
        frame_support::storage::unhashed::take(b"__mock_new_inherent_data");
124
2255

            
125
2255
    data
126
2255
}
127

            
128
2
fn set_new_inherent_data(data: MockInherentData) {
129
2
    frame_support::storage::unhashed::put(b"__mock_new_inherent_data", &Some(data));
130
2
}
131

            
132
#[derive(Clone, Encode, Decode, PartialEq, Debug, scale_info::TypeInfo, MaxEncodedLen)]
133
enum RunBlockState {
134
2143
    Start(u32),
135
2142
    End(u32),
136
}
137

            
138
impl RunBlockState {
139
4398
    fn assert_can_advance(&self, new_state: &RunBlockState) {
140
4398
        match self {
141
2143
            RunBlockState::Start(n) => {
142
2143
                assert_eq!(
143
2143
                    new_state,
144
2143
                    &RunBlockState::End(*n),
145
                    "expected a call to end_block({}), but user called {:?}",
146
                    *n,
147
                    new_state
148
                );
149
            }
150
2255
            RunBlockState::End(n) => {
151
2255
                assert_eq!(
152
2255
                    new_state,
153
2255
                    &RunBlockState::Start(*n + 1),
154
                    "expected a call to start_block({}), but user called {:?}",
155
                    *n + 1,
156
                    new_state
157
                )
158
            }
159
        }
160
4398
    }
161
}
162

            
163
4398
fn advance_block_state_machine(new_state: RunBlockState) {
164
4398
    if frame_support::storage::unhashed::exists(b"__mock_is_xcm_test") {
165
        // Disable this check in XCM tests, because the XCM emulator runs on_initialize and
166
        // on_finalize automatically
167
        return;
168
4398
    }
169
4398
    let old_state: RunBlockState =
170
4398
        frame_support::storage::unhashed::get(b"__mock_debug_block_state").unwrap_or(
171
4398
            // Initial state is expecting a call to start() with block number 1, so old state should be
172
4398
            // end of block 0
173
4398
            RunBlockState::End(0),
174
4398
        );
175
4398
    old_state.assert_can_advance(&new_state);
176
4398
    frame_support::storage::unhashed::put(b"__mock_debug_block_state", &new_state);
177
4398
}
178

            
179
2255
pub fn start_block() -> RunSummary {
180
2255
    let block_number = System::block_number();
181
2255
    advance_block_state_machine(RunBlockState::Start(block_number + 1));
182
2255
    let mut slot = current_slot() + 1;
183
2255
    if block_number == 0 {
184
113
        // Hack to avoid breaking all tests. When the current block is 1, the slot number should be
185
113
        // 1. But all of our tests assume it will be 0. So use slot number = block_number - 1.
186
113
        slot = 0;
187
2142
    }
188

            
189
2255
    let maybe_mock_inherent = take_new_inherent_data();
190

            
191
2255
    if let Some(mock_inherent_data) = maybe_mock_inherent {
192
2
        set_parachain_inherent_data(mock_inherent_data);
193
2253
    }
194

            
195
2255
    insert_authorities_and_slot_digests(slot);
196
2255

            
197
2255
    // Initialize the new block
198
2255
    CollatorAssignment::on_initialize(System::block_number());
199
2255
    Session::on_initialize(System::block_number());
200
2255
    Initializer::on_initialize(System::block_number());
201
2255
    AuthorInherent::on_initialize(System::block_number());
202
2255

            
203
2255
    // `Initializer::on_finalize` needs to run at least one to have
204
2255
    // author mapping setup.
205
2255
    let author_id = current_author();
206
2255

            
207
2255
    let current_issuance = Balances::total_issuance();
208
2255
    InflationRewards::on_initialize(System::block_number());
209
2255
    let new_issuance = Balances::total_issuance();
210
2255

            
211
2255
    frame_support::storage::unhashed::put(
212
2255
        &frame_support::storage::storage_prefix(b"AsyncBacking", b"SlotInfo"),
213
2255
        &(Slot::from(slot), 1),
214
2255
    );
215
2255

            
216
2255
    pallet_author_inherent::Pallet::<Runtime>::kick_off_authorship_validation(None.into())
217
2255
        .expect("author inherent to dispatch correctly");
218
2255

            
219
2255
    InactivityTracking::on_initialize(System::block_number());
220
2255

            
221
2255
    RunSummary {
222
2255
        author_id,
223
2255
        inflation: new_issuance - current_issuance,
224
2255
    }
225
2255
}
226

            
227
2143
pub fn end_block() {
228
2143
    let block_number = System::block_number();
229
2143
    advance_block_state_machine(RunBlockState::End(block_number));
230
2143
    // Finalize the block
231
2143
    CollatorAssignment::on_finalize(System::block_number());
232
2143
    Session::on_finalize(System::block_number());
233
2143
    Initializer::on_finalize(System::block_number());
234
2143
    AuthorInherent::on_finalize(System::block_number());
235
2143
    TransactionPayment::on_finalize(System::block_number());
236
2143
    InactivityTracking::on_finalize(System::block_number());
237
2143
}
238

            
239
2140
pub fn run_block() -> RunSummary {
240
2140
    end_block();
241
2140

            
242
2140
    start_block()
243
2140
}
244

            
245
/// Mock the inherent that sets validation data in ParachainSystem, which
246
/// contains the `relay_chain_block_number`, which is used in `collator-assignment` as a
247
/// source of randomness.
248
115
pub fn set_parachain_inherent_data(mock_inherent_data: MockInherentData) {
249
    use {
250
        cumulus_primitives_core::relay_chain::well_known_keys,
251
        cumulus_test_relay_sproof_builder::RelayStateSproofBuilder,
252
    };
253

            
254
115
    let relay_sproof = RelayStateSproofBuilder {
255
115
        para_id: 100u32.into(),
256
115
        included_para_head: Some(HeadData(vec![1, 2, 3])),
257
115
        current_slot: (current_slot()).into(),
258
115
        additional_key_values: if mock_inherent_data.random_seed.is_some() {
259
2
            vec![(
260
2
                well_known_keys::CURRENT_BLOCK_RANDOMNESS.to_vec(),
261
2
                Some(mock_inherent_data.random_seed).encode(),
262
2
            )]
263
        } else {
264
113
            vec![]
265
        },
266
115
        ..Default::default()
267
115
    };
268
115

            
269
115
    let (relay_parent_storage_root, relay_chain_state) = relay_sproof.into_state_root_and_proof();
270
115
    let vfp = PersistedValidationData {
271
115
        relay_parent_number: 1u32,
272
115
        relay_parent_storage_root,
273
115
        ..Default::default()
274
115
    };
275
115
    let parachain_inherent_data = ParachainInherentData {
276
115
        validation_data: vfp,
277
115
        relay_chain_state,
278
115
        downward_messages: Default::default(),
279
115
        horizontal_messages: Default::default(),
280
115
    };
281
115

            
282
115
    // Delete existing flag to avoid error
283
115
    // 'ValidationData must be updated only once in a block'
284
115
    // TODO: this is a hack
285
115
    frame_support::storage::unhashed::kill(&frame_support::storage::storage_prefix(
286
115
        b"ParachainSystem",
287
115
        b"ValidationData",
288
115
    ));
289
115

            
290
115
    assert_ok!(RuntimeCall::ParachainSystem(
291
115
        cumulus_pallet_parachain_system::Call::<Runtime>::set_validation_data {
292
115
            data: parachain_inherent_data
293
115
        }
294
115
    )
295
115
    .dispatch(inherent_origin()));
296
115
}
297

            
298
2
pub fn set_parachain_inherent_data_random_seed(random_seed: [u8; 32]) {
299
2
    set_new_inherent_data(MockInherentData {
300
2
        random_seed: Some(random_seed),
301
2
    });
302
2
}
303

            
304
#[derive(Default, Clone)]
305
pub struct ParaRegistrationParams {
306
    pub para_id: u32,
307
    pub genesis_data: ContainerChainGenesisData,
308
    pub block_production_credits: u32,
309
    pub collator_assignment_credits: u32,
310
    pub parathread_params: Option<tp_traits::ParathreadParams>,
311
}
312

            
313
113
pub fn default_config() -> pallet_configuration::HostConfiguration {
314
113
    pallet_configuration::HostConfiguration {
315
113
        max_collators: 100,
316
113
        min_orchestrator_collators: 2,
317
113
        max_orchestrator_collators: 2,
318
113
        collators_per_container: 2,
319
113
        full_rotation_period: 24,
320
113
        ..Default::default()
321
113
    }
322
113
}
323

            
324
pub struct ExtBuilder {
325
    // endowed accounts with balances
326
    balances: Vec<(AccountId, Balance)>,
327
    // [collator, amount]
328
    collators: Vec<(AccountId, Balance)>,
329
    // sudo key
330
    sudo: Option<AccountId>,
331
    // list of registered para ids: para_id, genesis_data, boot_nodes, block_credits, session_credits
332
    para_ids: Vec<ParaRegistrationParams>,
333
    // configuration to apply
334
    config: pallet_configuration::HostConfiguration,
335
    safe_xcm_version: Option<u32>,
336
    own_para_id: Option<ParaId>,
337
}
338

            
339
impl Default for ExtBuilder {
340
113
    fn default() -> Self {
341
113
        Self {
342
113
            balances: vec![
343
113
                // Alice gets 10k extra tokens for her mapping deposit
344
113
                (AccountId::from(ALICE), 210_000 * UNIT),
345
113
                (AccountId::from(BOB), 100_000 * UNIT),
346
113
            ],
347
113
            collators: vec![
348
113
                (AccountId::from(ALICE), 210 * UNIT),
349
113
                (AccountId::from(BOB), 100 * UNIT),
350
113
            ],
351
113
            sudo: Default::default(),
352
113
            para_ids: Default::default(),
353
113
            config: default_config(),
354
113
            safe_xcm_version: Default::default(),
355
113
            own_para_id: Default::default(),
356
113
        }
357
113
    }
358
}
359

            
360
impl ExtBuilder {
361
93
    pub fn with_balances(mut self, balances: Vec<(AccountId, Balance)>) -> Self {
362
93
        self.balances = balances;
363
93
        self
364
93
    }
365

            
366
85
    pub fn with_collators(mut self, collators: Vec<(AccountId, Balance)>) -> Self {
367
85
        self.collators = collators;
368
85
        self
369
85
    }
370

            
371
8
    pub fn with_sudo(mut self, sudo: AccountId) -> Self {
372
8
        self.sudo = Some(sudo);
373
8
        self
374
8
    }
375

            
376
4
    pub fn with_para_ids(mut self, para_ids: Vec<ParaRegistrationParams>) -> Self {
377
4
        self.para_ids = para_ids;
378
4
        self
379
4
    }
380

            
381
    /// Helper function like `with_para_ids` but registering parachains with an empty genesis data,
382
    /// and max amount of credits.
383
58
    pub fn with_empty_parachains(mut self, para_ids: Vec<u32>) -> Self {
384
58
        self.para_ids = para_ids
385
58
            .into_iter()
386
117
            .map(|para_id| ParaRegistrationParams {
387
117
                para_id,
388
117
                genesis_data: empty_genesis_data(),
389
117
                block_production_credits: u32::MAX,
390
117
                collator_assignment_credits: u32::MAX,
391
117
                parathread_params: None,
392
117
            })
393
58
            .collect();
394
58
        self
395
58
    }
396

            
397
8
    pub fn with_config(mut self, config: pallet_configuration::HostConfiguration) -> Self {
398
8
        self.config = config;
399
8
        self
400
8
    }
401

            
402
113
    pub fn build_storage(self) -> sp_core::storage::Storage {
403
113
        let mut t = frame_system::GenesisConfig::<Runtime>::default()
404
113
            .build_storage()
405
113
            .unwrap();
406
113

            
407
113
        pallet_balances::GenesisConfig::<Runtime> {
408
113
            balances: self.balances,
409
113
        }
410
113
        .assimilate_storage(&mut t)
411
113
        .unwrap();
412
113

            
413
113
        // We need to initialize these pallets first. When initializing pallet-session,
414
113
        // these values will be taken into account for collator-assignment.
415
113

            
416
113
        pallet_registrar::GenesisConfig::<Runtime> {
417
113
            para_ids: self
418
113
                .para_ids
419
113
                .iter()
420
113
                .cloned()
421
124
                .map(|registered_para| {
422
124
                    (
423
124
                        registered_para.para_id.into(),
424
124
                        registered_para.genesis_data,
425
124
                        registered_para.parathread_params,
426
124
                    )
427
124
                })
428
113
                .collect(),
429
113
            phantom: Default::default(),
430
113
        }
431
113
        .assimilate_storage(&mut t)
432
113
        .unwrap();
433
113

            
434
113
        pallet_services_payment::GenesisConfig::<Runtime> {
435
113
            para_id_credits: self
436
113
                .para_ids
437
113
                .clone()
438
113
                .into_iter()
439
124
                .map(|registered_para| {
440
124
                    (
441
124
                        registered_para.para_id.into(),
442
124
                        registered_para.block_production_credits,
443
124
                        registered_para.collator_assignment_credits,
444
124
                    )
445
124
                        .into()
446
124
                })
447
113
                .collect(),
448
113
        }
449
113
        .assimilate_storage(&mut t)
450
113
        .unwrap();
451
113

            
452
113
        pallet_configuration::GenesisConfig::<Runtime> {
453
113
            config: self.config,
454
113
            ..Default::default()
455
113
        }
456
113
        .assimilate_storage(&mut t)
457
113
        .unwrap();
458
113

            
459
113
        pallet_xcm::GenesisConfig::<Runtime> {
460
113
            safe_xcm_version: self.safe_xcm_version,
461
113
            ..Default::default()
462
113
        }
463
113
        .assimilate_storage(&mut t)
464
113
        .unwrap();
465

            
466
113
        if let Some(own_para_id) = self.own_para_id {
467
            parachain_info::GenesisConfig::<Runtime> {
468
                parachain_id: own_para_id,
469
                ..Default::default()
470
            }
471
            .assimilate_storage(&mut t)
472
            .unwrap();
473
113
        }
474

            
475
113
        if !self.collators.is_empty() {
476
113
            // We set invulnerables in pallet_invulnerables
477
113
            let invulnerables: Vec<AccountId> = self
478
113
                .collators
479
113
                .clone()
480
113
                .into_iter()
481
375
                .map(|(account, _balance)| account)
482
113
                .collect();
483
113

            
484
113
            pallet_invulnerables::GenesisConfig::<Runtime> {
485
113
                invulnerables: invulnerables.clone(),
486
113
            }
487
113
            .assimilate_storage(&mut t)
488
113
            .unwrap();
489
113

            
490
113
            // But we also initialize their keys in the session pallet
491
113
            let keys: Vec<_> = self
492
113
                .collators
493
113
                .into_iter()
494
375
                .map(|(account, _balance)| {
495
375
                    let nimbus_id = get_aura_id_from_seed(&account.to_string());
496
375
                    (
497
375
                        account.clone(),
498
375
                        account,
499
375
                        crate::SessionKeys { nimbus: nimbus_id },
500
375
                    )
501
375
                })
502
113
                .collect();
503
113
            pallet_session::GenesisConfig::<Runtime> {
504
113
                keys,
505
113
                ..Default::default()
506
113
            }
507
113
            .assimilate_storage(&mut t)
508
113
            .unwrap();
509
113
        }
510
113
        pallet_sudo::GenesisConfig::<Runtime> { key: self.sudo }
511
113
            .assimilate_storage(&mut t)
512
113
            .unwrap();
513
113

            
514
113
        if self.safe_xcm_version.is_some() {
515
            // Disable run_block checks in XCM tests, because the XCM emulator runs on_initialize and
516
            // on_finalize automatically
517
            t.top.insert(b"__mock_is_xcm_test".to_vec(), b"1".to_vec());
518
113
        }
519

            
520
113
        t
521
113
    }
522

            
523
113
    pub fn build(self) -> sp_io::TestExternalities {
524
113
        let t = self.build_storage();
525
113
        let mut ext = sp_io::TestExternalities::new(t);
526
113

            
527
113
        ext.execute_with(|| {
528
113
            // Start block 1
529
113
            start_block();
530
113
            set_parachain_inherent_data(Default::default());
531
113
        });
532
113
        ext
533
113
    }
534
}
535

            
536
87
pub fn root_origin() -> <Runtime as frame_system::Config>::RuntimeOrigin {
537
87
    <Runtime as frame_system::Config>::RuntimeOrigin::root()
538
87
}
539

            
540
205
pub fn origin_of(account_id: AccountId) -> <Runtime as frame_system::Config>::RuntimeOrigin {
541
205
    <Runtime as frame_system::Config>::RuntimeOrigin::signed(account_id)
542
205
}
543

            
544
126
pub fn inherent_origin() -> <Runtime as frame_system::Config>::RuntimeOrigin {
545
126
    <Runtime as frame_system::Config>::RuntimeOrigin::none()
546
126
}
547

            
548
/// Helper function to generate a crypto pair from seed
549
456
pub fn get_aura_id_from_seed(seed: &str) -> NimbusId {
550
456
    sp_core::sr25519::Pair::from_string(&format!("//{}", seed), None)
551
456
        .expect("static values are valid; qed")
552
456
        .public()
553
456
        .into()
554
456
}
555

            
556
4
pub fn get_orchestrator_current_author() -> Option<AccountId> {
557
4
    let slot: u64 = current_slot();
558
4
    let orchestrator_collators = Runtime::parachain_collators(ParachainInfo::get())?;
559
4
    let author_index = slot % orchestrator_collators.len() as u64;
560
4
    let account = orchestrator_collators.get(author_index as usize)?;
561
4
    Some(account.clone())
562
4
}
563
/// Mocks the author noting inherent to insert the data we
564
11
pub fn set_author_noting_inherent_data(builder: ParaHeaderSproofBuilder) {
565
11
    let (relay_storage_root, relay_storage_proof) = builder.into_state_root_and_proof();
566
11

            
567
11
    // For now we directly touch parachain_system storage to set the relay state root.
568
11
    // TODO: Properly set the parachain_system inherent, which require a sproof builder combining
569
11
    // what is required by parachain_system and author_noting.
570
11
    frame_support::storage::unhashed::put(
571
11
        &frame_support::storage::storage_prefix(b"ParachainSystem", b"ValidationData"),
572
11
        &PersistedValidationData {
573
11
            parent_head: HeadData(Default::default()),
574
11
            relay_parent_number: 0u32,
575
11
            relay_parent_storage_root: relay_storage_root,
576
11
            max_pov_size: 0u32,
577
11
        },
578
11
    );
579
11

            
580
11
    // But we also need to store the new proof submitted
581
11
    frame_support::storage::unhashed::put(
582
11
        &frame_support::storage::storage_prefix(b"ParachainSystem", b"RelayStateProof"),
583
11
        &relay_storage_proof,
584
11
    );
585
11

            
586
11
    assert_ok!(RuntimeCall::AuthorNoting(
587
11
        pallet_author_noting::Call::<Runtime>::set_latest_author_data {
588
11
            data: tp_author_noting_inherent::OwnParachainInherentData {
589
11
                relay_storage_proof,
590
11
            }
591
11
        }
592
11
    )
593
11
    .dispatch(inherent_origin()));
594
11
}
595

            
596
150
pub fn empty_genesis_data() -> ContainerChainGenesisData {
597
150
    ContainerChainGenesisData {
598
150
        storage: Default::default(),
599
150
        name: Default::default(),
600
150
        id: Default::default(),
601
150
        fork_id: Default::default(),
602
150
        extensions: Default::default(),
603
150
        properties: Default::default(),
604
150
    }
605
150
}
606

            
607
2397
pub fn current_slot() -> u64 {
608
2397
    u64::from(
609
2397
        pallet_async_backing::SlotInfo::<Runtime>::get()
610
2397
            .unwrap_or_default()
611
2397
            .0,
612
2397
    )
613
2397
}
614

            
615
31
pub fn authorities() -> Vec<NimbusId> {
616
31
    let session_index = Session::current_index();
617
31

            
618
31
    AuthorityAssignment::collator_container_chain(session_index)
619
31
        .expect("authorities should be set")
620
31
        .orchestrator_chain
621
31
}
622

            
623
2282
pub fn current_author() -> AccountId {
624
2282
    let current_session = Session::current_index();
625
2282
    let mapping =
626
2282
        pallet_authority_mapping::Pallet::<Runtime>::authority_id_mapping(current_session)
627
2282
            .expect("there is a mapping for the current session");
628
2282

            
629
2282
    let author = pallet_author_inherent::Author::<Runtime>::get()
630
2282
        .expect("there should be a registered author");
631
2282

            
632
2282
    mapping
633
2282
        .get(&author)
634
2282
        .expect("there is a mapping for the current author")
635
2282
        .clone()
636
2282
}
637

            
638
15
pub fn block_credits_to_required_balance(number_of_blocks: u32, para_id: ParaId) -> Balance {
639
15
    let block_cost = BlockProductionCost::block_cost(&para_id).0;
640
15
    u128::from(number_of_blocks).saturating_mul(block_cost)
641
15
}
642

            
643
4
pub fn collator_assignment_credits_to_required_balance(
644
4
    number_of_sessions: u32,
645
4
    para_id: ParaId,
646
4
) -> Balance {
647
4
    let collator_assignment_cost = CollatorAssignmentCost::collator_assignment_cost(&para_id).0;
648
4
    u128::from(number_of_sessions).saturating_mul(collator_assignment_cost)
649
4
}
650

            
651
pub const ALICE: [u8; 32] = [4u8; 32];
652
pub const BOB: [u8; 32] = [5u8; 32];
653
pub const CHARLIE: [u8; 32] = [6u8; 32];
654
pub const DAVE: [u8; 32] = [7u8; 32];
655
pub const EVE: [u8; 32] = [8u8; 32];
656
pub const FERDIE: [u8; 32] = [9u8; 32];
657

            
658
21
pub fn set_dummy_boot_node(para_manager: RuntimeOrigin, para_id: ParaId) {
659
    use {
660
        pallet_data_preservers::{ParaIdsFilter, Profile, ProfileMode},
661
        tp_data_preservers_common::{AssignerExtra, ProviderRequest},
662
    };
663

            
664
21
    let profile = Profile {
665
21
        url:
666
21
            b"/ip4/127.0.0.1/tcp/33049/ws/p2p/12D3KooWHVMhQDHBpj9vQmssgyfspYecgV6e3hH1dQVDUkUbCYC9"
667
21
                .to_vec()
668
21
                .try_into()
669
21
                .expect("to fit in BoundedVec"),
670
21
        para_ids: ParaIdsFilter::AnyParaId,
671
21
        mode: ProfileMode::Bootnode,
672
21
        assignment_request: ProviderRequest::Free,
673
21
    };
674
21

            
675
21
    let profile_id = pallet_data_preservers::NextProfileId::<Runtime>::get();
676
21
    let profile_owner = AccountId::new([1u8; 32]);
677
21
    DataPreservers::force_create_profile(RuntimeOrigin::root(), profile, profile_owner)
678
21
        .expect("profile create to succeed");
679
21

            
680
21
    DataPreservers::start_assignment(para_manager, profile_id, para_id, AssignerExtra::Free)
681
21
        .expect("assignement to work");
682
21

            
683
21
    assert!(
684
21
        pallet_data_preservers::Assignments::<Runtime>::get(para_id).contains(&profile_id),
685
        "profile should be correctly assigned"
686
    );
687
21
}