1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
use config::{Committee, Stake};
use crypto::{PublicKey, Signature};
use fastcrypto::traits::EncodeDecodeBase64;
use std::collections::HashSet;
use types::{
ensure,
error::{DagError, DagResult},
Certificate, Header, Vote,
};
pub struct VotesAggregator {
weight: Stake,
votes: Vec<(PublicKey, Signature)>,
used: HashSet<PublicKey>,
}
impl VotesAggregator {
pub fn new() -> Self {
Self {
weight: 0,
votes: Vec::new(),
used: HashSet::new(),
}
}
pub fn append(
&mut self,
vote: Vote,
committee: &Committee,
header: &Header,
) -> DagResult<Option<Certificate>> {
let author = vote.author;
ensure!(
self.used.insert(author.clone()),
DagError::AuthorityReuse(author.encode_base64())
);
self.votes.push((author.clone(), vote.signature));
self.weight += committee.stake(&author);
if self.weight >= committee.quorum_threshold() {
self.weight = 0; return Ok(Some(Certificate::new(
committee,
header.clone(),
self.votes.clone(),
)?));
}
Ok(None)
}
}
pub struct CertificatesAggregator {
weight: Stake,
certificates: Vec<Certificate>,
used: HashSet<PublicKey>,
}
impl CertificatesAggregator {
pub fn new() -> Self {
Self {
weight: 0,
certificates: Vec::new(),
used: HashSet::new(),
}
}
pub fn append(
&mut self,
certificate: Certificate,
committee: &Committee,
) -> Option<Vec<Certificate>> {
let origin = certificate.origin();
if !self.used.insert(origin.clone()) {
return None;
}
self.certificates.push(certificate);
self.weight += committee.stake(&origin);
if self.weight >= committee.quorum_threshold() {
return Some(self.certificates.drain(..).collect());
}
None
}
}