use alloc::vec::Vec;
use codec::{Decode, Encode, MaxEncodedLen};
use sp_core::Get;
use sp_runtime::{transaction_validity::TransactionValidityError, DispatchError, Perbill};
use crate::SessionIndex;
pub type Kind = [u8; 16];
pub type OffenceCount = u32;
pub trait Offence<Offender> {
const ID: Kind;
type TimeSlot: Clone + codec::Codec + Ord;
fn offenders(&self) -> Vec<Offender>;
fn session_index(&self) -> SessionIndex;
fn validator_set_count(&self) -> u32;
fn time_slot(&self) -> Self::TimeSlot;
fn slash_fraction(&self, offenders_count: u32) -> Perbill;
}
#[derive(PartialEq, Debug)]
pub enum OffenceError {
DuplicateReport,
Other(u8),
}
impl sp_runtime::traits::Printable for OffenceError {
fn print(&self) {
"OffenceError".print();
match self {
Self::DuplicateReport => "DuplicateReport".print(),
Self::Other(e) => {
"Other".print();
e.print();
},
}
}
}
pub trait ReportOffence<Reporter, Offender, O: Offence<Offender>> {
fn report_offence(reporters: Vec<Reporter>, offence: O) -> Result<(), OffenceError>;
fn is_known_offence(offenders: &[Offender], time_slot: &O::TimeSlot) -> bool;
}
impl<Reporter, Offender, O: Offence<Offender>> ReportOffence<Reporter, Offender, O> for () {
fn report_offence(_reporters: Vec<Reporter>, _offence: O) -> Result<(), OffenceError> {
Ok(())
}
fn is_known_offence(_offenders: &[Offender], _time_slot: &O::TimeSlot) -> bool {
true
}
}
pub trait OnOffenceHandler<Reporter, Offender, Res> {
fn on_offence(
offenders: &[OffenceDetails<Reporter, Offender>],
slash_fraction: &[Perbill],
session: SessionIndex,
) -> Res;
}
impl<Reporter, Offender, Res: Default> OnOffenceHandler<Reporter, Offender, Res> for () {
fn on_offence(
_offenders: &[OffenceDetails<Reporter, Offender>],
_slash_fraction: &[Perbill],
_session: SessionIndex,
) -> Res {
Default::default()
}
}
#[derive(Clone, PartialEq, Eq, Encode, Decode, Debug, scale_info::TypeInfo)]
pub struct OffenceDetails<Reporter, Offender> {
pub offender: Offender,
pub reporters: Vec<Reporter>,
}
pub trait OffenceReportSystem<Reporter, Evidence> {
type Longevity: Get<u64>;
fn publish_evidence(evidence: Evidence) -> Result<(), ()>;
fn check_evidence(evidence: Evidence) -> Result<(), TransactionValidityError>;
fn process_evidence(reporter: Reporter, evidence: Evidence) -> Result<(), DispatchError>;
}
impl<Reporter, Evidence> OffenceReportSystem<Reporter, Evidence> for () {
type Longevity = ();
fn publish_evidence(_evidence: Evidence) -> Result<(), ()> {
Ok(())
}
fn check_evidence(_evidence: Evidence) -> Result<(), TransactionValidityError> {
Ok(())
}
fn process_evidence(_reporter: Reporter, _evidence: Evidence) -> Result<(), DispatchError> {
Ok(())
}
}
#[derive(
Clone,
Copy,
PartialEq,
Eq,
Encode,
Decode,
MaxEncodedLen,
core::fmt::Debug,
scale_info::TypeInfo,
)]
pub struct OffenceSeverity(pub Perbill);
impl OffenceSeverity {
pub fn max_severity() -> Self {
Self(Perbill::from_percent(100))
}
pub fn min_severity() -> Self {
Self(Perbill::from_percent(0))
}
}
impl Default for OffenceSeverity {
fn default() -> Self {
Self::max_severity()
}
}
impl PartialOrd for OffenceSeverity {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
self.0.partial_cmp(&other.0)
}
}
impl Ord for OffenceSeverity {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.0.cmp(&other.0)
}
}