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},
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_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
    test_relay_sproof_builder::ParaHeaderSproofBuilder,
37
};
38

            
39
pub use crate::{
40
    AccountId, AuthorNoting, AuthorityAssignment, AuthorityMapping, Balance, Balances,
41
    CollatorAssignment, Configuration, DataPreservers, InflationRewards, Initializer,
42
    Invulnerables, ParachainInfo, Proxy, ProxyType, Registrar, RewardsPortion, Runtime,
43
    RuntimeCall, ServicesPayment, Session, StreamPayment, System, TransactionPayment,
44
};
45

            
46
pub const UNIT: Balance = 1_000_000_000_000;
47

            
48
77
pub fn session_to_block(n: u32) -> u32 {
49
77
    let block_number = crate::Period::get() * n;
50

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

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

            
62
77
pub fn run_to_session(n: u32) {
63
77
    run_to_block(session_to_block(n));
64
77
}
65

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

            
83
1100
    while System::block_number() < n {
84
975
        let summary = run_block();
85
975
        let block_number = System::block_number();
86
975
        summaries.insert(block_number, summary);
87
975
    }
88

            
89
125
    summaries
90
125
}
91

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

            
96
1062
    let authority: NimbusId = authorities[slot as usize % authorities.len()].clone();
97

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

            
105
1062
    System::reset_events();
106
1062
    System::initialize(
107
1062
        &(System::block_number() + 1),
108
1062
        &System::parent_hash(),
109
1062
        &pre_digest,
110
    );
111
1062
}
112

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

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

            
123
1062
    data
