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_registrar_runtime_api::ContainerChainGenesisData,
31
    pallet_services_payment::{ProvideBlockProductionCost, ProvideCollatorAssignmentCost},
32
    parity_scale_codec::{Decode, Encode, MaxEncodedLen},
33
    polkadot_parachain_primitives::primitives::HeadData,
34
    sp_consensus_aura::AURA_ENGINE_ID,
35
    sp_consensus_slots::Slot,
36
    sp_core::{Get, Pair},
37
    sp_runtime::{traits::Dispatchable, BuildStorage, Digest, DigestItem},
38
    std::{collections::BTreeMap, thread_local},
39
    test_relay_sproof_builder::ParaHeaderSproofBuilder,
40
};
41

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

            
50
pub const UNIT: Balance = 1_000_000_000_000;
51

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

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

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

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

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

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

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

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

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

            
105
416
    summaries
106
416
}
107

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

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

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

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

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

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

            
139
5070
    data
140
5070
}
141

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

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

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

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

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

            
203
5070
    let maybe_mock_inherent = take_new_inherent_data();
204

            
205
5070
    if let Some(mock_inherent_data) = maybe_mock_inherent {
206
4
        set_parachain_inherent_data(mock_inherent_data);
207
5066
    }
208

            
209
5070
    insert_authorities_and_slot_digests(slot);
210

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

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

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

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

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

            
235
5070
    InactivityTracking::on_initialize(System::block_number());
236
5070
    PooledStaking::on_initialize(System::block_number());
237

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

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

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

            
259
4832
    start_block()
260
4832
}
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
238
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
238
    let relay_sproof = RelayStateSproofBuilder {
272
238
        para_id: 100u32.into(),
273
238
        included_para_head: Some(HeadData(vec![1, 2, 3])),
274
238
        current_slot: (current_slot()).into(),
275
238
        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
234
            vec![]
282
        },
283
238
        ..Default::default()
284
    };
285

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

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

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

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

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

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

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

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

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

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

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

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

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

            
416
14
    pub fn with_config(mut self, config: pallet_configuration::HostConfiguration) -> Self {
417
14
        self.config = config;
418
14
        self
419
14
    }
420

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

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

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

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

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

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

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

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

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

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

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

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

            
540
234
        t
541
234
    }
