@@ -43,9 +43,10 @@ use frame_support::{
43
43
decl_error, decl_event, decl_module, decl_storage, storage, traits:: KeyOwnerProofSystem ,
44
44
Parameter ,
45
45
} ;
46
- use frame_system:: { ensure_none, ensure_signed, DigestOf } ;
46
+ use frame_system:: { ensure_none, ensure_root, ensure_signed} ;
47
+ use pallet_finality_tracker:: OnFinalizationStalled ;
47
48
use sp_runtime:: {
48
- generic:: { DigestItem , OpaqueDigestItemId } ,
49
+ generic:: DigestItem ,
49
50
traits:: Zero ,
50
51
DispatchResult , KeyTypeId ,
51
52
} ;
@@ -205,7 +206,7 @@ decl_storage! {
205
206
State get( fn state) : StoredState <T :: BlockNumber > = StoredState :: Live ;
206
207
207
208
/// Pending change: (signaled at, scheduled change).
208
- PendingChange : Option <StoredPendingChange <T :: BlockNumber >>;
209
+ PendingChange get ( fn pending_change ) : Option <StoredPendingChange <T :: BlockNumber >>;
209
210
210
211
/// next block number where we can force a change.
211
212
NextForced get( fn next_forced) : Option <T :: BlockNumber >;
@@ -280,6 +281,24 @@ decl_module! {
280
281
) ?;
281
282
}
282
283
284
+ /// Note that the current authority set of the GRANDPA finality gadget has
285
+ /// stalled. This will trigger a forced authority set change at the beginning
286
+ /// of the next session, to be enacted `delay` blocks after that. The delay
287
+ /// should be high enough to safely assume that the block signalling the
288
+ /// forced change will not be re-orged (e.g. 1000 blocks). The GRANDPA voters
289
+ /// will start the new authority set using the given finalized block as base.
290
+ /// Only callable by root.
291
+ #[ weight = weight_for:: note_stalled:: <T >( ) ]
292
+ fn note_stalled(
293
+ origin,
294
+ delay: T :: BlockNumber ,
295
+ best_finalized_block_number: T :: BlockNumber ,
296
+ ) {
297
+ ensure_root( origin) ?;
298
+
299
+ Self :: on_stalled( delay, best_finalized_block_number)
300
+ }
301
+
283
302
fn on_finalize( block_number: T :: BlockNumber ) {
284
303
// check for scheduled pending authority set changes
285
304
if let Some ( pending_change) = <PendingChange <T >>:: get( ) {
@@ -295,7 +314,7 @@ decl_module! {
295
314
) )
296
315
} else {
297
316
Self :: deposit_log( ConsensusLog :: ScheduledChange (
298
- ScheduledChange {
317
+ ScheduledChange {
299
318
delay: pending_change. delay,
300
319
next_authorities: pending_change. next_authorities. clone( ) ,
301
320
}
@@ -377,6 +396,11 @@ mod weight_for {
377
396
// fetching set id -> session index mappings
378
397
. saturating_add ( T :: DbWeight :: get ( ) . reads ( 2 ) )
379
398
}
399
+
400
+ pub fn note_stalled < T : super :: Trait > ( ) -> Weight {
401
+ ( 3 * WEIGHT_PER_MICROS )
402
+ . saturating_add ( T :: DbWeight :: get ( ) . writes ( 1 ) )
403
+ }
380
404
}
381
405
382
406
impl < T : Trait > Module < T > {
@@ -580,42 +604,6 @@ impl<T: Trait> Module<T> {
580
604
}
581
605
}
582
606
583
- impl < T : Trait > Module < T > {
584
- /// Attempt to extract a GRANDPA log from a generic digest.
585
- pub fn grandpa_log ( digest : & DigestOf < T > ) -> Option < ConsensusLog < T :: BlockNumber > > {
586
- let id = OpaqueDigestItemId :: Consensus ( & GRANDPA_ENGINE_ID ) ;
587
- digest. convert_first ( |l| l. try_to :: < ConsensusLog < T :: BlockNumber > > ( id) )
588
- }
589
-
590
- /// Attempt to extract a pending set-change signal from a digest.
591
- pub fn pending_change ( digest : & DigestOf < T > )
592
- -> Option < ScheduledChange < T :: BlockNumber > >
593
- {
594
- Self :: grandpa_log ( digest) . and_then ( |signal| signal. try_into_change ( ) )
595
- }
596
-
597
- /// Attempt to extract a forced set-change signal from a digest.
598
- pub fn forced_change ( digest : & DigestOf < T > )
599
- -> Option < ( T :: BlockNumber , ScheduledChange < T :: BlockNumber > ) >
600
- {
601
- Self :: grandpa_log ( digest) . and_then ( |signal| signal. try_into_forced_change ( ) )
602
- }
603
-
604
- /// Attempt to extract a pause signal from a digest.
605
- pub fn pending_pause ( digest : & DigestOf < T > )
606
- -> Option < T :: BlockNumber >
607
- {
608
- Self :: grandpa_log ( digest) . and_then ( |signal| signal. try_into_pause ( ) )
609
- }
610
-
611
- /// Attempt to extract a resume signal from a digest.
612
- pub fn pending_resume ( digest : & DigestOf < T > )
613
- -> Option < T :: BlockNumber >
614
- {
615
- Self :: grandpa_log ( digest) . and_then ( |signal| signal. try_into_resume ( ) )
616
- }
617
- }
618
-
619
607
impl < T : Trait > sp_runtime:: BoundToRuntimeAppPublic for Module < T > {
620
608
type Public = AuthorityId ;
621
609
}
@@ -638,14 +626,26 @@ impl<T: Trait> pallet_session::OneSessionHandler<T::AccountId> for Module<T>
638
626
// Always issue a change if `session` says that the validators have changed.
639
627
// Even if their session keys are the same as before, the underlying economic
640
628
// identities have changed.
641
- let current_set_id = if changed {
629
+ let current_set_id = if changed || < Stalled < T > > :: exists ( ) {
642
630
let next_authorities = validators. map ( |( _, k) | ( k, 1 ) ) . collect :: < Vec < _ > > ( ) ;
643
- if let Some ( ( further_wait, median) ) = <Stalled < T > >:: take ( ) {
644
- let _ = Self :: schedule_change ( next_authorities, further_wait, Some ( median) ) ;
631
+
632
+ let res = if let Some ( ( further_wait, median) ) = <Stalled < T > >:: take ( ) {
633
+ Self :: schedule_change ( next_authorities, further_wait, Some ( median) )
634
+ } else {
635
+ Self :: schedule_change ( next_authorities, Zero :: zero ( ) , None )
636
+ } ;
637
+
638
+ if res. is_ok ( ) {
639
+ CurrentSetId :: mutate ( |s| {
640
+ * s += 1 ;
641
+ * s
642
+ } )
645
643
} else {
646
- let _ = Self :: schedule_change ( next_authorities, Zero :: zero ( ) , None ) ;
644
+ // either the session module signalled that the validators have changed
645
+ // or the set was stalled. but since we didn't successfully schedule
646
+ // an authority set change we do not increment the set id.
647
+ Self :: current_set_id ( )
647
648
}
648
- CurrentSetId :: mutate ( |s| { * s += 1 ; * s } )
649
649
} else {
650
650
// nothing's changed, neither economic conditions nor session keys. update the pointer
651
651
// of the current set.
@@ -663,7 +663,7 @@ impl<T: Trait> pallet_session::OneSessionHandler<T::AccountId> for Module<T>
663
663
}
664
664
}
665
665
666
- impl < T : Trait > pallet_finality_tracker :: OnFinalizationStalled < T :: BlockNumber > for Module < T > {
666
+ impl < T : Trait > OnFinalizationStalled < T :: BlockNumber > for Module < T > {
667
667
fn on_stalled ( further_wait : T :: BlockNumber , median : T :: BlockNumber ) {
668
668
// when we record old authority sets, we can use `pallet_finality_tracker::median`
669
669
// to figure out _who_ failed. until then, we can't meaningfully guard
0 commit comments