124
1062
}
125

            
126
#[derive(Clone, Encode, Decode, PartialEq, Debug, scale_info::TypeInfo, MaxEncodedLen)]
127
enum RunBlockState {
128
    Start(u32),
129
    End(u32),
130
}
131

            
132
impl RunBlockState {
133
2052
    fn assert_can_advance(&self, new_state: &RunBlockState) {
134
2052
        match self {
135
990
            RunBlockState::Start(n) => {
136
990
                assert_eq!(
137
                    new_state,
138
990
                    &RunBlockState::End(*n),
139
                    "expected a call to end_block({}), but user called {:?}",
140
                    *n,
141
                    new_state
142
                );
143
            }
144
1062
            RunBlockState::End(n) => {
145
1062
                assert_eq!(
146
                    new_state,
147
1062
                    &RunBlockState::Start(*n + 1),
148
                    "expected a call to start_block({}), but user called {:?}",
149
                    *n + 1,
150
                    new_state
151
                )
152
            }
153
        }
154
2052
    }
155
}
156

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

            
173
1062
pub fn start_block() -> RunSummary {
174
1062
    let block_number = System::block_number();
175
1062
    advance_block_state_machine(RunBlockState::Start(block_number + 1));
176
1062
    let mut slot = current_slot() + 1;
177
1062
    if block_number == 0 {
178
73
        // Hack to avoid breaking all tests. When the current block is 1, the slot number should be
179
73
        // 1. But all of our tests assume it will be 0. So use slot number = block_number - 1.
180
73
        slot = 0;
181
989
    }
182

            
183
1062
    let maybe_mock_inherent = take_new_inherent_data();
184

            
185
1062
    if let Some(mock_inherent_data) = maybe_mock_inherent {
186
        set_parachain_inherent_data(mock_inherent_data);
187
1062
    }
188

            
189
1062
    insert_authorities_and_slot_digests(slot);
190

            
191
    // Initialize the new block
192
1062
    CollatorAssignment::on_initialize(System::block_number());
193
1062
    Session::on_initialize(System::block_number());
194
1062
    Initializer::on_initialize(System::block_number());
195
1062
    AuthorInherent::on_initialize(System::block_number());
196

            
197
    // `Initializer::on_finalize` needs to run at least one to have
198
    // author mapping setup.
199
1062
    let author_id = current_author();
200

            
201
1062
    let current_issuance = Balances::total_issuance();
202
1062
    InflationRewards::on_initialize(System::block_number());
203
1062
    let new_issuance = Balances::total_issuance();
204

            
205
1062
    frame_support::storage::unhashed::put(
206
1062
        &frame_support::storage::storage_prefix(b"AsyncBacking", b"SlotInfo"),
207
        // TODO: this should be 0?
208
1062
        &(Slot::from(slot), 1),
209
    );
210

            
211
1062
    pallet_author_inherent::Pallet::<Runtime>::kick_off_authorship_validation(None.into())
212
1062
        .expect("author inherent to dispatch correctly");
213

            
214
1062
    RunSummary {
215
1062
        author_id,
216
1062
        inflation: new_issuance - current_issuance,
217
1062
    }
218
1062
}
219

            
220
990
pub fn end_block() {
221
990
    let block_number = System::block_number();
222
990
    advance_block_state_machine(RunBlockState::End(block_number));
223
    // Finalize the block
224
990
    CollatorAssignment::on_finalize(System::block_number());
225
990
    Session::on_finalize(System::block_number());
226
990
    Initializer::on_finalize(System::block_number());
227
990
    AuthorInherent::on_finalize(System::block_number());
228
990
    TransactionPayment::on_finalize(System::block_number());
229
990
}
230

            
231
987
pub fn run_block() -> RunSummary {
232
987
    end_block();
233

            
234
987
    start_block()
235
987
}
236

            
237
/// Mock the inherent that sets validation data in ParachainSystem, which
238
/// contains the `relay_chain_block_number`, which is used in `collator-assignment` as a
239
/// source of randomness.
240
73
pub fn set_parachain_inherent_data(mock_inherent_data: MockInherentData) {
241
    use {
242
        cumulus_primitives_core::relay_chain::well_known_keys,
243
        cumulus_test_relay_sproof_builder::RelayStateSproofBuilder,
244
    };
245

            
246
73
    let relay_sproof = RelayStateSproofBuilder {
247
73
        para_id: 100u32.into(),
248
73
        included_para_head: Some(HeadData(vec![1, 2, 3])),
249
73
        current_slot: (current_slot()).into(),
250
73
        additional_key_values: if mock_inherent_data.random_seed.is_some() {
251
            vec![(
252
                well_known_keys::CURRENT_BLOCK_RANDOMNESS.to_vec(),
253
                Some(mock_inherent_data.random_seed).encode(),
254
            )]
255
        } else {
256
73
            vec![]
257
        },
258
73
        ..Default::default()
259
    };
260

            
261
73
    let (relay_parent_storage_root, relay_chain_state) = relay_sproof.into_state_root_and_proof();
262
73
    let vfp = PersistedValidationData {
263
73
        relay_parent_number: 1u32,
264
73
        relay_parent_storage_root,
265
73
        ..Default::default()
266
73
    };
267
73
    let parachain_inherent_data = ParachainInherentData {
268
73
        validation_data: vfp,
269
73
        relay_chain_state,
270
73
        downward_messages: Default::default(),
271
73
        horizontal_messages: Default::default(),
272
73
        relay_parent_descendants: Default::default(),
273
73
        collator_peer_id: Default::default(),
274
73
    };
275

            
276
    // Delete existing flag to avoid error
277
    // 'ValidationData must be updated only once in a block'
278
    // TODO: this is a hack
279
73
    frame_support::storage::unhashed::kill(&frame_support::storage::storage_prefix(
280
73
        b"ParachainSystem",
281
73
        b"ValidationData",
282
73
    ));
283

            
284
73
    assert_ok!(RuntimeCall::ParachainSystem(
285
73
        cumulus_pallet_parachain_system::Call::<Runtime>::set_validation_data {
286
73
            data: parachain_inherent_data
287
73
        }
288
73
    )
289
73
    .dispatch(inherent_origin()));
290
73
}
291

            
292
#[derive(Default, Clone)]
293
pub struct ParaRegistrationParams {
294
    pub para_id: u32,
295
    pub genesis_data: ContainerChainGenesisData,
296
    pub block_production_credits: u32,
297
    pub collator_assignment_credits: u32,
298
    pub parathread_params: Option<tp_traits::ParathreadParams>,
299
}
300

            
301
73
pub fn default_config() -> pallet_configuration::HostConfiguration {
302
73
    pallet_configuration::HostConfiguration {
303
73
        max_collators: 100,
304
73
        min_orchestrator_collators: 2,
305
73
        max_orchestrator_collators: 2,
306
73
        collators_per_container: 2,
307
73
        full_rotation_period: 0,
308
73
        ..Default::default()
309
73
    }
310
73
}
311

            
312
pub struct ExtBuilder {
313
    // endowed accounts with balances
314
    balances: Vec<(AccountId, Balance)>,
315
    // [collator, amount]
316
    collators: Vec<(AccountId, Balance)>,
317
    // sudo key
318
    sudo: Option<AccountId>,
319
    // list of registered para ids: para_id, genesis_data, boot_nodes, block_credits, session_credits
320
    para_ids: Vec<ParaRegistrationParams>,
321
    // configuration to apply
322
    config: pallet_configuration::HostConfiguration,
323
    own_para_id: Option<ParaId>,
324
}
325

            
326
impl Default for ExtBuilder {
327
73
    fn default() -> Self {
328
73
        Self {
329
73
            balances: vec![
330
73
                // Alice gets 10k extra tokens for her mapping deposit
331
73
                (AccountId::from(ALICE), 210_000 * UNIT),
332
73
                (AccountId::from(BOB), 100_000 * UNIT),
333
73
            ],
334
73
            collators: vec![
335
73
                (AccountId::from(ALICE), 210 * UNIT),
336
73
                (AccountId::from(BOB), 100 * UNIT),
337
73
            ],
338
73
            sudo: Default::default(),
339
73
            para_ids: Default::default(),
340
73
            config: default_config(),
341
73
            own_para_id: Default::default(),
342
73
        }
343
73
    }
344
}
345

            
346
impl ExtBuilder {
347
63
    pub fn with_balances(mut self, balances: Vec<(AccountId, Balance)>) -> Self {
348
63
        self.balances = balances;
349
63
        self
350
63
    }
351

            
352
7
    pub fn with_sudo(mut self, sudo: AccountId) -> Self {
353
7
        self.sudo = Some(sudo);
354
7
        self
355
7
    }
356

            
357
41
    pub fn with_collators(mut self, collators: Vec<(AccountId, Balance)>) -> Self {
358
41
        self.collators = collators;
359
41
        self
360
41
    }
361

            
362
2
    pub fn with_para_ids(mut self, para_ids: Vec<ParaRegistrationParams>) -> Self {
363
2
        self.para_ids = para_ids;
364
2
        self
365
2
    }
366

            
367
    /// Helper function like `with_para_ids` but registering parachains with an empty genesis data,
368
    /// and max amount of credits.
369
30
    pub fn with_empty_parachains(mut self, para_ids: Vec<u32>) -> Self {
370
30
        self.para_ids = para_ids
371
30
            .into_iter()
372
30
            .map(|para_id| ParaRegistrationParams {
373
63
                para_id,
374
63
                genesis_data: empty_genesis_data(),
375
                block_production_credits: u32::MAX,
376
                collator_assignment_credits: u32::MAX,
377
63
                parathread_params: None,
378
63
            })
379
30
            .collect();
380
30
        self
381
30
    }
382

            
383
5
    pub fn with_config(mut self, config: pallet_configuration::HostConfiguration) -> Self {
384
5
        self.config = config;
385
5
        self
386
5
    }
387

            
388
73
    pub fn build_storage(self) -> sp_core::storage::Storage {
389
73
        let mut t = frame_system::GenesisConfig::<Runtime>::default()
390
73
            .build_storage()
391
73
            .unwrap();
392

            
393
73
        pallet_balances::GenesisConfig::<Runtime> {
394
73
            balances: self.balances,
395
73
            ..Default::default()
396
73
        }
397
73
        .assimilate_storage(&mut t)
398
73
        .unwrap();
399

            
400
        // We need to initialize these pallets first. When initializing pallet-session,
401
        // these values will be taken into account for collator-assignment.
402

            
403
        pallet_registrar::GenesisConfig::<Runtime> {
404
73
            para_ids: self
405
73
                .para_ids
406
73
                .iter()
407
73
                .cloned()
408
73
                .map(|registered_para| {
409
66
                    (
410
66
                        registered_para.para_id.into(),
411
66
                        registered_para.genesis_data,
412
66
                        registered_para.parathread_params,
413
66
                    )
414
66
                })
415
73
                .collect(),
416
73
            phantom: Default::default(),
417
        }
418
73
        .assimilate_storage(&mut t)
419
73
        .unwrap();
420

            
421
        pallet_services_payment::GenesisConfig::<Runtime> {
422
73
            para_id_credits: self
423
73
                .para_ids
424
73
                .clone()
425
73
                .into_iter()
426
73
                .map(|registered_para| {
427
66
                    (
428
66
                        registered_para.para_id.into(),
429
66
                        registered_para.block_production_credits,
430
66
                        registered_para.collator_assignment_credits,
431
66
                    )
432
66
                        .into()
433
66
                })
434
73
                .collect(),
435
        }
436
73
        .assimilate_storage(&mut t)
437
73
        .unwrap();
438

            
439
73
        pallet_configuration::GenesisConfig::<Runtime> {
440
73
            config: self.config,
441
73
            ..Default::default()
442
73
        }
443
73
        .assimilate_storage(&mut t)
444
73
        .unwrap();
445

            
446
73
        if let Some(own_para_id) = self.own_para_id {
447
            parachain_info::GenesisConfig::<Runtime> {
448
                parachain_id: own_para_id,
449
                ..Default::default()
450
            }
451
            .assimilate_storage(&mut t)
452
            .unwrap();
453
73
        }
454

            
455
73
        if !self.collators.is_empty() {
456
            // We set invulnerables in pallet_invulnerables
457
73
            let invulnerables: Vec<AccountId> = self
458
73
                .collators
459
73
                .clone()
460
73
                .into_iter()
461
73
                .map(|(account, _balance)| account)
462
73
                .collect();
463

            
464
73
            pallet_invulnerables::GenesisConfig::<Runtime> {
465
73
                invulnerables: invulnerables.clone(),
466
73
            }
467
73
            .assimilate_storage(&mut t)
468
73
            .unwrap();
469

            
470
            // But we also initialize their keys in the session pallet
471
73
            let keys: Vec<_> = self
472
73
                .collators
473
73
                .into_iter()
474
222
                .map(|(account, _balance)| {
475
222
                    let nimbus_id = get_aura_id_from_seed(&account.to_string());
476
222
                    (
477
222
                        account.clone(),
478
222
                        account,
479
222
                        crate::SessionKeys { nimbus: nimbus_id },
480
222
                    )
481
222
                })
482
73
                .collect();
483
73
            pallet_session::GenesisConfig::<Runtime> {
484
73
                keys,
485
73
                ..Default::default()
486
73
            }
487
73
            .assimilate_storage(&mut t)
488
73
            .unwrap();
489
        }
490
73
        pallet_sudo::GenesisConfig::<Runtime> { key: self.sudo }
491
73
            .assimilate_storage(&mut t)
492
73
            .unwrap();
493
73
        t
494
73
    }
495

            
496
73
    pub fn build(self) -> sp_io::TestExternalities {
497
73
        let t = self.build_storage();
498
73
        let mut ext = sp_io::TestExternalities::new(t);
499

            
500
73
        ext.execute_with(|| {
501
            // Start block 1
502
73
            start_block();
503
73
            set_parachain_inherent_data(Default::default());
504
73
        });
505
73
        ext
506
73
    }
507
}
508

            
509
78
pub fn root_origin() -> <Runtime as frame_system::Config>::RuntimeOrigin {
510
78
    <Runtime as frame_system::Config>::RuntimeOrigin::root()
511
78
}
512

            
513
116
pub fn origin_of(account_id: AccountId) -> <Runtime as frame_system::Config>::RuntimeOrigin {
514
116
    <Runtime as frame_system::Config>::RuntimeOrigin::signed(account_id)
515
116
}
516

            
517
81
pub fn inherent_origin() -> <Runtime as frame_system::Config>::RuntimeOrigin {
518
81
    <Runtime as frame_system::Config>::RuntimeOrigin::none()
519
81
}
520

            
521
/// Helper function to generate a crypto pair from seed
522
294
pub fn get_aura_id_from_seed(seed: &str) -> NimbusId {
523
294
    sp_core::sr25519::Pair::from_string(&format!("//{}", seed), None)
524
294
        .expect("static values are valid; qed")
525
294
        .public()
526
294
        .into()
527
294
}
528

            
529
/// Return the parachain that the given `AccountId` is collating for.
530
/// Returns `None` if the `AccountId` is not collating.
531
8
pub fn current_collator_parachain_assignment(account: AccountId) -> Option<ParaId> {
532
8
    let assigned_collators = CollatorAssignment::collator_container_chain();
533
8
    let self_para_id = ParachainInfo::get();
534

            
535
8
    assigned_collators.para_id_of(&account, self_para_id)
536
8
}
537

            
538
/// Return the parachain that the given `AccountId` will be collating for
539
/// in the next session change.
540
/// Returns `None` if the `AccountId` will not be collating.
541
6
pub fn future_collator_parachain_assignment(account: AccountId) -> Option<ParaId> {
542
6
    let assigned_collators = CollatorAssignment::pending_collator_container_chain();
543

            
544
6
    match assigned_collators {
545
4
        Some(assigned_collators) => {
546
4
            let self_para_id = ParachainInfo::get();
547

            
548
4
            assigned_collators.para_id_of(&account, self_para_id)
549
        }
550
2
        None => current_collator_parachain_assignment(account),
551
    }
552
6
}
553

            
554
/// Return the list of collators of the given `ParaId`.
555
/// Returns `None` if the `ParaId` is not in the registrar.
556
14
pub fn parachain_collators(para_id: ParaId) -> Option<Vec<AccountId>> {
557
14
    let assigned_collators = CollatorAssignment::collator_container_chain();
558
14
    let self_para_id = ParachainInfo::get();
559

            
560
14
    if para_id == self_para_id {
561
9
        Some(assigned_collators.orchestrator_chain)
562
    } else {
563
5
        assigned_collators.container_chains.get(&para_id).cloned()
564
    }
565
14
}
566

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

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

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

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

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

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

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

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

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

            
640
1089
    let author = pallet_author_inherent::Author::<Runtime>::get()
641
1089
        .expect("there should be a registered author");
642

            
643
1089
    mapping
644
1089
        .get(&author)
645
1089
        .expect("there is a mapping for the current author")
646
1089
        .clone()
647
1089
}
648

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

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

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