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
    beefy_primitives::{ecdsa_crypto::AuthorityId as BeefyId, ConsensusLog, BEEFY_ENGINE_ID},
26
    bitvec::prelude::BitVec,
27
    cumulus_primitives_core::{
28
        relay_chain::{
29
            node_features::FeatureIndex, AvailabilityBitfield, BackedCandidate,
30
            CandidateCommitments, CandidateDescriptor, CollatorPair, CommittedCandidateReceipt,
31
            CompactStatement, CoreIndex, GroupIndex, HeadData,
32
            InherentData as ParachainsInherentData, PersistedValidationData, SigningContext,
33
            UncheckedSigned, ValidationCode, ValidatorIndex, ValidityAttestation,
34
        },
35
        ParaId,
36
    },
37
    frame_support::{
38
        assert_ok,
39
        traits::{OnFinalize, OnInitialize},
40
    },
41
    frame_system::pallet_prelude::{BlockNumberFor, HeaderFor},
42
    nimbus_primitives::NimbusId,
43
    pallet_registrar_runtime_api::ContainerChainGenesisData,
44
    pallet_services_payment::{ProvideBlockProductionCost, ProvideCollatorAssignmentCost},
45
    parity_scale_codec::{Decode, Encode, MaxEncodedLen},
46
    runtime_parachains::{
47
        paras::{ParaGenesisArgs, ParaKind},
48
        paras_inherent as parachains_paras_inherent,
49
    },
50
    sp_core::Pair,
51
    sp_keystore::{KeystoreExt, KeystorePtr},
52
    sp_runtime::{
53
        traits::{Dispatchable, Header, One, SaturatedConversion, Zero},
54
        BuildStorage, Digest, DigestItem,
55
    },
56
    sp_std::collections::btree_map::BTreeMap,
57
    test_relay_sproof_builder::ParaHeaderSproofBuilder,
58
};
59

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

            
67
pub const UNIT: Balance = 1_000_000_000_000_000_000;
68

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

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

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

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

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

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

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

            
109
3
pub fn get_beefy_digest(log: ConsensusLog<BeefyId>) -> DigestItem {
110
3
    DigestItem::Consensus(BEEFY_ENGINE_ID, log.encode())
111
3
}
112

            
113
146
pub fn run_to_session(n: u32) {
114
146
    run_to_block(session_to_block(n));
115
146
}
116

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

            
133
190
    let mut summaries = BTreeMap::new();
134

            
135
3048
    while System::block_number() < n {
136
2858
        let summary = run_block();
137
2858
        let block_number = System::block_number();
138
2858
        summaries.insert(block_number, summary);
139
2858
    }
140

            
141
190
    summaries
