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
//! Crate containing various traits used by moondance crates allowing to connect pallet
18
//! with each other or with mocks.
19

            
20
#![cfg_attr(not(feature = "std"), no_std)]
21

            
22
extern crate alloc;
23

            
24
pub mod alias;
25
pub mod prod_or_fast;
26

            
27
pub use {
28
    alias::*,
29
    cumulus_primitives_core::{
30
        relay_chain::{BlockNumber, HeadData, Slot, ValidationCode},
31
        ParaId,
32
    },
33
    dp_chain_state_snapshot::{GenericStateProof, ReadEntryErr},
34
    dp_container_chain_genesis_data::ContainerChainGenesisDataItem,
35
};
36

            
37
use {
38
    alloc::{
39
        collections::{btree_map::BTreeMap, btree_set::BTreeSet},
40
        vec,
41
        vec::Vec,
42
    },
43
    core::marker::PhantomData,
44
    frame_support::{
45
        dispatch::DispatchErrorWithPostInfo,
46
        pallet_prelude::{
47
            Decode, DecodeWithMemTracking, DispatchResultWithPostInfo, Encode, Get, MaxEncodedLen,
48
            Weight,
49
        },
50
    },
51
    scale_info::TypeInfo,
52
    serde::{Deserialize, Serialize},
53
    sp_core::H256,
54
    sp_runtime::{
55
        app_crypto::sp_core,
56
        traits::{CheckedAdd, CheckedMul},
57
        ArithmeticError, DispatchResult, Perbill, RuntimeDebug,
58
    },
59
};
60

            
61
/// The collator-assignment hook to react to collators being assigned to container chains.
62
pub trait CollatorAssignmentHook<Balance> {
63
    /// This hook is called when collators are assigned to a container
64
    ///
65
    /// The hook should never panic and is required to return the weight consumed.
66
    fn on_collators_assigned(
67
        para_id: ParaId,
68
        maybe_tip: Option<&Balance>,
69
        is_parathread: bool,
70
    ) -> Result<Weight, sp_runtime::DispatchError>;
71
}
72

            
73
#[impl_trait_for_tuples::impl_for_tuples(5)]
74
impl<Balance> CollatorAssignmentHook<Balance> for Tuple {
75
    fn on_collators_assigned(
76
        p: ParaId,
77
        t: Option<&Balance>,
78
        ip: bool,
79
    ) -> Result<Weight, sp_runtime::DispatchError> {
80
        let mut weight: Weight = Default::default();
81
        for_tuples!( #( weight.saturating_accrue(Tuple::on_collators_assigned(p, t, ip)?); )* );
82
        Ok(weight)
83
    }
84
}
85

            
86
/// Container chains collator assignment tip prioritization on congestion.
87
/// Tips paras are willing to pay for collator assignment in case of collators demand
88
/// surpasses the offer.
89
pub trait CollatorAssignmentTip<Balance> {
90
    /// Return the amount this para is willing to tip to be included.
91
    fn get_para_max_tip(a: ParaId) -> Option<Balance>;
92
}
93

            
94
impl<Balance> CollatorAssignmentTip<Balance> for () {
95
    fn get_para_max_tip(_: ParaId) -> Option<Balance> {
96
        None
97
    }
98
}
99

            
100
pub struct AuthorNotingInfo<AccountId> {
101
    pub author: AccountId,
102
    pub block_number: BlockNumber,
103
    pub para_id: ParaId,
104
}
105

            
106
/// The author-noting hook to react to container chains authoring.
107
pub trait AuthorNotingHook<AccountId> {
108
    /// This hook is called partway through the `set_latest_author_data` inherent in author-noting.
109
    ///
110
    /// The hook should never panic and is required to return the weight consumed.
111
    fn on_container_authors_noted(info: &[AuthorNotingInfo<AccountId>]) -> Weight;
112

            
113
    #[cfg(feature = "runtime-benchmarks")]
114
    fn prepare_worst_case_for_bench(author: &AccountId, block_number: BlockNumber, para_id: ParaId);
115
}
116

            
117
#[impl_trait_for_tuples::impl_for_tuples(5)]
118
impl<AccountId> AuthorNotingHook<AccountId> for Tuple {
119
142
    fn on_container_authors_noted(info: &[AuthorNotingInfo<AccountId>]) -> Weight {
120
142
        let mut weight: Weight = Default::default();
121
131
        for_tuples!( #( weight.saturating_accrue(Tuple::on_container_authors_noted(info)); )* );
122
142
        weight
123
142
    }
124

            
125
    #[cfg(feature = "runtime-benchmarks")]
126
    fn prepare_worst_case_for_bench(a: &AccountId, b: BlockNumber, p: ParaId) {
127
        for_tuples!( #( Tuple::prepare_worst_case_for_bench(a, b, p); )* );
128
    }
129
}
130

            
131
pub trait DistributeRewards<AccountId, Imbalance> {
132
    fn distribute_rewards(rewarded: AccountId, amount: Imbalance) -> DispatchResultWithPostInfo;
133
}
134

            
135
impl<AccountId, Imbalance> DistributeRewards<AccountId, Imbalance> for () {
136
26
    fn distribute_rewards(_rewarded: AccountId, _amount: Imbalance) -> DispatchResultWithPostInfo {
137
26
        Ok(().into())
138
26
    }
139
}
140

            
141
#[derive(Copy, Clone, PartialEq, Eq)]
142
pub enum ForSession {
143
    Current,
144
    Next,
145
}
146

            
147
/// Get the current list of container chains parachain ids with its assigned collators.
148
/// It can return a para id with an empty list of collators.
149
pub trait GetContainerChainsWithCollators<AccountId> {
150
    fn container_chains_with_collators(for_session: ForSession) -> Vec<(ParaId, Vec<AccountId>)>;
151

            
152
    fn get_all_collators_assigned_to_chains(for_session: ForSession) -> BTreeSet<AccountId>;
153

            
154
    #[cfg(feature = "runtime-benchmarks")]
155
    fn set_container_chains_with_collators(
156
        for_session: ForSession,
157
        container_chains: &[(ParaId, Vec<AccountId>)],
158
    );
159
}
160

            
161
/// How often should a parathread collator propose blocks. The units are "1 out of n slots", where the slot time is the
162
/// tanssi slot time, 6 seconds.
163
// TODO: this is currently ignored
164
#[derive(
165
    Clone,
166
    Debug,
167
    Encode,
168
    Decode,
169
    DecodeWithMemTracking,
170
    scale_info::TypeInfo,
171
    PartialEq,
172
    Eq,
173
    Serialize,
174
    Deserialize,
175
    MaxEncodedLen,
176
)]
177
pub struct SlotFrequency {
178
    /// The parathread will produce at most 1 block every x slots. min=10 means that collators can produce 1 block
179
    /// every `x >= 10` slots, but they are not enforced to. If collators produce a block after less than 10
180
    /// slots, they will not be rewarded by tanssi.
181
    pub min: u32,
182
    /// The parathread will produce at least 1 block every x slots. max=10 means that collators are forced to
183
    /// produce 1 block every `x <= 10` slots. Collators can produce a block sooner than that if the `min` allows it, but
184
    /// waiting more than 10 slots will make them lose the block reward.
185
    pub max: u32,
186
}
187

            
188
impl SlotFrequency {
189
1134
    pub fn should_parathread_buy_core(
190
1134
        &self,
191
1134
        current_slot: Slot,
192
1134
        max_slot_required_to_complete_purchase: Slot,
193
1134
        last_block_slot: Slot,
194
1134
    ) -> bool {
195
1134
        current_slot
196
1134
            >= last_block_slot
197
1134
                .saturating_add(Slot::from(u64::from(self.min)))
198
1134
                .saturating_sub(max_slot_required_to_complete_purchase)
199
1134
    }
200

            
201
    pub fn should_parathread_author_block(
202
        &self,
203
        current_slot: Slot,
204
        last_block_slot: Slot,
205
    ) -> bool {
206
        current_slot >= last_block_slot.saturating_add(Slot::from(u64::from(self.min)))
207
    }
208
}
209

            
210
impl Default for SlotFrequency {
211
605
    fn default() -> Self {
212
605
        Self { min: 1, max: 1 }
213
605
    }
214
}
215

            
216
#[derive(
217
    Clone,
218
    Debug,
219
    Encode,
220
    Decode,
221
    DecodeWithMemTracking,
222
    scale_info::TypeInfo,
223
    PartialEq,
224
    Eq,
225
    Serialize,
226
    Deserialize,
227
    MaxEncodedLen,
228
)]
229
pub struct ParathreadParams {
230
    pub slot_frequency: SlotFrequency,
231
}
232

            
233
#[derive(Clone, Debug, Encode, Decode, scale_info::TypeInfo, PartialEq, Eq)]
234
pub struct SessionContainerChains {
235
    pub parachains: Vec<ParaId>,
236
    pub parathreads: Vec<(ParaId, ParathreadParams)>,
237
}
238

            
239
/// Get the list of container chains parachain ids at given
240
/// session index.
241
pub trait GetSessionContainerChains<SessionIndex> {
242
    fn session_container_chains(session_index: SessionIndex) -> SessionContainerChains;
243
    #[cfg(feature = "runtime-benchmarks")]
244
    fn set_session_container_chains(session_index: SessionIndex, container_chains: &[ParaId]);
245
}
246

            
247
/// Returns author for a parachain id for the given slot.
248
pub trait GetContainerChainAuthor<AccountId> {
249
    fn author_for_slot(slot: Slot, para_id: ParaId) -> Option<AccountId>;
250
    #[cfg(feature = "runtime-benchmarks")]
251
    fn set_authors_for_para_id(para_id: ParaId, authors: Vec<AccountId>);
252
}
253

            
254
/// Returns the host configuration composed of the amount of collators assigned
255
/// to the orchestrator chain, and how many collators are assigned per container chain.
256
pub trait GetHostConfiguration<SessionIndex> {
257
    fn max_collators(session_index: SessionIndex) -> u32;
258
    fn min_collators_for_orchestrator(session_index: SessionIndex) -> u32;
259
    fn max_collators_for_orchestrator(session_index: SessionIndex) -> u32;
260
    fn collators_per_container(session_index: SessionIndex) -> u32;
261
    fn collators_per_parathread(session_index: SessionIndex) -> u32;
262
    fn target_container_chain_fullness(session_index: SessionIndex) -> Perbill;
263
    fn max_parachain_cores_percentage(session_index: SessionIndex) -> Option<Perbill>;
264
    fn full_rotation_mode(session_index: SessionIndex) -> FullRotationModes;
265
    #[cfg(feature = "runtime-benchmarks")]
266
    fn set_host_configuration(_session_index: SessionIndex) {}
267
}
268

            
269
/// Returns current session index.
270
pub trait GetSessionIndex<SessionIndex> {
271
    fn session_index() -> SessionIndex;
272

            
273
    #[cfg(feature = "runtime-benchmarks")]
274
    fn skip_to_session(session_index: SessionIndex);
275
}
276

            
277
/// Should pallet_collator_assignment trigger a full rotation on this session?
278
pub trait ShouldRotateAllCollators<SessionIndex> {
279
    fn should_rotate_all_collators(session_index: SessionIndex) -> bool;
280
}
281

            
282
impl<SessionIndex> ShouldRotateAllCollators<SessionIndex> for () {
283
    fn should_rotate_all_collators(_session_index: SessionIndex) -> bool {
284
        false
285
    }
286
}
287

            
288
/// Helper trait for pallet_collator_assignment to be able to give priority to invulnerables
289
pub trait RemoveInvulnerables<AccountId> {
290
    /// Remove the first n invulnerables from the list of collators. The order should be respected.
291
    fn remove_invulnerables(
292
        collators: &mut Vec<AccountId>,
293
        num_invulnerables: usize,
294
    ) -> Vec<AccountId>;
295
}
296

            
297
impl<AccountId: Clone> RemoveInvulnerables<AccountId> for () {
298
1756
    fn remove_invulnerables(
299
1756
        _collators: &mut Vec<AccountId>,
300
1756
        _num_invulnerables: usize,
301
1756
    ) -> Vec<AccountId> {
302
        // Default impl: no collators are invulnerables
303
1756
        vec![]
304
1756
    }
305
}
306

            
307
/// Helper trait for pallet_collator_assignment to be able to not assign collators to container chains with no credits
308
/// in pallet_services_payment
309
pub trait ParaIdAssignmentHooks<B, AC> {
310
    /// Remove para ids with not enough credits. The resulting order will affect priority: the first para id in the list
311
    /// will be the first one to get collators.
312
    fn pre_assignment(para_ids: &mut Vec<ParaId>, old_assigned: &BTreeSet<ParaId>);
313
    fn post_assignment(
314
        current_assigned: &BTreeSet<ParaId>,
315
        new_assigned: &mut BTreeMap<ParaId, Vec<AC>>,
316
        maybe_tip: &Option<B>,
317
    ) -> Weight;
318

            
319
    /// Make those para ids valid by giving them enough credits, for benchmarking.
320
    #[cfg(feature = "runtime-benchmarks")]
321
    fn make_valid_para_ids(para_ids: &[ParaId]);
322
}
323

            
324
impl<B, AC> ParaIdAssignmentHooks<B, AC> for () {
325
    fn pre_assignment(_para_ids: &mut Vec<ParaId>, _currently_assigned: &BTreeSet<ParaId>) {}
326

            
327
    fn post_assignment(
328
        _current_assigned: &BTreeSet<ParaId>,
329
        _new_assigned: &mut BTreeMap<ParaId, Vec<AC>>,
330
        _maybe_tip: &Option<B>,
331
    ) -> Weight {
332
        Default::default()
333
    }
334

            
335
    #[cfg(feature = "runtime-benchmarks")]
336
    fn make_valid_para_ids(_para_ids: &[ParaId]) {}
337
}
338

            
339
pub trait RelayStorageRootProvider {
340
    fn get_relay_storage_root(relay_block_number: u32) -> Option<H256>;
341

            
342
    #[cfg(feature = "runtime-benchmarks")]
343
    fn set_relay_storage_root(relay_block_number: u32, storage_root: Option<H256>);
344
}
345

            
346
impl RelayStorageRootProvider for () {
347
    fn get_relay_storage_root(_relay_block_number: u32) -> Option<H256> {
348
        None
349
    }
350

            
351
    #[cfg(feature = "runtime-benchmarks")]
352
    fn set_relay_storage_root(_relay_block_number: u32, _storage_root: Option<H256>) {}
353
}
354

            
355
/// Information extracted from the latest container chain header
356
#[derive(
357
    Default,
