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
#![allow(dead_code)]
18

            
19
use {
20
    crate::{BlockProductionCost, CollatorAssignmentCost, RuntimeCall},
21
    babe_primitives::{
22
        digests::{PreDigest, SecondaryPlainPreDigest},
23
        BABE_ENGINE_ID,
24
    },
25
    bitvec::prelude::BitVec,
26
    cumulus_primitives_core::{
27
        relay_chain::{
28
            node_features::FeatureIndex, AvailabilityBitfield, BackedCandidate,
29
            CandidateCommitments, CandidateDescriptor, CollatorPair, CommittedCandidateReceipt,
30
            CompactStatement, CoreIndex, GroupIndex, HeadData,
31
            InherentData as ParachainsInherentData, PersistedValidationData, SigningContext,
32
            UncheckedSigned, ValidationCode, ValidatorIndex, ValidityAttestation,
33
        },
34
        ParaId,
35
    },
36
    frame_support::{
37
        assert_ok,
38
        traits::{OnFinalize, OnInitialize},
39
    },
40
    frame_system::pallet_prelude::{BlockNumberFor, HeaderFor},
41
    nimbus_primitives::NimbusId,
42
    pallet_registrar_runtime_api::ContainerChainGenesisData,
43
    pallet_services_payment::{ProvideBlockProductionCost, ProvideCollatorAssignmentCost},
44
    parity_scale_codec::{Decode, Encode, MaxEncodedLen},
45
    runtime_parachains::{
46
        paras::{ParaGenesisArgs, ParaKind},
47
        paras_inherent as parachains_paras_inherent,
48
    },
49
    sp_core::Pair,
50
    sp_keystore::{KeystoreExt, KeystorePtr},
51
    sp_runtime::{
52
        traits::{Dispatchable, Header, One, SaturatedConversion, Zero},
53
        BuildStorage, Digest, DigestItem,
54
    },
55
    sp_std::collections::btree_map::BTreeMap,
56
    test_relay_sproof_builder::ParaHeaderSproofBuilder,
57
};
58

            
59
pub use crate::{
60
    genesis_config_presets::get_authority_keys_from_seed, AccountId, AuthorNoting, Babe, Balance,
61
    Balances, ContainerRegistrar, DataPreservers, Grandpa, InflationRewards, Initializer, Runtime,
62
    RuntimeOrigin, Session, System, TanssiAuthorityAssignment, TanssiCollatorAssignment,
63
    TransactionPayment,
64
};
65

            
66
pub const UNIT: Balance = 1_000_000_000_000_000_000;
67

            
68
119
pub fn session_to_block(n: u32) -> u32 {
69
119
    // let block_number = flashbox_runtime::Period::get() * n;
70
119
    let block_number = Babe::current_epoch().duration.saturated_into::<u32>() * n;
71
119

            
72
119
    // Add 1 because the block that emits the NewSession event cannot contain any extrinsics,
73
119
    // so this is the first block of the new session that can actually be used
74
119
    block_number + 1
75
119
}
76

            
77
17
pub fn babe_authorities() -> Vec<babe_primitives::AuthorityId> {
78
17
    Babe::authorities()
79
17
        .iter()
80
34
        .map(|(key, _)| key.clone())
81
17
        .collect()
82
17
}
83

            
84
8
pub fn grandpa_authorities() -> Vec<pallet_grandpa::AuthorityId> {
85
8
    Grandpa::grandpa_authorities()
86
8
        .iter()
87
16
        .map(|(key, _)| key.clone())
88
8
        .collect()
89
8
}
90

            
91
13
pub fn authorities_for_container(para_id: ParaId) -> Option<Vec<NimbusId>> {
92
13
    let session_index = Session::current_index();
93
13

            
94
13
    TanssiAuthorityAssignment::collator_container_chain(session_index)
95
13
        .expect("authorities should be set")
96
13
        .container_chains
97
13
        .get(&para_id)
98
13
        .cloned()
99
13
}
100

            
101
pub fn accounts_for_container(para_id: ParaId) -> Option<Vec<AccountId>> {
102
    TanssiCollatorAssignment::collator_container_chain()
103
        .container_chains
104
        .get(&para_id)
105
        .cloned()
106
}
107

            
108
118
pub fn run_to_session(n: u32) {
109
118
    run_to_block(session_to_block(n));
110
118
}
111

            
112
/// Utility function that advances the chain to the desired block number.
113
///
114
/// After this function returns, the current block number will be `n`, and the block will be "open",
115
/// meaning that on_initialize has been executed, but on_finalize has not. To execute on_finalize as
116
/// well, for example to test a runtime api, manually call `end_block` after this, run the test, and
117
/// call `start_block` to ensure that this function keeps working as expected.
118
/// Extrinsics should always be executed before on_finalize.
119
146
pub fn run_to_block(n: u32) -> BTreeMap<u32, RunSummary> {
120
146
    let current_block_number = System::block_number();
121
146
    assert!(
122
146
        current_block_number < n,
123
        "run_to_block called with block {} when current block is {}",
124
        n,
125
        current_block_number
126
    );
127

            
128
146
    let mut summaries = BTreeMap::new();
129

            
130
2287
    while System::block_number() < n {
131
2141
        let summary = run_block();
132
2141
        let block_number = System::block_number();
133
2141
        summaries.insert(block_number, summary);
134
2141
    }
135

            
136
146
    summaries
137
146
}
138

            
139
40
pub fn get_genesis_data_with_validation_code() -> (ContainerChainGenesisData, Vec<u8>) {
140
40
    let validation_code = mock_validation_code().0;
141
40
    let genesis_data = ContainerChainGenesisData {
142
40
        storage: vec![(b":code".to_vec(), validation_code.clone()).into()],
143
40
        name: Default::default(),
144
40
        id: Default::default(),
145
40
        fork_id: Default::default(),
146
40
        extensions: vec![],
147
40
        properties: Default::default(),
148
40
    };
149
40
    (genesis_data, validation_code)
150
40
}
151

            
152
2232
pub fn insert_authorities_and_slot_digests(slot: u64) {
153
2232
    let pre_digest = Digest {
154
2232
        logs: vec![DigestItem::PreRuntime(
155
2232
            BABE_ENGINE_ID,
156
2232
            PreDigest::SecondaryPlain(SecondaryPlainPreDigest {
157
2232
                slot: slot.into(),
158
2232
                authority_index: 0,
159
2232
            })
160
2232
            .encode(),
161
2232
        )],
162
2232
    };
163
2232

            
164
2232
    System::reset_events();
165
2232
    System::initialize(
166
2232
        &(System::block_number() + 1),
167
2232
        &System::parent_hash(),
168
2232
        &pre_digest,
169
2232
    );
170
2232
}
171

            
172
#[derive(Debug, Clone, Eq, PartialEq)]
173
pub struct RunSummary {
174
    pub inflation: Balance,
175
}
176

            
177
#[derive(Clone, Encode, Decode, PartialEq, Debug, scale_info::TypeInfo, MaxEncodedLen)]
178
enum RunBlockState {
179
2165
    Start(u32),
180
2164
    End(u32),
181
}
182

            
183
impl RunBlockState {
184
4397
    fn assert_can_advance(&self, new_state: &RunBlockState) {
185
4397
        match self {
186
2165
            RunBlockState::Start(n) => {
187
2165
                assert_eq!(
188
2165
                    new_state,
189
2165
                    &RunBlockState::End(*n),
190
                    "expected a call to end_block({}), but user called {:?}",
191
                    *n,
192
                    new_state
193
                );
194
            }
195
2232
            RunBlockState::End(n) => {
196
2232
                assert_eq!(
197
2232
                    new_state,
198
2232
                    &RunBlockState::Start(*n + 1),
199
                    "expected a call to start_block({}), but user called {:?}",
200
                    *n + 1,
201
                    new_state
202
                )
203
            }
204
        }
205
4397
    }
206
}
207

            
208
4397
fn advance_block_state_machine(new_state: RunBlockState) {
209
4397
    if frame_support::storage::unhashed::exists(b"__mock_is_xcm_test") {
210
        // Disable this check in XCM tests, because the XCM emulator runs on_initialize and
211
        // on_finalize automatically
212
        return;
213
4397
    }
214
4397
    let old_state: RunBlockState =
215
4397
        frame_support::storage::unhashed::get(b"__mock_debug_block_state").unwrap_or(
216
4397
            // Initial state is expecting a call to start() with block number 1, so old state should be
217
4397
            // end of block 0
218
4397
            RunBlockState::End(0),
219
4397
        );
220
4397
    old_state.assert_can_advance(&new_state);
221
4397
    frame_support::storage::unhashed::put(b"__mock_debug_block_state", &new_state);
222
4397
}
223

            
224
2232
pub fn start_block() -> RunSummary {
225
2232
    let block_number = System::block_number();
226
2232
    advance_block_state_machine(RunBlockState::Start(block_number + 1));
227
2232

            
228
2232
    insert_authorities_and_slot_digests(current_slot() + 1);
229
2232

            
230
2232
    // Initialize the new block
231
2232
    Babe::on_initialize(System::block_number());
232
2232
    ContainerRegistrar::on_initialize(System::block_number());
233
2232
    Session::on_initialize(System::block_number());
234
2232
    Initializer::on_initialize(System::block_number());
235
2232
    TanssiCollatorAssignment::on_initialize(System::block_number());
236
2232

            
237
2232
    let current_issuance = Balances::total_issuance();
238
2232
    InflationRewards::on_initialize(System::block_number());
239
2232
    let new_issuance = Balances::total_issuance();
240
2232

            
241
2232
    let maybe_mock_inherent = take_new_inherent_data();
242
2232
    if let Some(mock_inherent_data) = maybe_mock_inherent {
243
8
        set_paras_inherent(mock_inherent_data);
244
2224
    }
245

            
246
2232
    RunSummary {
247
2232
        inflation: new_issuance - current_issuance,
248
2232
    }
249
2232
}
250

            
251
2165
pub fn end_block() {
252
2165
    let block_number = System::block_number();
253
2165
    advance_block_state_machine(RunBlockState::End(block_number));
254
2165
    // Finalize the block
255
2165
    Babe::on_finalize(System::block_number());
256
2165
    Session::on_finalize(System::block_number());
257
2165
    Grandpa::on_finalize(System::block_number());
258
2165
    TransactionPayment::on_finalize(System::block_number());
259
2165
    Initializer::on_finalize(System::block_number());
260
2165
    ContainerRegistrar::on_finalize(System::block_number());
261
2165
    TanssiCollatorAssignment::on_finalize(System::block_number());
262
2165
}
263

            
264
2161
pub fn run_block() -> RunSummary {
265
2161
    end_block();
266
2161

            
267
2161
    start_block()
268
2161
}
269

            
270
#[derive(Default, Clone)]
271
pub struct ParaRegistrationParams {
272
    pub para_id: u32,
273
    pub genesis_data: ContainerChainGenesisData,
274
    pub block_production_credits: u32,
275
    pub collator_assignment_credits: u32,
276
    pub parathread_params: Option<tp_traits::ParathreadParams>,
277
}
278

            
279
impl From<(u32, ContainerChainGenesisData, u32, u32)> for ParaRegistrationParams {
280
10
    fn from(value: (u32, ContainerChainGenesisData, u32, u32)) -> Self {
281
10
        Self {
282
10
            para_id: value.0,
283
10
            genesis_data: value.1,
284
10
            block_production_credits: value.2,
285
10
            collator_assignment_credits: value.3,
286
10
            parathread_params: None,
287
10
        }
288
10
    }
289
}
290

            
291
68
pub fn default_config() -> pallet_configuration::HostConfiguration {
292
68
    pallet_configuration::HostConfiguration {
293
68
        max_collators: 100,
294
68
        min_orchestrator_collators: 2,
295
68
        max_orchestrator_collators: 2,
296
68
        collators_per_container: 2,
297
68
        full_rotation_period: 0,
298
68
        ..Default::default()
299
68
    }
300
68
}
301

            
302
#[derive(Clone)]
303
pub struct ExtBuilder {
304
    // endowed accounts with balances
305
    balances: Vec<(AccountId, Balance)>,
306
    // [validator, amount]
307
    validators: Vec<(AccountId, Balance)>,
308
    // [collator, amount]
309
    collators: Vec<(AccountId, Balance)>,
310
    // sudo key
311
    sudo: Option<AccountId>,
312
    // list of registered para ids: para_id, genesis_data, boot_nodes, block_credits, session_credits
313
    para_ids: Vec<ParaRegistrationParams>,
314
    // configuration to apply
315
    config: pallet_configuration::HostConfiguration,
316
    relay_config: runtime_parachains::configuration::HostConfiguration<BlockNumberFor<Runtime>>,
317
    own_para_id: Option<ParaId>,
318
    next_free_para_id: ParaId,
319
    keystore: Option<KeystorePtr>,
320
}
321

            
322
impl Default for ExtBuilder {
323
68
    fn default() -> Self {
324
68
        Self {
325
68
            balances: vec![
326
68
                // Alice gets 10k extra tokens for her mapping deposit
327
68
                (AccountId::from(ALICE), 210_000 * UNIT),
328
68
                (AccountId::from(BOB), 100_000 * UNIT),
329
68
            ],
330
68
            validators: vec![
331
68
                (AccountId::from(ALICE), 210 * UNIT),
332
68
                (AccountId::from(BOB), 100 * UNIT),
333
68
            ],
334
68
            collators: Default::default(),
335
68
            sudo: Default::default(),
336
68
            para_ids: Default::default(),
337
68
            config: default_config(),
338
68
            relay_config: runtime_parachains::configuration::HostConfiguration {
339
68
                scheduler_params: SchedulerParams {
340
68
                    num_cores: 6,
341
68
                    ..Default::default()
342
68
                },
343
68
                max_head_data_size: 20500,
344
68
                ..Default::default()
345
68
            },
346
68
            own_para_id: Default::default(),
347
68
            next_free_para_id: Default::default(),
348
68
            keystore: None,
349
68
        }
350
68
    }
351
}
352

            
353
impl ExtBuilder {
354
57
    pub fn with_balances(mut self, balances: Vec<(AccountId, Balance)>) -> Self {
355
57
        self.balances = balances;
356
57
        self
357
57
    }
358

            
359
1
    pub fn with_sudo(mut self, sudo: AccountId) -> Self {
360
1
        self.sudo = Some(sudo);
361
1
        self
362
1
    }
363

            
364
    pub fn with_validators(mut self, validators: Vec<(AccountId, Balance)>) -> Self {
365
        self.validators = validators;
366
        self
367
    }
368

            
369
51
    pub fn with_collators(mut self, collators: Vec<(AccountId, Balance)>) -> Self {
370
51
        self.collators = collators;
371
51
        self
372
51
    }
373

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

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

            
395
5
    pub fn with_additional_empty_parathreads(mut self, para_ids: Vec<u32>) -> Self {
396
5
        self.para_ids = self
397
5
            .para_ids
398
5
            .iter()
399
5
            .cloned()
400
14
            .chain(para_ids.into_iter().map(|para_id| ParaRegistrationParams {
401
14
                para_id,
402
14
                genesis_data: empty_genesis_data(),
403
14
                block_production_credits: u32::MAX,
404
14
                collator_assignment_credits: u32::MAX,
405
14
                parathread_params: Some(ParathreadParams {
406
14
                    slot_frequency: Default::default(),
407
14
                }),
408
14
            }))
409
5
            .collect();
410
5
        self
411
5
    }
412

            
413
    // Maybe change to with_collators_config?
414
18
    pub fn with_config(mut self, config: pallet_configuration::HostConfiguration) -> Self {
415
18
        self.config = config;
416
18
        self
417
18
    }
418

            
419
    // Maybe change to with_collators_config?
420
12
    pub fn with_relay_config(
421
12
        mut self,
422
12
        relay_config: runtime_parachains::configuration::HostConfiguration<BlockNumberFor<Runtime>>,
423
12
    ) -> Self {
424
12
        self.relay_config = relay_config;
425
12
        self
426
12
    }
427

            
428
    // Maybe change to with_collators_config?
429
1
    pub fn with_next_free_para_id(mut self, para_id: ParaId) -> Self {
430
1
        self.next_free_para_id = para_id;
431
1
        self
432
1
    }
433

            
434
    // Maybe change to with_collators_config?
435
7
    pub fn with_keystore(mut self, keystore: KeystorePtr) -> Self {
436
7
        self.keystore = Some(keystore);
437
7
        self
438
7
    }
439

            
440
68
    pub fn build_storage(self) -> sp_core::storage::Storage {
441
68
        let mut t = frame_system::GenesisConfig::<Runtime>::default()
442
68
            .build_storage()
443
68
            .unwrap();
444
68

            
445
68
        pallet_babe::GenesisConfig::<Runtime> {
446
68
            ..Default::default()
447
68
        }
448
68
        .assimilate_storage(&mut t)
449
68
        .unwrap();
450
68

            
451
68
        pallet_balances::GenesisConfig::<Runtime> {
452
68
            balances: self.balances,
453
68
        }
454
68
        .assimilate_storage(&mut t)
455
68
        .unwrap();
456
68

            
457
68
        // We need to initialize these pallets first. When initializing pallet-session,
458
68
        // these values will be taken into account for collator-assignment.
459
68

            
460
68
        pallet_registrar::GenesisConfig::<Runtime> {
461
68
            para_ids: self
462
68
                .para_ids
463
68
                .iter()
464
68
                .cloned()
465
90
                .map(|registered_para| {
466
90
                    (
467
90
                        registered_para.para_id.into(),
468
90
                        registered_para.genesis_data,
469
90
                        registered_para.parathread_params,
470
90
                    )
471
90
                })
472
68
                .collect(),
473
68
            ..Default::default()
474
68
        }
475
68
        .assimilate_storage(&mut t)
476
68
        .unwrap();
477
68

            
478
68
        // We register mock wasm
479
68
        runtime_parachains::paras::GenesisConfig::<Runtime> {
480
68
            paras: self
481
68
                .para_ids
482
68
                .iter()
483
68
                .cloned()
484
90
                .map(|registered_para| {
485
90
                    let para_kind = if registered_para.parathread_params.is_some() {
486
18
                        ParaKind::Parathread
487
                    } else {
488
72
                        ParaKind::Parachain
489
                    };
490
90
                    (
491
90
                        registered_para.para_id.into(),
492
90
                        ParaGenesisArgs {
493
90
                            validation_code: mock_validation_code(),
494
90
                            para_kind,
495
90
                            genesis_head: HeadData::from(vec![0u8]),
496
90
                        },
497
90
                    )
498
90
                })
499
68
                .collect(),
500
68
            ..Default::default()
501
68
        }
502
68
        .assimilate_storage(&mut t)
503
68
        .unwrap();
504
68

            
505
68
        pallet_services_payment::GenesisConfig::<Runtime> {
506
68
            para_id_credits: self
507
68
                .para_ids
508
68
                .clone()
509
68
                .into_iter()
510
90
                .map(|registered_para| {
511
90
                    (
512
90
                        registered_para.para_id.into(),
513
90
                        registered_para.block_production_credits,
514
90
                        registered_para.collator_assignment_credits,
515
90
                    )
516
90
                        .into()
517
90
                })
518
68
                .collect(),
519
68
        }
520
68
        .assimilate_storage(&mut t)
521
68
        .unwrap();
522
68

            
523
68
        runtime_common::paras_registrar::GenesisConfig::<Runtime> {
524
68
            next_free_para_id: self.next_free_para_id,
525
68
            ..Default::default()
526
68
        }
527
68
        .assimilate_storage(&mut t)
528
68
        .unwrap();
529
68

            
530
68
        // TODO: add here pallet_services_payment::GenesisConfig
531
68

            
532
68
        pallet_configuration::GenesisConfig::<Runtime> {
533
68
            config: self.config,
534
68
            ..Default::default()
535
68
        }
536
68
        .assimilate_storage(&mut t)
537
68
        .unwrap();
538
68

            
539
68
        runtime_parachains::configuration::GenesisConfig::<Runtime> {
540
68
            config: self.relay_config,
541
68
        }
542
68
        .assimilate_storage(&mut t)
543
68
        .unwrap();
544
68

            
545
68
        let mut keys: Vec<_> = Vec::new();
546
68
        if !self.validators.is_empty() {
547
68
            let validator_keys: Vec<_> = self
548
68
                .validators
549
68
                .clone()
550
68
                .into_iter()
551
136
                .map(|(account, _balance)| {
552
136
                    let authority_keys =
553
136
                        get_authority_keys_from_seed(&account.to_string(), self.keystore.as_ref());
554
136
                    (
555
136
                        account.clone(),
556
136
                        account,
557
136
                        crate::SessionKeys {
558
136
                            babe: authority_keys.babe.clone(),
559
136
                            grandpa: authority_keys.grandpa.clone(),
560
136
                            para_validator: authority_keys.para_validator.clone(),
561
136
                            para_assignment: authority_keys.para_assignment.clone(),
562
136
                            authority_discovery: authority_keys.authority_discovery.clone(),
563
136
                            beefy: authority_keys.beefy.clone(),
564
136
                            nimbus: authority_keys.nimbus.clone(),
565
136
                        },
566
136
                    )
567
136
                })
568
68
                .collect();
569
68
            keys.extend(validator_keys)
570
        }
571

            
572
68
        if !self.collators.is_empty() {
573
            // We set invulnerables in pallet_invulnerables
574
51
            let invulnerables: Vec<AccountId> = self
575
51
                .collators
576
51
                .clone()
577
51
                .into_iter()
578
147
                .map(|(account, _balance)| account)
579
51
                .collect();
580
51

            
581
51
            pallet_invulnerables::GenesisConfig::<Runtime> {
582
51
                invulnerables: invulnerables.clone(),
583
51
            }
584
51
            .assimilate_storage(&mut t)
585
51
            .unwrap();
586
51

            
587
51
            // But we also initialize their keys in the session pallet
588
51
            // We discard those that had the key initialized already
589
51
            // from the validator list
590
51
            // in other words, for testing purposes we allow to inject a validator account
591
51
            // in the collator list
592
51
            let validator_unique_accounts: Vec<_> = self
593
51
                .validators
594
51
                .iter()
595
102
                .map(|(account, _)| account.clone())
596
51
                .collect();
597
51
            let collator_keys: Vec<_> = self
598
51
                .collators
599
51
                .into_iter()
600
147
                .filter_map(|(account, _balance)| {
601
147
                    if validator_unique_accounts.contains(&account) {
602
102
                        None
603
                    } else {
604
45
                        let authority_keys =
605
45
                            get_authority_keys_from_seed(&account.to_string(), None);
606
45
                        Some((
607
45
                            account.clone(),
608
45
                            account,
609
45
                            crate::SessionKeys {
610
45
                                babe: authority_keys.babe.clone(),
611
45
                                grandpa: authority_keys.grandpa.clone(),
612
45
                                para_validator: authority_keys.para_validator.clone(),
613
45
                                para_assignment: authority_keys.para_assignment.clone(),
614
45
                                authority_discovery: authority_keys.authority_discovery.clone(),
615
45
                                beefy: authority_keys.beefy.clone(),
616
45
                                nimbus: authority_keys.nimbus.clone(),
617
45
                            },
618
45
                        ))
619
                    }
620
147
                })
621
51
                .collect();
622
51
            keys.extend(collator_keys)
623
17
        }
624

            
625
68
        pallet_session::GenesisConfig::<Runtime> {
626
68
            keys,
627
68
            ..Default::default()
628
68
        }
629
68
        .assimilate_storage(&mut t)
630
68
        .unwrap();
631
68

            
632
68
        pallet_sudo::GenesisConfig::<Runtime> { key: self.sudo }
633
68
            .assimilate_storage(&mut t)
634
68
            .unwrap();
635
68
        t
636
68
    }
637

            
638
68
    pub fn build(self) -> sp_io::TestExternalities {
639
68
        let keystore = self.keystore.clone();
640
68
        let t = self.build_storage();
641
68
        let mut ext = sp_io::TestExternalities::new(t);
642
68
        if let Some(keystore) = keystore {
643
7
            ext.register_extension(KeystoreExt(keystore));
644
61
        }
645
68
        ext.execute_with(|| {
646
68
            // Start block 1
647
68
            start_block();
648
68
        });
649
68
        ext
650
68
    }
651
}
652

            
653
99
pub fn root_origin() -> <Runtime as frame_system::Config>::RuntimeOrigin {
654
99
    <Runtime as frame_system::Config>::RuntimeOrigin::root()
655
99
}
656

            
657
107
pub fn origin_of(account_id: AccountId) -> <Runtime as frame_system::Config>::RuntimeOrigin {
658
107
    <Runtime as frame_system::Config>::RuntimeOrigin::signed(account_id)
659
107
}
660

            
661
16
pub fn inherent_origin() -> <Runtime as frame_system::Config>::RuntimeOrigin {
662
16
    <Runtime as frame_system::Config>::RuntimeOrigin::none()
663
16
}
664

            
665
/// This function is different in solochains: instead of creating a storage proof and calling the
666
/// `set_latest_author_data` inherent with that proof as argument, this writes to storage directly.
667
8
pub fn set_author_noting_inherent_data(builder: ParaHeaderSproofBuilder) {
668
8
    for (k, v) in builder.key_values() {
669
8
        frame_support::storage::unhashed::put_raw(&k, &v);
670
8
    }
671

            
672
8
    assert_ok!(RuntimeCall::AuthorNoting(
673
8
        pallet_author_noting::Call::<Runtime>::set_latest_author_data { data: () }
674
8
    )
675
8
    .dispatch(inherent_origin()));
676
8
}
677

            
678
90
pub fn empty_genesis_data() -> ContainerChainGenesisData {
679
90
    ContainerChainGenesisData {
680
90
        storage: Default::default(),
681
90
        name: Default::default(),
682
90
        id: Default::default(),
683
90
        fork_id: Default::default(),
684
90
        extensions: Default::default(),
685
90
        properties: Default::default(),
686
90
    }
687
90
}
688

            
689
2232
pub fn current_slot() -> u64 {
690
2232
    Babe::current_slot().into()
691
2232
}
692

            
693
21
pub fn block_credits_to_required_balance(number_of_blocks: u32, para_id: ParaId) -> Balance {
694
21
    let block_cost = BlockProductionCost::block_cost(&para_id).0;
695
21
    u128::from(number_of_blocks).saturating_mul(block_cost)
696
21
}
697

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

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

            
713
2232
fn take_new_inherent_data() -> Option<cumulus_primitives_core::relay_chain::InherentData> {
714
2232
    let data: Option<cumulus_primitives_core::relay_chain::InherentData> =
715
2232
        frame_support::storage::unhashed::take(b"ParasInherent");
716
2232

            
717
2232
    data
718
2232
}
719

            
720
8
pub fn set_new_inherent_data(data: cumulus_primitives_core::relay_chain::InherentData) {
721
8
    frame_support::storage::unhashed::put(b"ParasInherent", &data);
722
8
}
723

            
724
1
pub fn set_new_randomness_data(data: Option<[u8; 32]>) {
725
1
    pallet_babe::AuthorVrfRandomness::<Runtime>::set(data);
726
1
}
727

            
728
/// Mock the inherent that sets validation data in ParachainSystem, which
729
/// contains the `relay_chain_block_number`, which is used in `collator-assignment` as a
730
/// source of randomness.
731
8
pub fn set_paras_inherent(data: cumulus_primitives_core::relay_chain::InherentData) {
732
8
    // In order for this inherent to work, we need to match the parent header
733
8
    // the parent header does not play a significant role in the rest of the framework so
734
8
    // we are simply going to mock it
735
8
    System::set_parent_hash(data.parent_header.hash());
736
8
    assert_ok!(
737
8
        RuntimeCall::ParaInherent(parachains_paras_inherent::Call::<Runtime>::enter { data })
738
8
            .dispatch(inherent_origin())
739
8
    );
740
5
    frame_support::storage::unhashed::kill(&frame_support::storage::storage_prefix(
741
5
        b"ParaInherent",
742
5
        b"Included",
743
5
    ));
744
5
}
745

            
746
pub(crate) struct ParasInherentTestBuilder<T: runtime_parachains::paras_inherent::Config> {
747
    /// Starting block number; we expect it to get incremented on session setup.
748
    block_number: BlockNumberFor<T>,
749
    /// Paras here will both be backed in the inherent data and already occupying a core (which is
750
    /// freed via bitfields).
751
    ///
752
    /// Map from para id to number of validity votes. Core indices are generated based on
753
    /// `elastic_paras` configuration. Each para id in `elastic_paras` gets the
754
    /// specified amount of consecutive cores assigned to it. If a para id is not present
755
    /// in `elastic_paras` it get assigned to a single core.
756
    backed_and_concluding_paras: BTreeMap<u32, u32>,
757

            
758
    /// Paras which don't yet occupy a core, but will after the inherent has been processed.
759
    backed_in_inherent_paras: BTreeMap<u32, u32>,
760
    _phantom: core::marker::PhantomData<T>,
761
}
762

            
763
139
pub fn mock_validation_code() -> ValidationCode {
764
139
    ValidationCode(vec![1; 10])
765
139
}
766

            
767
#[allow(dead_code)]
768
impl<T: runtime_parachains::paras_inherent::Config> ParasInherentTestBuilder<T> {
769
    /// Create a new `BenchBuilder` with some opinionated values that should work with the rest
770
    /// of the functions in this implementation.
771
8
    pub(crate) fn new() -> Self {
772
8
        ParasInherentTestBuilder {
773
8
            block_number: Zero::zero(),
774
8
            backed_and_concluding_paras: Default::default(),
775
8
            backed_in_inherent_paras: Default::default(),
776
8
            _phantom: core::marker::PhantomData::<T>,
777
8
        }
778
8
    }
779

            
780
    /// Set a map from para id seed to number of validity votes.
781
8
    pub(crate) fn set_backed_and_concluding_paras(
782
8
        mut self,
783
8
        backed_and_concluding_paras: BTreeMap<u32, u32>,
784
8
    ) -> Self {
785
8
        self.backed_and_concluding_paras = backed_and_concluding_paras;
786
8
        self
787
8
    }
788

            
789
    /// Set a map from para id seed to number of validity votes for votes in inherent data.
790
    pub(crate) fn set_backed_in_inherent_paras(mut self, backed: BTreeMap<u32, u32>) -> Self {
791
        self.backed_in_inherent_paras = backed;
792
        self
793
    }
794

            
795
    /// Mock header.
796
42
    pub(crate) fn header(block_number: BlockNumberFor<T>) -> HeaderFor<T> {
797
42
        HeaderFor::<T>::new(
798
42
            block_number,       // `block_number`,
799
42
            Default::default(), // `extrinsics_root`,
800
42
            Default::default(), // `storage_root`,
801
42
            Default::default(), // `parent_hash`,
802
42
            Default::default(), // digest,
803
42
        )
804
42
    }
805

            
806
    /// Maximum number of validators that may be part of a validator group.
807
8
    pub(crate) fn fallback_max_validators() -> u32 {
808
8
        runtime_parachains::configuration::ActiveConfig::<T>::get()
809
8
            .max_validators
810
8
            .unwrap_or(200)
811
8
    }
812

            
813
    /// Maximum number of validators participating in parachains consensus (a.k.a. active
814
    /// validators).
815
8
    fn max_validators(&self) -> u32 {
816
8
        Self::fallback_max_validators()
817
8
    }
818

            
819
    /// Maximum number of validators per core (a.k.a. max validators per group). This value is used
820
    /// if none is explicitly set on the builder.
821
8
    pub(crate) fn fallback_max_validators_per_core() -> u32 {
822
8
        runtime_parachains::configuration::ActiveConfig::<T>::get()
823
8
            .scheduler_params
824
8
            .max_validators_per_core
825
8
            .unwrap_or(5)
826
8
    }
827

            
828
    /// Get the maximum number of validators per core.
829
8
    fn max_validators_per_core(&self) -> u32 {
830
8
        Self::fallback_max_validators_per_core()
831
8
    }
832

            
833
    /// Get the maximum number of cores we expect from this configuration.
834
8
    pub(crate) fn max_cores(&self) -> u32 {
835
8
        self.max_validators() / self.max_validators_per_core()
836
8
    }
837

            
838
    /// Create an `AvailabilityBitfield` where `concluding` is a map where each key is a core index
839
    /// that is concluding and `cores` is the total number of cores in the system.
840
8
    fn availability_bitvec(used_cores: usize, cores: usize) -> AvailabilityBitfield {
841
8
        let mut bitfields = bitvec::bitvec![u8, bitvec::order::Lsb0; 0; 0];
842
320
        for i in 0..cores {
843
320
            if i < used_cores {
844
9
                bitfields.push(true);
845
9
            } else {
846
311
                bitfields.push(false)
847
            }
848
        }
849

            
850
8
        bitfields.into()
851
8
    }
852

            
853
    /// Create a bitvec of `validators` length with all yes votes.
854
    fn validator_availability_votes_yes(validators: usize) -> BitVec<u8, bitvec::order::Lsb0> {
855
        // every validator confirms availability.
856
        bitvec::bitvec![u8, bitvec::order::Lsb0; 1; validators]
857
    }
858

            
859
18
    pub fn mock_head_data() -> HeadData {
860
18
        let max_head_size =
861
18
            runtime_parachains::configuration::ActiveConfig::<T>::get().max_head_data_size;
862
18
        HeadData(vec![0xFF; max_head_size as usize])
863
18
    }
864

            
865
    /// Number of the relay parent block.
866
18
    fn relay_parent_number(&self) -> u32 {
867
18
        (Self::block_number() - One::one())
868
18
            .try_into()
869
18
            .map_err(|_| ())
870
18
            .expect("Self::block_number() is u32")
871
18
    }
872

            
873
    /// Create backed candidates for `cores_with_backed_candidates`. You need these cores to be
874
    /// scheduled _within_ paras inherent, which requires marking the available bitfields as fully
875
    /// available.
876
    /// - `cores_with_backed_candidates` Mapping of `para_id` seed to number of
877
    /// validity votes.
878
    /// Important! this uses a BtreeMap, which means that elements will use increasing core orders
879
    /// example: if we have parachains 1000, 1001, and 1002, they will use respectively cores
880
    /// 0 1 and 2. There is no way in which we force 1002 to use core 0 in this setup
881
8
    fn create_backed_candidates(
882
8
        &self,
883
8
        paras_with_backed_candidates: &BTreeMap<u32, u32>,
884
8
    ) -> Vec<BackedCandidate<T::Hash>> {
885
8
        let current_session = runtime_parachains::shared::CurrentSessionIndex::<T>::get();
886
8
        // We need to refetch validators since they have been shuffled.
887
8
        let validators_shuffled =
888
8
            runtime_parachains::session_info::Sessions::<T>::get(current_session)
889
8
                .unwrap()
890
8
                .validators
891
8
                .clone();
892
8

            
893
8
        let config = runtime_parachains::configuration::ActiveConfig::<T>::get();
894
8
        let mut current_core_idx = 0u32;
895
8
        paras_with_backed_candidates
896
8
            .iter()
897
9
            .flat_map(|(seed, num_votes)| {
898
9
                assert!(*num_votes <= validators_shuffled.len() as u32);
899

            
900
9
                let para_id = ParaId::from(*seed);
901
9
                let prev_head_non_mut = runtime_parachains::paras::Heads::<T>::get(para_id);
902
9
                let prev_head = prev_head_non_mut.unwrap_or(Self::mock_head_data());
903
9
                // How many chained candidates we want to build ?
904
9
                (0..1)
905
9
                    .map(|chain_idx| {
906
9
                        let core_idx = CoreIndex::from(current_core_idx);
907
9
                        // Advance core index.
908
9
                        current_core_idx += 1;
909
9
                        let group_idx =
910
9
                            Self::group_assigned_to_core(core_idx, Self::block_number())
911
9
                                .unwrap_or_else(|| {
912
                                    panic!("Validator group not assigned to core {:?}", core_idx)
913
9
                                });
914
9

            
915
9
                        let header = Self::header(Self::block_number());
916
9
                        let relay_parent = header.hash();
917
9

            
918
9
                        // Set the head data so it can be used while validating the signatures on
919
9
                        // the candidate receipt.
920
9
                        let mut head_data = Self::mock_head_data();
921
9

            
922
9
                        if chain_idx == 0 {
923
9
                            // Only first parahead of the chain needs to be set in storage.
924
9
                            Self::heads_insert(&para_id, prev_head.clone());
925
9
                        } else {
926
                            // Make each candidate head data unique to avoid cycles.
927
                            head_data.0[0] = chain_idx;
928
                        }
929

            
930
9
                        let persisted_validation_data = PersistedValidationData::<T::Hash> {
931
9
                            // To form a chain we set parent head to previous block if any, or
932
9
                            // default to what is in storage already setup.
933
9
                            parent_head: prev_head.clone(),
934
9
                            relay_parent_number: self.relay_parent_number() + 1,
935
9
                            relay_parent_storage_root: Default::default(),
936
9
                            max_pov_size: config.max_pov_size,
937
9
                        };
938
9

            
939
9
                        let persisted_validation_data_hash = persisted_validation_data.hash();
940
9

            
941
9
                        let pov_hash = Default::default();
942
9
                        let validation_code_hash = mock_validation_code().hash();
943
9
                        let payload =
944
9
                            cumulus_primitives_core::relay_chain::collator_signature_payload(
945
9
                                &relay_parent,
946
9
                                &para_id,
947
9
                                &persisted_validation_data_hash,
948
9
                                &pov_hash,
949
9
                                &validation_code_hash,
950
9
                            );
951
9

            
952
9
                        let collator_pair = CollatorPair::generate().0;
953
9

            
954
9
                        let signature = collator_pair.sign(&payload);
955
9

            
956
9
                        let group_validators = Self::group_validators(group_idx).unwrap();
957
9

            
958
9
                        let candidate = CommittedCandidateReceipt::<T::Hash> {
959
9
                            descriptor: CandidateDescriptor::<T::Hash> {
960
9
                                para_id,
961
9
                                relay_parent,
962
9
                                collator: collator_pair.public(),
963
9
                                persisted_validation_data_hash,
964
9
                                pov_hash,
965
9
                                erasure_root: Default::default(),
966
9
                                signature,
967
9
                                para_head: prev_head.hash(),
968
9
                                validation_code_hash,
969
9
                            },
970
9
                            commitments: CandidateCommitments::<u32> {
971
9
                                upward_messages: Default::default(),
972
9
                                horizontal_messages: Default::default(),
973
9
                                new_validation_code: None,
974
9
                                head_data: prev_head.clone(),
975
9
                                processed_downward_messages: 0,
976
9
                                hrmp_watermark: self.relay_parent_number() + 1,
977
9
                            },
978
9
                        };
979
9

            
980
9
                        let candidate_hash = candidate.hash();
981
9

            
982
9
                        let validity_votes: Vec<_> = group_validators
983
9
                            .iter()
984
9
                            .take(*num_votes as usize)
985
9
                            .map(|val_idx| {
986
9
                                let public = validators_shuffled.get(*val_idx).unwrap();
987
9

            
988
9
                                let signature_ctx = SigningContext {
989
9
                                    parent_hash: Self::header(Self::block_number()).hash(),
990
9
                                    session_index: Session::current_index(),
991
9
                                };
992
9
                                let sig = UncheckedSigned::<CompactStatement>::benchmark_sign(
993
9
                                    public,
994
9
                                    CompactStatement::Valid(candidate_hash),
995
9
                                    &signature_ctx,
996
9
                                    *val_idx,
997
9
                                )
998
9
                                .benchmark_signature();
999
9

            
9
                                ValidityAttestation::Explicit(sig.clone())
9
                            })
9
                            .collect();
9

            
9
                        // Check if the elastic scaling bit is set, if so we need to supply the core
9
                        // index in the generated candidate.
9
                        let core_idx = runtime_parachains::configuration::ActiveConfig::<T>::get()
9
                            .node_features
9
                            .get(FeatureIndex::ElasticScalingMVP as usize)
9
                            .map(|_the_bit| core_idx);
9

            
9
                        BackedCandidate::<T::Hash>::new(
9
                            candidate,
9
                            validity_votes,
9
                            bitvec::bitvec![u8, bitvec::order::Lsb0; 1; group_validators.len()],
9
                            core_idx,
9
                        )
9
                    })
9
                    .collect::<Vec<_>>()
9
            })
8
            .collect()
8
    }
    /// Get the group assigned to a specific core by index at the current block number. Result
    /// undefined if the core index is unknown or the block number is less than the session start
    /// index.
9
    pub(crate) fn group_assigned_to_core(
9
        core: CoreIndex,
9
        at: BlockNumberFor<T>,
9
    ) -> Option<GroupIndex> {
9
        let config = runtime_parachains::configuration::ActiveConfig::<T>::get();
9
        let session_start_block = runtime_parachains::scheduler::SessionStartBlock::<T>::get();
9

            
9
        if at < session_start_block {
            return None;
9
        }
9

            
9
        let validator_groups = runtime_parachains::scheduler::ValidatorGroups::<T>::get();
9

            
9
        if core.0 as usize >= validator_groups.len() {
            return None;
9
        }
9

            
9
        let rotations_since_session_start: BlockNumberFor<T> =
9
            (at - session_start_block) / config.scheduler_params.group_rotation_frequency;
9

            
9
        let rotations_since_session_start =
9
            <BlockNumberFor<T> as TryInto<u32>>::try_into(rotations_since_session_start)
9
                .unwrap_or(0);
9
        // Error case can only happen if rotations occur only once every u32::max(),
9
        // so functionally no difference in behavior.
9

            
9
        let group_idx =
9
            (core.0 as usize + rotations_since_session_start as usize) % validator_groups.len();
9
        Some(GroupIndex(group_idx as u32))
9
    }
    /// Get the validators in the given group, if the group index is valid for this session.
9
    pub(crate) fn group_validators(group_index: GroupIndex) -> Option<Vec<ValidatorIndex>> {
9
        runtime_parachains::scheduler::ValidatorGroups::<T>::get()
9
            .get(group_index.0 as usize)
9
            .cloned()
9
    }
9
    pub fn heads_insert(para_id: &ParaId, head_data: HeadData) {
9
        runtime_parachains::paras::Heads::<T>::insert(para_id, head_data);
9
    }
    /// Build a scenario for testing.
    ///
    /// Note that this API only allows building scenarios where the `backed_and_concluding_paras`
    /// are mutually exclusive with the cores for disputes. So
    /// `backed_and_concluding_paras.len() + dispute_sessions.len() + backed_in_inherent_paras` must
    /// be less than the max number of cores.
8
    pub(crate) fn build(self) -> ParachainsInherentData<HeaderFor<T>> {
8
        let current_session = runtime_parachains::shared::CurrentSessionIndex::<T>::get();
8
        // We need to refetch validators since they have been shuffled.
8
        let validators = runtime_parachains::session_info::Sessions::<T>::get(current_session)
8
            .unwrap()
8
            .validators
8
            .clone();
8

            
8
        let max_cores = self.max_cores() as usize;
8

            
8
        let used_cores =
8
            self.backed_and_concluding_paras.len() + self.backed_in_inherent_paras.len();
8
        assert!(used_cores <= max_cores);
8
        let mut backed_in_inherent = BTreeMap::new();
8
        backed_in_inherent.append(&mut self.backed_and_concluding_paras.clone());
8
        backed_in_inherent.append(&mut self.backed_in_inherent_paras.clone());
8
        let backed_candidates = self.create_backed_candidates(&backed_in_inherent);
8

            
8
        let availability_bitvec = Self::availability_bitvec(used_cores, max_cores);
8

            
8
        let bitfields: Vec<UncheckedSigned<AvailabilityBitfield>> = validators
8
            .iter()
8
            .enumerate()
16
            .map(|(i, public)| {
16
                UncheckedSigned::<AvailabilityBitfield>::benchmark_sign(
16
                    public,
16
                    availability_bitvec.clone(),
16
                    &SigningContext {
16
                        parent_hash: Self::header(Self::block_number()).hash(),
16
                        session_index: Session::current_index(),
16
                    },
16
                    ValidatorIndex(i as u32),
16
                )
16
            })
8
            .collect();
8

            
8
        ParachainsInherentData {
8
            bitfields,
8
            backed_candidates,
8
            disputes: vec![],
8
            parent_header: Self::header(Self::block_number()),
8
        }
8
    }
69
    pub(crate) fn block_number() -> BlockNumberFor<T> {
69
        frame_system::Pallet::<T>::block_number()
69
    }
}
use {
    frame_support::StorageHasher, primitives::vstaging::SchedulerParams,
    tp_traits::ParathreadParams,
};
2
pub fn storage_map_final_key<H: frame_support::StorageHasher>(
2
    pallet_prefix: &str,
2
    map_name: &str,
2
    key: &[u8],
2
) -> Vec<u8> {
2
    let key_hashed = H::hash(key);
2
    let pallet_prefix_hashed = frame_support::Twox128::hash(pallet_prefix.as_bytes());
2
    let storage_prefix_hashed = frame_support::Twox128::hash(map_name.as_bytes());
2

            
2
    let mut final_key = Vec::with_capacity(
2
        pallet_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.as_ref().len(),
2
    );
2

            
2
    final_key.extend_from_slice(&pallet_prefix_hashed[..]);
2
    final_key.extend_from_slice(&storage_prefix_hashed[..]);
2
    final_key.extend_from_slice(key_hashed.as_ref());
2

            
2
    final_key
2
}
23
pub fn set_dummy_boot_node(para_manager: RuntimeOrigin, para_id: ParaId) {
    use {
        crate::{PreserversAssignmentPaymentExtra, PreserversAssignmentPaymentRequest},
        pallet_data_preservers::{ParaIdsFilter, Profile, ProfileMode},
    };
23
    let profile = Profile {
23
        url:
23
            b"/ip4/127.0.0.1/tcp/33049/ws/p2p/12D3KooWHVMhQDHBpj9vQmssgyfspYecgV6e3hH1dQVDUkUbCYC9"
23
                .to_vec()
23
                .try_into()
23
                .expect("to fit in BoundedVec"),
23
        para_ids: ParaIdsFilter::AnyParaId,
23
        mode: ProfileMode::Bootnode,
23
        assignment_request: PreserversAssignmentPaymentRequest::Free,
23
    };
23

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

            
23
    DataPreservers::start_assignment(
23
        para_manager,
23
        profile_id,
23
        para_id,
23
        PreserversAssignmentPaymentExtra::Free,
23
    )
23
    .expect("assignment to work");
23

            
23
    assert!(
23
        pallet_data_preservers::Assignments::<Runtime>::get(para_id).contains(&profile_id),
        "profile should be correctly assigned"
    );
23
}