37
37
//!
38
38
//! ### Public Functions
39
39
//!
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.
41
41
//!
42
42
//! ## Usage
43
43
//!
52
52
//! pub struct Module<T: Trait> for enum Call where origin: T::Origin {
53
53
//! pub fn is_online(origin, authority_index: u32) -> Result {
54
54
//! 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);
56
56
//! Ok(())
57
57
//! }
58
58
//! }
@@ -200,9 +200,14 @@ pub trait Trait: system::Trait + session::historical::Trait {
200
200
decl_event ! (
201
201
pub enum Event <T > where
202
202
<T as Trait >:: AuthorityId ,
203
+ IdentificationTuple = IdentificationTuple <T >,
203
204
{
204
205
/// A new heartbeat was received from `AuthorityId`
205
206
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 >) ,
206
211
}
207
212
) ;
208
213
@@ -217,7 +222,7 @@ decl_storage! {
217
222
/// For each session index, we keep a mapping of `AuthIndex`
218
223
/// to `offchain::OpaqueNetworkState`.
219
224
ReceivedHeartbeats get( fn received_heartbeats) : double_map SessionIndex ,
220
- blake2_256( AuthIndex ) => Vec <u8 >;
225
+ blake2_256( AuthIndex ) => Option < Vec <u8 > >;
221
226
222
227
/// For each session index, we keep a mapping of `T::ValidatorId` to the
223
228
/// number of blocks authored by the given authority.
@@ -249,8 +254,8 @@ decl_module! {
249
254
& heartbeat. authority_index
250
255
) ;
251
256
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 ) {
254
259
let signature_valid = heartbeat. using_encoded( |encoded_heartbeat| {
255
260
public. verify( & encoded_heartbeat, & signature)
256
261
} ) ;
@@ -300,7 +305,7 @@ impl<T: Trait> Module<T> {
300
305
/// `authority_index` in the authorities series or if the authority has
301
306
/// authored at least one block, during the current session. Otherwise
302
307
/// `false`.
303
- pub fn is_online_in_current_session ( authority_index : AuthIndex ) -> bool {
308
+ pub fn is_online ( authority_index : AuthIndex ) -> bool {
304
309
let current_validators = <session:: Module < T > >:: validators ( ) ;
305
310
306
311
if authority_index >= current_validators. len ( ) as u32 {
@@ -309,10 +314,10 @@ impl<T: Trait> Module<T> {
309
314
310
315
let authority = & current_validators[ authority_index as usize ] ;
311
316
312
- Self :: is_online_in_current_session_aux ( authority_index, authority)
317
+ Self :: is_online_aux ( authority_index, authority)
313
318
}
314
319
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 {
316
321
let current_session = <session:: Module < T > >:: current_index ( ) ;
317
322
318
323
<ReceivedHeartbeats >:: exists ( & current_session, & authority_index) ||
@@ -507,46 +512,32 @@ impl<T: Trait> session::OneSessionHandler<T::AccountId> for Module<T> {
507
512
}
508
513
509
514
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 ( ) ;
514
516
let keys = Keys :: < T > :: get ( ) ;
515
517
let current_validators = <session:: Module < T > >:: validators ( ) ;
516
518
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 > > > ( ) ;
531
525
532
526
// Remove all received heartbeats and number of authored blocks from the
533
527
// current session, they have already been processed and won't be needed
534
528
// anymore.
535
529
<ReceivedHeartbeats >:: remove_prefix ( & <session:: Module < T > >:: current_index ( ) ) ;
536
530
<AuthoredBlocks < T > >:: remove_prefix ( & <session:: Module < T > >:: current_index ( ) ) ;
537
531
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 ( ) ) ) ;
548
536
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
+ }
550
541
}
551
542
552
543
fn on_disabled ( _i : usize ) {
@@ -559,7 +550,7 @@ impl<T: Trait> support::unsigned::ValidateUnsigned for Module<T> {
559
550
560
551
fn validate_unsigned ( call : & Self :: Call ) -> TransactionValidity {
561
552
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 ) {
563
554
// we already received a heartbeat for this authority
564
555
return InvalidTransaction :: Stale . into ( ) ;
565
556
}
0 commit comments