1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
#![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");

// Same as GRANDPA_ENGINE_ID because as of right now substrate sends only
// grandpa justifications over the network.
// TODO: change this once https://github.com/paritytech/substrate/issues/8172 will be resolved.
pub const PHRON_ENGINE_ID: sp_runtime::ConsensusEngineId = *b"FRNK";

/// Version returned when no version has been set.
pub const DEFAULT_FINALITY_VERSION: Version = 0;
/// Current version of abft.
pub const CURRENT_FINALITY_VERSION: u16 = LEGACY_FINALITY_VERSION + 1;
/// Legacy version of abft.
pub const LEGACY_FINALITY_VERSION: u16 = 1;


/// The default session period in number of blocks.
#[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;
// We agreed to 5MB as the block size limit.
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! {
    /// An phronesis keypair using ed25519 as its crypto.
    pub type AuthorityPair = app::Pair;
}

pub type AuthorityId = app::Public;
pub type AuthoritySignature = app::Signature;

pub type Version = u32;

/// An index to a block.
pub type BlockNumber = u32;

/// Signature type for Phron Validators
pub type Signature = account::EthereumSignature;

/// AccountId for Phron Validators
pub type AccountId = <<Signature as sp_runtime::traits::Verify>::Signer as sp_runtime::traits::IdentifyAccount>::AccountId;

// Signature type for Chain transactions
// pub type TxSignature = fp_account::EthereumSignature;
//
// /// AccountId for Chain transactions
// pub type TxAccountId = <<TxSignature as sp_runtime::traits::Verify>::Signer as sp_runtime::traits::IdentifyAccount>::AccountId;

/// Balance of an account.
pub type Balance = u128;

/// Index of a transaction in the chain.
pub type Nonce = u32;

/// Priority for a transaction. Additive. Higher is better.
pub type TransactionPriority = u64;

pub type Index = u32;
pub type SessionCount = u32;
pub type BlockCount = u32;

/// A hash of some data used by the chain.
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> {
    /// `committee` is the set elected for finality committee for the next session
    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>;
        /// Returns owner (`AccountId`) corresponding to an AuthorityId (in some contexts referenced
        /// also as `aleph_key` - consensus engine's part of session keys) in the current session
        /// of AlephBFT (finalisation committee).
        fn key_owner(key: AuthorityId) -> Option<AccountId>;
    }
}

/// Configurable parameters for ban validator mechanism
#[derive(Decode, Encode, TypeInfo, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BanConfig {
    /// performance ratio threshold in a session
    /// calculated as ratio of number of blocks produced to expected number of blocks for a single validator
    pub minimal_expected_performance: sp_runtime::Perbill,
    /// how many bad uptime sessions force validator to be removed from the committee?
    pub underperformed_session_count_threshold: SessionCount,
    /// underperformed session counter is cleared every subsequent `clean_session_counter_delay` session
    pub clean_session_counter_delay: SessionCount,
    /// how many eras validators are banned for?
    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,
        }
    }
}

/// Represent any possible reason a validator can be removed from the committee due to
#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo, Debug)]
pub enum BanReason {
    /// Validator has been removed from the committee due to insufficient uptime in a given number
    /// of sessions
    InsufficientUptime(u32),

    /// Any arbitrary reason
    OtherReason(BoundedVec<u8, sp_runtime::traits::ConstU32<DEFAULT_BAN_REASON_LENGTH>>),
}

/// Details of why and for how long a validator is removed from the committee
#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo, Debug)]
pub struct BanInfo {
    /// reason for banning a validator
    pub reason: BanReason,
    /// index of the first era when a ban starts
    pub start: EraIndex,
}

/// Represent committee, ie set of nodes that produce and finalize blocks in the session
#[derive(Eq, PartialEq, Decode, Encode, TypeInfo)]
pub struct EraValidators<AccountId> {
    /// Validators that are chosen to be in committee every single session.
    pub reserved: Vec<AccountId>,
    /// Validators that can be banned out from the committee, under the circumstances
    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;
    /// returns whether the account can be banned
    fn can_ban(who: &Self::AccountId) -> bool;
}

pub trait ValidatorProvider {
    type AccountId;
    /// returns validators for the current era.
    fn current_era_validators() -> EraValidators<Self::AccountId>;
    /// returns committee seats for the current era.
    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(),
        }
    }
}

/// Represent desirable size of a committee in a session
#[derive(Decode, Encode, TypeInfo, Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct CommitteeSeats {
    /// Size of reserved validators in a session
    pub reserved_seats: u32,
    /// Size of non-reserved validators in a session
    pub non_reserved_seats: u32,
    /// Size of non-reserved validators participating in the finality in a session.
    /// A subset of the non-reserved validators.
    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;
    /// returns currently banned validators
    fn banned() -> Vec<Self::AccountId>;
}

pub trait EraManager {
    /// new era has been planned
    fn on_new_era(era: EraIndex);
}

/// Openness of the process of the elections
#[derive(Decode, Encode, TypeInfo, Debug, Clone, PartialEq, Eq)]
pub enum ElectionOpenness {
    Permissioned,
    Permissionless,
}