358
    Clone,
359
    Encode,
360
    Decode,
361
    PartialEq,
362
    sp_core::RuntimeDebug,
363
    scale_info::TypeInfo,
364
    MaxEncodedLen,
365
    Serialize,
366
    Deserialize,
367
)]
368
pub struct ContainerChainBlockInfo<AccountId> {
369
    pub block_number: BlockNumber,
370
    pub author: AccountId,
371
    pub latest_slot_number: Slot,
372
}
373

            
374
pub trait LatestAuthorInfoFetcher<AccountId> {
375
    fn get_latest_author_info(para_id: ParaId) -> Option<ContainerChainBlockInfo<AccountId>>;
376
}
377

            
378
pub trait StorageDeposit<Data, Balance> {
379
    fn compute_deposit(data: &Data) -> Result<Balance, DispatchErrorWithPostInfo>;
380
}
381

            
382
pub struct BytesDeposit<BaseCost, ByteCost>(PhantomData<(BaseCost, ByteCost)>);
383
impl<Data, Balance, BaseCost, ByteCost> StorageDeposit<Data, Balance>
384
    for BytesDeposit<BaseCost, ByteCost>
385
where
386
    Data: Encode,
387
    Balance: TryFrom<usize> + CheckedAdd + CheckedMul,
388
    BaseCost: Get<Balance>,
