fedimint_hbbft/sender_queue/
dynamic_honey_badger.rs1use std::collections::BTreeSet;
4use std::result;
5
6use crate::crypto::PublicKey;
7use rand::Rng;
8use serde::{de::DeserializeOwned, Serialize};
9
10use super::{
11 Error, Message, SenderQueue, SenderQueueableConsensusProtocol, SenderQueueableMessage,
12 SenderQueueableOutput,
13};
14use crate::{Contribution, CpStep, NodeIdT};
15
16use crate::dynamic_honey_badger::{
17 Batch, Change, ChangeState, DynamicHoneyBadger, Error as DhbError, JoinPlan,
18 Message as DhbMessage,
19};
20
21impl<C, N> SenderQueueableOutput<N, (u64, u64)> for Batch<C, N>
22where
23 C: Contribution,
24 N: NodeIdT,
25{
26 fn participant_change(&self) -> Option<BTreeSet<N>> {
27 if let ChangeState::InProgress(Change::NodeChange(pub_keys)) = self.change() {
28 let candidates = pub_keys.keys();
29 let current_validators: BTreeSet<&N> = self.public_keys().keys().collect();
30 let participants = candidates.chain(current_validators).cloned().collect();
31 Some(participants)
32 } else if let ChangeState::Complete(Change::NodeChange(pub_keys)) = self.change() {
33 let next_validators = pub_keys.keys().cloned().collect();
34 Some(next_validators)
35 } else {
36 None
37 }
38 }
39
40 fn output_epoch(&self) -> (u64, u64) {
41 let hb_epoch = self.epoch() - self.era();
42 (self.era(), hb_epoch)
43 }
44}
45
46impl<N: Ord> SenderQueueableMessage for DhbMessage<N> {
47 type Epoch = (u64, u64);
48
49 fn is_premature(&self, (them_era, them): (u64, u64), max_future_epochs: u64) -> bool {
50 match *self {
51 DhbMessage::HoneyBadger(era, ref msg) => {
52 era > them_era || (era == them_era && msg.epoch() > them + max_future_epochs)
53 }
54 DhbMessage::KeyGen(era, _, _) => era > them_era,
55 DhbMessage::SignedVote(ref signed_vote) => signed_vote.era() > them_era,
56 }
57 }
58
59 fn is_obsolete(&self, (them_era, them): (u64, u64)) -> bool {
60 match *self {
61 DhbMessage::HoneyBadger(era, ref msg) => {
62 era < them_era || (era == them_era && msg.epoch() < them)
63 }
64 DhbMessage::KeyGen(era, _, _) => era < them_era,
65 DhbMessage::SignedVote(ref signed_vote) => signed_vote.era() < them_era,
66 }
67 }
68
69 fn first_epoch(&self) -> (u64, u64) {
70 match *self {
71 DhbMessage::HoneyBadger(era, ref msg) => (era, msg.epoch()),
72 DhbMessage::KeyGen(era, _, _) => (era, 0),
73 DhbMessage::SignedVote(ref signed_vote) => (signed_vote.era(), 0),
74 }
75 }
76}
77
78impl<C, N> SenderQueueableConsensusProtocol for DynamicHoneyBadger<C, N>
79where
80 C: Contribution + Serialize + DeserializeOwned,
81 N: NodeIdT + Serialize + DeserializeOwned,
82{
83 fn max_future_epochs(&self) -> u64 {
84 self.max_future_epochs()
85 }
86}
87
88type Result<C, N> = result::Result<CpStep<SenderQueue<DynamicHoneyBadger<C, N>>>, Error<DhbError>>;
89
90impl<C, N> SenderQueue<DynamicHoneyBadger<C, N>>
91where
92 C: Contribution + Serialize + DeserializeOwned,
93 N: NodeIdT + Serialize + DeserializeOwned,
94{
95 pub fn propose<R: Rng>(&mut self, rng: &mut R, contrib: C) -> Result<C, N> {
102 self.apply(|algo| algo.propose(contrib, rng))
103 }
104
105 pub fn vote_for(&mut self, change: Change<N>) -> Result<C, N> {
110 self.apply(|algo| algo.vote_for(change))
111 }
112
113 pub fn vote_to_add(&mut self, node_id: N, pub_key: PublicKey) -> Result<C, N> {
118 self.apply(|algo| algo.vote_to_add(node_id, pub_key))
119 }
120
121 pub fn vote_to_remove(&mut self, node_id: &N) -> Result<C, N> {
126 self.apply(|algo| algo.vote_to_remove(node_id))
127 }
128
129 pub fn restart<I, R: Rng>(
134 &mut self,
135 join_plan: JoinPlan<N>,
136 peer_ids: I,
137 rng: &mut R,
138 ) -> Result<C, N>
139 where
140 I: Iterator<Item = N>,
141 {
142 if !self.is_removed {
143 return Err(Error::DynamicHoneyBadgerNotRemoved);
144 }
145 let secret_key = self.algo().secret_key().clone();
146 let id = self.algo().netinfo().our_id().clone();
147 let (dhb, dhb_step) =
148 DynamicHoneyBadger::new_joining(id.clone(), secret_key, join_plan, rng)
149 .map_err(Error::DynamicHoneyBadgerNewJoining)?;
150 let (sq, mut sq_step) = SenderQueue::builder(dhb, peer_ids).build(id);
151 sq_step.extend(dhb_step.map(|output| output, |fault| fault, Message::from));
152 *self = sq;
153 Ok(sq_step)
154 }
155}