mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 11:41:02 +00:00
parachains runtime: configurable maximum validators per core (#2043)
* parachains runtime: configurable maximum validators per core * update guide and add test
This commit is contained in:
committed by
GitHub
parent
8081c54428
commit
0f4395fc44
@@ -178,8 +178,9 @@ Actions:
|
|||||||
1. Resize `AvailabilityCores` to have length `Paras::parachains().len() + configuration.parathread_cores with all `None` entries.
|
1. Resize `AvailabilityCores` to have length `Paras::parachains().len() + configuration.parathread_cores with all `None` entries.
|
||||||
1. Compute new validator groups by shuffling using a secure randomness beacon
|
1. Compute new validator groups by shuffling using a secure randomness beacon
|
||||||
- We need a total of `N = Paras::parachains().len() + configuration.parathread_cores` validator groups.
|
- We need a total of `N = Paras::parachains().len() + configuration.parathread_cores` validator groups.
|
||||||
- The total number of validators `V` in the `SessionChangeNotification`'s `validators` may not be evenly divided by `V`.
|
|
||||||
- First, we obtain "shuffled validators" `SV` by shuffling the validators using the `SessionChangeNotification`'s random seed.
|
- First, we obtain "shuffled validators" `SV` by shuffling the validators using the `SessionChangeNotification`'s random seed.
|
||||||
|
- Then, we truncate `SV` to have at most `configuration.max_validators_per_core * N` members, if `configuration.max_validators_per_core` is `Some`.
|
||||||
|
- Note that the total number of validators `V` in `SV` may not be evenly divided by `N`.
|
||||||
- The groups are selected by partitioning `SV`. The first V % N groups will have (V / N) + 1 members, while the remaining groups will have (V / N) members each.
|
- The groups are selected by partitioning `SV`. The first V % N groups will have (V / N) + 1 members, while the remaining groups will have (V / N) members each.
|
||||||
1. Prune the parathread queue to remove all retries beyond `configuration.parathread_retries`.
|
1. Prune the parathread queue to remove all retries beyond `configuration.parathread_retries`.
|
||||||
- Also prune all parathread claims corresponding to de-registered parathreads.
|
- Also prune all parathread claims corresponding to de-registered parathreads.
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ struct HostConfiguration {
|
|||||||
pub thread_availability_period: BlockNumber,
|
pub thread_availability_period: BlockNumber,
|
||||||
/// The amount of blocks ahead to schedule parathreads.
|
/// The amount of blocks ahead to schedule parathreads.
|
||||||
pub scheduling_lookahead: u32,
|
pub scheduling_lookahead: u32,
|
||||||
|
/// The maximum number of validators to have per core. `None` means no maximum.
|
||||||
|
pub max_validators_per_core: Option<u32>,
|
||||||
/// The amount of sessions to keep for disputes.
|
/// The amount of sessions to keep for disputes.
|
||||||
pub dispute_period: SessionIndex,
|
pub dispute_period: SessionIndex,
|
||||||
/// The amount of consensus slots that must pass between submitting an assignment and
|
/// The amount of consensus slots that must pass between submitting an assignment and
|
||||||
|
|||||||
@@ -61,6 +61,8 @@ pub struct HostConfiguration<BlockNumber> {
|
|||||||
pub thread_availability_period: BlockNumber,
|
pub thread_availability_period: BlockNumber,
|
||||||
/// The amount of blocks ahead to schedule parachains and parathreads.
|
/// The amount of blocks ahead to schedule parachains and parathreads.
|
||||||
pub scheduling_lookahead: u32,
|
pub scheduling_lookahead: u32,
|
||||||
|
/// The maximum number of validators to have per core. `None` means no maximum.
|
||||||
|
pub max_validators_per_core: Option<u32>,
|
||||||
/// The amount of sessions to keep for disputes.
|
/// The amount of sessions to keep for disputes.
|
||||||
pub dispute_period: SessionIndex,
|
pub dispute_period: SessionIndex,
|
||||||
/// The amount of consensus slots that must pass between submitting an assignment and
|
/// The amount of consensus slots that must pass between submitting an assignment and
|
||||||
@@ -271,6 +273,16 @@ decl_module! {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the maximum number of validators to assign to any core.
|
||||||
|
#[weight = (1_000, DispatchClass::Operational)]
|
||||||
|
pub fn set_max_validators_per_core(origin, new: Option<u32>) -> DispatchResult {
|
||||||
|
ensure_root(origin)?;
|
||||||
|
Self::update_config_member(|config| {
|
||||||
|
sp_std::mem::replace(&mut config.max_validators_per_core, new) != new
|
||||||
|
});
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Set the dispute period, in number of sessions to keep for disputes.
|
/// Set the dispute period, in number of sessions to keep for disputes.
|
||||||
#[weight = (1_000, DispatchClass::Operational)]
|
#[weight = (1_000, DispatchClass::Operational)]
|
||||||
pub fn set_dispute_period(origin, new: SessionIndex) -> DispatchResult {
|
pub fn set_dispute_period(origin, new: SessionIndex) -> DispatchResult {
|
||||||
@@ -582,6 +594,7 @@ mod tests {
|
|||||||
chain_availability_period: 10,
|
chain_availability_period: 10,
|
||||||
thread_availability_period: 8,
|
thread_availability_period: 8,
|
||||||
scheduling_lookahead: 3,
|
scheduling_lookahead: 3,
|
||||||
|
max_validators_per_core: None,
|
||||||
dispute_period: 239,
|
dispute_period: 239,
|
||||||
no_show_slots: 240,
|
no_show_slots: 240,
|
||||||
n_delay_tranches: 241,
|
n_delay_tranches: 241,
|
||||||
@@ -645,6 +658,9 @@ mod tests {
|
|||||||
Configuration::set_scheduling_lookahead(
|
Configuration::set_scheduling_lookahead(
|
||||||
Origin::root(), new_config.scheduling_lookahead,
|
Origin::root(), new_config.scheduling_lookahead,
|
||||||
).unwrap();
|
).unwrap();
|
||||||
|
Configuration::set_max_validators_per_core(
|
||||||
|
Origin::root(), new_config.max_validators_per_core,
|
||||||
|
).unwrap();
|
||||||
Configuration::set_dispute_period(
|
Configuration::set_dispute_period(
|
||||||
Origin::root(), new_config.dispute_period,
|
Origin::root(), new_config.dispute_period,
|
||||||
).unwrap();
|
).unwrap();
|
||||||
|
|||||||
@@ -273,8 +273,17 @@ impl<T: Config> Module<T> {
|
|||||||
|
|
||||||
shuffled_indices.shuffle(&mut rng);
|
shuffled_indices.shuffle(&mut rng);
|
||||||
|
|
||||||
let group_base_size = validators.len() / n_cores as usize;
|
// trim to max per cores. do this after shuffling.
|
||||||
let n_larger_groups = validators.len() % n_cores as usize;
|
{
|
||||||
|
if let Some(max_per_core) = config.max_validators_per_core {
|
||||||
|
let max_total = max_per_core * n_cores;
|
||||||
|
shuffled_indices.truncate(max_total as usize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let group_base_size = shuffled_indices.len() / n_cores as usize;
|
||||||
|
let n_larger_groups = shuffled_indices.len() % n_cores as usize;
|
||||||
|
|
||||||
let groups: Vec<Vec<_>> = (0..n_cores).map(|core_id| {
|
let groups: Vec<Vec<_>> = (0..n_cores).map(|core_id| {
|
||||||
let n_members = if (core_id as usize) < n_larger_groups {
|
let n_members = if (core_id as usize) < n_larger_groups {
|
||||||
group_base_size + 1
|
group_base_size + 1
|
||||||
@@ -1055,6 +1064,68 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn session_change_takes_only_max_per_core() {
|
||||||
|
let config = {
|
||||||
|
let mut config = default_config();
|
||||||
|
config.parathread_cores = 0;
|
||||||
|
config.max_validators_per_core = Some(1);
|
||||||
|
config
|
||||||
|
};
|
||||||
|
|
||||||
|
let genesis_config = MockGenesisConfig {
|
||||||
|
configuration: crate::configuration::GenesisConfig {
|
||||||
|
config: config.clone(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
new_test_ext(genesis_config).execute_with(|| {
|
||||||
|
let chain_a = ParaId::from(1);
|
||||||
|
let chain_b = ParaId::from(2);
|
||||||
|
|
||||||
|
// ensure that we have 5 groups by registering 2 parachains.
|
||||||
|
Paras::schedule_para_initialize(chain_a, ParaGenesisArgs {
|
||||||
|
genesis_head: Vec::new().into(),
|
||||||
|
validation_code: Vec::new().into(),
|
||||||
|
parachain: true,
|
||||||
|
});
|
||||||
|
Paras::schedule_para_initialize(chain_b, ParaGenesisArgs {
|
||||||
|
genesis_head: Vec::new().into(),
|
||||||
|
validation_code: Vec::new().into(),
|
||||||
|
parachain: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
run_to_block(1, |number| match number {
|
||||||
|
1 => Some(SessionChangeNotification {
|
||||||
|
new_config: config.clone(),
|
||||||
|
validators: vec![
|
||||||
|
ValidatorId::from(Sr25519Keyring::Alice.public()),
|
||||||
|
ValidatorId::from(Sr25519Keyring::Bob.public()),
|
||||||
|
ValidatorId::from(Sr25519Keyring::Charlie.public()),
|
||||||
|
ValidatorId::from(Sr25519Keyring::Dave.public()),
|
||||||
|
ValidatorId::from(Sr25519Keyring::Eve.public()),
|
||||||
|
ValidatorId::from(Sr25519Keyring::Ferdie.public()),
|
||||||
|
ValidatorId::from(Sr25519Keyring::One.public()),
|
||||||
|
],
|
||||||
|
random_seed: [99; 32],
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
_ => None,
|
||||||
|
});
|
||||||
|
|
||||||
|
let groups = ValidatorGroups::get();
|
||||||
|
assert_eq!(groups.len(), 2);
|
||||||
|
|
||||||
|
// Even though there are 7 validators, only 1 validator per group
|
||||||
|
// due to the max.
|
||||||
|
for i in 0..2 {
|
||||||
|
assert_eq!(groups[i].len(), 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn schedule_schedules() {
|
fn schedule_schedules() {
|
||||||
let genesis_config = MockGenesisConfig {
|
let genesis_config = MockGenesisConfig {
|
||||||
|
|||||||
Reference in New Issue
Block a user