542

            
543
234
    pub fn build(self) -> sp_io::TestExternalities {
544
234
        let t = self.build_storage();
545
234
        let mut ext = sp_io::TestExternalities::new(t);
546

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

            
556
184
pub fn root_origin() -> <Runtime as frame_system::Config>::RuntimeOrigin {
557
184
    <Runtime as frame_system::Config>::RuntimeOrigin::root()
558
184
}
559

            
560
416
pub fn origin_of(account_id: AccountId) -> <Runtime as frame_system::Config>::RuntimeOrigin {
561
416
    <Runtime as frame_system::Config>::RuntimeOrigin::signed(account_id)
562
416
}
563

            
564
260
pub fn inherent_origin() -> <Runtime as frame_system::Config>::RuntimeOrigin {
565
260
    <Runtime as frame_system::Config>::RuntimeOrigin::none()
566
260
}
567

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

            
576
/// Return the parachain that the given `AccountId` is collating for.
577
/// Returns `None` if the `AccountId` is not collating.
578
16
pub fn current_collator_parachain_assignment(account: AccountId) -> Option<ParaId> {
579
16
    let assigned_collators = CollatorAssignment::collator_container_chain();
580
16
    let self_para_id = ParachainInfo::get();
581

            
582
16
    assigned_collators.para_id_of(&account, self_para_id)
583
16
}
584

            
585
/// Return the parachain that the given `AccountId` will be collating for
586
/// in the next session change.
587
/// Returns `None` if the `AccountId` will not be collating.
588
12
pub fn future_collator_parachain_assignment(account: AccountId) -> Option<ParaId> {
589
12
    let assigned_collators = CollatorAssignment::pending_collator_container_chain();
590

            
591
12
    match assigned_collators {
592
8
        Some(assigned_collators) => {
593
8
            let self_para_id = ParachainInfo::get();
594

            
595
8
            assigned_collators.para_id_of(&account, self_para_id)
596
        }
597
4
        None => current_collator_parachain_assignment(account),
598
    }
599
12
}
600

            
601
/// Return the list of collators of the given `ParaId`.
602
/// Returns `None` if the `ParaId` is not in the registrar.
603
28
pub fn parachain_collators(para_id: ParaId) -> Option<Vec<AccountId>> {
604
28
    let assigned_collators = CollatorAssignment::collator_container_chain();
605
28
    let self_para_id = ParachainInfo::get();
606

            
607
28
    if para_id == self_para_id {
608
18
        Some(assigned_collators.orchestrator_chain)
609
    } else {
610
10
        assigned_collators.container_chains.get(&para_id).cloned()
611
    }
612
28
}
613

            
614
8
pub fn get_orchestrator_current_author() -> Option<AccountId> {
615
8
    let slot: u64 = current_slot();
616
8
    let orchestrator_collators = parachain_collators(ParachainInfo::get())?;
617
8
    let author_index = slot % orchestrator_collators.len() as u64;
618
8
    let account = orchestrator_collators.get(author_index as usize)?;
619
8
    Some(account.clone())
620
8
}
621
/// Mocks the author noting inherent to insert the data we
622
22
pub fn set_author_noting_inherent_data(builder: ParaHeaderSproofBuilder) {
623
22
    let (relay_storage_root, relay_storage_proof) = builder.into_state_root_and_proof();
624

            
625
    // For now we directly touch parachain_system storage to set the relay state root.
626
    // TODO: Properly set the parachain_system inherent, which require a sproof builder combining
627
    // what is required by parachain_system and author_noting.
628
22
    frame_support::storage::unhashed::put(
629
22
        &frame_support::storage::storage_prefix(b"ParachainSystem", b"ValidationData"),
630
22
        &PersistedValidationData {
631
22
            parent_head: HeadData(Default::default()),
632
22
            relay_parent_number: 0u32,
633
22
            relay_parent_storage_root: relay_storage_root,
634
22
            max_pov_size: 0u32,
635
22
        },
636
    );
637

            
638
    // But we also need to store the new proof submitted
639
22
    frame_support::storage::unhashed::put(
640
22
        &frame_support::storage::storage_prefix(b"ParachainSystem", b"RelayStateProof"),
641
22
        &relay_storage_proof,
642
    );
643

            
644
22
    assert_ok!(RuntimeCall::AuthorNoting(
645
22
        pallet_author_noting::Call::<Runtime>::set_latest_author_data {
646
22
            data: tp_author_noting_inherent::OwnParachainInherentData {
647
22
                relay_storage_proof,
648
22
            }
649
22
        }
650
22
    )
651
22
    .dispatch(inherent_origin()));
652
22
}
653

            
654
336
pub fn empty_genesis_data() -> ContainerChainGenesisData {
655
336
    ContainerChainGenesisData {
656
336
        storage: Default::default(),
657
336
        name: Default::default(),
658
336
        id: Default::default(),
659
336
        fork_id: Default::default(),
660
336
        extensions: Default::default(),
661
336
        properties: Default::default(),
662
336
    }
663
336
}
664

            
665
5362
pub fn current_slot() -> u64 {
666
5362
    u64::from(
667
5362
        pallet_async_backing::SlotInfo::<Runtime>::get()
668
5362
            .unwrap_or_default()
669
5362
            .0,
670
    )
671
5362
}
672

            
673
62
pub fn authorities() -> Vec<NimbusId> {
674
62
    let session_index = Session::current_index();
675

            
676
62
    AuthorityAssignment::collator_container_chain(session_index)
677
62
        .expect("authorities should be set")
678
62
        .orchestrator_chain
679
62
}
680

            
681
5124
pub fn current_author() -> AccountId {
682
5124
    let current_session = Session::current_index();
683
5124
    let mapping =
684
5124
        pallet_authority_mapping::Pallet::<Runtime>::authority_id_mapping(current_session)
685
5124
            .expect("there is a mapping for the current session");
686

            
687
5124
    let author = pallet_author_inherent::Author::<Runtime>::get()
688
5124
        .expect("there should be a registered author");
689

            
690
5124
    mapping
691
5124
        .get(&author)
692
5124
        .expect("there is a mapping for the current author")
693
5124
        .clone()
694
5124
}
695

            
696
30
pub fn block_credits_to_required_balance(number_of_blocks: u32, para_id: ParaId) -> Balance {
697
30
    let block_cost = BlockProductionCost::block_cost(&para_id).0;
698
30
    u128::from(number_of_blocks).saturating_mul(block_cost)
699
30
}
700

            
701
8
pub fn collator_assignment_credits_to_required_balance(
702
8
    number_of_sessions: u32,
703
8
    para_id: ParaId,
704
8
) -> Balance {
705
8
    let collator_assignment_cost = CollatorAssignmentCost::collator_assignment_cost(&para_id).0;
706
8
    u128::from(number_of_sessions).saturating_mul(collator_assignment_cost)
707
8
}
708

            
709
pub const ALICE: [u8; 32] = [4u8; 32];
710
pub const BOB: [u8; 32] = [5u8; 32];
711
pub const CHARLIE: [u8; 32] = [6u8; 32];
712
pub const DAVE: [u8; 32] = [7u8; 32];
713
pub const EVE: [u8; 32] = [8u8; 32];
714
pub const FERDIE: [u8; 32] = [9u8; 32];
715

            
716
66
pub fn set_dummy_boot_node(para_manager: RuntimeOrigin, para_id: ParaId) {
717
    use {
718
        pallet_data_preservers::{NodeType, ParaIdsFilter, Profile},
719
        tp_data_preservers_common::{AssignerExtra, ProviderRequest},
720
    };
721

            
722
66
    let profile = Profile {
723
66
        bootnode_url: Some(
724
66
            b"/ip4/127.0.0.1/tcp/33049/ws/p2p/12D3KooWHVMhQDHBpj9vQmssgyfspYecgV6e3hH1dQVDUkUbCYC9"
725
66
                .to_vec()
726
66
                .try_into()
727
66
                .expect("to fit in BoundedVec"),
728
66
        ),
729
66
        direct_rpc_urls: Default::default(),
730
66
        proxy_rpc_urls: Default::default(),
731
66
        para_ids: ParaIdsFilter::AnyParaId,
732
66
        node_type: NodeType::Substrate,
733
66
        additional_info: Default::default(),
734
66
        assignment_request: ProviderRequest::Free,
735
66
    };
736

            
737
66
    let profile_id = pallet_data_preservers::NextProfileId::<Runtime>::get();
738
66
    let profile_owner = AccountId::new([1u8; 32]);
739
66
    DataPreservers::force_create_profile(RuntimeOrigin::root(), profile, profile_owner)
740
66
        .expect("profile create to succeed");
741

            
742
66
    DataPreservers::start_assignment(para_manager, profile_id, para_id, AssignerExtra::Free)
743
66
        .expect("assignement to work");
744

            
745
66
    assert!(
746
66
        pallet_data_preservers::Assignments::<Runtime>::get(para_id).contains(&profile_id),
747
        "profile should be correctly assigned"
748
    );
749
66
}