hotmint_storage/
evidence_store.rs1use std::collections::HashSet;
2
3use hotmint_consensus::evidence_store::EvidenceStore;
4use hotmint_types::evidence::EquivocationProof;
5use hotmint_types::validator::ValidatorId;
6use hotmint_types::view::ViewNumber;
7
8pub struct MemoryEvidenceStore {
10 proofs: Vec<EquivocationProof>,
11 committed: HashSet<(ViewNumber, ValidatorId)>,
12}
13
14impl MemoryEvidenceStore {
15 pub fn new() -> Self {
16 Self {
17 proofs: Vec::new(),
18 committed: HashSet::new(),
19 }
20 }
21}
22
23impl Default for MemoryEvidenceStore {
24 fn default() -> Self {
25 Self::new()
26 }
27}
28
29impl EvidenceStore for MemoryEvidenceStore {
30 fn put_evidence(&mut self, proof: EquivocationProof) {
31 let dominated = self
33 .proofs
34 .iter()
35 .any(|p| p.view == proof.view && p.validator == proof.validator);
36 if !dominated {
37 self.proofs.push(proof);
38 }
39 }
40
41 fn get_pending(&self) -> Vec<EquivocationProof> {
42 self.proofs
43 .iter()
44 .filter(|p| !self.committed.contains(&(p.view, p.validator)))
45 .cloned()
46 .collect()
47 }
48
49 fn mark_committed(&mut self, view: ViewNumber, validator: ValidatorId) {
50 self.committed.insert((view, validator));
51 }
52
53 fn all(&self) -> Vec<EquivocationProof> {
54 self.proofs.clone()
55 }
56}
57
58#[cfg(test)]
59mod tests {
60 use super::*;
61 use hotmint_types::block::BlockHash;
62 use hotmint_types::crypto::Signature;
63 use hotmint_types::vote::VoteType;
64
65 fn dummy_proof(view: u64, validator: u64) -> EquivocationProof {
66 EquivocationProof {
67 validator: ValidatorId(validator),
68 view: ViewNumber(view),
69 vote_type: VoteType::Vote,
70 epoch: Default::default(),
71 block_hash_a: BlockHash::GENESIS,
72 signature_a: Signature(vec![1]),
73 block_hash_b: BlockHash::GENESIS,
74 signature_b: Signature(vec![2]),
75 }
76 }
77
78 #[test]
79 fn put_and_get_pending() {
80 let mut store = MemoryEvidenceStore::new();
81 store.put_evidence(dummy_proof(1, 0));
82 store.put_evidence(dummy_proof(2, 1));
83
84 assert_eq!(store.get_pending().len(), 2);
85 assert_eq!(store.all().len(), 2);
86 }
87
88 #[test]
89 fn mark_committed_filters_pending() {
90 let mut store = MemoryEvidenceStore::new();
91 store.put_evidence(dummy_proof(1, 0));
92 store.put_evidence(dummy_proof(2, 1));
93 store.mark_committed(ViewNumber(1), ValidatorId(0));
94
95 let pending = store.get_pending();
96 assert_eq!(pending.len(), 1);
97 assert_eq!(pending[0].view, ViewNumber(2));
98 assert_eq!(store.all().len(), 2);
100 }
101
102 #[test]
103 fn deduplication() {
104 let mut store = MemoryEvidenceStore::new();
105 store.put_evidence(dummy_proof(1, 0));
106 store.put_evidence(dummy_proof(1, 0)); assert_eq!(store.all().len(), 1);
108 }
109}