@@ -382,12 +382,16 @@ impl Decodable for SealedEmptyStep {
382
382
}
383
383
}
384
384
385
+ struct PermissionedStep {
386
+ inner : Step ,
387
+ can_propose : AtomicBool ,
388
+ }
389
+
385
390
/// Engine using `AuthorityRound` proof-of-authority BFT consensus.
386
391
pub struct AuthorityRound {
387
392
transition_service : IoService < ( ) > ,
388
- step : Arc < Step > ,
389
- can_propose : AtomicBool ,
390
- client : RwLock < Option < Weak < EngineClient > > > ,
393
+ step : Arc < PermissionedStep > ,
394
+ client : Arc < RwLock < Option < Weak < EngineClient > > > > ,
391
395
signer : RwLock < EngineSigner > ,
392
396
validators : Box < ValidatorSet > ,
393
397
validate_score_transition : u64 ,
@@ -407,15 +411,15 @@ pub struct AuthorityRound {
407
411
408
412
// header-chain validator.
409
413
struct EpochVerifier {
410
- step : Arc < Step > ,
414
+ step : Arc < PermissionedStep > ,
411
415
subchain_validators : SimpleList ,
412
416
empty_steps_transition : u64 ,
413
417
}
414
418
415
419
impl super :: EpochVerifier < EthereumMachine > for EpochVerifier {
416
420
fn verify_light ( & self , header : & Header ) -> Result < ( ) , Error > {
417
421
// Validate the timestamp
418
- verify_timestamp ( & * self . step , header_step ( header, self . empty_steps_transition ) ?) ?;
422
+ verify_timestamp ( & self . step . inner , header_step ( header, self . empty_steps_transition ) ?) ?;
419
423
// always check the seal since it's fast.
420
424
// nothing heavier to do.
421
425
verify_external ( header, & self . subchain_validators , self . empty_steps_transition )
@@ -615,13 +619,15 @@ impl AuthorityRound {
615
619
let engine = Arc :: new (
616
620
AuthorityRound {
617
621
transition_service : IoService :: < ( ) > :: start ( ) ?,
618
- step : Arc :: new ( Step {
619
- inner : AtomicUsize :: new ( initial_step) ,
620
- calibrate : our_params. start_step . is_none ( ) ,
621
- duration : our_params. step_duration ,
622
+ step : Arc :: new ( PermissionedStep {
623
+ inner : Step {
624
+ inner : AtomicUsize :: new ( initial_step) ,
625
+ calibrate : our_params. start_step . is_none ( ) ,
626
+ duration : our_params. step_duration ,
627
+ } ,
628
+ can_propose : AtomicBool :: new ( true ) ,
622
629
} ) ,
623
- can_propose : AtomicBool :: new ( true ) ,
624
- client : RwLock :: new ( None ) ,
630
+ client : Arc :: new ( RwLock :: new ( None ) ) ,
625
631
signer : Default :: default ( ) ,
626
632
validators : our_params. validators ,
627
633
validate_score_transition : our_params. validate_score_transition ,
@@ -641,7 +647,10 @@ impl AuthorityRound {
641
647
642
648
// Do not initialize timeouts for tests.
643
649
if should_timeout {
644
- let handler = TransitionHandler { engine : Arc :: downgrade ( & engine) } ;
650
+ let handler = TransitionHandler {
651
+ step : engine. step . clone ( ) ,
652
+ client : engine. client . clone ( ) ,
653
+ } ;
645
654
engine. transition_service . register_handler ( Arc :: new ( handler) ) ?;
646
655
}
647
656
Ok ( engine)
@@ -666,7 +675,7 @@ impl AuthorityRound {
666
675
}
667
676
668
677
fn generate_empty_step ( & self , parent_hash : & H256 ) {
669
- let step = self . step . load ( ) ;
678
+ let step = self . step . inner . load ( ) ;
670
679
let empty_step_rlp = empty_step_rlp ( step, parent_hash) ;
671
680
672
681
if let Ok ( signature) = self . sign ( keccak ( & empty_step_rlp) ) . map ( Into :: into) {
@@ -698,34 +707,37 @@ fn unix_now() -> Duration {
698
707
}
699
708
700
709
struct TransitionHandler {
701
- engine : Weak < AuthorityRound > ,
710
+ step : Arc < PermissionedStep > ,
711
+ client : Arc < RwLock < Option < Weak < EngineClient > > > > ,
702
712
}
703
713
704
714
const ENGINE_TIMEOUT_TOKEN : TimerToken = 23 ;
705
715
706
716
impl IoHandler < ( ) > for TransitionHandler {
707
717
fn initialize ( & self , io : & IoContext < ( ) > ) {
708
- if let Some ( engine) = self . engine . upgrade ( ) {
709
- let remaining = engine. step . duration_remaining ( ) . as_millis ( ) ;
710
- io. register_timer_once ( ENGINE_TIMEOUT_TOKEN , Duration :: from_millis ( remaining) )
711
- . unwrap_or_else ( |e| warn ! ( target: "engine" , "Failed to start consensus step timer: {}." , e) )
712
- }
718
+ let remaining = self . step . inner . duration_remaining ( ) . as_millis ( ) ;
719
+ io. register_timer_once ( ENGINE_TIMEOUT_TOKEN , Duration :: from_millis ( remaining) )
720
+ . unwrap_or_else ( |e| warn ! ( target: "engine" , "Failed to start consensus step timer: {}." , e) )
713
721
}
714
722
715
723
fn timeout ( & self , io : & IoContext < ( ) > , timer : TimerToken ) {
716
724
if timer == ENGINE_TIMEOUT_TOKEN {
717
- if let Some ( engine) = self . engine . upgrade ( ) {
718
- // NOTE we might be lagging by couple of steps in case the timeout
719
- // has not been called fast enough.
720
- // Make sure to advance up to the actual step.
721
- while engine. step . duration_remaining ( ) . as_millis ( ) == 0 {
722
- engine. step ( ) ;
725
+ // NOTE we might be lagging by couple of steps in case the timeout
726
+ // has not been called fast enough.
727
+ // Make sure to advance up to the actual step.
728
+ while self . step . inner . duration_remaining ( ) . as_millis ( ) == 0 {
729
+ self . step . inner . increment ( ) ;
730
+ self . step . can_propose . store ( true , AtomicOrdering :: SeqCst ) ;
731
+ if let Some ( ref weak) = * self . client . read ( ) {
732
+ if let Some ( c) = weak. upgrade ( ) {
733
+ c. update_sealing ( ) ;
734
+ }
723
735
}
724
-
725
- let next_run_at = engine. step . duration_remaining ( ) . as_millis ( ) >> 2 ;
726
- io. register_timer_once ( ENGINE_TIMEOUT_TOKEN , Duration :: from_millis ( next_run_at) )
727
- . unwrap_or_else ( |e| warn ! ( target: "engine" , "Failed to restart consensus step timer: {}." , e) )
728
736
}
737
+
738
+ let next_run_at = self . step . inner . duration_remaining ( ) . as_millis ( ) >> 2 ;
739
+ io. register_timer_once ( ENGINE_TIMEOUT_TOKEN , Duration :: from_millis ( next_run_at) )
740
+ . unwrap_or_else ( |e| warn ! ( target: "engine" , "Failed to restart consensus step timer: {}." , e) )
729
741
}
730
742
}
731
743
}
@@ -742,8 +754,8 @@ impl Engine<EthereumMachine> for AuthorityRound {
742
754
}
743
755
744
756
fn step ( & self ) {
745
- self . step . increment ( ) ;
746
- self . can_propose . store ( true , AtomicOrdering :: SeqCst ) ;
757
+ self . step . inner . increment ( ) ;
758
+ self . step . can_propose . store ( true , AtomicOrdering :: SeqCst ) ;
747
759
if let Some ( ref weak) = * self . client . read ( ) {
748
760
if let Some ( c) = weak. upgrade ( ) {
749
761
c. update_sealing ( ) ;
@@ -790,7 +802,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
790
802
791
803
fn populate_from_parent ( & self , header : & mut Header , parent : & Header ) {
792
804
let parent_step = header_step ( parent, self . empty_steps_transition ) . expect ( "Header has been verified; qed" ) ;
793
- let current_step = self . step . load ( ) ;
805
+ let current_step = self . step . inner . load ( ) ;
794
806
795
807
let current_empty_steps_len = if header. number ( ) >= self . empty_steps_transition {
796
808
self . empty_steps ( parent_step. into ( ) , current_step. into ( ) , parent. hash ( ) ) . len ( )
@@ -816,7 +828,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
816
828
let empty_step: EmptyStep = rlp. as_val ( ) . map_err ( fmt_err) ?; ;
817
829
818
830
if empty_step. verify ( & * self . validators ) . unwrap_or ( false ) {
819
- if self . step . check_future ( empty_step. step ) . is_ok ( ) {
831
+ if self . step . inner . check_future ( empty_step. step ) . is_ok ( ) {
820
832
trace ! ( target: "engine" , "handle_message: received empty step message {:?}" , empty_step) ;
821
833
self . handle_empty_step_message ( empty_step) ;
822
834
} else {
@@ -836,7 +848,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
836
848
fn generate_seal ( & self , block : & ExecutedBlock , parent : & Header ) -> Seal {
837
849
// first check to avoid generating signature most of the time
838
850
// (but there's still a race to the `compare_and_swap`)
839
- if !self . can_propose . load ( AtomicOrdering :: SeqCst ) {
851
+ if !self . step . can_propose . load ( AtomicOrdering :: SeqCst ) {
840
852
trace ! ( target: "engine" , "Aborting seal generation. Can't propose." ) ;
841
853
return Seal :: None ;
842
854
}
@@ -845,7 +857,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
845
857
let parent_step: U256 = header_step ( parent, self . empty_steps_transition )
846
858
. expect ( "Header has been verified; qed" ) . into ( ) ;
847
859
848
- let step = self . step . load ( ) ;
860
+ let step = self . step . inner . load ( ) ;
849
861
850
862
// filter messages from old and future steps and different parents
851
863
let empty_steps = if header. number ( ) >= self . empty_steps_transition {
@@ -922,7 +934,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
922
934
trace ! ( target: "engine" , "generate_seal: Issuing a block for step {}." , step) ;
923
935
924
936
// only issue the seal if we were the first to reach the compare_and_swap.
925
- if self . can_propose . compare_and_swap ( true , false , AtomicOrdering :: SeqCst ) {
937
+ if self . step . can_propose . compare_and_swap ( true , false , AtomicOrdering :: SeqCst ) {
926
938
927
939
self . clear_empty_steps ( parent_step) ;
928
940
@@ -999,7 +1011,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
999
1011
. decode ( ) ?;
1000
1012
1001
1013
let parent_step = header_step ( & parent, self . empty_steps_transition ) ?;
1002
- let current_step = self . step . load ( ) ;
1014
+ let current_step = self . step . inner . load ( ) ;
1003
1015
self . empty_steps ( parent_step. into ( ) , current_step. into ( ) , parent. hash ( ) )
1004
1016
} else {
1005
1017
// we're verifying a block, extract empty steps from the seal
@@ -1052,7 +1064,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
1052
1064
// If yes then probably benign reporting needs to be moved further in the verification.
1053
1065
let set_number = header. number ( ) ;
1054
1066
1055
- match verify_timestamp ( & * self . step , header_step ( header, self . empty_steps_transition ) ?) {
1067
+ match verify_timestamp ( & self . step . inner , header_step ( header, self . empty_steps_transition ) ?) {
1056
1068
Err ( BlockError :: InvalidSeal ) => {
1057
1069
self . validators . report_benign ( header. author ( ) , set_number, header. number ( ) ) ;
1058
1070
Err ( BlockError :: InvalidSeal . into ( ) )
@@ -1294,7 +1306,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
1294
1306
// This way, upon encountering an epoch change, the proposer from the
1295
1307
// new set will be forced to wait until the next step to avoid sealing a
1296
1308
// block that breaks the invariant that the parent's step < the block's step.
1297
- self . can_propose . store ( false , AtomicOrdering :: SeqCst ) ;
1309
+ self . step . can_propose . store ( false , AtomicOrdering :: SeqCst ) ;
1298
1310
return Some ( combine_proofs ( signal_number, & pending. proof , & * finality_proof) ) ;
1299
1311
}
1300
1312
}
0 commit comments