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
    InflationRewards, Initializer, Invulnerables, MinimumSelfDelegation, ParachainInfo,
44
    PooledStaking, Proxy, ProxyType, Registrar, RewardsPortion, Runtime, RuntimeCall,
45
    ServicesPayment, Session, System, TransactionPayment,
46
};
47

            
48
mod xcm;
49

            
50
pub const UNIT: Balance = 1_000_000_000_000_000_000;
51

            
52
118
pub fn session_to_block(n: u32) -> u32 {
53
118
    let block_number = crate::Period::get() * n;
54
118

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

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

            
66
116
pub fn run_to_session(n: u32) {
67
116
    run_to_block(session_to_block(n));
68
116
}
69

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

            
87
2296
    while System::block_number() < n {
88
2105
        let summary = run_block();
89
2105
        let block_number = System::block_number();
90
2105
        summaries.insert(block_number, summary);
91
2105
    }
92

            
93
191
    summaries
94
191
}
95

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

            
100
2236
    let authority: NimbusId = authorities[slot as usize % authorities.len()].clone();
101
2236

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

            
109
2236
    System::reset_events();
110
2236
    System::initialize(
111
2236
        &(System::block_number() + 1),
112
2236
        &System::parent_hash(),
113
2236
        &pre_digest,
114
2236
    );
115
2236
}
116

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

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

            
127
2236
    data
128
2236
}
129

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

            
134
#[derive(Clone, Encode, Decode, PartialEq, Debug, scale_info::TypeInfo, MaxEncodedLen)]
135
enum RunBlockState {
136
1932
    Start(u32),
137
1931
    End(u32),
138
}
139

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

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

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

            
191
2236
    let maybe_mock_inherent = take_new_inherent_data();
192

            
193
2236
    if let Some(mock_inherent_data) = maybe_mock_inherent {
194
2
        set_parachain_inherent_data(mock_inherent_data);
195
2234
    }
196

            
197
2236
    insert_authorities_and_slot_digests(slot);
198
2236

            
199
2236
    // Initialize the new block
200
2236
    CollatorAssignment::on_initialize(System::block_number());
201
2236
    Session::on_initialize(System::block_number());
202
2236
    Initializer::on_initialize(System::block_number());
203
2236
    AuthorInherent::on_initialize(System::block_number());
204
2236

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

            
209
2236
    let current_issuance = Balances::total_issuance();
210
2236
    InflationRewards::on_initialize(System::block_number());
211
2236
    let new_issuance = Balances::total_issuance();
212
2236

            
213
2236
    frame_support::storage::unhashed::put(
214
2236
        &frame_support::storage::storage_prefix(b"AsyncBacking", b"SlotInfo"),
215
2236
        &(Slot::from(slot), 1),
216
2236
    );
217
2236

            
218
2236
    pallet_author_inherent::Pallet::<Runtime>::kick_off_authorship_validation(None.into())
219
2236
        .expect("author inherent to dispatch correctly");
220
2236

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

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

            
238
2119
pub fn run_block() -> RunSummary {
239
2119
    end_block();
240
2119

            
241
2119
    start_block()
242
2119
}
243

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            
401
88
    pub fn with_safe_xcm_version(mut self, safe_xcm_version: u32) -> Self {
402
88
        self.safe_xcm_version = Some(safe_xcm_version);
403
88
        self
404
88
    }
405

            
406
88
    pub fn with_own_para_id(mut self, own_para_id: ParaId) -> Self {
407
88
        self.own_para_id = Some(own_para_id);
408
88
        self
409
88
    }
