@@ -18,13 +18,13 @@ use std::sync::{Arc, Weak};
18
18
19
19
use ckey:: { public_to_address, Address , Public } ;
20
20
use ctypes:: util:: unexpected:: OutOfBounds ;
21
- use ctypes:: BlockHash ;
21
+ use ctypes:: { BlockHash , Header } ;
22
22
use parking_lot:: RwLock ;
23
23
24
24
use super :: { RoundRobinValidator , ValidatorSet } ;
25
25
use crate :: client:: ConsensusClient ;
26
26
use crate :: consensus:: bit_set:: BitSet ;
27
- use crate :: consensus:: stake:: { get_validators, Validator } ;
27
+ use crate :: consensus:: stake:: { get_validators, CurrentValidators , Validator } ;
28
28
use crate :: consensus:: EngineError ;
29
29
30
30
/// Validator set containing a known set of public keys.
@@ -41,7 +41,7 @@ impl DynamicValidator {
41
41
}
42
42
}
43
43
44
- fn validators ( & self , parent : BlockHash ) -> Option < Vec < Validator > > {
44
+ fn next_validators ( & self , parent : BlockHash ) -> Option < Vec < Validator > > {
45
45
let client: Arc < dyn ConsensusClient > =
46
46
self . client . read ( ) . as_ref ( ) . and_then ( Weak :: upgrade) . expect ( "Client is not initialized" ) ;
47
47
let block_id = parent. into ( ) ;
@@ -64,19 +64,84 @@ impl DynamicValidator {
64
64
}
65
65
}
66
66
67
+ fn current_validators ( & self , hash : BlockHash ) -> Option < Vec < Validator > > {
68
+ let client: Arc < dyn ConsensusClient > =
69
+ self . client . read ( ) . as_ref ( ) . and_then ( Weak :: upgrade) . expect ( "Client is not initialized" ) ;
70
+ let block_id = hash. into ( ) ;
71
+ let term_id = client. current_term_id ( block_id) . expect (
72
+ "valdators() is called when creating a block or verifying a block.
73
+ Minor creates a block only when the parent block is imported.
74
+ The n'th block is verified only when the parent block is imported." ,
75
+ ) ;
76
+ if term_id == 0 {
77
+ return None
78
+ }
79
+ let state = client. state_at ( block_id) ?;
80
+ let validators = CurrentValidators :: load_from_state ( & state) . unwrap ( ) ;
81
+ if validators. is_empty ( ) {
82
+ None
83
+ } else {
84
+ let mut validators: Vec < _ > = ( * validators) . clone ( ) ;
85
+ validators. reverse ( ) ;
86
+ Some ( validators)
87
+ }
88
+ }
89
+
67
90
fn validators_pubkey ( & self , parent : BlockHash ) -> Option < Vec < Public > > {
68
- self . validators ( parent) . map ( |validators| validators. into_iter ( ) . map ( |val| * val. pubkey ( ) ) . collect ( ) )
91
+ self . next_validators ( parent) . map ( |validators| validators. into_iter ( ) . map ( |val| * val. pubkey ( ) ) . collect ( ) )
69
92
}
70
93
71
94
pub fn proposer_index ( & self , parent : BlockHash , prev_proposer_index : usize , proposed_view : usize ) -> usize {
72
- if let Some ( validators) = self . validators ( parent) {
95
+ if let Some ( validators) = self . next_validators ( parent) {
73
96
let num_validators = validators. len ( ) ;
74
97
proposed_view % num_validators
75
98
} else {
76
99
let num_validators = self . initial_list . count ( & parent) ;
77
100
( prev_proposer_index + proposed_view + 1 ) % num_validators
78
101
}
79
102
}
103
+
104
+ pub fn check_enough_votes_with_validators (
105
+ & self ,
106
+ validators : & [ Validator ] ,
107
+ votes : & BitSet ,
108
+ ) -> Result < ( ) , EngineError > {
109
+ let mut voted_delegation = 0u64 ;
110
+ let n_validators = validators. len ( ) ;
111
+ for index in votes. true_index_iter ( ) {
112
+ assert ! ( index < n_validators) ;
113
+ let validator = validators. get ( index) . ok_or_else ( || {
114
+ EngineError :: ValidatorNotExist {
115
+ height : 0 , // FIXME
116
+ index,
117
+ }
118
+ } ) ?;
119
+ voted_delegation += validator. delegation ( ) ;
120
+ }
121
+ let total_delegation: u64 = validators. iter ( ) . map ( Validator :: delegation) . sum ( ) ;
122
+ if voted_delegation * 3 > total_delegation * 2 {
123
+ Ok ( ( ) )
124
+ } else {
125
+ let threshold = total_delegation as usize * 2 / 3 ;
126
+ Err ( EngineError :: BadSealFieldSize ( OutOfBounds {
127
+ min : Some ( threshold) ,
128
+ max : Some ( total_delegation as usize ) ,
129
+ found : voted_delegation as usize ,
130
+ } ) )
131
+ }
132
+ }
133
+
134
+ pub fn check_enough_votes_with_header ( & self , header : & Header , votes : & BitSet ) -> Result < ( ) , EngineError > {
135
+ let hash = header. hash ( ) ;
136
+ let parent = * header. parent_hash ( ) ;
137
+ let validators = self . current_validators ( hash) . or_else ( move || self . next_validators ( parent) ) ;
138
+
139
+ if let Some ( validators) = validators {
140
+ self . check_enough_votes_with_validators ( & validators, votes)
141
+ } else {
142
+ self . initial_list . check_enough_votes ( header. parent_hash ( ) , votes)
143
+ }
144
+ }
80
145
}
81
146
82
147
impl ValidatorSet for DynamicValidator {
@@ -136,38 +201,16 @@ impl ValidatorSet for DynamicValidator {
136
201
}
137
202
138
203
fn count ( & self , parent : & BlockHash ) -> usize {
139
- if let Some ( validators) = self . validators ( * parent) {
204
+ if let Some ( validators) = self . next_validators ( * parent) {
140
205
validators. len ( )
141
206
} else {
142
207
self . initial_list . count ( parent)
143
208
}
144
209
}
145
210
146
211
fn check_enough_votes ( & self , parent : & BlockHash , votes : & BitSet ) -> Result < ( ) , EngineError > {
147
- if let Some ( validators) = self . validators ( * parent) {
148
- let mut voted_delegation = 0u64 ;
149
- let n_validators = validators. len ( ) ;
150
- for index in votes. true_index_iter ( ) {
151
- assert ! ( index < n_validators) ;
152
- let validator = validators. get ( index) . ok_or_else ( || {
153
- EngineError :: ValidatorNotExist {
154
- height : 0 , // FIXME
155
- index,
156
- }
157
- } ) ?;
158
- voted_delegation += validator. delegation ( ) ;
159
- }
160
- let total_delegation: u64 = validators. iter ( ) . map ( Validator :: delegation) . sum ( ) ;
161
- if voted_delegation * 3 > total_delegation * 2 {
162
- Ok ( ( ) )
163
- } else {
164
- let threshold = total_delegation as usize * 2 / 3 ;
165
- Err ( EngineError :: BadSealFieldSize ( OutOfBounds {
166
- min : Some ( threshold) ,
167
- max : Some ( total_delegation as usize ) ,
168
- found : voted_delegation as usize ,
169
- } ) )
170
- }
212
+ if let Some ( validators) = self . next_validators ( * parent) {
213
+ self . check_enough_votes_with_validators ( & validators, votes)
171
214
} else {
172
215
self . initial_list . check_enough_votes ( parent, votes)
173
216
}
0 commit comments