use codec::{Decode, Encode};
use sp_core::Get;
use sp_runtime::{transaction_validity::TransactionValidityError, DispatchError, Perbill};
use sp_std::vec::Vec;
use crate::SessionIndex;
pub type Kind = [u8; 16];
pub type OffenceCount = u32;
#[derive(
Clone,
Copy,
PartialEq,
Eq,
Hash,
PartialOrd,
Ord,
Encode,
Decode,
sp_runtime::RuntimeDebug,
scale_info::TypeInfo,
)]
pub enum DisableStrategy {
Never,
WhenSlashed,
Always,
}
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 disable_strategy(&self) -> DisableStrategy {
DisableStrategy::WhenSlashed
}
fn slash_fraction(&self, offenders_count: u32) -> Perbill;
}
#[derive(PartialEq, sp_runtime::RuntimeDebug)]
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,
disable_strategy: DisableStrategy,
) -> Res;
}
impl<Reporter, Offender, Res: Default> OnOffenceHandler<Reporter, Offender, Res> for () {
fn on_offence(
_offenders: &[OffenceDetails<Reporter, Offender>],
_slash_fraction: &[Perbill],
_session: SessionIndex,
_disable_strategy: DisableStrategy,
) -> Res {
Default::default()
}
}
#[derive(Clone, PartialEq, Eq, Encode, Decode, sp_runtime::RuntimeDebug, 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(())
}
}