replacing the average claps in session with median to determine a harmful authority
Signed-off-by: Uncle Stinky <uncle.stinky@ghostchain.io>
This commit is contained in:
parent
04a63e234d
commit
9cb7f3c782
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ghost-slow-clap"
|
name = "ghost-slow-clap"
|
||||||
version = "0.3.17"
|
version = "0.3.18"
|
||||||
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
|
||||||
|
@ -858,9 +858,9 @@ impl<T: Config> Pallet<T> {
|
|||||||
fn is_good_actor(
|
fn is_good_actor(
|
||||||
authority_index: usize,
|
authority_index: usize,
|
||||||
session_index: SessionIndex,
|
session_index: SessionIndex,
|
||||||
average_claps: u32,
|
median_claps: u32,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if average_claps == 0 {
|
if median_claps == 0 {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -869,10 +869,10 @@ impl<T: Config> Pallet<T> {
|
|||||||
.or_default()
|
.or_default()
|
||||||
.claps;
|
.claps;
|
||||||
|
|
||||||
let authority_deviation = if number_of_claps < average_claps {
|
let authority_deviation = if number_of_claps < median_claps {
|
||||||
Perbill::from_rational(average_claps - number_of_claps, average_claps)
|
Perbill::from_rational(median_claps - number_of_claps, median_claps)
|
||||||
} else {
|
} else {
|
||||||
Perbill::from_rational(number_of_claps - average_claps, average_claps)
|
Perbill::from_rational(number_of_claps - median_claps, median_claps)
|
||||||
};
|
};
|
||||||
authority_deviation < Perbill::from_percent(T::OffenceThreshold::get())
|
authority_deviation < Perbill::from_percent(T::OffenceThreshold::get())
|
||||||
}
|
}
|
||||||
@ -886,6 +886,28 @@ impl<T: Config> Pallet<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn calculate_median_claps(session_index: &SessionIndex) -> u32 {
|
||||||
|
let mut claps_in_session = ClapsInSession::<T>::get(session_index)
|
||||||
|
.values()
|
||||||
|
.filter_map(|value| (!value.disabled).then(|| value.claps))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
if claps_in_session.is_empty() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
claps_in_session.sort();
|
||||||
|
let number_of_claps = claps_in_session.len();
|
||||||
|
|
||||||
|
if number_of_claps % 2 == 0 {
|
||||||
|
let mid_left = claps_in_session[number_of_claps / 2 - 1];
|
||||||
|
let mid_right = claps_in_session[number_of_claps / 2];
|
||||||
|
(mid_left + mid_right) / 2
|
||||||
|
} else {
|
||||||
|
claps_in_session[number_of_claps / 2]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
fn set_test_authorities(authorities: Vec<T::AuthorityId>) {
|
fn set_test_authorities(authorities: Vec<T::AuthorityId>) {
|
||||||
let bounded_authorities = WeakBoundedVec::<_, T::MaxAuthorities>::try_from(authorities)
|
let bounded_authorities = WeakBoundedVec::<_, T::MaxAuthorities>::try_from(authorities)
|
||||||
@ -931,21 +953,12 @@ impl<T: Config> OneSessionHandler<T::AccountId> for Pallet<T> {
|
|||||||
let validators = T::ValidatorSet::validators();
|
let validators = T::ValidatorSet::validators();
|
||||||
let authorities = Authorities::<T>::get();
|
let authorities = Authorities::<T>::get();
|
||||||
|
|
||||||
let (sum_claps, total_claps) = ClapsInSession::<T>::get(&session_index)
|
let median_claps = Self::calculate_median_claps(&session_index);
|
||||||
.iter()
|
|
||||||
.filter(|(_, value)| !value.disabled)
|
|
||||||
.fold((0u32, 0u32), |(sum, total), (_, value)|
|
|
||||||
(sum.saturating_add(value.claps), total.saturating_add(1))
|
|
||||||
);
|
|
||||||
|
|
||||||
let average_claps = sum_claps
|
|
||||||
.checked_div(total_claps)
|
|
||||||
.unwrap_or_default();
|
|
||||||
|
|
||||||
let offenders = validators
|
let offenders = validators
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.filter(|(index, _)| !Self::is_good_actor(*index, session_index, average_claps))
|
.filter(|(index, _)| !Self::is_good_actor(*index, session_index, median_claps))
|
||||||
.filter_map(|(_, id)| {
|
.filter_map(|(_, id)| {
|
||||||
<T::ValidatorSet as ValidatorSetWithIdentification<T::AccountId>>::IdentificationOf::convert(
|
<T::ValidatorSet as ValidatorSetWithIdentification<T::AccountId>>::IdentificationOf::convert(
|
||||||
id.clone(),
|
id.clone(),
|
||||||
|
Loading…
Reference in New Issue
Block a user