1use std::collections::HashMap;
2
3use bit_vec::BitVec;
4use derive_more::Display;
5use prime_tools::get_primes_less_than_x;
6
7use crate::error::ConsensusError;
8use crate::types::{Address, Node};
9use crate::utils::rand_proposer::get_random_proposer_index;
10use crate::ConsensusResult;
11
12#[derive(Clone, Debug, Display, PartialEq, Eq)]
17#[display(fmt = "Authority List {:?}", address)]
18pub struct AuthorityManage {
19 address: Vec<Address>,
20 propose_weights: Vec<u64>,
21 vote_weight_map: HashMap<Address, u32>,
22 propose_weight_sum: u64,
23 vote_weight_sum: u64,
24}
25
26impl AuthorityManage {
27 pub fn new() -> Self {
29 AuthorityManage {
30 address: Vec::new(),
31 propose_weights: Vec::new(),
32 vote_weight_map: HashMap::new(),
33 propose_weight_sum: 0u64,
34 vote_weight_sum: 0u64,
35 }
36 }
37
38 pub fn update(&mut self, authority_list: &mut [Node]) {
40 self.flush();
41 authority_list.sort();
42
43 for node in authority_list.iter_mut() {
44 let propose_weight = u64::from(node.propose_weight);
45 let vote_weight = node.vote_weight;
46
47 self.address.push(node.address.clone());
48 self.propose_weights.push(propose_weight);
49 self.vote_weight_map
50 .insert(node.address.clone(), vote_weight);
51 self.propose_weight_sum += propose_weight;
52 self.vote_weight_sum += u64::from(vote_weight);
53 }
54 }
55
56 pub fn get_vote_weight(&self, addr: &Address) -> ConsensusResult<&u32> {
58 self.vote_weight_map
59 .get(addr)
60 .ok_or(ConsensusError::InvalidAddress)
61 }
62
63 pub fn get_proposer(&self, height: u64, round: u64) -> ConsensusResult<Address> {
65 let index = if cfg!(feature = "random_leader") {
66 get_random_proposer_index(
67 height + round,
68 &self.propose_weights,
69 self.propose_weight_sum,
70 )
71 } else {
72 rotation_leader_index(height, round, self.address.len())
73 };
74
75 if let Some(addr) = self.address.get(index) {
76 return Ok(addr.to_owned());
77 }
78 Err(ConsensusError::Other(
79 "The address list mismatch propose weight list".to_string(),
80 ))
81 }
82
83 pub fn is_above_threshold(&self, bitmap: &[u8]) -> ConsensusResult<bool> {
85 let bitmap = BitVec::from_bytes(bitmap);
86 let mut acc = 0u64;
87
88 for node in bitmap.iter().zip(self.address.iter()) {
89 if node.0 {
90 if let Some(weight) = self.vote_weight_map.get(node.1) {
91 acc += u64::from(*weight);
92 } else {
93 return Err(ConsensusError::Other(format!(
94 "Lose {:?} vote weight",
95 node.1.clone()
96 )));
97 }
98 }
99 }
100
101 Ok(acc * 3 > self.vote_weight_sum * 2)
102 }
103
104 pub fn get_voters(&self, bitmap: &[u8]) -> ConsensusResult<Vec<Address>> {
105 let bitmap = BitVec::from_bytes(bitmap);
106 let voters = bitmap
107 .iter()
108 .zip(self.address.iter())
109 .filter(|node| node.0)
110 .map(|node| node.1.clone())
111 .collect::<Vec<_>>();
112 Ok(voters)
113 }
114
115 pub fn contains(&self, address: &Address) -> bool {
117 self.address.contains(address)
118 }
119
120 pub fn get_vote_weight_sum(&self) -> u64 {
122 self.vote_weight_sum
123 }
124
125 pub fn flush(&mut self) {
127 self.address.clear();
128 self.propose_weights.clear();
129 self.vote_weight_map.clear();
130 self.propose_weight_sum = 0;
131 self.vote_weight_sum = 0;
132 }
133
134 pub fn len(&self) -> usize {
136 self.address.len()
137 }
138
139 pub fn get_address_ref(&self) -> &Vec<Address> {
140 &self.address
141 }
142}
143
144pub fn extract_voters(
147 authority_list: &mut [Node],
148 address_bitmap: &bytes::Bytes,
149) -> ConsensusResult<Vec<Address>> {
150 authority_list.sort();
151 let bitmap = BitVec::from_bytes(address_bitmap);
152 let voters: Vec<Address> = bitmap
153 .iter()
154 .zip(authority_list.iter())
155 .filter(|pair| pair.0) .map(|pair| pair.1.address.clone()) .collect::<Vec<_>>();
158 Ok(voters)
159}
160
161pub fn get_leader(height: u64, round: u64, mut authority_list: Vec<Node>) -> Address {
163 authority_list.sort();
164 let mut weight_sum = 0;
165 let mut propose_weights = Vec::new();
166 for node in authority_list.iter() {
167 weight_sum += node.propose_weight;
168 propose_weights.push(node.propose_weight as u64);
169 }
170
171 let index = if cfg!(feature = "random_leader") {
172 get_random_proposer_index(height + round, &propose_weights, weight_sum as u64)
173 } else {
174 rotation_leader_index(height, round, authority_list.len())
175 };
176
177 authority_list[index].address.clone()
178}
179
180fn rotation_leader_index(height: u64, round: u64, authority_len: usize) -> usize {
181 let len = authority_len as u32;
182 let prime_num = *get_primes_less_than_x(len).last().unwrap_or(&1) as u64;
183 let res = (height * prime_num + round) % (len as u64);
184 res as usize
185}
186
187#[cfg(test)]
188mod test {
189 use bit_vec::BitVec;
190 use bytes::Bytes;
191 use rand::random;
192
193 use crate::error::ConsensusError;
194 use crate::extract_voters;
195 use crate::types::{Address, Node};
196 use crate::utils::auth_manage::AuthorityManage;
197
198 fn gen_address() -> Address {
199 Address::from((0..32).map(|_| random::<u8>()).collect::<Vec<_>>())
200 }
201
202 fn gen_auth_list(len: usize) -> Vec<Node> {
203 if len == 0 {
204 return vec![];
205 }
206
207 let mut authority_list = Vec::new();
208 for _ in 0..len {
209 authority_list.push(gen_node(gen_address(), random::<u32>(), random::<u32>()));
210 }
211 authority_list
212 }
213
214 fn gen_node(addr: Address, propose_weight: u32, vote_weight: u32) -> Node {
215 let mut node = Node::new(addr);
216 node.set_propose_weight(propose_weight);
217 node.set_vote_weight(vote_weight);
218 node
219 }
220
221 fn gen_bitmap(len: usize, nbits: Vec<usize>) -> BitVec {
222 let mut bv = BitVec::from_elem(len, false);
223 for n in nbits.into_iter() {
224 bv.set(n, true);
225 }
226 bv
227 }
228
229 #[test]
230 fn test_vote_weight() {
231 let mut authority_list = gen_auth_list(0);
232 let mut authority_manage = AuthorityManage::new();
233 authority_manage.update(&mut authority_list);
234
235 for node in authority_list.iter() {
236 assert_eq!(
237 authority_manage.get_vote_weight(&node.address),
238 Err(ConsensusError::InvalidAddress)
239 );
240 }
241
242 let mut auth_len = random::<u8>();
243 while auth_len == 0 {
244 auth_len = random::<u8>();
245 }
246 authority_manage.update(&mut gen_auth_list(auth_len as usize));
247
248 for node in authority_list.iter() {
249 assert_eq!(
250 *authority_manage.get_vote_weight(&node.address).unwrap(),
251 node.propose_weight
252 );
253 }
254 }
255
256 #[test]
257 fn test_update() {
258 let mut authority_list = gen_auth_list(random::<u8>() as usize);
259 let mut auth_manage = AuthorityManage::new();
260 auth_manage.update(&mut authority_list);
261 assert_eq!(
262 auth_manage.address,
263 authority_list
264 .into_iter()
265 .map(|node| node.address)
266 .collect::<Vec<Address>>()
267 );
268 }
269
270 #[test]
271 fn test_vote_threshold() {
272 let mut authority_list = vec![
273 gen_node(gen_address(), 1u32, 1u32),
274 gen_node(gen_address(), 1u32, 1u32),
275 gen_node(gen_address(), 1u32, 1u32),
276 gen_node(gen_address(), 1u32, 1u32),
277 ];
278 authority_list.sort();
279 let mut authority = AuthorityManage::new();
280 authority.update(&mut authority_list);
281
282 for i in 0..4 {
283 let bit_map = gen_bitmap(4, vec![i]);
284 let res = authority.is_above_threshold(Bytes::from(bit_map.to_bytes()).as_ref());
285 assert!(!res.unwrap())
286 }
287
288 let tmp = vec![vec![1, 2], vec![1, 3], vec![2, 3], vec![0, 1], vec![0, 2]];
289 for i in tmp.into_iter() {
290 let bit_map = gen_bitmap(4, i);
291 let res = authority.is_above_threshold(Bytes::from(bit_map.to_bytes()).as_ref());
292 assert!(!res.unwrap())
293 }
294
295 let tmp = vec![vec![0, 1, 2], vec![0, 1, 3], vec![1, 2, 3]];
296 for i in tmp.into_iter() {
297 let bit_map = gen_bitmap(4, i);
298 let res = authority.is_above_threshold(Bytes::from(bit_map.to_bytes()).as_ref());
299 assert!(res.unwrap())
300 }
301
302 let bit_map = gen_bitmap(4, vec![0, 1, 2, 3]);
303 let res = authority.is_above_threshold(Bytes::from(bit_map.to_bytes()).as_ref());
304 assert!(res.unwrap())
305 }
306
307 #[test]
308 fn test_bitmap() {
309 let len = random::<u8>() as usize;
310 let bitmap = (0..len).map(|_| random::<bool>()).collect::<Vec<_>>();
311 let mut bv = BitVec::from_elem(len, false);
312 for (index, is_vote) in bitmap.iter().enumerate() {
313 if *is_vote {
314 bv.set(index, true);
315 }
316 }
317
318 let tmp = Bytes::from(bv.to_bytes());
319 let output = BitVec::from_bytes(tmp.as_ref());
320
321 for item in output.iter().zip(bitmap.iter()) {
322 assert_eq!(item.0, *item.1);
323 }
324 }
325
326 #[test]
327 fn test_get_voters() {
328 let auth_list = (0..4).map(|_| gen_address()).collect::<Vec<_>>();
329 let bitmap = BitVec::from_bytes(&[0b1010_0000]);
330 let voters = bitmap
331 .iter()
332 .zip(auth_list.iter())
333 .filter(|node| node.0)
334 .map(|node| node.1.clone())
335 .collect::<Vec<_>>();
336
337 assert_eq!(voters.len(), 2);
338 assert_eq!(voters[0], auth_list[0]);
339 assert_eq!(voters[1], auth_list[2]);
340 }
341
342 #[test]
343 fn test_poll_leader() {
344 let mut authority_list = vec![
345 gen_node(gen_address(), 1u32, 1u32),
346 gen_node(gen_address(), 1u32, 1u32),
347 gen_node(gen_address(), 1u32, 1u32),
348 gen_node(gen_address(), 1u32, 1u32),
349 ];
350 authority_list.sort();
351 let mut authority = AuthorityManage::new();
352 authority.update(&mut authority_list);
353
354 assert_eq!(
355 authority.get_proposer(1, 0).unwrap(),
356 authority_list[3].address
357 );
358 assert_eq!(
359 authority.get_proposer(1, 1).unwrap(),
360 authority_list[0].address
361 );
362 assert_eq!(
363 authority.get_proposer(2, 0).unwrap(),
364 authority_list[2].address
365 );
366 assert_eq!(
367 authority.get_proposer(2, 2).unwrap(),
368 authority_list[0].address
369 );
370 assert_eq!(
371 authority.get_proposer(3, 0).unwrap(),
372 authority_list[1].address
373 );
374 assert_eq!(
375 authority.get_proposer(3, 1).unwrap(),
376 authority_list[2].address
377 );
378 }
379
380 #[test]
381 fn test_extract_voters() {
382 let mut auth_list = gen_auth_list(10);
383 let mut origin_auth_list = auth_list.clone();
384 origin_auth_list.sort();
385 let bit_map = gen_bitmap(10, vec![0, 1, 2]);
386 let res = extract_voters(&mut auth_list, &Bytes::from(bit_map.to_bytes())).unwrap();
387
388 assert_eq!(res.len(), 3);
389
390 for (index, address) in res.iter().enumerate() {
391 assert_eq!(
392 origin_auth_list.get(index).unwrap().address,
393 address.clone()
394 );
395 }
396 }
397}