fedimint_hbbft/dynamic_honey_badger/
batch.rs

1use std::collections::BTreeMap;
2use std::sync::Arc;
3
4use super::{ChangeState, JoinPlan, Params};
5use crate::{NetworkInfo, NodeIdT, PubKeyMap};
6
7/// A batch of transactions the algorithm has output.
8#[derive(Clone, Debug)]
9pub struct Batch<C, N: Ord> {
10    /// The sequence number: there is exactly one batch in each epoch.
11    pub(super) epoch: u64,
12    /// The current `DynamicHoneyBadger` era.
13    pub(super) era: u64,
14    /// The user contributions committed in this epoch.
15    pub(super) contributions: BTreeMap<N, C>,
16    /// The current state of adding or removing a node: whether any is in progress, or completed
17    /// this epoch.
18    pub(super) change: ChangeState<N>,
19    /// The current set of public keys.
20    pub(super) pub_keys: PubKeyMap<N>,
21    /// The network info that applies to the _next_ epoch.
22    pub(super) netinfo: Arc<NetworkInfo<N>>,
23    /// Parameters controlling Honey Badger's behavior and performance.
24    pub(super) params: Params,
25}
26
27impl<C, N: NodeIdT> Batch<C, N> {
28    /// Returns the linear epoch of this `DynamicHoneyBadger` batch.
29    pub fn epoch(&self) -> u64 {
30        self.epoch
31    }
32
33    /// Returns the `DynamicHoneyBadger` era of the batch.
34    pub fn era(&self) -> u64 {
35        self.era
36    }
37
38    /// Returns whether any change to the set of participating nodes is in progress or was
39    /// completed in this epoch.
40    pub fn change(&self) -> &ChangeState<N> {
41        &self.change
42    }
43
44    /// Returns the map of public keys, by node ID.
45    pub fn public_keys(&self) -> &PubKeyMap<N> {
46        &self.pub_keys
47    }
48
49    /// Returns the `NetworkInfo` containing the information about the validators that will produce
50    /// the _next_ epoch after this one.
51    pub fn network_info(&self) -> &Arc<NetworkInfo<N>> {
52        &self.netinfo
53    }
54
55    /// Returns the contributions and their proposers.
56    pub fn contributions(&self) -> impl Iterator<Item = (&N, &C)> {
57        self.contributions.iter()
58    }
59
60    /// Returns an iterator over references to all transactions included in the batch.
61    pub fn iter<'a>(&'a self) -> impl Iterator<Item = <&'a C as IntoIterator>::Item>
62    where
63        &'a C: IntoIterator,
64    {
65        self.contributions.values().flatten()
66    }
67
68    /// Returns an iterator over all transactions included in the batch. Consumes the batch.
69    pub fn into_tx_iter(self) -> impl Iterator<Item = <C as IntoIterator>::Item>
70    where
71        C: IntoIterator,
72    {
73        self.contributions.into_iter().flat_map(|(_, vec)| vec)
74    }
75
76    /// Returns the number of transactions in the batch (without detecting duplicates).
77    pub fn len<T>(&self) -> usize
78    where
79        C: AsRef<[T]>,
80    {
81        self.contributions
82            .values()
83            .map(C::as_ref)
84            .map(<[T]>::len)
85            .sum()
86    }
87
88    /// Returns `true` if the batch contains no transactions.
89    pub fn is_empty<T>(&self) -> bool
90    where
91        C: AsRef<[T]>,
92    {
93        self.contributions
94            .values()
95            .map(C::as_ref)
96            .all(<[T]>::is_empty)
97    }
98
99    /// Returns the `JoinPlan` to be sent to new observer nodes, if it is possible to join in the
100    /// next epoch.
101    pub fn join_plan(&self) -> Option<JoinPlan<N>> {
102        if self.change == ChangeState::None {
103            return None;
104        }
105        Some(JoinPlan {
106            era: self.epoch + 1,
107            change: self.change.clone(),
108            pub_keys: self.pub_keys.clone(),
109            pub_key_set: self.netinfo.public_key_set().clone(),
110            params: self.params.clone(),
111        })
112    }
113
114    /// Returns `true` if all public parts of the batch are equal to `other`. Secret keys and our
115    /// own node ID are ignored.
116    pub fn public_eq(&self, other: &Self) -> bool
117    where
118        C: PartialEq,
119    {
120        self.epoch == other.epoch
121            && self.era == other.era
122            && self.contributions == other.contributions
123            && self.change == other.change
124            && self.pub_keys == other.pub_keys
125            && self.netinfo.public_key_set() == other.netinfo.public_key_set()
126            && self.params == other.params
127    }
128}