410

            
411
191
    pub fn build_storage(self) -> sp_core::storage::Storage {
412
191
        let mut t = frame_system::GenesisConfig::<Runtime>::default()
413
191
            .build_storage()
414
191
            .unwrap();
415
191

            
416
191
        pallet_balances::GenesisConfig::<Runtime> {
417
191
            balances: self.balances,
418
191
        }
419
191
        .assimilate_storage(&mut t)
420
191
        .unwrap();
421
191

            
422
191
        // We need to initialize these pallets first. When initializing pallet-session,
423
191
        // these values will be taken into account for collator-assignment.
424
191

            
425
191
        pallet_registrar::GenesisConfig::<Runtime> {
426
191
            para_ids: self
427
191
                .para_ids
428
191
                .iter()
429
191
                .cloned()
430
191
                .map(|registered_para| {
431
115
                    (
432
115
                        registered_para.para_id.into(),
433
115
                        registered_para.genesis_data,
434
115
                        registered_para.parathread_params,
435
115
                    )
436
191
                })
437
191
                .collect(),
438
191
            phantom: Default::default(),
439
191
        }
440
191
        .assimilate_storage(&mut t)
441
191
        .unwrap();
442
191

            
443
191
        pallet_services_payment::GenesisConfig::<Runtime> {
444
191
            para_id_credits: self
445
191
                .para_ids
446
191
                .clone()
447
191
                .into_iter()
448
191
                .map(|registered_para| {
449
115
                    (
450
115
                        registered_para.para_id.into(),
451
115
                        registered_para.block_production_credits,
452
115
                        registered_para.collator_assignment_credits,
453
115
                    )
454
115
                        .into()
455
191
                })
456
191
                .collect(),
457
191
        }
458
191
        .assimilate_storage(&mut t)
459
191
        .unwrap();
460
191

            
461
191
        pallet_configuration::GenesisConfig::<Runtime> {
462
191
            config: self.config,
463
191
            ..Default::default()
464
191
        }
465
191
        .assimilate_storage(&mut t)
466
191
        .unwrap();
467
191

            
468
191
        pallet_xcm::GenesisConfig::<Runtime> {
469
191
            safe_xcm_version: self.safe_xcm_version,
470
191
            ..Default::default()
471
191
        }
472
191
        .assimilate_storage(&mut t)
473
191
        .unwrap();
474

            
475
191
        if let Some(own_para_id) = self.own_para_id {
476
88
            parachain_info::GenesisConfig::<Runtime> {
477
88
                parachain_id: own_para_id,
478
88
                ..Default::default()
479
88
            }
480
88
            .assimilate_storage(&mut t)
481
88
            .unwrap();
482
103
        }
483

            
484
191
        if !self.collators.is_empty() {
485
191
            // We set invulnerables in pallet_invulnerables
486
191
            let invulnerables: Vec<AccountId> = self
487
191
                .collators
488
191
                .clone()
489
191
                .into_iter()
490
505
                .map(|(account, _balance)| account)
491
191
                .collect();
492
191

            
493
191
            pallet_invulnerables::GenesisConfig::<Runtime> {
494
191
                invulnerables: invulnerables.clone(),
495
191
            }
496
191
            .assimilate_storage(&mut t)
497
191
            .unwrap();
498
191

            
499
191
            // But we also initialize their keys in the session pallet
500
191
            let keys: Vec<_> = self
501
191
                .collators
502
191
                .into_iter()
503
505
                .map(|(account, _balance)| {
504
505
                    let nimbus_id = get_aura_id_from_seed(&account.to_string());
505
505
                    (
506
505
                        account.clone(),
507
505
                        account,
508
505
                        crate::SessionKeys { nimbus: nimbus_id },
509
505
                    )
510
505
                })
511
191
                .collect();
512
191
            pallet_session::GenesisConfig::<Runtime> {
513
191
                keys,
514
191
                ..Default::default()
515
191
            }
516
191
            .assimilate_storage(&mut t)
517
191
            .unwrap();
518
191
        }
519
191
        pallet_sudo::GenesisConfig::<Runtime> { key: self.sudo }
520
191
            .assimilate_storage(&mut t)
521
191
            .unwrap();
522
191

            
523
191
        if self.safe_xcm_version.is_some() {
524
88
            // Disable run_block checks in XCM tests, because the XCM emulator runs on_initialize and
525
88
            // on_finalize automatically
526
88
            t.top.insert(b"__mock_is_xcm_test".to_vec(), b"1".to_vec());
527
103
        }
528

            
529
191
        t
530
191
    }
