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
    alloc::collections::btree_map::BTreeMap,
20
    cumulus_primitives_core::{ParaId, PersistedValidationData},
21
    cumulus_primitives_parachain_inherent::ParachainInherentData,
22
    dp_consensus::runtime_decl_for_tanssi_authority_assignment_api::TanssiAuthorityAssignmentApi,
23
    frame_support::{
24
        assert_ok,
25
        traits::{OnFinalize, OnInitialize},
26
    },
27
    nimbus_primitives::{NimbusId, NIMBUS_ENGINE_ID},
28
    pallet_collator_assignment_runtime_api::runtime_decl_for_collator_assignment_api::CollatorAssignmentApi,
29
    pallet_registrar_runtime_api::ContainerChainGenesisData,
30
    pallet_services_payment::{ProvideBlockProductionCost, ProvideCollatorAssignmentCost},
31
    parity_scale_codec::{Decode, Encode, MaxEncodedLen},
32
    polkadot_parachain_primitives::primitives::HeadData,
33
    sp_consensus_aura::AURA_ENGINE_ID,
34
    sp_consensus_slots::Slot,
35
    sp_core::{Get, Pair},
36
    sp_runtime::{traits::Dispatchable, BuildStorage, Digest, DigestItem},
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
121
pub fn session_to_block(n: u32) -> u32 {
51
121
    let block_number = crate::Period::get() * n;
52
121

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

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

            
64
118
pub fn run_to_session(n: u32) {
65
118
    run_to_block(session_to_block(n));
66
118
}
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
193
pub fn run_to_block(n: u32) -> BTreeMap<u32, RunSummary> {
76
193
    let current_block_number = System::block_number();
77
193
    assert!(
78
193
        current_block_number < n,
79
        "run_to_block called with block {} when current block is {}",
80
        n,
81
        current_block_number
82
    );
83
193
    let mut summaries = BTreeMap::new();
84

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

            
91
193
    summaries
92
193
}
93

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

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

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

            
107
2319
    System::reset_events();
108
2319
    System::initialize(
109
2319
        &(System::block_number() + 1),
110
2319
        &System::parent_hash(),
111
2319
        &pre_digest,
112
2319
    );
113
2319
}
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
2319
fn take_new_inherent_data() -> Option<MockInherentData> {
122
2319
    let data: Option<MockInherentData> =
123
2319
        frame_support::storage::unhashed::take(b"__mock_new_inherent_data");
124
2319

            
125
2319
    data
126
2319
}
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
    Start(u32),
135
    End(u32),
136
}
137

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

            
163
4524
fn advance_block_state_machine(new_state: RunBlockState) {
164
4524
    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
4524
    }
169
4524
    let old_state: RunBlockState =
170
4524
        frame_support::storage::unhashed::get(b"__mock_debug_block_state").unwrap_or(
171
4524
            // Initial state is expecting a call to start() with block number 1, so old state should be
172
4524
            // end of block 0
173
4524
            RunBlockState::End(0),
174
4524
        );
175
4524
    old_state.assert_can_advance(&new_state);
176
4524
    frame_support::storage::unhashed::put(b"__mock_debug_block_state", &new_state);
177
4524
}
178

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

            
189
2319
    let maybe_mock_inherent = take_new_inherent_data();
190

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

            
195
2319
    insert_authorities_and_slot_digests(slot);
196
2319

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

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

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

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

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

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

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

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

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

            
242
2202
    start_block()
243
2202
}
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
117
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
117
    let relay_sproof = RelayStateSproofBuilder {
255
117
        para_id: 100u32.into(),
256
117
        included_para_head: Some(HeadData(vec![1, 2, 3])),
257
117
        current_slot: (current_slot()).into(),
258
117
        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
115
            vec![]
265
        },
266
117
        ..Default::default()
267
117
    };
268
117

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

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

            
290
117
    assert_ok!(RuntimeCall::ParachainSystem(
291
117
        cumulus_pallet_parachain_system::Call::<Runtime>::set_validation_data {
292
117
            data: parachain_inherent_data
293
117
        }
294
117
    )
295
117
    .dispatch(inherent_origin()));
296
117
}
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
115
pub fn default_config() -> pallet_configuration::HostConfiguration {
314
115
    pallet_configuration::HostConfiguration {
315
115
        max_collators: 100,
316
115
        min_orchestrator_collators: 2,
317
115
        max_orchestrator_collators: 2,
318
115
        collators_per_container: 2,
319
115
        full_rotation_period: 24,
320
115
        ..Default::default()
321
115
    }
322
115
}
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
115
    fn default() -> Self {
341
115
        Self {
342
115
            balances: vec![
343
115
                // Alice gets 10k extra tokens for her mapping deposit
344
115
                (AccountId::from(ALICE), 210_000 * UNIT),
345
115
                (AccountId::from(BOB), 100_000 * UNIT),
346
115
            ],
347
115
            collators: vec![
348
115
                (AccountId::from(ALICE), 210 * UNIT),
349
115
                (AccountId::from(BOB), 100 * UNIT),
350
115
            ],
351
115
            sudo: Default::default(),
352
115
            para_ids: Default::default(),
353
115
            config: default_config(),
354
115
            safe_xcm_version: Default::default(),
355
115
            own_para_id: Default::default(),
356
115
        }
357
115
    }
358
}
359

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

            
366
87
    pub fn with_collators(mut self, collators: Vec<(AccountId, Balance)>) -> Self {
367
87
        self.collators = collators;
368
87
        self
369
87
    }
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
60
    pub fn with_empty_parachains(mut self, para_ids: Vec<u32>) -> Self {
384
60
        self.para_ids = para_ids
385
60
            .into_iter()
386
121
            .map(|para_id| ParaRegistrationParams {
387
121
                para_id,
388
121
                genesis_data: empty_genesis_data(),
389
121
                block_production_credits: u32::MAX,
390
121
                collator_assignment_credits: u32::MAX,
391
121
                parathread_params: None,
392
121
            })
393
60
            .collect();
394
60
        self
395
60
    }
396

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

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

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

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

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

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

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

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

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

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

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

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

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

            
521
115
        t
522
115
    }
523

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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