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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use std::collections::BTreeMap;
use std::sync::Arc;
use super::{ChangeState, JoinPlan, Params};
use crate::{NetworkInfo, NodeIdT, PubKeyMap};
/// A batch of transactions the algorithm has output.
#[derive(Clone, Debug)]
pub struct Batch<C, N: Ord> {
/// The sequence number: there is exactly one batch in each epoch.
pub(super) epoch: u64,
/// The current `DynamicHoneyBadger` era.
pub(super) era: u64,
/// The user contributions committed in this epoch.
pub(super) contributions: BTreeMap<N, C>,
/// The current state of adding or removing a node: whether any is in progress, or completed
/// this epoch.
pub(super) change: ChangeState<N>,
/// The current set of public keys.
pub(super) pub_keys: PubKeyMap<N>,
/// The network info that applies to the _next_ epoch.
pub(super) netinfo: Arc<NetworkInfo<N>>,
/// Parameters controlling Honey Badger's behavior and performance.
pub(super) params: Params,
}
impl<C, N: NodeIdT> Batch<C, N> {
/// Returns the linear epoch of this `DynamicHoneyBadger` batch.
pub fn epoch(&self) -> u64 {
self.epoch
}
/// Returns the `DynamicHoneyBadger` era of the batch.
pub fn era(&self) -> u64 {
self.era
}
/// Returns whether any change to the set of participating nodes is in progress or was
/// completed in this epoch.
pub fn change(&self) -> &ChangeState<N> {
&self.change
}
/// Returns the map of public keys, by node ID.
pub fn public_keys(&self) -> &PubKeyMap<N> {
&self.pub_keys
}
/// Returns the `NetworkInfo` containing the information about the validators that will produce
/// the _next_ epoch after this one.
pub fn network_info(&self) -> &Arc<NetworkInfo<N>> {
&self.netinfo
}
/// Returns the contributions and their proposers.
pub fn contributions(&self) -> impl Iterator<Item = (&N, &C)> {
self.contributions.iter()
}
/// Returns an iterator over references to all transactions included in the batch.
pub fn iter<'a>(&'a self) -> impl Iterator<Item = <&'a C as IntoIterator>::Item>
where
&'a C: IntoIterator,
{
self.contributions.values().flatten()
}
/// Returns an iterator over all transactions included in the batch. Consumes the batch.
pub fn into_tx_iter(self) -> impl Iterator<Item = <C as IntoIterator>::Item>
where
C: IntoIterator,
{
self.contributions.into_iter().flat_map(|(_, vec)| vec)
}
/// Returns the number of transactions in the batch (without detecting duplicates).
pub fn len<T>(&self) -> usize
where
C: AsRef<[T]>,
{
self.contributions
.values()
.map(C::as_ref)
.map(<[T]>::len)
.sum()
}
/// Returns `true` if the batch contains no transactions.
pub fn is_empty<T>(&self) -> bool
where
C: AsRef<[T]>,
{
self.contributions
.values()
.map(C::as_ref)
.all(<[T]>::is_empty)
}
/// Returns the `JoinPlan` to be sent to new observer nodes, if it is possible to join in the
/// next epoch.
pub fn join_plan(&self) -> Option<JoinPlan<N>> {
if self.change == ChangeState::None {
return None;
}
Some(JoinPlan {
era: self.epoch + 1,
change: self.change.clone(),
pub_keys: self.pub_keys.clone(),
pub_key_set: self.netinfo.public_key_set().clone(),
params: self.params.clone(),
})
}
/// Returns `true` if all public parts of the batch are equal to `other`. Secret keys and our
/// own node ID are ignored.
pub fn public_eq(&self, other: &Self) -> bool
where
C: PartialEq,
{
self.epoch == other.epoch
&& self.era == other.era
&& self.contributions == other.contributions
&& self.change == other.change
&& self.pub_keys == other.pub_keys
&& self.netinfo.public_key_set() == other.netinfo.public_key_set()
&& self.params == other.params
}
}