531

            
532
103
    pub fn build(self) -> sp_io::TestExternalities {
533
103
        let t = self.build_storage();
534
103
        let mut ext = sp_io::TestExternalities::new(t);
535
103

            
536
103
        ext.execute_with(|| {
537
103
            // Start block 1
538
103
            start_block();
539
103
            set_parachain_inherent_data(Default::default());
540
103
        });
541
103
        ext
542
103
    }
543
}
544

            
545
85
pub fn root_origin() -> <Runtime as frame_system::Config>::RuntimeOrigin {
546
85
    <Runtime as frame_system::Config>::RuntimeOrigin::root()
547
85
}
548

            
549
197
pub fn origin_of(account_id: AccountId) -> <Runtime as frame_system::Config>::RuntimeOrigin {
550
197
    <Runtime as frame_system::Config>::RuntimeOrigin::signed(account_id)
551
197
}
552

            
553
113
pub fn inherent_origin() -> <Runtime as frame_system::Config>::RuntimeOrigin {
554
113
    <Runtime as frame_system::Config>::RuntimeOrigin::none()
555
113
}
556

            
557
/// Helper function to generate a crypto pair from seed
558
586
pub fn get_aura_id_from_seed(seed: &str) -> NimbusId {
559
586
    sp_core::sr25519::Pair::from_string(&format!("//{}", seed), None)
560
586
        .expect("static values are valid; qed")
561
586
        .public()
562
586
        .into()
563
586
}
564

            
565
4
pub fn get_orchestrator_current_author() -> Option<AccountId> {
566
4
    let slot: u64 = current_slot();
567
4
    let orchestrator_collators = Runtime::parachain_collators(ParachainInfo::get())?;
568
4
    let author_index = slot % orchestrator_collators.len() as u64;
569
4
    let account = orchestrator_collators.get(author_index as usize)?;
570
4
    Some(account.clone())
571
4
}
572
/// Mocks the author noting inherent to insert the data we
573
8
pub fn set_author_noting_inherent_data(builder: ParaHeaderSproofBuilder) {
574
8
    let (relay_storage_root, relay_storage_proof) = builder.into_state_root_and_proof();
575
8

            
576
8
    // For now we directly touch parachain_system storage to set the relay state root.
577
8
    // TODO: Properly set the parachain_system inherent, which require a sproof builder combining
578
8
    // what is required by parachain_system and author_noting.
579
8
    frame_support::storage::unhashed::put(
580
8
        &frame_support::storage::storage_prefix(b"ParachainSystem", b"ValidationData"),
581
8
        &PersistedValidationData {
582
8
            parent_head: HeadData(Default::default()),
583
8
            relay_parent_number: 0u32,
584
8
            relay_parent_storage_root: relay_storage_root,
585
8
            max_pov_size: 0u32,
586
8
        },
587
8
    );
588
8

            
589
8
    // But we also need to store the new proof submitted
590
8
    frame_support::storage::unhashed::put(
591
8
        &frame_support::storage::storage_prefix(b"ParachainSystem", b"RelayStateProof"),
592
8
        &relay_storage_proof,
593
8
    );
594
8

            
595
8
    assert_ok!(RuntimeCall::AuthorNoting(
596
8
        pallet_author_noting::Call::<Runtime>::set_latest_author_data {
597
8
            data: tp_author_noting_inherent::OwnParachainInherentData {
598
8
                relay_storage_proof,
599
8
            }
600
8
        }
601
8
    )
602
8
    .dispatch(inherent_origin()));
603
8
}
604

            
605
151
pub fn empty_genesis_data() -> ContainerChainGenesisData {
606
151
    ContainerChainGenesisData {
607
151
        storage: Default::default(),
608
151
        name: Default::default(),
609
151
        id: Default::default(),
610
151
        fork_id: Default::default(),
611
151
        extensions: Default::default(),
612
151
        properties: Default::default(),
613
151
    }
614
151
}
615

            
616
2368
pub fn current_slot() -> u64 {
617
2368
    u64::from(
618
2368
        pallet_async_backing::SlotInfo::<Runtime>::get()
619
2368
            .unwrap_or_default()
620
2368
            .0,
621
2368
    )
622
2368
}
623

            
624
31
pub fn authorities() -> Vec<NimbusId> {
625
31
    let session_index = Session::current_index();
626
31

            
627
31
    AuthorityAssignment::collator_container_chain(session_index)
628
31
        .expect("authorities should be set")
629
31
        .orchestrator_chain
630
31
}
631

            
632
2263
pub fn current_author() -> AccountId {
633
2263
    let current_session = Session::current_index();
634
2263
    let mapping =
635
2263
        pallet_authority_mapping::Pallet::<Runtime>::authority_id_mapping(current_session)
636
2263
            .expect("there is a mapping for the current session");
637
2263

            
638
2263
    let author = pallet_author_inherent::Author::<Runtime>::get()
639
2263
        .expect("there should be a registered author");
640
2263

            
641
2263
    mapping
642
2263
        .get(&author)
643
2263
        .expect("there is a mapping for the current author")
644
2263
        .clone()
645
2263
}
646

            
647
15
pub fn block_credits_to_required_balance(number_of_blocks: u32, para_id: ParaId) -> Balance {
648
15
    let block_cost = BlockProductionCost::block_cost(&para_id).0;
649
15
    u128::from(number_of_blocks).saturating_mul(block_cost)
650
15
}
651

            
652
4
pub fn collator_assignment_credits_to_required_balance(
653
4
    number_of_sessions: u32,
654
4
    para_id: ParaId,
655
4
) -> Balance {
656
4
    let collator_assignment_cost = CollatorAssignmentCost::collator_assignment_cost(&para_id).0;
657
4
    u128::from(number_of_sessions).saturating_mul(collator_assignment_cost)
658
4
}
659

            
660
pub const ALICE: [u8; 32] = [4u8; 32];
661
pub const BOB: [u8; 32] = [5u8; 32];
662
pub const CHARLIE: [u8; 32] = [6u8; 32];
663
pub const DAVE: [u8; 32] = [7u8; 32];
664
pub const EVE: [u8; 32] = [8u8; 32];
665
pub const FERDIE: [u8; 32] = [9u8; 32];
666

            
667
33
pub fn set_dummy_boot_node(para_manager: RuntimeOrigin, para_id: ParaId) {
668
    use {
669
        crate::{PreserversAssignementPaymentExtra, PreserversAssignementPaymentRequest},
670
        pallet_data_preservers::{ParaIdsFilter, Profile, ProfileMode},
671
    };
672

            
673
33
    let profile = Profile {
674
33
        url:
675
33
            b"/ip4/127.0.0.1/tcp/33049/ws/p2p/12D3KooWHVMhQDHBpj9vQmssgyfspYecgV6e3hH1dQVDUkUbCYC9"
676
33
                .to_vec()
677
33
                .try_into()
678
33
                .expect("to fit in BoundedVec"),
679
33
        para_ids: ParaIdsFilter::AnyParaId,
680
33
        mode: ProfileMode::Bootnode,
681
33
        assignment_request: PreserversAssignementPaymentRequest::Free,
682
33
    };
683
33

            
684
33
    let profile_id = pallet_data_preservers::NextProfileId::<Runtime>::get();
685
33
    let profile_owner = AccountId::new([1u8; 32]);
686
33
    DataPreservers::force_create_profile(RuntimeOrigin::root(), profile, profile_owner)
687
33
        .expect("profile create to succeed");
688
33

            
689
33
    DataPreservers::start_assignment(
690
33
        para_manager,
691
33
        profile_id,
692
33
        para_id,
693
33
        PreserversAssignementPaymentExtra::Free,
694
33
    )
695
33
    .expect("assignement to work");
696
33

            
697
33
    assert!(
698
33
        pallet_data_preservers::Assignments::<Runtime>::get(para_id).contains(&profile_id),
699
        "profile should be correctly assigned"
700
    );
701
33
}