hotshot_new_protocol/consensus/
proposals.rs1use std::{collections::BTreeMap, ops::RangeBounds};
2
3use committable::Commitment;
4use hotshot_types::{
5 data::{Leaf2, ViewNumber},
6 traits::node_implementation::NodeType,
7 vote::HasViewNumber,
8};
9
10use crate::message::Proposal;
11
12pub struct Proposals<T: NodeType> {
23 live: BTreeMap<ViewNumber, Commitment<Leaf2<T>>>,
24 all: BTreeMap<ViewNumber, BTreeMap<Commitment<Leaf2<T>>, Proposal<T>>>,
25}
26
27impl<T: NodeType> Proposals<T> {
28 pub fn new() -> Self {
29 Self {
30 live: BTreeMap::new(),
31 all: BTreeMap::new(),
32 }
33 }
34
35 pub fn live(&self, v: ViewNumber) -> Option<&Proposal<T>> {
36 self.get(v, *self.live.get(&v)?)
37 }
38
39 pub fn at(&self, v: ViewNumber) -> impl Iterator<Item = &Proposal<T>> {
40 self.all.get(&v).into_iter().flat_map(|a| a.values())
41 }
42
43 pub fn get(&self, v: ViewNumber, c: Commitment<Leaf2<T>>) -> Option<&Proposal<T>> {
44 self.all.get(&v)?.get(&c)
45 }
46
47 pub fn contains(&self, v: ViewNumber, c: Commitment<Leaf2<T>>) -> bool {
48 self.get(v, c).is_some()
49 }
50
51 pub fn range<R>(&self, r: R) -> impl Iterator<Item = &Proposal<T>>
52 where
53 R: RangeBounds<ViewNumber>,
54 {
55 self.all.range(r).flat_map(|(_, a)| a.values())
56 }
57
58 pub fn latest_before(&self, v: ViewNumber, c: Commitment<Leaf2<T>>) -> Option<&Proposal<T>> {
60 self.all.range(..v).rev().find_map(|(_, a)| a.get(&c))
61 }
62
63 pub fn last(&self) -> Option<&Proposal<T>> {
64 let (_, all) = self.all.last_key_value()?;
65 all.values().max_by_key(|p| p.justify_qc.view_number())
66 }
67
68 pub fn insert_under(&mut self, p: Proposal<T>, c: Commitment<Leaf2<T>>) {
69 self.all.entry(p.view_number).or_default().insert(c, p);
70 }
71
72 pub fn set_live(&mut self, v: ViewNumber, c: Commitment<Leaf2<T>>) {
73 self.live.insert(v, c);
74 }
75
76 pub fn retain_from(&mut self, view: ViewNumber) {
77 self.all = self.all.split_off(&view);
78 self.live = self.live.split_off(&view);
79 }
80
81 #[cfg(test)]
82 pub fn insert(&mut self, p: Proposal<T>) -> Commitment<Leaf2<T>> {
83 let c = crate::helpers::proposal_commitment(&p);
84 self.insert_under(p, c);
85 c
86 }
87
88 #[cfg(test)]
89 pub(crate) fn replace_view(&mut self, proposal: Proposal<T>) {
90 let view = proposal.view_number;
91 self.all.remove(&view);
92 self.live.remove(&view);
93 self.insert(proposal);
94 }
95}