389
    ByteCost: Get<Balance>,
390
{
391
103
    fn compute_deposit(data: &Data) -> Result<Balance, DispatchErrorWithPostInfo> {
392
103
        let base = BaseCost::get();
393
103
        let byte = ByteCost::get();
394
103
        let size: Balance = data
395
103
            .encoded_size()
396
103
            .try_into()
397
103
            .map_err(|_| ArithmeticError::Overflow)?;
398

            
399
103
        let deposit = byte
400
103
            .checked_mul(&size)
401
103
            .ok_or(ArithmeticError::Overflow)?
402
103
            .checked_add(&base)
403
103
            .ok_or(ArithmeticError::Overflow)?;
404

            
405
103
        Ok(deposit)
406
103
    }
407
}
408

            
409
/// Trait to abstract away relay storage proofs, and allow the same logic to work on both parachains and solochains.
410
/// Parachains should use relay storage proofs, while solochains should read from storage directly.
411
pub trait GenericStorageReader {
412
    fn read_entry<T: Decode>(&self, key: &[u8], fallback: Option<T>) -> Result<T, ReadEntryErr>;
413
}
414

            
415
impl GenericStorageReader for GenericStateProof<cumulus_primitives_core::relay_chain::Block> {
416
142
    fn read_entry<T: Decode>(&self, key: &[u8], fallback: Option<T>) -> Result<T, ReadEntryErr> {
417
142
        GenericStateProof::read_entry(self, key, fallback)
418
142
    }
419
}
420

            
421
/// Solo chain impl, read directly from storage
422
pub struct NativeStorageReader;
423
impl GenericStorageReader for NativeStorageReader {
424
36
    fn read_entry<T: Decode>(&self, key: &[u8], fallback: Option<T>) -> Result<T, ReadEntryErr> {
425
36
        match frame_support::storage::unhashed::get(key).or(fallback) {
426
36
            Some(x) => Ok(x),
427
            None => Err(ReadEntryErr::Absent),
428
        }
429
36
    }
430
}
431

            
432
/// Trait to handle registrar-related operations in a relay-chain context.
433
/// Mostly used to wire Tanssi's and Polkadot's registrars, for them to
434
/// work together in a solo-chain environment.
435
pub trait RegistrarHandler<AccountId> {
436
    fn register(
437
        who: AccountId,
438
        id: ParaId,
439
        genesis_storage: &[ContainerChainGenesisDataItem],
440
        head_data: Option<HeadData>,
441
    ) -> DispatchResult;
442

            
443
    fn schedule_para_upgrade(id: ParaId) -> DispatchResult;
444
    fn schedule_para_downgrade(id: ParaId) -> DispatchResult;
445
    fn deregister(id: ParaId);
446
    fn deregister_weight() -> Weight;
447

            
448
    #[cfg(feature = "runtime-benchmarks")]
449
    fn bench_head_data() -> Option<HeadData> {
450
        None
451
    }
452
    #[cfg(feature = "runtime-benchmarks")]
453
    fn add_trusted_validation_code(_code: Vec<u8>) {}
454
    #[cfg(feature = "runtime-benchmarks")]
455
    fn registrar_new_session(_session: u32) {}
456
    #[cfg(feature = "runtime-benchmarks")]
457
    fn prepare_chain_registration(_id: ParaId, _who: AccountId) {}
458
}
459

            
460
impl<AccountId> RegistrarHandler<AccountId> for () {
461
63
    fn register(
462
63
        _who: AccountId,
463
63
        _id: ParaId,
464
63
        _genesis_storage: &[ContainerChainGenesisDataItem],
465
63
        _head_data: Option<HeadData>,
466
63
    ) -> DispatchResult {
467
63
        Ok(())
468
63
    }
469

            
470
40
    fn schedule_para_upgrade(_id: ParaId) -> DispatchResult {
471
40
        Ok(())
472
40
    }
473

            
474
10
    fn schedule_para_downgrade(_id: ParaId) -> DispatchResult {
475
10
        Ok(())
476
10
    }
477

            
478
    fn deregister(_id: ParaId) {}
479

            
480
    fn deregister_weight() -> Weight {
481
        Weight::default()
482
    }
483
}
484

            
485
/// Trait to retrieve the orchestrator block author (if any).
486
/// In a relay-chain context we will return None.
487
pub trait MaybeSelfChainBlockAuthor<AccountId> {
488
    fn get_block_author() -> Option<AccountId>;
489
}
490

            
491
impl<AccountId> MaybeSelfChainBlockAuthor<AccountId> for () {
492
15244
    fn get_block_author() -> Option<AccountId> {
493
15244
        None
494
15244
    }
495
}
496

            
497
/// Information regarding the active era (era in used in session).
498
#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)]
499
pub struct ActiveEraInfo {
500
    /// Index of era.
501
    pub index: EraIndex,
502
    /// Moment of start expressed as millisecond from `$UNIX_EPOCH`.
503
    ///
504
    /// Start can be none if start hasn't been set for the era yet,
505
    /// Start is set on the first on_finalize of the era to guarantee usage of `Time`.
506
    pub start: Option<u64>,
507
}
508

            
509
/// Counter for the number of eras that have passed.
510
pub type EraIndex = u32;
511

            
512
pub trait EraIndexProvider {
513
    fn active_era() -> ActiveEraInfo;
514
    fn era_to_session_start(era_index: EraIndex) -> Option<u32>;
515
}
516

            
517
pub trait ValidatorProvider<ValidatorId> {
518
    fn validators() -> Vec<ValidatorId>;
519
}
520

            
521
pub trait InvulnerablesProvider<ValidatorId> {
522
    fn invulnerables() -> Vec<ValidatorId>;
523
}
524

            
525
pub trait OnEraStart {
526
    fn on_era_start(_era_index: EraIndex, _session_start: u32, _external_idx: u64) {}
527
}
528

            
529
#[impl_trait_for_tuples::impl_for_tuples(5)]
530
impl OnEraStart for Tuple {
531
1195
    fn on_era_start(era_index: EraIndex, session_start: u32, external_idx: u64) {
532
1195
        for_tuples!( #( Tuple::on_era_start(era_index, session_start, external_idx); )* );
533
1195
    }
534
}
535

            
536
pub trait OnEraEnd {
537
    fn on_era_end(_era_index: EraIndex) {}
538
}
539

            
540
#[impl_trait_for_tuples::impl_for_tuples(5)]
541
impl OnEraEnd for Tuple {
542
    fn on_era_end(era_index: EraIndex) {
543
        for_tuples!( #( Tuple::on_era_end(era_index); )* );
544
    }
545
}
546

            
547
/// Strategy to use when rotating collators. Default: rotate all of them. Allows to rotate only a random subset.
548
#[derive(
549
    Clone,
550
    Debug,
551
    Default,
552
    Encode,
553
    Decode,
554
    DecodeWithMemTracking,
555
    scale_info::TypeInfo,
556
    PartialEq,
557
    Eq,
558
    Serialize,
559
    Deserialize,
560
    MaxEncodedLen,
561
)]
562
pub enum FullRotationMode {
563
    #[default]
564
    RotateAll,
565
    KeepAll,
566
    /// Keep this many collators
567
    KeepCollators {
568
        keep: u32,
569
    },
570
    /// Keep a ratio of collators wrt to max collators.
571
    /// If max collators changes, the number of collators kept also changes.
572
    KeepPerbill {
573
        percentage: Perbill,
574
    },
575
}
576

            
577
/// Allow to set a different [FullRotationMode] for each kind of chain. Default: rotate all.
578
#[derive(
579
    Clone,
