use super::*;
use crate::{
configuration,
mock::{new_test_ext, Configuration, MockGenesisConfig, ParasShared, RuntimeOrigin, Test},
};
use bitvec::{bitvec, prelude::Lsb0};
use pezframe_support::{assert_err, assert_ok};
fn on_new_session(session_index: SessionIndex) -> (HostConfiguration<u32>, HostConfiguration<u32>) {
ParasShared::set_session_index(session_index);
let SessionChangeOutcome { prev_config, new_config } =
Configuration::initializer_on_new_session(&session_index);
let new_config = new_config.unwrap_or_else(|| prev_config.clone());
(prev_config, new_config)
}
#[test]
fn default_is_consistent() {
new_test_ext(Default::default()).execute_with(|| {
configuration::ActiveConfig::<Test>::get().panic_if_not_consistent();
});
}
#[test]
fn scheduled_session_is_two_sessions_from_now() {
new_test_ext(Default::default()).execute_with(|| {
on_new_session(1);
assert_eq!(Configuration::scheduled_session(), 3);
});
}
#[test]
fn initializer_on_new_session() {
new_test_ext(Default::default()).execute_with(|| {
let (prev_config, new_config) = on_new_session(1);
assert_eq!(prev_config, new_config);
assert_ok!(Configuration::set_validation_upgrade_delay(RuntimeOrigin::root(), 100));
let (prev_config, new_config) = on_new_session(2);
assert_eq!(prev_config, new_config);
let (prev_config, new_config) = on_new_session(3);
assert_eq!(prev_config, HostConfiguration::default());
assert_eq!(new_config, HostConfiguration { validation_upgrade_delay: 100, ..prev_config });
});
}
#[test]
fn config_changes_after_2_session_boundary() {
new_test_ext(Default::default()).execute_with(|| {
let old_config = configuration::ActiveConfig::<Test>::get();
let mut config = old_config.clone();
config.validation_upgrade_delay = 100;
assert!(old_config != config);
assert_ok!(Configuration::set_validation_upgrade_delay(RuntimeOrigin::root(), 100));
assert_eq!(configuration::ActiveConfig::<Test>::get(), old_config);
assert_eq!(PendingConfigs::<Test>::get(), vec![(2, config.clone())]);
on_new_session(1);
assert_eq!(configuration::ActiveConfig::<Test>::get(), old_config);
assert_eq!(PendingConfigs::<Test>::get(), vec![(2, config.clone())]);
on_new_session(2);
assert_eq!(configuration::ActiveConfig::<Test>::get(), config);
assert_eq!(PendingConfigs::<Test>::get(), vec![]);
})
}
#[test]
fn consecutive_changes_within_one_session() {
new_test_ext(Default::default()).execute_with(|| {
let old_config = configuration::ActiveConfig::<Test>::get();
let mut config = old_config.clone();
config.validation_upgrade_delay = 100;
config.validation_upgrade_cooldown = 100;
assert!(old_config != config);
assert_ok!(Configuration::set_validation_upgrade_delay(RuntimeOrigin::root(), 100));
assert_ok!(Configuration::set_validation_upgrade_cooldown(RuntimeOrigin::root(), 100));
assert_eq!(configuration::ActiveConfig::<Test>::get(), old_config);
assert_eq!(PendingConfigs::<Test>::get(), vec![(2, config.clone())]);
on_new_session(1);
assert_eq!(configuration::ActiveConfig::<Test>::get(), old_config);
assert_eq!(PendingConfigs::<Test>::get(), vec![(2, config.clone())]);
on_new_session(2);
assert_eq!(configuration::ActiveConfig::<Test>::get(), config);
assert_eq!(PendingConfigs::<Test>::get(), vec![]);
});
}
#[test]
fn pending_next_session_but_we_upgrade_once_more() {
new_test_ext(Default::default()).execute_with(|| {
let initial_config = configuration::ActiveConfig::<Test>::get();
let intermediate_config =
HostConfiguration { validation_upgrade_delay: 100, ..initial_config.clone() };
let final_config = HostConfiguration {
validation_upgrade_delay: 100,
validation_upgrade_cooldown: 99,
..initial_config.clone()
};
assert_ok!(Configuration::set_validation_upgrade_delay(RuntimeOrigin::root(), 100));
assert_eq!(configuration::ActiveConfig::<Test>::get(), initial_config);
assert_eq!(PendingConfigs::<Test>::get(), vec![(2, intermediate_config.clone())]);
on_new_session(1);
assert_ok!(Configuration::set_validation_upgrade_cooldown(RuntimeOrigin::root(), 99));
assert_eq!(configuration::ActiveConfig::<Test>::get(), initial_config);
assert_eq!(
PendingConfigs::<Test>::get(),
vec![(2, intermediate_config.clone()), (3, final_config.clone())]
);
on_new_session(2);
assert_eq!(configuration::ActiveConfig::<Test>::get(), intermediate_config);
assert_eq!(PendingConfigs::<Test>::get(), vec![(3, final_config.clone())]);
on_new_session(3);
assert_eq!(configuration::ActiveConfig::<Test>::get(), final_config);
assert_eq!(PendingConfigs::<Test>::get(), vec![]);
});
}
#[test]
fn scheduled_session_config_update_while_next_session_pending() {
new_test_ext(Default::default()).execute_with(|| {
let initial_config = configuration::ActiveConfig::<Test>::get();
let intermediate_config =
HostConfiguration { validation_upgrade_delay: 100, ..initial_config.clone() };
let final_config = HostConfiguration {
validation_upgrade_delay: 100,
validation_upgrade_cooldown: 99,
code_retention_period: 98,
..initial_config.clone()
};
assert_ok!(Configuration::set_validation_upgrade_delay(RuntimeOrigin::root(), 100));
assert_eq!(configuration::ActiveConfig::<Test>::get(), initial_config);
assert_eq!(PendingConfigs::<Test>::get(), vec![(2, intermediate_config.clone())]);
on_new_session(1);
assert_ok!(Configuration::set_validation_upgrade_cooldown(RuntimeOrigin::root(), 99));
assert_ok!(Configuration::set_code_retention_period(RuntimeOrigin::root(), 98));
assert_eq!(configuration::ActiveConfig::<Test>::get(), initial_config);
assert_eq!(
PendingConfigs::<Test>::get(),
vec![(2, intermediate_config.clone()), (3, final_config.clone())]
);
on_new_session(2);
assert_eq!(configuration::ActiveConfig::<Test>::get(), intermediate_config);
assert_eq!(PendingConfigs::<Test>::get(), vec![(3, final_config.clone())]);
on_new_session(3);
assert_eq!(configuration::ActiveConfig::<Test>::get(), final_config);
assert_eq!(PendingConfigs::<Test>::get(), vec![]);
});
}
#[test]
fn invariants() {
new_test_ext(Default::default()).execute_with(|| {
assert_err!(
Configuration::set_max_code_size(RuntimeOrigin::root(), MAX_CODE_SIZE + 1),
Error::<Test>::InvalidNewValue
);
assert_err!(
Configuration::set_max_pov_size(RuntimeOrigin::root(), POV_SIZE_HARD_LIMIT + 1),
Error::<Test>::InvalidNewValue
);
assert_err!(
Configuration::set_max_head_data_size(RuntimeOrigin::root(), MAX_HEAD_DATA_SIZE + 1),
Error::<Test>::InvalidNewValue
);
assert_err!(
Configuration::set_paras_availability_period(RuntimeOrigin::root(), 0),
Error::<Test>::InvalidNewValue
);
assert_err!(
Configuration::set_no_show_slots(RuntimeOrigin::root(), 0),
Error::<Test>::InvalidNewValue
);
ActiveConfig::<Test>::put(HostConfiguration {
minimum_validation_upgrade_delay: 11,
scheduler_params: SchedulerParams {
paras_availability_period: 10,
..Default::default()
},
..Default::default()
});
assert_err!(
Configuration::set_paras_availability_period(RuntimeOrigin::root(), 12),
Error::<Test>::InvalidNewValue
);
assert_err!(
Configuration::set_minimum_validation_upgrade_delay(RuntimeOrigin::root(), 9),
Error::<Test>::InvalidNewValue
);
assert_err!(
Configuration::set_validation_upgrade_delay(RuntimeOrigin::root(), 0),
Error::<Test>::InvalidNewValue
);
});
}
#[test]
fn consistency_bypass_works() {
new_test_ext(Default::default()).execute_with(|| {
assert_err!(
Configuration::set_max_code_size(RuntimeOrigin::root(), MAX_CODE_SIZE + 1),
Error::<Test>::InvalidNewValue
);
assert_ok!(Configuration::set_bypass_consistency_check(RuntimeOrigin::root(), true));
assert_ok!(Configuration::set_max_code_size(RuntimeOrigin::root(), MAX_CODE_SIZE + 1));
assert_eq!(
configuration::ActiveConfig::<Test>::get().max_code_size,
HostConfiguration::<u32>::default().max_code_size
);
on_new_session(1);
on_new_session(2);
assert_eq!(configuration::ActiveConfig::<Test>::get().max_code_size, MAX_CODE_SIZE + 1);
});
}
#[test]
fn setting_pending_config_members() {
new_test_ext(Default::default()).execute_with(|| {
let new_config = HostConfiguration {
async_backing_params: AsyncBackingParams {
allowed_ancestry_len: 0,
max_candidate_depth: 0,
},
validation_upgrade_cooldown: 100,
validation_upgrade_delay: 10,
code_retention_period: 5,
max_code_size: 100_000,
max_pov_size: 1024,
max_head_data_size: 1_000,
max_validators: None,
dispute_period: 239,
dispute_post_conclusion_acceptance_period: 10,
no_show_slots: 240,
n_delay_tranches: 241,
zeroth_delay_tranche_width: 242,
needed_approvals: 242,
relay_vrf_modulo_samples: 243,
max_upward_queue_count: 1337,
max_upward_queue_size: 228,
max_downward_message_size: 2048,
max_upward_message_size: 448,
max_upward_message_num_per_candidate: 5,
hrmp_sender_deposit: 22,
hrmp_recipient_deposit: 4905,
hrmp_channel_max_capacity: 3921,
hrmp_channel_max_total_size: 7687,
hrmp_max_teyrchain_inbound_channels: 37,
hrmp_channel_max_message_size: 8192,
hrmp_max_teyrchain_outbound_channels: 10,
hrmp_max_message_num_per_candidate: 20,
pvf_voting_ttl: 3,
minimum_validation_upgrade_delay: 20,
executor_params: Default::default(),
approval_voting_params: ApprovalVotingParams { max_approval_coalesce_count: 1 },
minimum_backing_votes: 5,
node_features: bitvec![u8, Lsb0; 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1],
#[allow(deprecated)]
scheduler_params: SchedulerParams {
group_rotation_frequency: 20,
paras_availability_period: 10,
max_validators_per_core: None,
lookahead: 3,
num_cores: 2,
max_availability_timeouts: 0,
on_demand_queue_max_size: 10_000u32,
on_demand_base_fee: 10_000_000u128,
on_demand_fee_variability: Perbill::from_percent(3),
on_demand_target_queue_utilization: Perbill::from_percent(25),
ttl: 5u32,
},
};
Configuration::set_validation_upgrade_cooldown(
RuntimeOrigin::root(),
new_config.validation_upgrade_cooldown,
)
.unwrap();
Configuration::set_validation_upgrade_delay(
RuntimeOrigin::root(),
new_config.validation_upgrade_delay,
)
.unwrap();
Configuration::set_code_retention_period(
RuntimeOrigin::root(),
new_config.code_retention_period,
)
.unwrap();
Configuration::set_max_code_size(RuntimeOrigin::root(), new_config.max_code_size).unwrap();
Configuration::set_max_pov_size(RuntimeOrigin::root(), new_config.max_pov_size).unwrap();
Configuration::set_max_head_data_size(RuntimeOrigin::root(), new_config.max_head_data_size)
.unwrap();
Configuration::set_coretime_cores(
RuntimeOrigin::root(),
new_config.scheduler_params.num_cores,
)
.unwrap();
Configuration::set_group_rotation_frequency(
RuntimeOrigin::root(),
new_config.scheduler_params.group_rotation_frequency,
)
.unwrap();
Configuration::set_minimum_validation_upgrade_delay(
RuntimeOrigin::root(),
new_config.minimum_validation_upgrade_delay,
)
.unwrap();
Configuration::set_paras_availability_period(
RuntimeOrigin::root(),
new_config.scheduler_params.paras_availability_period,
)
.unwrap();
Configuration::set_scheduling_lookahead(
RuntimeOrigin::root(),
new_config.scheduler_params.lookahead,
)
.unwrap();
Configuration::set_max_validators_per_core(
RuntimeOrigin::root(),
new_config.scheduler_params.max_validators_per_core,
)
.unwrap();
Configuration::set_max_validators(RuntimeOrigin::root(), new_config.max_validators)
.unwrap();
Configuration::set_dispute_period(RuntimeOrigin::root(), new_config.dispute_period)
.unwrap();
Configuration::set_dispute_post_conclusion_acceptance_period(
RuntimeOrigin::root(),
new_config.dispute_post_conclusion_acceptance_period,
)
.unwrap();
Configuration::set_no_show_slots(RuntimeOrigin::root(), new_config.no_show_slots).unwrap();
Configuration::set_n_delay_tranches(RuntimeOrigin::root(), new_config.n_delay_tranches)
.unwrap();
Configuration::set_zeroth_delay_tranche_width(
RuntimeOrigin::root(),
new_config.zeroth_delay_tranche_width,
)
.unwrap();
Configuration::set_needed_approvals(RuntimeOrigin::root(), new_config.needed_approvals)
.unwrap();
Configuration::set_relay_vrf_modulo_samples(
RuntimeOrigin::root(),
new_config.relay_vrf_modulo_samples,
)
.unwrap();
Configuration::set_max_upward_queue_count(
RuntimeOrigin::root(),
new_config.max_upward_queue_count,
)
.unwrap();
Configuration::set_max_upward_queue_size(
RuntimeOrigin::root(),
new_config.max_upward_queue_size,
)
.unwrap();
Configuration::set_max_downward_message_size(
RuntimeOrigin::root(),
new_config.max_downward_message_size,
)
.unwrap();
Configuration::set_max_upward_message_size(
RuntimeOrigin::root(),
new_config.max_upward_message_size,
)
.unwrap();
Configuration::set_max_upward_message_num_per_candidate(
RuntimeOrigin::root(),
new_config.max_upward_message_num_per_candidate,
)
.unwrap();
Configuration::set_hrmp_sender_deposit(
RuntimeOrigin::root(),
new_config.hrmp_sender_deposit,
)
.unwrap();
Configuration::set_hrmp_recipient_deposit(
RuntimeOrigin::root(),
new_config.hrmp_recipient_deposit,
)
.unwrap();
Configuration::set_hrmp_channel_max_capacity(
RuntimeOrigin::root(),
new_config.hrmp_channel_max_capacity,
)
.unwrap();
Configuration::set_hrmp_channel_max_total_size(
RuntimeOrigin::root(),
new_config.hrmp_channel_max_total_size,
)
.unwrap();
Configuration::set_hrmp_max_teyrchain_inbound_channels(
RuntimeOrigin::root(),
new_config.hrmp_max_teyrchain_inbound_channels,
)
.unwrap();
Configuration::set_hrmp_channel_max_message_size(
RuntimeOrigin::root(),
new_config.hrmp_channel_max_message_size,
)
.unwrap();
Configuration::set_hrmp_max_teyrchain_outbound_channels(
RuntimeOrigin::root(),
new_config.hrmp_max_teyrchain_outbound_channels,
)
.unwrap();
Configuration::set_hrmp_max_message_num_per_candidate(
RuntimeOrigin::root(),
new_config.hrmp_max_message_num_per_candidate,
)
.unwrap();
Configuration::set_pvf_voting_ttl(RuntimeOrigin::root(), new_config.pvf_voting_ttl)
.unwrap();
Configuration::set_minimum_backing_votes(
RuntimeOrigin::root(),
new_config.minimum_backing_votes,
)
.unwrap();
Configuration::set_node_feature(RuntimeOrigin::root(), 1, true).unwrap();
Configuration::set_node_feature(RuntimeOrigin::root(), 1, true).unwrap();
Configuration::set_node_feature(RuntimeOrigin::root(), 3, true).unwrap();
Configuration::set_node_feature(RuntimeOrigin::root(), 10, true).unwrap();
Configuration::set_node_feature(RuntimeOrigin::root(), 10, false).unwrap();
Configuration::set_node_feature(RuntimeOrigin::root(), 11, true).unwrap();
assert_eq!(PendingConfigs::<Test>::get(), vec![(shared::SESSION_DELAY, new_config)],);
})
}
#[test]
fn non_root_cannot_set_config() {
new_test_ext(Default::default()).execute_with(|| {
assert!(Configuration::set_validation_upgrade_delay(RuntimeOrigin::signed(1), 100).is_err());
});
}
#[test]
fn verify_externally_accessible() {
use pezkuwi_primitives::{well_known_keys, AbridgedHostConfiguration};
new_test_ext(Default::default()).execute_with(|| {
let mut ground_truth = HostConfiguration::default();
ground_truth.async_backing_params =
AsyncBackingParams { allowed_ancestry_len: 111, max_candidate_depth: 222 };
ActiveConfig::<Test>::put(ground_truth.clone());
let raw_active_config = pezsp_io::storage::get(well_known_keys::ACTIVE_CONFIG)
.expect("config must be present in storage under ACTIVE_CONFIG");
let abridged_config = AbridgedHostConfiguration::decode(&mut &raw_active_config[..])
.expect("HostConfiguration must be decodable into AbridgedHostConfiguration");
assert_eq!(
abridged_config,
AbridgedHostConfiguration {
max_code_size: ground_truth.max_code_size,
max_head_data_size: ground_truth.max_head_data_size,
max_upward_queue_count: ground_truth.max_upward_queue_count,
max_upward_queue_size: ground_truth.max_upward_queue_size,
max_upward_message_size: ground_truth.max_upward_message_size,
max_upward_message_num_per_candidate: ground_truth
.max_upward_message_num_per_candidate,
hrmp_max_message_num_per_candidate: ground_truth.hrmp_max_message_num_per_candidate,
validation_upgrade_cooldown: ground_truth.validation_upgrade_cooldown,
validation_upgrade_delay: ground_truth.validation_upgrade_delay,
async_backing_params: ground_truth.async_backing_params,
},
);
});
}
#[test]
fn active_config_hrmp_channel_size_and_capacity_ratio_works() {
pezframe_support::parameter_types! {
pub Ratio100: Percent = Percent::from_percent(100);
pub Ratio50: Percent = Percent::from_percent(50);
}
let mut genesis: MockGenesisConfig = Default::default();
genesis.configuration.config.hrmp_channel_max_message_size = 1024;
genesis.configuration.config.hrmp_channel_max_capacity = 100;
new_test_ext(genesis).execute_with(|| {
let active_config = configuration::ActiveConfig::<Test>::get();
assert_eq!(active_config.hrmp_channel_max_message_size, 1024);
assert_eq!(active_config.hrmp_channel_max_capacity, 100);
assert_eq!(
ActiveConfigHrmpChannelSizeAndCapacityRatio::<Test, Ratio100>::get(),
(1024, 100)
);
assert_eq!(ActiveConfigHrmpChannelSizeAndCapacityRatio::<Test, Ratio50>::get(), (512, 50));
assert_ok!(Configuration::set_hrmp_channel_max_message_size(
RuntimeOrigin::root(),
active_config.hrmp_channel_max_message_size * 4
));
assert_ok!(Configuration::set_hrmp_channel_max_capacity(
RuntimeOrigin::root(),
active_config.hrmp_channel_max_capacity * 4
));
on_new_session(1);
on_new_session(2);
let active_config = configuration::ActiveConfig::<Test>::get();
assert_eq!(active_config.hrmp_channel_max_message_size, 4096);
assert_eq!(active_config.hrmp_channel_max_capacity, 400);
assert_eq!(
ActiveConfigHrmpChannelSizeAndCapacityRatio::<Test, Ratio100>::get(),
(4096, 400)
);
assert_eq!(
ActiveConfigHrmpChannelSizeAndCapacityRatio::<Test, Ratio50>::get(),
(2048, 200)
);
})
}