3737//!
3838//! ### Public Functions
3939//!
40- //! - `is_online_in_current_session ` - True if the validator sent a heartbeat in the current session.
40+ //! - `is_online ` - True if the validator sent a heartbeat in the current session.
4141//!
4242//! ## Usage
4343//!
5252//! pub struct Module<T: Trait> for enum Call where origin: T::Origin {
5353//! pub fn is_online(origin, authority_index: u32) -> Result {
5454//! let _sender = ensure_signed(origin)?;
55- //! let _is_online = <im_online::Module<T>>::is_online_in_current_session (authority_index);
55+ //! let _is_online = <im_online::Module<T>>::is_online (authority_index);
5656//! Ok(())
5757//! }
5858//! }
@@ -200,9 +200,14 @@ pub trait Trait: system::Trait + session::historical::Trait {
200200decl_event ! (
201201 pub enum Event <T > where
202202 <T as Trait >:: AuthorityId ,
203+ IdentificationTuple = IdentificationTuple <T >,
203204 {
204205 /// A new heartbeat was received from `AuthorityId`
205206 HeartbeatReceived ( AuthorityId ) ,
207+ /// At the end of the session, no offence was committed.
208+ AllGood ,
209+ /// At the end of the session, at least once validator was found to be offline.
210+ SomeOffline ( Vec <IdentificationTuple >) ,
206211 }
207212) ;
208213
@@ -217,7 +222,7 @@ decl_storage! {
217222 /// For each session index, we keep a mapping of `AuthIndex`
218223 /// to `offchain::OpaqueNetworkState`.
219224 ReceivedHeartbeats get( fn received_heartbeats) : double_map SessionIndex ,
220- blake2_256( AuthIndex ) => Vec <u8 >;
225+ blake2_256( AuthIndex ) => Option < Vec <u8 > >;
221226
222227 /// For each session index, we keep a mapping of `T::ValidatorId` to the
223228 /// number of blocks authored by the given authority.
@@ -249,8 +254,8 @@ decl_module! {
249254 & heartbeat. authority_index
250255 ) ;
251256 let keys = Keys :: <T >:: get( ) ;
252- let public = keys. get( heartbeat. authority_index as usize ) ;
253- if let ( true , Some ( public) ) = ( ! exists, public ) {
257+ let maybe_public = keys. get( heartbeat. authority_index as usize ) ;
258+ if let ( false , Some ( public) ) = ( exists, maybe_public ) {
254259 let signature_valid = heartbeat. using_encoded( |encoded_heartbeat| {
255260 public. verify( & encoded_heartbeat, & signature)
256261 } ) ;
@@ -300,7 +305,7 @@ impl<T: Trait> Module<T> {
300305 /// `authority_index` in the authorities series or if the authority has
301306 /// authored at least one block, during the current session. Otherwise
302307 /// `false`.
303- pub fn is_online_in_current_session ( authority_index : AuthIndex ) -> bool {
308+ pub fn is_online ( authority_index : AuthIndex ) -> bool {
304309 let current_validators = <session:: Module < T > >:: validators ( ) ;
305310
306311 if authority_index >= current_validators. len ( ) as u32 {
@@ -309,10 +314,10 @@ impl<T: Trait> Module<T> {
309314
310315 let authority = & current_validators[ authority_index as usize ] ;
311316
312- Self :: is_online_in_current_session_aux ( authority_index, authority)
317+ Self :: is_online_aux ( authority_index, authority)
313318 }
314319
315- fn is_online_in_current_session_aux ( authority_index : AuthIndex , authority : & T :: ValidatorId ) -> bool {
320+ fn is_online_aux ( authority_index : AuthIndex , authority : & T :: ValidatorId ) -> bool {
316321 let current_session = <session:: Module < T > >:: current_index ( ) ;
317322
318323 <ReceivedHeartbeats >:: exists ( & current_session, & authority_index) ||
@@ -507,46 +512,32 @@ impl<T: Trait> session::OneSessionHandler<T::AccountId> for Module<T> {
507512 }
508513
509514 fn on_before_session_ending ( ) {
510- let mut unresponsive = vec ! [ ] ;
511-
512- let current_session = <session:: Module < T > >:: current_index ( ) ;
513-
515+ let session_index = <session:: Module < T > >:: current_index ( ) ;
514516 let keys = Keys :: < T > :: get ( ) ;
515517 let current_validators = <session:: Module < T > >:: validators ( ) ;
516518
517- for ( auth_idx, validator_id) in current_validators. into_iter ( ) . enumerate ( ) {
518- if !Self :: is_online_in_current_session_aux ( auth_idx as u32 , & validator_id) {
519- let full_identification = T :: FullIdentificationOf :: convert ( validator_id. clone ( ) )
520- . expect (
521- "we got the validator_id from current_validators;
522- current_validators is set of currently acting validators;
523- the mapping between the validator id and its full identification should be valid;
524- thus `FullIdentificationOf::convert` can't return `None`;
525- qed" ,
526- ) ;
527-
528- unresponsive. push ( ( validator_id, full_identification) ) ;
529- }
530- }
519+ let offenders = current_validators. into_iter ( ) . enumerate ( )
520+ . filter ( |( index, id) |
521+ !Self :: is_online_aux ( * index as u32 , id)
522+ ) . filter_map ( |( _, id) |
523+ T :: FullIdentificationOf :: convert ( id. clone ( ) ) . map ( |full_id| ( id, full_id) )
524+ ) . collect :: < Vec < IdentificationTuple < T > > > ( ) ;
531525
532526 // Remove all received heartbeats and number of authored blocks from the
533527 // current session, they have already been processed and won't be needed
534528 // anymore.
535529 <ReceivedHeartbeats >:: remove_prefix ( & <session:: Module < T > >:: current_index ( ) ) ;
536530 <AuthoredBlocks < T > >:: remove_prefix ( & <session:: Module < T > >:: current_index ( ) ) ;
537531
538- if unresponsive. is_empty ( ) {
539- return ;
540- }
541-
542- let validator_set_count = keys. len ( ) as u32 ;
543- let offence = UnresponsivenessOffence {
544- session_index : current_session,
545- validator_set_count,
546- offenders : unresponsive,
547- } ;
532+ if offenders. is_empty ( ) {
533+ Self :: deposit_event ( RawEvent :: AllGood ) ;
534+ } else {
535+ Self :: deposit_event ( RawEvent :: SomeOffline ( offenders. clone ( ) ) ) ;
548536
549- T :: ReportUnresponsiveness :: report_offence ( vec ! [ ] , offence) ;
537+ let validator_set_count = keys. len ( ) as u32 ;
538+ let offence = UnresponsivenessOffence { session_index, validator_set_count, offenders } ;
539+ T :: ReportUnresponsiveness :: report_offence ( vec ! [ ] , offence) ;
540+ }
550541 }
551542
552543 fn on_disabled ( _i : usize ) {
@@ -559,7 +550,7 @@ impl<T: Trait> support::unsigned::ValidateUnsigned for Module<T> {
559550
560551 fn validate_unsigned ( call : & Self :: Call ) -> TransactionValidity {
561552 if let Call :: heartbeat( heartbeat, signature) = call {
562- if <Module < T > >:: is_online_in_current_session ( heartbeat. authority_index ) {
553+ if <Module < T > >:: is_online ( heartbeat. authority_index ) {
563554 // we already received a heartbeat for this authority
564555 return InvalidTransaction :: Stale . into ( ) ;
565556 }
0 commit comments