#![cfg_attr(not(feature = "std"), no_std)]
use parity_scale_codec::{Decode, Encode};
use scale_info::TypeInfo;
use serde::{Deserialize, Serialize};
pub use sp_consensus_aura::sr25519::AuthorityId as AuraId;
pub use sp_staking::{SessionIndex, EraIndex,};
pub use sp_runtime::{
    generic, BoundedVec,
};
use sp_core::crypto::KeyTypeId;
use sp_std::vec::Vec;
pub const KEY_TYPE: KeyTypeId = KeyTypeId(*b"phro");
pub const PHRON_ENGINE_ID: sp_runtime::ConsensusEngineId = *b"FRNK";
pub const DEFAULT_FINALITY_VERSION: Version = 0;
pub const CURRENT_FINALITY_VERSION: u16 = LEGACY_FINALITY_VERSION + 1;
pub const LEGACY_FINALITY_VERSION: u16 = 1;
#[cfg(feature = "short_session")]
pub const DEFAULT_SESSION_PERIOD: u32 = 30;
#[cfg(feature = "short_session")]
pub const DEFAULT_SESSIONS_PER_ERA: u32 = 3;
#[cfg(not(feature = "short_session"))]
pub const DEFAULT_SESSION_PERIOD: u32 = 900;
#[cfg(not(feature = "short_session"))]
pub const DEFAULT_SESSIONS_PER_ERA: u32 = 8;
pub const MILLISECS_PER_BLOCK: u64 = 1000;
pub const MAX_BLOCK_SIZE: u32 = 5 * 1024 * 1024;
pub const DEFAULT_UNIT_CREATION_DELAY: u64 = 300;
pub const LENIENT_THRESHOLD: sp_runtime::Perquintill = sp_runtime::Perquintill::from_percent(90);
pub const DEFAULT_BAN_MINIMAL_EXPECTED_PERFORMANCE: sp_runtime::Perbill = sp_runtime::Perbill::from_percent(0);
pub const DEFAULT_BAN_SESSION_COUNT_THRESHOLD: SessionCount = 3;
pub const DEFAULT_BAN_REASON_LENGTH: u32 = 300;
pub const DEFAULT_MAX_WINNERS: u32 = u32::MAX;
pub const DEFAULT_COMMITTEE_SIZE: u32 = 4;
pub const DEFAULT_CLEAN_SESSION_COUNTER_DELAY: SessionCount = 960;
pub const DEFAULT_BAN_PERIOD: EraIndex = 10;
mod app {
    use sp_application_crypto::{app_crypto, ed25519};
    app_crypto!(ed25519, crate::KEY_TYPE);
}
sp_application_crypto::with_pair! {
    pub type AuthorityPair = app::Pair;
}
pub type AuthorityId = app::Public;
pub type AuthoritySignature = app::Signature;
pub type Version = u32;
pub type BlockNumber = u32;
pub type Signature = account::EthereumSignature;
pub type AccountId = <<Signature as sp_runtime::traits::Verify>::Signer as sp_runtime::traits::IdentifyAccount>::AccountId;
pub type Balance = u128;
pub type Nonce = u32;
pub type TransactionPriority = u64;
pub type Index = u32;
pub type SessionCount = u32;
pub type BlockCount = u32;
pub type Hash = sp_core::H256;
pub type Header = sp_runtime::generic::Header<BlockNumber, sp_runtime::traits::BlakeTwo256>;
pub type Block = sp_runtime::generic::Block<Header, sp_runtime::OpaqueExtrinsic>;
pub type BlockHash = <Header as sp_runtime::traits::Header>::Hash;
#[derive(Clone, Eq, PartialEq, Debug, Encode, Decode, TypeInfo)]
pub struct VersionChange {
    pub version_incoming: Version,
    pub session: SessionIndex,
}
pub trait FinalityCommitteeManager<T> {
    fn on_next_session_finality_committee(committee: Vec<T>);
}
pub trait SessionInfoProvider<T> {
    fn current_session() -> SessionIndex;
    fn next_session_block_number(current_block: T) -> Option<T>;
}
#[derive(Eq, PartialEq, Debug, Encode, Decode, TypeInfo)]
pub enum ApiError {
    DecodeKey
}
#[derive(Clone, Eq, PartialEq, Debug, Encode, Decode, TypeInfo)]
pub struct SessionAuthorityData {
    authorities: Vec<AuthorityId>,
    emergency_finalizer: Option<AuthorityId>,
}
impl SessionAuthorityData {
    pub fn new(authorities: Vec<AuthorityId>, emergency_finalizer: Option<AuthorityId>) -> Self {
        Self {
            authorities,
            emergency_finalizer,
        }
    }
    pub fn authorities(&self) -> &Vec<AuthorityId> {
        &self.authorities
    }
    pub fn emergency_finalizer(&self) -> &Option<AuthorityId> {
        &self.emergency_finalizer
    }
}
#[derive(Clone, Eq, PartialEq, Debug, Encode, Decode, TypeInfo)]
pub struct SessionCommittee<T> {
    pub finality_committee: Vec<T>,
    pub block_producers: Vec<T>,
}
#[derive(Eq, PartialEq, Debug, Encode, Decode, TypeInfo)]
pub enum SessionValidatorError {
    SessionNotWithinRange {
        lower_limit: SessionIndex,
        upper_limit: SessionIndex,
    },
    Other(Vec<u8>),
}
sp_api::decl_runtime_apis! {
    pub trait PhronSessionApi {
        fn next_session_authorities() -> Result<Vec<AuthorityId>, ApiError>;
        fn authorities() -> Vec<AuthorityId>;
        fn next_session_authority_data() -> Result<SessionAuthorityData, ApiError>;
        fn authority_data() -> SessionAuthorityData;
        fn session_period() -> u32;
        fn millisecs_per_block() -> u64;
        fn finality_version() -> Version;
        fn next_session_finality_version() -> Version;
        fn next_session_aura_authorities() -> Vec<AuraId>;
        fn key_owner(key: AuthorityId) -> Option<AccountId>;
    }
}
#[derive(Decode, Encode, TypeInfo, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BanConfig {
    pub minimal_expected_performance: sp_runtime::Perbill,
    pub underperformed_session_count_threshold: SessionCount,
    pub clean_session_counter_delay: SessionCount,
    pub ban_period: EraIndex,
}
impl Default for BanConfig {
    fn default() -> Self {
        BanConfig {
            minimal_expected_performance: DEFAULT_BAN_MINIMAL_EXPECTED_PERFORMANCE,
            underperformed_session_count_threshold: DEFAULT_BAN_SESSION_COUNT_THRESHOLD,
            clean_session_counter_delay: DEFAULT_CLEAN_SESSION_COUNTER_DELAY,
            ban_period: DEFAULT_BAN_PERIOD,
        }
    }
}
#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo, Debug)]
pub enum BanReason {
    InsufficientUptime(u32),
    OtherReason(BoundedVec<u8, sp_runtime::traits::ConstU32<DEFAULT_BAN_REASON_LENGTH>>),
}
#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo, Debug)]
pub struct BanInfo {
    pub reason: BanReason,
    pub start: EraIndex,
}
#[derive(Eq, PartialEq, Decode, Encode, TypeInfo)]
pub struct EraValidators<AccountId> {
    pub reserved: Vec<AccountId>,
    pub non_reserved: Vec<AccountId>,
}
impl<AccountId> Default for EraValidators<AccountId> {
    fn default() -> Self {
        Self {
            reserved: Vec::new(),
            non_reserved: Vec::new(),
        }
    }
}
pub trait BanHandler {
    type AccountId;
    fn can_ban(who: &Self::AccountId) -> bool;
}
pub trait ValidatorProvider {
    type AccountId;
    fn current_era_validators() -> EraValidators<Self::AccountId>;
    fn current_era_committee_size() -> CommitteeSeats;
}
#[derive(Decode, Encode, TypeInfo, Clone, Serialize, Deserialize)]
pub struct SessionValidators<T> {
    pub committee: Vec<T>,
    pub non_committee: Vec<T>,
}
impl<T> Default for SessionValidators<T> {
    fn default() -> Self {
        Self {
            committee: Vec::new(),
            non_committee: Vec::new(),
        }
    }
}
#[derive(Decode, Encode, TypeInfo, Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct CommitteeSeats {
    pub reserved_seats: u32,
    pub non_reserved_seats: u32,
    pub non_reserved_finality_seats: u32,
}
impl CommitteeSeats {
    pub fn size(&self) -> u32 {
        self.reserved_seats.saturating_add(self.non_reserved_seats)
    }
}
impl Default for CommitteeSeats {
    fn default() -> Self {
        CommitteeSeats {
            reserved_seats: DEFAULT_COMMITTEE_SIZE,
            non_reserved_seats: 0,
            non_reserved_finality_seats: 0,
        }
    }
}
pub trait BannedValidators {
    type AccountId;
    fn banned() -> Vec<Self::AccountId>;
}
pub trait EraManager {
    fn on_new_era(era: EraIndex);
}
#[derive(Decode, Encode, TypeInfo, Debug, Clone, PartialEq, Eq)]
pub enum ElectionOpenness {
    Permissioned,
    Permissionless,
}