580
    Debug,
581
    Default,
582
    Encode,
583
    DecodeWithMemTracking,
584
    Decode,
585
    scale_info::TypeInfo,
586
    PartialEq,
587
    Eq,
588
    Serialize,
589
    Deserialize,
590
    MaxEncodedLen,
591
)]
592
pub struct FullRotationModes {
593
    pub orchestrator: FullRotationMode,
594
    pub parachain: FullRotationMode,
595
    pub parathread: FullRotationMode,
596
}
597

            
598
impl FullRotationModes {
599
    /// Keep all collators assigned to their current chain if possible. This is equivalent to disabling rotation.
600
57739
    pub fn keep_all() -> Self {
601
57739
        Self {
602
57739
            orchestrator: FullRotationMode::KeepAll,
603
57739
            parachain: FullRotationMode::KeepAll,
604
57739
            parathread: FullRotationMode::KeepAll,
605
57739
        }
606
57739
    }
607
}
608

            
609
// A trait to retrieve the external index provider identifying some set of data
610
// In starlight, used to retrieve the external index associated to validators
611
pub trait ExternalIndexProvider {
612
    fn get_external_index() -> u64;
613
}
614

            
615
// A trait to check invulnerables
616
pub trait InvulnerablesHelper<AccountId> {
617
    /// Checks if the given `AccountId` is invulnerable.
618
    fn is_invulnerable(account_id: &AccountId) -> bool;
619
}
620

            
621
// A trait to verify the inactivity status of nodes
622
// and handle the offline status of nodes
623
pub trait NodeActivityTrackingHelper<AccountId> {
624
    /// Check if a node is inactive.
625
    fn is_node_inactive(node: &AccountId) -> bool;
626
    /// Check if a node is offline.
627
    fn is_node_offline(node: &AccountId) -> bool;
628
    #[cfg(feature = "runtime-benchmarks")]
629
    /// Marks online node as online
630
    fn make_node_online(node: &AccountId);
631
    /// Marks node as inactive for the current activity window so it could be notified as inactive
632
    #[cfg(feature = "runtime-benchmarks")]
633
    fn make_node_inactive(node: &AccountId);
634
}
635

            
636
// A trait to help verify if a ParaId is a chain or parathread
637
pub trait ParathreadHelper {
638
    fn get_parathreads_for_session() -> BTreeSet<ParaId>;
639
}
640

            
641
// A trait to help updating the collators rewards when a collator's online status changes.
642
pub trait StakingCandidateHelper<AccountId> {
643
    /// Check if the candidate is in SortedEligibleCandidates list.
644
    fn is_candidate_selected(candidate: &AccountId) -> bool;
645
    /// Updates stake when candidate's online status change.
646
    fn on_online_status_change(
647
        candidate: &AccountId,
648
        is_online: bool,
649
    ) -> DispatchResultWithPostInfo;
650
    /// Benchmarking helper function that makes collator part of the SortedEligibleCollators list.
651
    #[cfg(feature = "runtime-benchmarks")]
652
    fn make_collator_eligible_candidate(collator: &AccountId);
653
}