@@ -24,7 +24,7 @@ use parking_lot::RwLock;
2424use super :: { RoundRobinValidator , ValidatorSet } ;
2525use crate :: client:: ConsensusClient ;
2626use crate :: consensus:: bit_set:: BitSet ;
27- use crate :: consensus:: stake:: { CurrentValidators , NextValidators , Validator } ;
27+ use crate :: consensus:: stake:: { CurrentValidators , NextValidators , PreviousValidators , Validator } ;
2828use crate :: consensus:: EngineError ;
2929
3030/// Validator set containing a known set of public keys.
@@ -87,6 +87,29 @@ impl DynamicValidator {
8787 }
8888 }
8989
90+ fn previous_validators ( & self , hash : BlockHash ) -> Option < Vec < Validator > > {
91+ let client: Arc < dyn ConsensusClient > =
92+ self . client . read ( ) . as_ref ( ) . and_then ( Weak :: upgrade) . expect ( "Client is not initialized" ) ;
93+ let block_id = hash. into ( ) ;
94+ let term_id = client. current_term_id ( block_id) . expect (
95+ "valdators() is called when creating a block or verifying a block.
96+ Minor creates a block only when the parent block is imported.
97+ The n'th block is verified only when the parent block is imported." ,
98+ ) ;
99+ if term_id == 0 {
100+ return None
101+ }
102+ let state = client. state_at ( block_id) ?;
103+ let validators = PreviousValidators :: load_from_state ( & state) . unwrap ( ) ;
104+ if validators. is_empty ( ) {
105+ None
106+ } else {
107+ let mut validators: Vec < _ > = validators. into ( ) ;
108+ validators. reverse ( ) ;
109+ Some ( validators)
110+ }
111+ }
112+
90113 fn validators_pubkey ( & self , hash : BlockHash ) -> Option < Vec < Public > > {
91114 self . next_validators ( hash) . map ( |validators| validators. into_iter ( ) . map ( |val| * val. pubkey ( ) ) . collect ( ) )
92115 }
@@ -95,6 +118,10 @@ impl DynamicValidator {
95118 self . current_validators ( hash) . map ( |validators| validators. into_iter ( ) . map ( |val| * val. pubkey ( ) ) . collect ( ) )
96119 }
97120
121+ fn previous_validators_pubkey ( & self , hash : BlockHash ) -> Option < Vec < Public > > {
122+ self . previous_validators ( hash) . map ( |validators| validators. into_iter ( ) . map ( |val| * val. pubkey ( ) ) . collect ( ) )
123+ }
124+
98125 pub fn proposer_index ( & self , parent : BlockHash , prev_proposer_index : usize , proposed_view : usize ) -> usize {
99126 if let Some ( validators) = self . next_validators ( parent) {
100127 let num_validators = validators. len ( ) ;
@@ -104,6 +131,44 @@ impl DynamicValidator {
104131 ( prev_proposer_index + proposed_view + 1 ) % num_validators
105132 }
106133 }
134+
135+ pub fn get_current ( & self , hash : & BlockHash , index : usize ) -> Option < Public > {
136+ let validators = self . current_validators_pubkey ( * hash) ?;
137+ let n_validators = validators. len ( ) ;
138+ Some ( * validators. get ( index % n_validators) . unwrap ( ) )
139+ }
140+
141+ pub fn check_enough_votes_with_current ( & self , hash : & BlockHash , votes : & BitSet ) -> Result < ( ) , EngineError > {
142+ if let Some ( validators) = self . current_validators ( * hash) {
143+ let mut voted_delegation = 0u64 ;
144+ let n_validators = validators. len ( ) ;
145+ for index in votes. true_index_iter ( ) {
146+ assert ! ( index < n_validators) ;
147+ let validator = validators. get ( index) . ok_or_else ( || {
148+ EngineError :: ValidatorNotExist {
149+ height : 0 , // FIXME
150+ index,
151+ }
152+ } ) ?;
153+ voted_delegation += validator. delegation ( ) ;
154+ }
155+ let total_delegation: u64 = validators. iter ( ) . map ( Validator :: delegation) . sum ( ) ;
156+ if voted_delegation * 3 > total_delegation * 2 {
157+ Ok ( ( ) )
158+ } else {
159+ let threshold = total_delegation as usize * 2 / 3 ;
160+ Err ( EngineError :: BadSealFieldSize ( OutOfBounds {
161+ min : Some ( threshold) ,
162+ max : Some ( total_delegation as usize ) ,
163+ found : voted_delegation as usize ,
164+ } ) )
165+ }
166+ } else {
167+ let client = self . client . read ( ) . as_ref ( ) . and_then ( Weak :: upgrade) . expect ( "Client is not initialized" ) ;
168+ let header = client. block_header ( & ( * hash) . into ( ) ) . unwrap ( ) ;
169+ self . check_enough_votes ( & header. parent_hash ( ) , votes)
170+ }
171+ }
107172}
108173
109174impl ValidatorSet for DynamicValidator {
@@ -208,6 +273,14 @@ impl ValidatorSet for DynamicValidator {
208273 * client_lock = Some ( client) ;
209274 }
210275
276+ fn previous_addresses ( & self , hash : & BlockHash ) -> Vec < Address > {
277+ if let Some ( validators) = self . previous_validators_pubkey ( * hash) {
278+ validators. iter ( ) . map ( public_to_address) . collect ( )
279+ } else {
280+ self . initial_list . previous_addresses ( hash)
281+ }
282+ }
283+
211284 fn current_addresses ( & self , hash : & BlockHash ) -> Vec < Address > {
212285 if let Some ( validators) = self . current_validators_pubkey ( * hash) {
213286 validators. iter ( ) . map ( public_to_address) . collect ( )
0 commit comments