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

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

            
51
pub const UNIT: Balance = 1_000_000_000_000;
52

            
53
266
pub fn session_to_block(n: u32) -> u32 {
54
266
    let block_number = dancebox_runtime::Period::get() * n;
55
266

            
56
266
    // Add 1 because the block that emits the NewSession event cannot contain any extrinsics,
57
266
    // so this is the first block of the new session that can actually be used
58
266
    block_number + 1
59
266
}
60

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

            
67
thread_local! {
68
    static SHOULD_WRITE_SLOT_INFO: Cell<bool> = Cell::new(true);
69
}
70

            
71
24
pub fn set_should_write_slot_info(value: bool) {
72
24
    SHOULD_WRITE_SLOT_INFO.with(|flag| flag.set(value));
73
24
}
74

            
75
5042
fn should_write_slot_info() -> bool {
76
5042
    SHOULD_WRITE_SLOT_INFO.with(|flag| flag.get())
77
5042
}
78

            
79
260
pub fn run_to_session(n: u32) {
80
260
    run_to_block(session_to_block(n));
81
260
}
82

            
83
/// Utility function that advances the chain to the desired block number.
84
///
85
/// After this function returns, the current block number will be `n`, and the block will be "open",
86
/// meaning that on_initialize has been executed, but on_finalize has not. To execute on_finalize as
87
/// well, for example to test a runtime api, manually call `end_block` after this, run the test, and
88
/// call `start_block` to ensure that this function keeps working as expected.
89
/// Extrinsics should always be executed before on_finalize.
90
410
pub fn run_to_block(n: u32) -> BTreeMap<u32, RunSummary> {
91
410
    let current_block_number = System::block_number();
92
410
    assert!(
93
410
        current_block_number < n,
94
        "run_to_block called with block {} when current block is {}",
95
        n,
96
        current_block_number
97
    );
98
410
    let mut summaries = BTreeMap::new();
99

            
100
5102
    while System::block_number() < n {
101
4692
        let summary = run_block();
102
4692
        let block_number = System::block_number();
103
4692
        summaries.insert(block_number, summary);
104
4692
    }
105

            
106
410
    summaries
107
410
}
108

            
109
5042
pub fn insert_authorities_and_slot_digests(slot: u64) {
110
5042
    let authorities =
111
5042
        Runtime::para_id_authorities(ParachainInfo::get()).expect("authorities should be set");
112
5042

            
113
5042
    let authority: NimbusId = authorities[slot as usize % authorities.len()].clone();
114
5042

            
115
5042
    let pre_digest = Digest {
116
5042
        logs: vec![
117
5042
            DigestItem::PreRuntime(AURA_ENGINE_ID, slot.encode()),
118
5042
            DigestItem::PreRuntime(NIMBUS_ENGINE_ID, authority.encode()),
119
5042
        ],
120
5042
    };
121
5042

            
122
5042
    System::reset_events();
123
5042
    System::initialize(
124
5042
        &(System::block_number() + 1),
125
5042
        &System::parent_hash(),
126
5042
        &pre_digest,
127
5042
    );
128
5042
}
129

            
130
// Used to create the next block inherent data
131
#[derive(Clone, Encode, Decode, Default, PartialEq, Debug, scale_info::TypeInfo, MaxEncodedLen)]
132
pub struct MockInherentData {
133
    pub random_seed: Option<[u8; 32]>,
134
}
135

            
136
5042
fn take_new_inherent_data() -> Option<MockInherentData> {
137
5042
    let data: Option<MockInherentData> =
138
5042
        frame_support::storage::unhashed::take(b"__mock_new_inherent_data");
139
5042

            
140
5042
    data
141
5042
}
142

            
143
4
fn set_new_inherent_data(data: MockInherentData) {
144
4
    frame_support::storage::unhashed::put(b"__mock_new_inherent_data", &Some(data));
145
4
}
146

            
147
#[derive(Clone, Encode, Decode, PartialEq, Debug, scale_info::TypeInfo, MaxEncodedLen)]
148
enum RunBlockState {
149
    Start(u32),
150
    End(u32),
151
}
152

            
153
impl RunBlockState {
154
9048
    fn assert_can_advance(&self, new_state: &RunBlockState) {
155
9048
        match self {
156
4410
            RunBlockState::Start(n) => {
157
4410
                assert_eq!(
158
4410
                    new_state,
159
4410
                    &RunBlockState::End(*n),
160
                    "expected a call to end_block({}), but user called {:?}",
161
                    *n,
162
                    new_state
163
                );
164
            }
165
4638
            RunBlockState::End(n) => {
166
4638
                assert_eq!(
167
4638
                    new_state,
168
4638
                    &RunBlockState::Start(*n + 1),
169
                    "expected a call to start_block({}), but user called {:?}",
170
                    *n + 1,
171
                    new_state
172
                )
173
            }
174
        }
175
9048
    }
176
}
177

            
178
9856
fn advance_block_state_machine(new_state: RunBlockState) {
179
9856
    if frame_support::storage::unhashed::exists(b"__mock_is_xcm_test") {
180
        // Disable this check in XCM tests, because the XCM emulator runs on_initialize and
181
        // on_finalize automatically
182
808
        return;
183
9048
    }
184
9048
    let old_state: RunBlockState =
185
9048
        frame_support::storage::unhashed::get(b"__mock_debug_block_state").unwrap_or(
186
9048
            // Initial state is expecting a call to start() with block number 1, so old state should be
187
9048
            // end of block 0
188
9048
            RunBlockState::End(0),
189
9048
        );
190
9048
    old_state.assert_can_advance(&new_state);
191
9048
    frame_support::storage::unhashed::put(b"__mock_debug_block_state", &new_state);
192
9856
}
193

            
194
5042
pub fn start_block() -> RunSummary {
195
5042
    let block_number = System::block_number();
196
5042
    advance_block_state_machine(RunBlockState::Start(block_number + 1));
197
5042
    let mut slot = current_slot() + 1;
198
5042
    if block_number == 0 {
199
230
        // Hack to avoid breaking all tests. When the current block is 1, the slot number should be
200
230
        // 1. But all of our tests assume it will be 0. So use slot number = block_number - 1.
201
230
        slot = 0;
202
4812
    }
203

            
204
5042
    let maybe_mock_inherent = take_new_inherent_data();
205

            
206
5042
    if let Some(mock_inherent_data) = maybe_mock_inherent {
207
4
        set_parachain_inherent_data(mock_inherent_data);
208
5038
    }
209

            
210
5042
    insert_authorities_and_slot_digests(slot);
211
5042

            
212
5042
    // Initialize the new block
213
5042
    CollatorAssignment::on_initialize(System::block_number());
214
5042
    Session::on_initialize(System::block_number());
215
5042
    Initializer::on_initialize(System::block_number());
216
5042
    AuthorInherent::on_initialize(System::block_number());
217
5042

            
218
5042
    // `Initializer::on_finalize` needs to run at least one to have
219
5042
    // author mapping setup.
220
5042
    let author_id = current_author();
221
5042

            
222
5042
    let current_issuance = Balances::total_issuance();
223
5042
    InflationRewards::on_initialize(System::block_number());
224
5042
    let new_issuance = Balances::total_issuance();
225
5042

            
226
5042
    if should_write_slot_info() {
227
4638
        frame_support::storage::unhashed::put(
228
4638
            &frame_support::storage::storage_prefix(b"AsyncBacking", b"SlotInfo"),
229
4638
            &(Slot::from(slot), 1),
230
4638
        );
231
4638
    }
232

            
233
5042
    pallet_author_inherent::Pallet::<Runtime>::kick_off_authorship_validation(None.into())
234
5042
        .expect("author inherent to dispatch correctly");
235
5042

            
236
5042
    InactivityTracking::on_initialize(System::block_number());
237
5042

            
238
5042
    RunSummary {
239
5042
        author_id,
240
5042
        inflation: new_issuance - current_issuance,
241
5042
    }
242
5042
}
243

            
244
4814
pub fn end_block() {
245
4814
    let block_number = System::block_number();
246
4814
    advance_block_state_machine(RunBlockState::End(block_number));
247
4814
    // Finalize the block
248
4814
    CollatorAssignment::on_finalize(System::block_number());
249
4814
    Session::on_finalize(System::block_number());
250
4814
    Initializer::on_finalize(System::block_number());
251
4814
    AuthorInherent::on_finalize(System::block_number());
252
4814
    TransactionPayment::on_finalize(System::block_number());
253
4814
    InactivityTracking::on_finalize(System::block_number());
254
4814
}
255

            
256
4808
pub fn run_block() -> RunSummary {
257
4808
    end_block();
258
4808

            
259
4808
    start_block()
260
4808
}
261

            
262
/// Mock the inherent that sets validation data in ParachainSystem, which
263
/// contains the `relay_chain_block_number`, which is used in `collator-assignment` as a
264
/// source of randomness.
265
234
pub fn set_parachain_inherent_data(mock_inherent_data: MockInherentData) {
266
    use {
267
        cumulus_primitives_core::relay_chain::well_known_keys,
268
        cumulus_test_relay_sproof_builder::RelayStateSproofBuilder,
269
    };
270

            
271
234
    let relay_sproof = RelayStateSproofBuilder {
272
234
        para_id: 100u32.into(),
273
234
        included_para_head: Some(HeadData(vec![1, 2, 3])),
274
234
        current_slot: (current_slot()).into(),
275
234
        additional_key_values: if mock_inherent_data.random_seed.is_some() {
276
4
            vec![(
277
4
                well_known_keys::CURRENT_BLOCK_RANDOMNESS.to_vec(),
278
4
                Some(mock_inherent_data.random_seed).encode(),
279
4
            )]
280
        } else {
281
230
            vec![]
282
        },
283
234
        ..Default::default()
284
234
    };
285
234

            
286
234
    let (relay_parent_storage_root, relay_chain_state) = relay_sproof.into_state_root_and_proof();
287
234
    let vfp = PersistedValidationData {
288
234
        relay_parent_number: 1u32,
289
234
        relay_parent_storage_root,
290
234
        ..Default::default()
291
234
    };
292
234
    let parachain_inherent_data = ParachainInherentData {
293
234
        validation_data: vfp,
294
234
        relay_chain_state,
295
234
        downward_messages: Default::default(),
296
234
        horizontal_messages: Default::default(),
297
234
    };
298
234

            
299
234
    // Delete existing flag to avoid error
300
234
    // 'ValidationData must be updated only once in a block'
301
234
    // TODO: this is a hack
302
234
    frame_support::storage::unhashed::kill(&frame_support::storage::storage_prefix(
303
234
        b"ParachainSystem",
304
234
        b"ValidationData",
305
234
    ));
306
234

            
307
234
    assert_ok!(RuntimeCall::ParachainSystem(
308
234
        cumulus_pallet_parachain_system::Call::<Runtime>::set_validation_data {
309
234
            data: parachain_inherent_data
310
234
        }
311
234
    )
312
234
    .dispatch(inherent_origin()));
313
234
}
314

            
315
4
pub fn set_parachain_inherent_data_random_seed(random_seed: [u8; 32]) {
316
4
    set_new_inherent_data(MockInherentData {
317
4
        random_seed: Some(random_seed),
318
4
    });
319
4
}
320

            
321
#[derive(Default, Clone)]
322
pub struct ParaRegistrationParams {
323
    pub para_id: u32,
324
    pub genesis_data: ContainerChainGenesisData,
325
    pub block_production_credits: u32,
326
    pub collator_assignment_credits: u32,
327
    pub parathread_params: Option<tp_traits::ParathreadParams>,
328
}
329

            
330
230
pub fn default_config() -> pallet_configuration::HostConfiguration {
331
230
    pallet_configuration::HostConfiguration {
332
230
        max_collators: 100,
333
230
        min_orchestrator_collators: 2,
334
230
        max_orchestrator_collators: 2,
335
230
        collators_per_container: 2,
336
230
        full_rotation_period: 24,
337
230
        ..Default::default()
338
230
    }
339
230
}
340

            
341
pub struct ExtBuilder {
342
    // endowed accounts with balances
343
    balances: Vec<(AccountId, Balance)>,
344
    // [collator, amount]
345
    collators: Vec<(AccountId, Balance)>,
346
    // sudo key
347
    sudo: Option<AccountId>,
348
    // list of registered para ids: para_id, genesis_data, boot_nodes, block_credits, session_credits
349
    para_ids: Vec<ParaRegistrationParams>,
350
    // configuration to apply
351
    config: pallet_configuration::HostConfiguration,
352
    safe_xcm_version: Option<u32>,
353
    own_para_id: Option<ParaId>,
354
}
355

            
356
impl Default for ExtBuilder {
357
230
    fn default() -> Self {
358
230
        Self {
359
230
            balances: vec![
360
230
                // Alice gets 10k extra tokens for her mapping deposit
361
230
                (AccountId::from(ALICE), 210_000 * UNIT),
362
230
                (AccountId::from(BOB), 100_000 * UNIT),
363
230
            ],
364
230
            collators: vec![
365
230
                (AccountId::from(ALICE), 210 * UNIT),
366
230
                (AccountId::from(BOB), 100 * UNIT),
367
230
            ],
368
230
            sudo: Default::default(),
369
230
            para_ids: Default::default(),
370
230
            config: default_config(),
371
230
            safe_xcm_version: Default::default(),
372
230
            own_para_id: Default::default(),
373
230
        }
374
230
    }
375
}
376

            
377
impl ExtBuilder {
378
190
    pub fn with_balances(mut self, balances: Vec<(AccountId, Balance)>) -> Self {
379
190
        self.balances = balances;
380
190
        self
381
190
    }
382

            
383
174
    pub fn with_collators(mut self, collators: Vec<(AccountId, Balance)>) -> Self {
384
174
        self.collators = collators;
385
174
        self
386
174
    }
387

            
388
8
    pub fn with_sudo(mut self, sudo: AccountId) -> Self {
389
8
        self.sudo = Some(sudo);
390
8
        self
391
8
    }
392

            
393
8
    pub fn with_para_ids(mut self, para_ids: Vec<ParaRegistrationParams>) -> Self {
394
8
        self.para_ids = para_ids;
395
8
        self
396
8
    }
397

            
398
    /// Helper function like `with_para_ids` but registering parachains with an empty genesis data,
399
    /// and max amount of credits.
400
120
    pub fn with_empty_parachains(mut self, para_ids: Vec<u32>) -> Self {
401
120
        self.para_ids = para_ids
402
120
            .into_iter()
403
242
            .map(|para_id| ParaRegistrationParams {
404
242
                para_id,
405
242
                genesis_data: empty_genesis_data(),
406
242
                block_production_credits: u32::MAX,
407
242
                collator_assignment_credits: u32::MAX,
408
242
                parathread_params: None,
409
242
            })
410
120
            .collect();
411
120
        self
412
120
    }
413

            
414
10
    pub fn with_config(mut self, config: pallet_configuration::HostConfiguration) -> Self {
415
10
        self.config = config;
416
10
        self
417
10
    }
418

            
419
230
    pub fn build_storage(self) -> sp_core::storage::Storage {
420
230
        let mut t = frame_system::GenesisConfig::<Runtime>::default()
421
230
            .build_storage()
422
230
            .unwrap();
423
230

            
424
230
        pallet_balances::GenesisConfig::<Runtime> {
425
230
            balances: self.balances,
426
230
            ..Default::default()
427
230
        }
428
230
        .assimilate_storage(&mut t)
429
230
        .unwrap();
430
230

            
431
230
        // We need to initialize these pallets first. When initializing pallet-session,
432
230
        // these values will be taken into account for collator-assignment.
433
230

            
434
230
        pallet_registrar::GenesisConfig::<Runtime> {
435
230
            para_ids: self
436
230
                .para_ids
437
230
                .iter()
438
230
                .cloned()
439
256
                .map(|registered_para| {
440
256
                    (
441
256
                        registered_para.para_id.into(),
442
256
                        registered_para.genesis_data,
443
256
                        registered_para.parathread_params,
444
256
                    )
445
256
                })
446
230
                .collect(),
447
230
            phantom: Default::default(),
448
230
        }
449
230
        .assimilate_storage(&mut t)
450
230
        .unwrap();
451
230

            
452
230
        pallet_services_payment::GenesisConfig::<Runtime> {
453
230
            para_id_credits: self
454
230
                .para_ids
455
230
                .clone()
456
230
                .into_iter()
457
256
                .map(|registered_para| {
458
256
                    (
459
256
                        registered_para.para_id.into(),
460
256
                        registered_para.block_production_credits,
461
256
                        registered_para.collator_assignment_credits,
462
256
                    )
463
256
                        .into()
464
256
                })
465
230
                .collect(),
466
230
        }
467
230
        .assimilate_storage(&mut t)
468
230
        .unwrap();
469
230

            
470
230
        pallet_configuration::GenesisConfig::<Runtime> {
471
230
            config: self.config,
472
230
            ..Default::default()
473
230
        }
474
230
        .assimilate_storage(&mut t)
475
230
        .unwrap();
476
230

            
477
230
        pallet_xcm::GenesisConfig::<Runtime> {
478
230
            safe_xcm_version: self.safe_xcm_version,
479
230
            ..Default::default()
480
230
        }
481
230
        .assimilate_storage(&mut t)
482
230
        .unwrap();
483

            
484
230
        if let Some(own_para_id) = self.own_para_id {
485
            parachain_info::GenesisConfig::<Runtime> {
486
                parachain_id: own_para_id,
487
                ..Default::default()
488
            }
489
            .assimilate_storage(&mut t)
490
            .unwrap();
491
230
        }
492

            
493
230
        if !self.collators.is_empty() {
494
230
            // We set invulnerables in pallet_invulnerables
495
230
            let invulnerables: Vec<AccountId> = self
496
230
                .collators
497
230
                .clone()
498
230
                .into_iter()
499
770
                .map(|(account, _balance)| account)
500
230
                .collect();
501
230

            
502
230
            pallet_invulnerables::GenesisConfig::<Runtime> {
503
230
                invulnerables: invulnerables.clone(),
504
230
            }
505
230
            .assimilate_storage(&mut t)
506
230
            .unwrap();
507
230

            
508
230
            // But we also initialize their keys in the session pallet
509
230
            let keys: Vec<_> = self
510
230
                .collators
511
230
                .into_iter()
512
770
                .map(|(account, _balance)| {
513
770
                    let nimbus_id = get_aura_id_from_seed(&account.to_string());
514
770
                    (
515
770
                        account.clone(),
516
770
                        account,
517
770
                        dancebox_runtime::SessionKeys { nimbus: nimbus_id },
518
770
                    )
519
770
                })
520
230
                .collect();
521
230
            pallet_session::GenesisConfig::<Runtime> {
522
230
                keys,
523
230
                ..Default::default()
524
230
            }
525
230
            .assimilate_storage(&mut t)
526
230
            .unwrap();
527
230
        }
528
230
        pallet_sudo::GenesisConfig::<Runtime> { key: self.sudo }
529
230
            .assimilate_storage(&mut t)
530
230
            .unwrap();
531
230

            
532
230
        if self.safe_xcm_version.is_some() {
533
            // Disable run_block checks in XCM tests, because the XCM emulator runs on_initialize and
534
            // on_finalize automatically
535
            t.top.insert(b"__mock_is_xcm_test".to_vec(), b"1".to_vec());
536
230
        }
537

            
538
230
        t
539
230
    }
540

            
541
230
    pub fn build(self) -> sp_io::TestExternalities {
542
230
        let t = self.build_storage();
543
230
        let mut ext = sp_io::TestExternalities::new(t);
544
230

            
545
230
        ext.execute_with(|| {
546
230
            // Start block 1
547
230
            start_block();
548
230
            set_parachain_inherent_data(Default::default());
549
230
        });
550
230
        ext
551
230
    }
552
}
553

            
554
182
pub fn root_origin() -> <Runtime as frame_system::Config>::RuntimeOrigin {
555
182
    <Runtime as frame_system::Config>::RuntimeOrigin::root()
556
182
}
557

            
558
420
pub fn origin_of(account_id: AccountId) -> <Runtime as frame_system::Config>::RuntimeOrigin {
559
420
    <Runtime as frame_system::Config>::RuntimeOrigin::signed(account_id)
560
420
}
561

            
562
256
pub fn inherent_origin() -> <Runtime as frame_system::Config>::RuntimeOrigin {
563
256
    <Runtime as frame_system::Config>::RuntimeOrigin::none()
564
256
}
565

            
566
/// Helper function to generate a crypto pair from seed
567
932
pub fn get_aura_id_from_seed(seed: &str) -> NimbusId {
568
932
    sp_core::sr25519::Pair::from_string(&format!("//{}", seed), None)
569
932
        .expect("static values are valid; qed")
570
932
        .public()
571
932
        .into()
572
932
}
573

            
574
8
pub fn get_orchestrator_current_author() -> Option<AccountId> {
575
8
    let slot: u64 = current_slot();
576
8
    let orchestrator_collators = Runtime::parachain_collators(ParachainInfo::get())?;
577
8
    let author_index = slot % orchestrator_collators.len() as u64;
578
8
    let account = orchestrator_collators.get(author_index as usize)?;
579
8
    Some(account.clone())
580
8
}
581
/// Mocks the author noting inherent to insert the data we
582
22
pub fn set_author_noting_inherent_data(builder: ParaHeaderSproofBuilder) {
583
22
    let (relay_storage_root, relay_storage_proof) = builder.into_state_root_and_proof();
584
22

            
585
22
    // For now we directly touch parachain_system storage to set the relay state root.
586
22
    // TODO: Properly set the parachain_system inherent, which require a sproof builder combining
587
22
    // what is required by parachain_system and author_noting.
588
22
    frame_support::storage::unhashed::put(
589
22
        &frame_support::storage::storage_prefix(b"ParachainSystem", b"ValidationData"),
590
22
        &PersistedValidationData {
591
22
            parent_head: HeadData(Default::default()),
592
22
            relay_parent_number: 0u32,
593
22
            relay_parent_storage_root: relay_storage_root,
594
22
            max_pov_size: 0u32,
595
22
        },
596
22
    );
597
22

            
598
22
    // But we also need to store the new proof submitted
599
22
    frame_support::storage::unhashed::put(
600
22
        &frame_support::storage::storage_prefix(b"ParachainSystem", b"RelayStateProof"),
601
22
        &relay_storage_proof,
602
22
    );
603
22

            
604
22
    assert_ok!(RuntimeCall::AuthorNoting(
605
22
        pallet_author_noting::Call::<Runtime>::set_latest_author_data {
606
22
            data: tp_author_noting_inherent::OwnParachainInherentData {
607
22
                relay_storage_proof,
608
22
            }
609
22
        }
610
22
    )
611
22
    .dispatch(inherent_origin()));
612
22
}
613

            
614
332
pub fn empty_genesis_data() -> ContainerChainGenesisData {
615
332
    ContainerChainGenesisData {
616
332
        storage: Default::default(),
617
332
        name: Default::default(),
618
332
        id: Default::default(),
619
332
        fork_id: Default::default(),
620
332
        extensions: Default::default(),
621
332
        properties: Default::default(),
622
332
    }
623
332
}
624

            
625
5330
pub fn current_slot() -> u64 {
626
5330
    u64::from(
627
5330
        pallet_async_backing::SlotInfo::<Runtime>::get()
628
5330
            .unwrap_or_default()
629
5330
            .0,
630
5330
    )
631
5330
}
632

            
633
62
pub fn authorities() -> Vec<NimbusId> {
634
62
    let session_index = Session::current_index();
635
62

            
636
62
    AuthorityAssignment::collator_container_chain(session_index)
637
62
        .expect("authorities should be set")
638
62
        .orchestrator_chain
639
62
}
640

            
641
5096
pub fn current_author() -> AccountId {
642
5096
    let current_session = Session::current_index();
643
5096
    let mapping =
644
5096
        pallet_authority_mapping::Pallet::<Runtime>::authority_id_mapping(current_session)
645
5096
            .expect("there is a mapping for the current session");
646
5096

            
647
5096
    let author = pallet_author_inherent::Author::<Runtime>::get()
648
5096
        .expect("there should be a registered author");
649
5096

            
650
5096
    mapping
651
5096
        .get(&author)
652
5096
        .expect("there is a mapping for the current author")
653
5096
        .clone()
654
5096
}
655

            
656
30
pub fn block_credits_to_required_balance(number_of_blocks: u32, para_id: ParaId) -> Balance {
657
30
    let block_cost = BlockProductionCost::block_cost(&para_id).0;
658
30
    u128::from(number_of_blocks).saturating_mul(block_cost)
659
30
}
660

            
661
8
pub fn collator_assignment_credits_to_required_balance(
662
8
    number_of_sessions: u32,
663
8
    para_id: ParaId,
664
8
) -> Balance {
665
8
    let collator_assignment_cost = CollatorAssignmentCost::collator_assignment_cost(&para_id).0;
666
8
    u128::from(number_of_sessions).saturating_mul(collator_assignment_cost)
667
8
}
668

            
669
pub const ALICE: [u8; 32] = [4u8; 32];
670
pub const BOB: [u8; 32] = [5u8; 32];
671
pub const CHARLIE: [u8; 32] = [6u8; 32];
672
pub const DAVE: [u8; 32] = [7u8; 32];
673
pub const EVE: [u8; 32] = [8u8; 32];
674
pub const FERDIE: [u8; 32] = [9u8; 32];
675

            
676
66
pub fn set_dummy_boot_node(para_manager: RuntimeOrigin, para_id: ParaId) {
677
    use {
678
        pallet_data_preservers::{ParaIdsFilter, Profile, ProfileMode},
679
        tp_data_preservers_common::{AssignerExtra, ProviderRequest},
680
    };
681

            
682
66
    let profile = Profile {
683
66
        url:
684
66
            b"/ip4/127.0.0.1/tcp/33049/ws/p2p/12D3KooWHVMhQDHBpj9vQmssgyfspYecgV6e3hH1dQVDUkUbCYC9"
685
66
                .to_vec()
686
66
                .try_into()
687
66
                .expect("to fit in BoundedVec"),
688
66
        para_ids: ParaIdsFilter::AnyParaId,
689
66
        mode: ProfileMode::Bootnode,
690
66
        assignment_request: ProviderRequest::Free,
691
66
    };
692
66

            
693
66
    let profile_id = pallet_data_preservers::NextProfileId::<Runtime>::get();
694
66
    let profile_owner = AccountId::new([1u8; 32]);
695
66
    DataPreservers::force_create_profile(RuntimeOrigin::root(), profile, profile_owner)
696
66
        .expect("profile create to succeed");
697
66

            
698
66
    DataPreservers::start_assignment(para_manager, profile_id, para_id, AssignerExtra::Free)
699
66
        .expect("assignement to work");
700
66

            
701
66
    assert!(
702
66
        pallet_data_preservers::Assignments::<Runtime>::get(para_id).contains(&profile_id),
703
        "profile should be correctly assigned"
704
    );
705
66
}