fix calculation of median, include special case when there're no claps
Signed-off-by: Uncle Stinky <uncle.stinky@ghostchain.io>
This commit is contained in:
parent
f7b1b75d5a
commit
c4b16805f7
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ghost-slow-clap"
|
name = "ghost-slow-clap"
|
||||||
version = "0.3.35"
|
version = "0.3.36"
|
||||||
description = "Applause protocol for the EVM bridge"
|
description = "Applause protocol for the EVM bridge"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
|
@ -90,7 +90,7 @@ pub struct Clap<AccountId, NetworkId, Balance> {
|
|||||||
pub amount: Balance,
|
pub amount: Balance,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)]
|
#[derive(Default, Clone, Copy, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)]
|
||||||
pub struct SessionAuthorityInfo {
|
pub struct SessionAuthorityInfo {
|
||||||
pub claps: u32,
|
pub claps: u32,
|
||||||
pub disabled: bool,
|
pub disabled: bool,
|
||||||
@ -967,10 +967,18 @@ impl<T: Config> Pallet<T> {
|
|||||||
.ok_or(OffchainErr::ErrorInEvmResponse)?)
|
.ok_or(OffchainErr::ErrorInEvmResponse)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calculate_median_claps(session_index: &SessionIndex) -> u32 {
|
fn calculate_median_claps(
|
||||||
let mut claps_in_session = ClapsInSession::<T>::get(session_index)
|
actual_claps_in_session: &BTreeMap<AuthIndex, SessionAuthorityInfo>,
|
||||||
.values()
|
authorities_len: usize,
|
||||||
.filter_map(|value| (!value.disabled).then(|| value.claps))
|
) -> u32 {
|
||||||
|
let mut claps_in_session = (0..authorities_len)
|
||||||
|
.filter_map(|index| {
|
||||||
|
let clap_info = actual_claps_in_session
|
||||||
|
.get(&(index as u32))
|
||||||
|
.copied()
|
||||||
|
.unwrap_or_default();
|
||||||
|
(!clap_info.disabled).then(|| clap_info.claps)
|
||||||
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
if claps_in_session.is_empty() {
|
if claps_in_session.is_empty() {
|
||||||
@ -1083,9 +1091,10 @@ impl<T: Config> OneSessionHandler<T::AccountId> for Pallet<T> {
|
|||||||
fn on_before_session_ending() {
|
fn on_before_session_ending() {
|
||||||
let session_index = T::ValidatorSet::session_index();
|
let session_index = T::ValidatorSet::session_index();
|
||||||
let validators = T::ValidatorSet::validators();
|
let validators = T::ValidatorSet::validators();
|
||||||
let authorities = Authorities::<T>::get(&session_index);
|
let authorities_len = Authorities::<T>::get(&session_index).len();
|
||||||
|
let actual_claps_in_session = ClapsInSession::<T>::get(&session_index);
|
||||||
|
|
||||||
let median_claps = Self::calculate_median_claps(&session_index);
|
let median_claps = Self::calculate_median_claps(&actual_claps_in_session, authorities_len);
|
||||||
|
|
||||||
let offenders = validators
|
let offenders = validators
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@ -1105,7 +1114,7 @@ impl<T: Config> OneSessionHandler<T::AccountId> for Pallet<T> {
|
|||||||
throttling: offenders.clone(),
|
throttling: offenders.clone(),
|
||||||
});
|
});
|
||||||
|
|
||||||
let validator_set_count = authorities.len() as u32;
|
let validator_set_count = authorities_len as u32;
|
||||||
let offence = ThrottlingOffence {
|
let offence = ThrottlingOffence {
|
||||||
session_index,
|
session_index,
|
||||||
validator_set_count,
|
validator_set_count,
|
||||||
|
@ -119,6 +119,157 @@ fn test_throttling_slash_function() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_median_calculations_are_correct() {
|
||||||
|
new_test_ext().execute_with(|| {
|
||||||
|
let data = BTreeMap::from([
|
||||||
|
(
|
||||||
|
0u32,
|
||||||
|
SessionAuthorityInfo {
|
||||||
|
claps: 0,
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
3u32,
|
||||||
|
SessionAuthorityInfo {
|
||||||
|
claps: 1,
|
||||||
|
disabled: false,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
assert_eq!(SlowClap::calculate_median_claps(&data, 4), 0);
|
||||||
|
|
||||||
|
let data = BTreeMap::from([
|
||||||
|
(
|
||||||
|
0u32,
|
||||||
|
SessionAuthorityInfo {
|
||||||
|
claps: 0,
|
||||||
|
disabled: false,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
1u32,
|
||||||
|
SessionAuthorityInfo {
|
||||||
|
claps: 69,
|
||||||
|
disabled: false,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
2u32,
|
||||||
|
SessionAuthorityInfo {
|
||||||
|
claps: 69,
|
||||||
|
disabled: false,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
3u32,
|
||||||
|
SessionAuthorityInfo {
|
||||||
|
claps: 420,
|
||||||
|
disabled: false,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
assert_eq!(SlowClap::calculate_median_claps(&data, 4), 69);
|
||||||
|
|
||||||
|
let data = BTreeMap::from([
|
||||||
|
(
|
||||||
|
0u32,
|
||||||
|
SessionAuthorityInfo {
|
||||||
|
claps: 31,
|
||||||
|
disabled: false,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
1u32,
|
||||||
|
SessionAuthorityInfo {
|
||||||
|
claps: 420,
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
2u32,
|
||||||
|
SessionAuthorityInfo {
|
||||||
|
claps: 69,
|
||||||
|
disabled: false,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
3u32,
|
||||||
|
SessionAuthorityInfo {
|
||||||
|
claps: 156,
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
assert_eq!(SlowClap::calculate_median_claps(&data, 4), 50);
|
||||||
|
|
||||||
|
let data = BTreeMap::from([
|
||||||
|
(
|
||||||
|
0u32,
|
||||||
|
SessionAuthorityInfo {
|
||||||
|
claps: 0,
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
1u32,
|
||||||
|
SessionAuthorityInfo {
|
||||||
|
claps: 420,
|
||||||
|
disabled: false,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
2u32,
|
||||||
|
SessionAuthorityInfo {
|
||||||
|
claps: 0,
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
3u32,
|
||||||
|
SessionAuthorityInfo {
|
||||||
|
claps: 0,
|
||||||
|
disabled: false,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
assert_eq!(SlowClap::calculate_median_claps(&data, 4), 210);
|
||||||
|
|
||||||
|
let data = BTreeMap::from([
|
||||||
|
(
|
||||||
|
0u32,
|
||||||
|
SessionAuthorityInfo {
|
||||||
|
claps: 0,
|
||||||
|
disabled: false,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
1u32,
|
||||||
|
SessionAuthorityInfo {
|
||||||
|
claps: 420,
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
2u32,
|
||||||
|
SessionAuthorityInfo {
|
||||||
|
claps: 69,
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
3u32,
|
||||||
|
SessionAuthorityInfo {
|
||||||
|
claps: 0,
|
||||||
|
disabled: false,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
assert_eq!(SlowClap::calculate_median_claps(&data, 4), 0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn request_body_is_correct_for_get_block_number() {
|
fn request_body_is_correct_for_get_block_number() {
|
||||||
let (offchain, _) = TestOffchainExt::new();
|
let (offchain, _) = TestOffchainExt::new();
|
||||||
|
Loading…
Reference in New Issue
Block a user