142
190
}
143

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

            
157
2981
pub fn insert_authorities_and_slot_digests(slot: u64) {
158
2981
    let pre_digest = Digest {
159
2981
        logs: vec![DigestItem::PreRuntime(
160
2981
            BABE_ENGINE_ID,
161
2981
            PreDigest::SecondaryPlain(SecondaryPlainPreDigest {
162
2981
                slot: slot.into(),
163
2981
                authority_index: 0,
164
2981
            })
165
2981
            .encode(),
166
2981
        )],
167
2981
    };
168
2981

            
169
2981
    System::reset_events();
170
2981
    System::initialize(
171
2981
        &(System::block_number() + 1),
172
2981
        &System::parent_hash(),
173
2981
        &pre_digest,
174
2981
    );
175
2981
}
176

            
177
#[derive(Debug, Clone, Eq, PartialEq)]
178
pub struct RunSummary {
179
    pub inflation: Balance,
180
}
181

            
182
#[derive(Clone, Encode, Decode, PartialEq, Debug, scale_info::TypeInfo, MaxEncodedLen)]
183
enum RunBlockState {
184
2883
    Start(u32),
185
2882
    End(u32),
186
}
187

            
188
impl RunBlockState {
189
5864
    fn assert_can_advance(&self, new_state: &RunBlockState) {
190
5864
        match self {
191
2883
            RunBlockState::Start(n) => {
192
2883
                assert_eq!(
193
2883
                    new_state,
194
2883
                    &RunBlockState::End(*n),
195
                    "expected a call to end_block({}), but user called {:?}",
196
                    *n,
197
                    new_state
198
                );
199
            }
200
2981
            RunBlockState::End(n) => {
201
2981
                assert_eq!(
202
2981
                    new_state,
203
2981
                    &RunBlockState::Start(*n + 1),
204
                    "expected a call to start_block({}), but user called {:?}",
205
                    *n + 1,
206
                    new_state
207
                )
208
            }
209
        }
210
5864
    }
211
}
212

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

            
229
2981
pub fn start_block() -> RunSummary {
230
2981
    let block_number = System::block_number();
231
2981
    advance_block_state_machine(RunBlockState::Start(block_number + 1));
232
2981

            
233
2981
    insert_authorities_and_slot_digests(current_slot() + 1);
234
2981

            
235
2981
    // Initialize the new block
236
2981
    Babe::on_initialize(System::block_number());
237
2981
    ContainerRegistrar::on_initialize(System::block_number());
238
2981
    Session::on_initialize(System::block_number());
239
2981
    Initializer::on_initialize(System::block_number());
240
2981
    TanssiCollatorAssignment::on_initialize(System::block_number());
241
2981

            
242
2981
    let current_issuance = Balances::total_issuance();
243
2981
    InflationRewards::on_initialize(System::block_number());
244
2981
    let new_issuance = Balances::total_issuance();
245
2981

            
246
2981
    let maybe_mock_inherent = take_new_inherent_data();
247
2981
    if let Some(mock_inherent_data) = maybe_mock_inherent {
248
8
        set_paras_inherent(mock_inherent_data);
249
2973
    }
250

            
251
2981
    Beefy::on_initialize(System::block_number());
252
2981
    Mmr::on_initialize(System::block_number());
253
2981
    BeefyMmrLeaf::on_initialize(System::block_number());
254
2981

            
255
2981
    RunSummary {
256
2981
        inflation: new_issuance - current_issuance,
257
2981
    }
258
2981
}
259

            
260
2883
pub fn end_block() {
261
2883
    let block_number = System::block_number();
262
2883
    advance_block_state_machine(RunBlockState::End(block_number));
263
2883
    // Finalize the block
264
2883
    Babe::on_finalize(System::block_number());
265
2883
    Session::on_finalize(System::block_number());
266
2883
    Grandpa::on_finalize(System::block_number());
267
2883
    TransactionPayment::on_finalize(System::block_number());
268
2883
    Initializer::on_finalize(System::block_number());
269
2883
    ContainerRegistrar::on_finalize(System::block_number());
270
2883
    TanssiCollatorAssignment::on_finalize(System::block_number());
271
2883
    Beefy::on_finalize(System::block_number());
272
2883
    Mmr::on_finalize(System::block_number());
273
2883
    BeefyMmrLeaf::on_finalize(System::block_number());
274
2883
}
275

            
276
2879
pub fn run_block() -> RunSummary {
277
2879
    end_block();
278
2879

            
279
2879
    start_block()
280
2879
}
281

            
282
#[derive(Default, Clone)]
283
pub struct ParaRegistrationParams {
284
    pub para_id: u32,
285
    pub genesis_data: ContainerChainGenesisData,
286
    pub block_production_credits: u32,
287
    pub collator_assignment_credits: u32,
288
    pub parathread_params: Option<tp_traits::ParathreadParams>,
289
}
290

            
291
impl From<(u32, ContainerChainGenesisData, u32, u32)> for ParaRegistrationParams {
292
10
    fn from(value: (u32, ContainerChainGenesisData, u32, u32)) -> Self {
293
10
        Self {
294
10
            para_id: value.0,
295
10
            genesis_data: value.1,
296
10
            block_production_credits: value.2,
297
10
            collator_assignment_credits: value.3,
298
10
            parathread_params: None,
299
10
        }
300
10
    }
301
}
302

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

            
314
#[derive(Clone)]
315
pub struct ExtBuilder {
316
    // endowed accounts with balances
317
    balances: Vec<(AccountId, Balance)>,
318
    // [validator, amount]
319
    validators: Vec<(AccountId, Balance)>,
320
    // [collator, amount]
321
    collators: Vec<(AccountId, Balance)>,
322
    // sudo key
323
    sudo: Option<AccountId>,
324
    // list of registered para ids: para_id, genesis_data, boot_nodes, block_credits, session_credits
325
    para_ids: Vec<ParaRegistrationParams>,
326
    // configuration to apply
327
    config: pallet_configuration::HostConfiguration,
328
    relay_config: runtime_parachains::configuration::HostConfiguration<BlockNumberFor<Runtime>>,
329
    own_para_id: Option<ParaId>,
330
    next_free_para_id: ParaId,
331
    keystore: Option<KeystorePtr>,
332
}
333

            
334
impl Default for ExtBuilder {
335
99
    fn default() -> Self {
336
99
        Self {
337
99
            balances: vec![
338
99
                // Alice gets 10k extra tokens for her mapping deposit
339
99
                (AccountId::from(ALICE), 210_000 * UNIT),
340
99
                (AccountId::from(BOB), 100_000 * UNIT),
341
99
            ],
342
99
            validators: vec![
343
99
                (AccountId::from(ALICE), 210 * UNIT),
344
99
                (AccountId::from(BOB), 100 * UNIT),
345
99
            ],
346
99
            collators: Default::default(),
347
99
            sudo: Default::default(),
348
99
            para_ids: Default::default(),
349
99
            config: default_config(),
350
99
            relay_config: runtime_parachains::configuration::HostConfiguration {
351
99
                scheduler_params: SchedulerParams {
352
99
                    num_cores: 6,
353
99
                    ..Default::default()
354
99
                },
355
99
                max_head_data_size: 20500,
356
99
                ..Default::default()
357
99
            },
358
99
            own_para_id: Default::default(),
359
99
            next_free_para_id: Default::default(),
360
99
            keystore: None,
361
99
        }
362
99
    }
363
}
364

            
365
impl ExtBuilder {
366
86
    pub fn with_balances(mut self, balances: Vec<(AccountId, Balance)>) -> Self {
367
86
        self.balances = balances;
368
86
        self
369
86
    }
370

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

            
376
7
    pub fn with_validators(mut self, validators: Vec<(AccountId, Balance)>) -> Self {
377
7
        self.validators = validators;
378
7
        self
379
7
    }
380

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

            
386
12
    pub fn with_para_ids(mut self, para_ids: Vec<ParaRegistrationParams>) -> Self {
387
12
        self.para_ids = para_ids;
388
12
        self
389
12
    }
390

            
391
    /// Helper function like `with_para_ids` but registering parachains with an empty genesis data,
392
    /// and max amount of credits.
393
24
    pub fn with_empty_parachains(mut self, para_ids: Vec<u32>) -> Self {
394
24
        self.para_ids = para_ids
395
24
            .into_iter()
396
58
            .map(|para_id| ParaRegistrationParams {
397
58
                para_id,
398
58
                genesis_data: empty_genesis_data(),
399
58
                block_production_credits: u32::MAX,
400
58
                collator_assignment_credits: u32::MAX,
401
58
                parathread_params: None,
402
58
            })
403
24
            .collect();
404
24
        self
405
24
    }
406

            
407
5
    pub fn with_additional_empty_parathreads(mut self, para_ids: Vec<u32>) -> Self {
408
5
        self.para_ids = self
409
5
            .para_ids
410
5
            .iter()
411
5
            .cloned()
412
14
            .chain(para_ids.into_iter().map(|para_id| ParaRegistrationParams {
413
14
                para_id,
414
14
                genesis_data: empty_genesis_data(),
415
14
                block_production_credits: u32::MAX,
416
14
                collator_assignment_credits: u32::MAX,
417
14
                parathread_params: Some(ParathreadParams {
418
14
                    slot_frequency: Default::default(),
419
14
                }),
420
14
            }))
421
5
            .collect();
422
5
        self
423
5
    }
424

            
425
    // Maybe change to with_collators_config?
426
18
    pub fn with_config(mut self, config: pallet_configuration::HostConfiguration) -> Self {
427
18
        self.config = config;
428
18
        self
429
18
    }
430

            
431
    // Maybe change to with_collators_config?
432
12
    pub fn with_relay_config(
433
12
        mut self,
434
12
        relay_config: runtime_parachains::configuration::HostConfiguration<BlockNumberFor<Runtime>>,
435
12
    ) -> Self {
436
12
        self.relay_config = relay_config;
437
12
        self
438
12
    }
439

            
440
    // Maybe change to with_collators_config?
441
1
    pub fn with_next_free_para_id(mut self, para_id: ParaId) -> Self {
442
1
        self.next_free_para_id = para_id;
443
1
        self
444
1
    }
445

            
446
    // Maybe change to with_collators_config?
447
7
    pub fn with_keystore(mut self, keystore: KeystorePtr) -> Self {
448
7
        self.keystore = Some(keystore);
449
7
        self
450
7
    }
451

            
452
99
    pub fn build_storage(self) -> sp_core::storage::Storage {
453
99
        let mut t = frame_system::GenesisConfig::<Runtime>::default()
454
99
            .build_storage()
455
99
            .unwrap();
456
99

            
457
99
        pallet_babe::GenesisConfig::<Runtime> {
458
99
            ..Default::default()
459
99
        }
460
99
        .assimilate_storage(&mut t)
461
99
        .unwrap();
462
99

            
463
99
        pallet_balances::GenesisConfig::<Runtime> {
464
99
            balances: self.balances,
465
99
        }
466
99
        .assimilate_storage(&mut t)
467
99
        .unwrap();
468
99

            
469
99
        // We need to initialize these pallets first. When initializing pallet-session,
470
99
        // these values will be taken into account for collator-assignment.
471
99

            
472
99
        pallet_registrar::GenesisConfig::<Runtime> {
473
99
            para_ids: self
474
99
                .para_ids
475
99
                .iter()
476
99
                .cloned()
477
99
                .map(|registered_para| {
478
90
                    (
479
90
                        registered_para.para_id.into(),
480
90
                        registered_para.genesis_data,
481
90
                        registered_para.parathread_params,
482
90
                    )
483
99
                })
484
99
                .collect(),
485
99
            ..Default::default()
486
99
        }
487
99
        .assimilate_storage(&mut t)
488
99
        .unwrap();
489
99

            
490
99
        // We register mock wasm
491
99
        runtime_parachains::paras::GenesisConfig::<Runtime> {
492
99
            paras: self
493
99
                .para_ids
494
99
                .iter()
495
99
                .cloned()
496
99
                .map(|registered_para| {
497
90
                    let para_kind = if registered_para.parathread_params.is_some() {
498
18
                        ParaKind::Parathread
499
                    } else {
500
72
                        ParaKind::Parachain
501
                    };
502
90
                    (
503
90
                        registered_para.para_id.into(),
504
90
                        ParaGenesisArgs {
505
90
                            validation_code: mock_validation_code(),
506
90
                            para_kind,
507
90
                            genesis_head: HeadData::from(vec![0u8]),
508
90
                        },
509
90
                    )
510
99
                })
511
99
                .collect(),
512
99
            ..Default::default()
513
99
        }
514
99
        .assimilate_storage(&mut t)
515
99
        .unwrap();
516
99

            
517
99
        pallet_services_payment::GenesisConfig::<Runtime> {
518
99
            para_id_credits: self
519
99
                .para_ids
520
99
                .clone()
521
99
                .into_iter()
522
99
                .map(|registered_para| {
523
90
                    (
524
90
                        registered_para.para_id.into(),
525
90
                        registered_para.block_production_credits,
526
90
                        registered_para.collator_assignment_credits,
527
90
                    )
528
90
                        .into()
529
99
                })
530
99
                .collect(),
531
99
        }
532
99
        .assimilate_storage(&mut t)
533
99
        .unwrap();
534
99

            
535
99
        runtime_common::paras_registrar::GenesisConfig::<Runtime> {
536
99
            next_free_para_id: self.next_free_para_id,
537
99
            ..Default::default()
538
99
        }
539
99
        .assimilate_storage(&mut t)
540
99
        .unwrap();
541
99

            
542
99
        // TODO: add here pallet_services_payment::GenesisConfig
543
99

            
544
99
        pallet_configuration::GenesisConfig::<Runtime> {
545
99
            config: self.config,
546
99
            ..Default::default()
547
99
        }
548
99
        .assimilate_storage(&mut t)
549
99
        .unwrap();
550
99

            
551
99
        runtime_parachains::configuration::GenesisConfig::<Runtime> {
552
99
            config: self.relay_config,
553
99
        }
554
99
        .assimilate_storage(&mut t)
555
99
        .unwrap();
556
99

            
557
99
        let mut keys: Vec<_> = Vec::new();
558
99
        let mut non_authority_keys: Vec<_> = Vec::new();
559
99
        if !self.validators.is_empty() {
560
99
            let validator_keys: Vec<_> = self
561
99
                .validators
562
99
                .clone()
563
99
                .into_iter()
564
213
                .map(|(account, _balance)| {
565
213
                    let authority_keys =
566
213
                        get_authority_keys_from_seed(&account.to_string(), self.keystore.as_ref());
567
213
                    (
568
213
                        account.clone(),
569
213
                        account,
570
213
                        crate::SessionKeys {
571
213
                            babe: authority_keys.babe.clone(),
572
213
                            grandpa: authority_keys.grandpa.clone(),
573
213
                            para_validator: authority_keys.para_validator.clone(),
574
213
                            para_assignment: authority_keys.para_assignment.clone(),
575
213
                            authority_discovery: authority_keys.authority_discovery.clone(),
576
213
                            beefy: authority_keys.beefy.clone(),
577
213
                            nimbus: authority_keys.nimbus.clone(),
578
213
                        },
579
213
                    )
580
213
                })
581
99
                .collect();
582
99
            keys.extend(validator_keys)
583
        }
584

            
585
99
        if !self.collators.is_empty() {
586
            // We set invulnerables in pallet_invulnerables
587
51
            let invulnerables: Vec<AccountId> = self
588
51
                .collators
589
51
                .clone()
590
51
                .into_iter()
591
147
                .map(|(account, _balance)| account)
592
51
                .collect();
593
51

            
594
51
            pallet_invulnerables::GenesisConfig::<Runtime> {
595
51
                invulnerables: invulnerables.clone(),
596
51
            }
597
51
            .assimilate_storage(&mut t)
598
51
            .unwrap();
599
51

            
600
51
            // But we also initialize their keys in the session pallet
601
51
            // We discard those that had the key initialized already
602
51
            // from the validator list
603
51
            // in other words, for testing purposes we allow to inject a validator account
604
51
            // in the collator list
605
51
            let validator_unique_accounts: Vec<_> = self
606
51
                .validators
607
51
                .iter()
608
102
                .map(|(account, _)| account.clone())
609
51
                .collect();
610
51
            let collator_keys: Vec<_> = self
611
51
                .collators
612
51
                .into_iter()
613
147
                .filter_map(|(account, _balance)| {
614
147
                    if validator_unique_accounts.contains(&account) {
615
102
                        None
616
                    } else {
617
45
                        let authority_keys =
618
45
                            get_authority_keys_from_seed(&account.to_string(), None);
619
45
                        Some((
620
45
                            account.clone(),
621
45
                            account,
622
45
                            crate::SessionKeys {
623
45
                                babe: authority_keys.babe.clone(),
624
45
                                grandpa: authority_keys.grandpa.clone(),
625
45
                                para_validator: authority_keys.para_validator.clone(),
626
45
                                para_assignment: authority_keys.para_assignment.clone(),
627
45
                                authority_discovery: authority_keys.authority_discovery.clone(),
628
45
                                beefy: authority_keys.beefy.clone(),
629
45
                                nimbus: authority_keys.nimbus.clone(),
630
45
                            },
631
45
                        ))
632
                    }
633
147
                })
634
51
                .collect();
635
51
            non_authority_keys.extend(collator_keys)
636
48
        }
637

            
638
99
        pallet_external_validators::GenesisConfig::<Runtime> {
639
99
            skip_external_validators: false,
640
99
            whitelisted_validators: self
641
99
                .validators
642
99
                .iter()
643
213
                .map(|(account, _)| account.clone())
644
99
                .collect(),
645
99
        }
646
99
        .assimilate_storage(&mut t)
647
99
        .unwrap();
648
99

            
649
99
        pallet_session::GenesisConfig::<Runtime> {
650
99
            keys,
651
99
            non_authority_keys,
652
99
        }
653
99
        .assimilate_storage(&mut t)
654
99
        .unwrap();
655
99

            
656
99
        pallet_sudo::GenesisConfig::<Runtime> { key: self.sudo }
657
99
            .assimilate_storage(&mut t)
658
99
            .unwrap();
659
99
        t
660
99
    }
661

            
662
99
    pub fn build(self) -> sp_io::TestExternalities {
663
99
        let keystore = self.keystore.clone();
664
99
        let t = self.build_storage();
665
99
        let mut ext = sp_io::TestExternalities::new(t);
666
99
        if let Some(keystore) = keystore {
667
7
            ext.register_extension(KeystoreExt(keystore));
668
92
        }
669
99
        ext.execute_with(|| {
670
99
            // Start block 1
671
99
            start_block();
672
99
        });
673
99
        ext
674
99
    }
675
}
676

            
677
115
pub fn root_origin() -> <Runtime as frame_system::Config>::RuntimeOrigin {
678
115
    <Runtime as frame_system::Config>::RuntimeOrigin::root()
679
115
}
680

            
681
260
pub fn origin_of(account_id: AccountId) -> <Runtime as frame_system::Config>::RuntimeOrigin {
682
260
    <Runtime as frame_system::Config>::RuntimeOrigin::signed(account_id)
683
260
}
684

            
685
16
pub fn inherent_origin() -> <Runtime as frame_system::Config>::RuntimeOrigin {
686
16
    <Runtime as frame_system::Config>::RuntimeOrigin::none()
687
16
}
688

            
689
/// This function is different in solochains: instead of creating a storage proof and calling the
690
/// `set_latest_author_data` inherent with that proof as argument, this writes to storage directly.
691
8
pub fn set_author_noting_inherent_data(builder: ParaHeaderSproofBuilder) {
692
8
    for (k, v) in builder.key_values() {
693
8
        frame_support::storage::unhashed::put_raw(&k, &v);
694
8
    }
695

            
696
8
    assert_ok!(RuntimeCall::AuthorNoting(
697
8
        pallet_author_noting::Call::<Runtime>::set_latest_author_data { data: () }
698
8
    )
699
8
    .dispatch(inherent_origin()));
700
8
}
701

            
702
90
pub fn empty_genesis_data() -> ContainerChainGenesisData {
703
90
    ContainerChainGenesisData {
704
90
        storage: Default::default(),
705
90
        name: Default::default(),
706
90
        id: Default::default(),
707
90
        fork_id: Default::default(),
708
90
        extensions: Default::default(),
709
90
        properties: Default::default(),
710
90
    }
711
90
}
712

            
713
2981
pub fn current_slot() -> u64 {
714
2981
    Babe::current_slot().into()
715
2981
}
716

            
717
21
pub fn block_credits_to_required_balance(number_of_blocks: u32, para_id: ParaId) -> Balance {
718
21
    let block_cost = BlockProductionCost::block_cost(&para_id).0;
719
21
    u128::from(number_of_blocks).saturating_mul(block_cost)
720
21
}
721

            
722
4
pub fn collator_assignment_credits_to_required_balance(
723
4
    number_of_sessions: u32,
724
4
    para_id: ParaId,
725
4
) -> Balance {
726
4
    let collator_assignment_cost = CollatorAssignmentCost::collator_assignment_cost(&para_id).0;
727
4
    u128::from(number_of_sessions).saturating_mul(collator_assignment_cost)
728
4
}
729

            
730
pub const ALICE: [u8; 32] = [4u8; 32];
731
pub const BOB: [u8; 32] = [5u8; 32];
732
pub const CHARLIE: [u8; 32] = [6u8; 32];
733
pub const DAVE: [u8; 32] = [7u8; 32];
734
pub const EVE: [u8; 32] = [8u8; 32];
735
pub const FERDIE: [u8; 32] = [9u8; 32];
736

            
737
2981
fn take_new_inherent_data() -> Option<cumulus_primitives_core::relay_chain::InherentData> {
738
2981
    let data: Option<cumulus_primitives_core::relay_chain::InherentData> =
739
2981
        frame_support::storage::unhashed::take(b"ParasInherent");
740
2981

            
741
2981
    data
742
2981
}
743

            
744
8
pub fn set_new_inherent_data(data: cumulus_primitives_core::relay_chain::InherentData) {
745
8
    frame_support::storage::unhashed::put(b"ParasInherent", &data);
746
8
}
747

            
748
1
pub fn set_new_randomness_data(data: Option<[u8; 32]>) {
749
1
    pallet_babe::AuthorVrfRandomness::<Runtime>::set(data);
750
1
}
751

            
752
/// Mock the inherent that sets validation data in ParachainSystem, which
753
/// contains the `relay_chain_block_number`, which is used in `collator-assignment` as a
754
/// source of randomness.
755
8
pub fn set_paras_inherent(data: cumulus_primitives_core::relay_chain::InherentData) {
756
8
    // In order for this inherent to work, we need to match the parent header
757
8
    // the parent header does not play a significant role in the rest of the framework so
758
8
    // we are simply going to mock it
759
8
    System::set_parent_hash(data.parent_header.hash());
760
8
    assert_ok!(
761
8
        RuntimeCall::ParaInherent(parachains_paras_inherent::Call::<Runtime>::enter { data })
762
8
            .dispatch(inherent_origin())
763
8
    );
764
5
    frame_support::storage::unhashed::kill(&frame_support::storage::storage_prefix(
765
5
        b"ParaInherent",
766
5
        b"Included",
767
5
    ));
768
5
}
769

            
770
pub(crate) struct ParasInherentTestBuilder<T: runtime_parachains::paras_inherent::Config> {
771
    /// Starting block number; we expect it to get incremented on session setup.
772
    block_number: BlockNumberFor<T>,
773
    /// Paras here will both be backed in the inherent data and already occupying a core (which is
774
    /// freed via bitfields).
775
    ///
776
    /// Map from para id to number of validity votes. Core indices are generated based on
777
    /// `elastic_paras` configuration. Each para id in `elastic_paras` gets the
778
    /// specified amount of consecutive cores assigned to it. If a para id is not present
779
    /// in `elastic_paras` it get assigned to a single core.
780
    backed_and_concluding_paras: BTreeMap<u32, u32>,
781

            
782
    /// Paras which don't yet occupy a core, but will after the inherent has been processed.
783
    backed_in_inherent_paras: BTreeMap<u32, u32>,
784
    _phantom: core::marker::PhantomData<T>,
785
}
786

            
787
139
pub fn mock_validation_code() -> ValidationCode {
788
139
    ValidationCode(vec![1; 10])
789
139
}
790

            
791
#[allow(dead_code)]
792
impl<T: runtime_parachains::paras_inherent::Config> ParasInherentTestBuilder<T> {
793
    /// Create a new `BenchBuilder` with some opinionated values that should work with the rest
794
    /// of the functions in this implementation.
795
8
    pub(crate) fn new() -> Self {
796
8
        ParasInherentTestBuilder {
797
8
            block_number: Zero::zero(),
798
8
            backed_and_concluding_paras: Default::default(),
799
8
            backed_in_inherent_paras: Default::default(),
800
8
            _phantom: core::marker::PhantomData::<T>,
801
8
        }
802
8
    }
803

            
804
    /// Set a map from para id seed to number of validity votes.
805
8
    pub(crate) fn set_backed_and_concluding_paras(
806
8
        mut self,
807
8
        backed_and_concluding_paras: BTreeMap<u32, u32>,
808
8
    ) -> Self {
809
8
        self.backed_and_concluding_paras = backed_and_concluding_paras;
810
8
        self
811
8
    }
812

            
813
    /// Set a map from para id seed to number of validity votes for votes in inherent data.
814
    pub(crate) fn set_backed_in_inherent_paras(mut self, backed: BTreeMap<u32, u32>) -> Self {
815
        self.backed_in_inherent_paras = backed;
816
        self
817
    }
818

            
819
    /// Mock header.
820
42
    pub(crate) fn header(block_number: BlockNumberFor<T>) -> HeaderFor<T> {
821
42
        HeaderFor::<T>::new(
822
42
            block_number,       // `block_number`,
823
42
            Default::default(), // `extrinsics_root`,
824
42
            Default::default(), // `storage_root`,
825
42
            Default::default(), // `parent_hash`,
826
42
            Default::default(), // digest,
827
42
        )
828
42
    }
829

            
830
    /// Maximum number of validators that may be part of a validator group.
831
8
    pub(crate) fn fallback_max_validators() -> u32 {
832
8
        runtime_parachains::configuration::ActiveConfig::<T>::get()
833
8
            .max_validators
834
8
            .unwrap_or(200)
835
8
    }
836

            
837
    /// Maximum number of validators participating in parachains consensus (a.k.a. active
838
    /// validators).
839
8
    fn max_validators(&self) -> u32 {
840
8
        Self::fallback_max_validators()
841
8
    }
842

            
843
    /// Maximum number of validators per core (a.k.a. max validators per group). This value is used
844
    /// if none is explicitly set on the builder.
845
8
    pub(crate) fn fallback_max_validators_per_core() -> u32 {
846
8
        runtime_parachains::configuration::ActiveConfig::<T>::get()
847
8
            .scheduler_params
848
8
            .max_validators_per_core
849
8
            .unwrap_or(5)
850
8
    }
851

            
852
    /// Get the maximum number of validators per core.
853
8
    fn max_validators_per_core(&self) -> u32 {
854
8
        Self::fallback_max_validators_per_core()
855
8
    }
856

            
857
    /// Get the maximum number of cores we expect from this configuration.
858
8
    pub(crate) fn max_cores(&self) -> u32 {
859
8
        self.max_validators() / self.max_validators_per_core()
860
8
    }
861

            
862
    /// Create an `AvailabilityBitfield` where `concluding` is a map where each key is a core index
863
    /// that is concluding and `cores` is the total number of cores in the system.
864
8
    fn availability_bitvec(used_cores: usize, cores: usize) -> AvailabilityBitfield {
865
8
        let mut bitfields = bitvec::bitvec![u8, bitvec::order::Lsb0; 0; 0];
866
320
        for i in 0..cores {
867
320
            if i < used_cores {
868
9
                bitfields.push(true);
869
9
            } else {
870
311
                bitfields.push(false)
871
            }
872
        }
873

            
874
8
        bitfields.into()
875
8
    }
876

            
877
    /// Create a bitvec of `validators` length with all yes votes.
878
    fn validator_availability_votes_yes(validators: usize) -> BitVec<u8, bitvec::order::Lsb0> {
879
        // every validator confirms availability.
880
        bitvec::bitvec![u8, bitvec::order::Lsb0; 1; validators]
881
    }
882

            
883
18
    pub fn mock_head_data() -> HeadData {
884
18
        let max_head_size =
885
18
            runtime_parachains::configuration::ActiveConfig::<T>::get().max_head_data_size;
886
18
        HeadData(vec![0xFF; max_head_size as usize])
887
18
    }
888

            
889
    /// Number of the relay parent block.
890
18
    fn relay_parent_number(&self) -> u32 {
891
18
        (Self::block_number() - One::one())
892
18
            .try_into()
893
18
            .map_err(|_| ())
894
18
            .expect("Self::block_number() is u32")
895
18
    }
896

            
897
    /// Create backed candidates for `cores_with_backed_candidates`. You need these cores to be
898
    /// scheduled _within_ paras inherent, which requires marking the available bitfields as fully
899
    /// available.
900
    /// - `cores_with_backed_candidates` Mapping of `para_id` seed to number of
901
    /// validity votes.
902
    /// Important! this uses a BtreeMap, which means that elements will use increasing core orders
903
    /// example: if we have parachains 1000, 1001, and 1002, they will use respectively cores
904
    /// 0 1 and 2. There is no way in which we force 1002 to use core 0 in this setup
905
8
    fn create_backed_candidates(
906
8
        &self,
907
8
        paras_with_backed_candidates: &BTreeMap<u32, u32>,
908
8
    ) -> Vec<BackedCandidate<T::Hash>> {
909
8
        let current_session = runtime_parachains::shared::CurrentSessionIndex::<T>::get();
910
8
        // We need to refetch validators since they have been shuffled.
911
8
        let validators_shuffled =
912
8
            runtime_parachains::session_info::Sessions::<T>::get(current_session)
913
8
                .unwrap()
914
8
                .validators
915
8
                .clone();
916
8

            
917
8
        let config = runtime_parachains::configuration::ActiveConfig::<T>::get();
918
8
        let mut current_core_idx = 0u32;
919
8
        paras_with_backed_candidates
920
8
            .iter()
921
9
            .flat_map(|(seed, num_votes)| {
922
9
                assert!(*num_votes <= validators_shuffled.len() as u32);
923

            
924
9
                let para_id = ParaId::from(*seed);
925
9
                let prev_head_non_mut = runtime_parachains::paras::Heads::<T>::get(para_id);
926
9
                let prev_head = prev_head_non_mut.unwrap_or(Self::mock_head_data());
927
9
                // How many chained candidates we want to build ?
928
9
                (0..1)
929
9
                    .map(|chain_idx| {
930
9
                        let core_idx = CoreIndex::from(current_core_idx);
931
9
                        // Advance core index.
932
9
                        current_core_idx += 1;
933
9
                        let group_idx =
934
9
                            Self::group_assigned_to_core(core_idx, Self::block_number())
935
9
                                .unwrap_or_else(|| {
936
                                    panic!("Validator group not assigned to core {:?}", core_idx)
937
9
                                });
938
9

            
939
9
                        let header = Self::header(Self::block_number());
940
9
                        let relay_parent = header.hash();
941
9

            
942
9
                        // Set the head data so it can be used while validating the signatures on
943
9
                        // the candidate receipt.
944
9
                        let mut head_data = Self::mock_head_data();
945
9

            
946
9
                        if chain_idx == 0 {
947
9
                            // Only first parahead of the chain needs to be set in storage.
948
9
                            Self::heads_insert(&para_id, prev_head.clone());
949
9
                        } else {
950
                            // Make each candidate head data unique to avoid cycles.
951
                            head_data.0[0] = chain_idx;
952
                        }
953

            
954
9
                        let persisted_validation_data = PersistedValidationData::<T::Hash> {
955
9
                            // To form a chain we set parent head to previous block if any, or
956
9
                            // default to what is in storage already setup.
957
9
                            parent_head: prev_head.clone(),
958
9
                            relay_parent_number: self.relay_parent_number() + 1,
959
9
                            relay_parent_storage_root: Default::default(),
960
9
                            max_pov_size: config.max_pov_size,
961
9
                        };
962
9

            
963
9
                        let persisted_validation_data_hash = persisted_validation_data.hash();
964
9

            
965
9
                        let pov_hash = Default::default();
966
9
                        let validation_code_hash = mock_validation_code().hash();
967
9
                        let payload =
968
9
                            cumulus_primitives_core::relay_chain::collator_signature_payload(
969
9
                                &relay_parent,
970
9
                                &para_id,
971
9
                                &persisted_validation_data_hash,
972
9
                                &pov_hash,
973
9
                                &validation_code_hash,
974
9
                            );
975
9

            
976
9
                        let collator_pair = CollatorPair::generate().0;
977
9

            
978
9
                        let signature = collator_pair.sign(&payload);
979
9

            
980
9
                        let group_validators = Self::group_validators(group_idx).unwrap();
981
9

            
982
9
                        let candidate = CommittedCandidateReceipt::<T::Hash> {
983
9
                            descriptor: CandidateDescriptor::<T::Hash> {
984
9
                                para_id,
985
9
                                relay_parent,
986
9
                                collator: collator_pair.public(),
987
9
                                persisted_validation_data_hash,
988
9
                                pov_hash,
989
9
                                erasure_root: Default::default(),
990
9
                                signature,
991
9
                                para_head: prev_head.hash(),
992
9
                                validation_code_hash,
993
9
                            },
994
9
                            commitments: CandidateCommitments::<u32> {
995
9
                                upward_messages: Default::default(),
996
9
                                horizontal_messages: Default::default(),
997
9
                                new_validation_code: None,
998
9
                                head_data: prev_head.clone(),
999
9
                                processed_downward_messages: 0,
9
                                hrmp_watermark: self.relay_parent_number() + 1,
9
                            },
9
                        };
9

            
9
                        let candidate_hash = candidate.hash();
9

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

            
9
                                let signature_ctx = SigningContext {
9
                                    parent_hash: Self::header(Self::block_number()).hash(),
9
                                    session_index: Session::current_index(),
9
                                };
9
                                let sig = UncheckedSigned::<CompactStatement>::benchmark_sign(
9
                                    public,
9
                                    CompactStatement::Valid(candidate_hash),
9
                                    &signature_ctx,
9
                                    *val_idx,
9
                                )
9
                                .benchmark_signature();
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
}
use milagro_bls::Keypair;
1
pub fn generate_ethereum_pub_keys(n: u32) -> Vec<Keypair> {
1
    let mut keys = vec![];
512
    for _i in 0..n {
512
        let keypair = Keypair::random(&mut rand::thread_rng());
512
        keys.push(keypair);
512
    }
1
    keys
1
}
use babe_primitives::AuthorityPair as BabeAuthorityPair;
use grandpa_primitives::{
    AuthorityPair as GrandpaAuthorityPair, Equivocation, EquivocationProof, RoundNumber, SetId,
};
use sp_core::H256;
2
pub fn generate_grandpa_equivocation_proof(
2
    set_id: SetId,
2
    vote1: (RoundNumber, H256, u32, &GrandpaAuthorityPair),
2
    vote2: (RoundNumber, H256, u32, &GrandpaAuthorityPair),
2
) -> EquivocationProof<H256, u32> {
4
    let signed_prevote = |round, hash, number, authority_pair: &GrandpaAuthorityPair| {
4
        let prevote = finality_grandpa::Prevote {
4
            target_hash: hash,
4
            target_number: number,
4
        };
4

            
4
        let prevote_msg = finality_grandpa::Message::Prevote(prevote.clone());
4
        let payload = grandpa_primitives::localized_payload(round, set_id, &prevote_msg);
4
        let signed = authority_pair.sign(&payload);
4
        (prevote, signed)
4
    };
2
    let (prevote1, signed1) = signed_prevote(vote1.0, vote1.1, vote1.2, vote1.3);
2
    let (prevote2, signed2) = signed_prevote(vote2.0, vote2.1, vote2.2, vote2.3);
2

            
2
    EquivocationProof::new(
2
        set_id,
2
        Equivocation::Prevote(finality_grandpa::Equivocation {
2
            round_number: vote1.0,
2
            identity: vote1.3.public(),
2
            first: (prevote1, signed1),
2
            second: (prevote2, signed2),
2
        }),
2
    )
2
}
/// Creates an equivocation at the current block, by generating two headers.
7
pub fn generate_babe_equivocation_proof(
7
    offender_authority_pair: &BabeAuthorityPair,
7
) -> babe_primitives::EquivocationProof<crate::Header> {
    use babe_primitives::digests::CompatibleDigestItem;
7
    let current_digest = System::digest();
7
    let babe_predigest = current_digest
7
        .clone()
7
        .logs()
7
        .iter()
7
        .find_map(|log| log.as_babe_pre_digest());
7
    let slot_proof = babe_predigest.expect("babe should be presesnt").slot();
7

            
7
    let make_headers = || {
7
        (
7
            HeaderFor::<Runtime>::new(
7
                0,
7
                H256::default(),
7
                H256::default(),
7
                H256::default(),
7
                current_digest.clone(),
7
            ),
7
            HeaderFor::<Runtime>::new(
7
                1,
7
                H256::default(),
7
                H256::default(),
7
                H256::default(),
7
                current_digest.clone(),
7
            ),
7
        )
7
    };
    // sign the header prehash and sign it, adding it to the block as the seal
    // digest item
14
    let seal_header = |header: &mut crate::Header| {
14
        let prehash = header.hash();
14
        let seal = <DigestItem as CompatibleDigestItem>::babe_seal(
14
            offender_authority_pair.sign(prehash.as_ref()),
14
        );
14
        header.digest_mut().push(seal);
14
    };
    // generate two headers at the current block
7
    let (mut h1, mut h2) = make_headers();
7

            
7
    seal_header(&mut h1);
7
    seal_header(&mut h2);
7

            
7
    babe_primitives::EquivocationProof {
7
        slot: slot_proof,
7
        offender: offender_authority_pair.public(),
7
        first_header: h1,
7
        second_header: h2,
7
    }
7
}
use sp_core::Public;
/// Helper function to generate a crypto pair from seed
9
pub fn get_pair_from_seed<TPublic: Public>(seed: &str) -> TPublic::Pair {
9
    let secret_uri = format!("//{}", seed);
9
    let pair = TPublic::Pair::from_string(&secret_uri, None).expect("static values are valid; qed");
9

            
9
    pair
9
}