1use std::{
2 collections::{BTreeMap, HashMap, HashSet},
3 iter::once,
4 sync::Arc,
5};
6
7use anyhow::Context;
8use async_lock::RwLock;
9use async_trait::async_trait;
10use hotshot::{
11 tasks::EventTransformerState,
12 types::{SignatureKey, SystemContextHandle},
13};
14use hotshot_task_impls::{
15 events::HotShotEvent,
16 network::{
17 test::{ModifierClosure, NetworkEventTaskStateModifier},
18 NetworkEventTaskState,
19 },
20};
21use hotshot_types::{
22 consensus::OuterConsensus,
23 data::QuorumProposalWrapper,
24 epoch_membership::EpochMembershipCoordinator,
25 message::{
26 convert_proposal, GeneralConsensusMessage, Message, MessageKind, Proposal,
27 SequencingMessage, UpgradeLock,
28 },
29 simple_vote::{
30 HasEpoch, QuorumVote2, ViewSyncPreCommitData, ViewSyncPreCommitData2,
31 ViewSyncPreCommitVote, ViewSyncPreCommitVote2,
32 },
33 traits::{
34 election::Membership,
35 network::ConnectedNetwork,
36 node_implementation::{ConsensusTime, NodeImplementation, NodeType, Versions},
37 },
38 vote::HasViewNumber,
39};
40
41#[derive(Debug)]
42pub struct BadProposalViewDos {
44 pub multiplier: u64,
46 pub increment: u64,
48}
49
50#[async_trait]
51impl<TYPES: NodeType, I: NodeImplementation<TYPES>, V: Versions> EventTransformerState<TYPES, I, V>
52 for BadProposalViewDos
53{
54 async fn recv_handler(&mut self, event: &HotShotEvent<TYPES>) -> Vec<HotShotEvent<TYPES>> {
55 vec![event.clone()]
56 }
57
58 async fn send_handler(
59 &mut self,
60 event: &HotShotEvent<TYPES>,
61 _public_key: &TYPES::SignatureKey,
62 _private_key: &<TYPES::SignatureKey as SignatureKey>::PrivateKey,
63 _upgrade_lock: &UpgradeLock<TYPES, V>,
64 consensus: OuterConsensus<TYPES>,
65 _membership_coordinator: EpochMembershipCoordinator<TYPES>,
66 _network: Arc<I::Network>,
67 ) -> Vec<HotShotEvent<TYPES>> {
68 match event {
69 HotShotEvent::QuorumProposalSend(proposal, signature) => {
70 let mut result = Vec::new();
71
72 for n in 1..self.multiplier {
73 let mut modified_proposal = proposal.clone();
74
75 modified_proposal.data.proposal.view_number += n * self.increment;
76
77 result.push(HotShotEvent::QuorumProposalSend(
78 modified_proposal,
79 signature.clone(),
80 ));
81 }
82
83 consensus.write().await.reset_actions();
84 result
85 },
86 _ => vec![event.clone()],
87 }
88 }
89}
90
91#[derive(Debug)]
92pub struct DoubleProposeVote;
94
95#[async_trait]
96impl<TYPES: NodeType, I: NodeImplementation<TYPES>, V: Versions> EventTransformerState<TYPES, I, V>
97 for DoubleProposeVote
98{
99 async fn recv_handler(&mut self, event: &HotShotEvent<TYPES>) -> Vec<HotShotEvent<TYPES>> {
100 vec![event.clone()]
101 }
102
103 async fn send_handler(
104 &mut self,
105 event: &HotShotEvent<TYPES>,
106 _public_key: &TYPES::SignatureKey,
107 _private_key: &<TYPES::SignatureKey as SignatureKey>::PrivateKey,
108 _upgrade_lock: &UpgradeLock<TYPES, V>,
109 _consensus: OuterConsensus<TYPES>,
110 _membership_coordinator: EpochMembershipCoordinator<TYPES>,
111 _network: Arc<I::Network>,
112 ) -> Vec<HotShotEvent<TYPES>> {
113 match event {
114 HotShotEvent::QuorumProposalSend(..) | HotShotEvent::QuorumVoteSend(_) => {
115 vec![event.clone(), event.clone()]
116 },
117 _ => vec![event.clone()],
118 }
119 }
120}
121
122#[derive(Debug)]
123pub struct DishonestLeader<TYPES: NodeType> {
125 pub validated_proposals: Vec<QuorumProposalWrapper<TYPES>>,
127 pub total_proposals_from_node: u64,
129 pub dishonest_at_proposal_numbers: HashSet<u64>,
131 pub view_look_back: usize,
133 pub dishonest_proposal_view_numbers: Arc<RwLock<HashSet<TYPES::View>>>,
135}
136
137impl<TYPES: NodeType> DishonestLeader<TYPES> {
141 async fn handle_proposal_send_event(
144 &self,
145 event: &HotShotEvent<TYPES>,
146 proposal: &Proposal<TYPES, QuorumProposalWrapper<TYPES>>,
147 sender: &TYPES::SignatureKey,
148 ) -> HotShotEvent<TYPES> {
149 let length = self.validated_proposals.len();
150 if !self
151 .dishonest_at_proposal_numbers
152 .contains(&self.total_proposals_from_node)
153 || length == 0
154 {
155 return event.clone();
156 }
157
158 let proposal_from_look_back = if length - 1 < self.view_look_back {
160 self.validated_proposals[0].clone()
162 } else {
163 let index = (self.validated_proposals.len() - 1) - self.view_look_back;
164 self.validated_proposals[index].clone()
165 };
166
167 let mut dishonest_proposal = proposal.clone();
169 dishonest_proposal.data.proposal.justify_qc = proposal_from_look_back.proposal.justify_qc;
170
171 let mut dishonest_proposal_sent = self.dishonest_proposal_view_numbers.write().await;
173 dishonest_proposal_sent.insert(proposal.data.view_number());
174
175 HotShotEvent::QuorumProposalSend(dishonest_proposal, sender.clone())
176 }
177}
178
179#[async_trait]
180impl<TYPES: NodeType, I: NodeImplementation<TYPES> + std::fmt::Debug, V: Versions>
181 EventTransformerState<TYPES, I, V> for DishonestLeader<TYPES>
182{
183 async fn recv_handler(&mut self, event: &HotShotEvent<TYPES>) -> Vec<HotShotEvent<TYPES>> {
184 vec![event.clone()]
185 }
186
187 async fn send_handler(
188 &mut self,
189 event: &HotShotEvent<TYPES>,
190 _public_key: &TYPES::SignatureKey,
191 _private_key: &<TYPES::SignatureKey as SignatureKey>::PrivateKey,
192 _upgrade_lock: &UpgradeLock<TYPES, V>,
193 _consensus: OuterConsensus<TYPES>,
194 _membership_coordinator: EpochMembershipCoordinator<TYPES>,
195 _network: Arc<I::Network>,
196 ) -> Vec<HotShotEvent<TYPES>> {
197 match event {
198 HotShotEvent::QuorumProposalSend(proposal, sender) => {
199 self.total_proposals_from_node += 1;
200 return vec![
201 self.handle_proposal_send_event(event, proposal, sender)
202 .await,
203 ];
204 },
205 HotShotEvent::QuorumProposalValidated(proposal, _) => {
206 self.validated_proposals.push(proposal.data.clone());
207 },
208 _ => {},
209 }
210 vec![event.clone()]
211 }
212}
213
214#[derive(Debug)]
215pub struct DishonestDa {
217 pub total_da_certs_sent_from_node: u64,
219 pub dishonest_at_da_cert_sent_numbers: HashSet<u64>,
221 pub total_views_add_to_cert: u64,
223}
224
225#[async_trait]
226impl<TYPES: NodeType, I: NodeImplementation<TYPES> + std::fmt::Debug, V: Versions>
227 EventTransformerState<TYPES, I, V> for DishonestDa
228{
229 async fn recv_handler(&mut self, event: &HotShotEvent<TYPES>) -> Vec<HotShotEvent<TYPES>> {
230 vec![event.clone()]
231 }
232
233 async fn send_handler(
234 &mut self,
235 event: &HotShotEvent<TYPES>,
236 _public_key: &TYPES::SignatureKey,
237 _private_key: &<TYPES::SignatureKey as SignatureKey>::PrivateKey,
238 _upgrade_lock: &UpgradeLock<TYPES, V>,
239 _consensus: OuterConsensus<TYPES>,
240 _membership_coordinator: EpochMembershipCoordinator<TYPES>,
241 _network: Arc<I::Network>,
242 ) -> Vec<HotShotEvent<TYPES>> {
243 if let HotShotEvent::DacSend(cert, sender) = event {
244 self.total_da_certs_sent_from_node += 1;
245 if self
246 .dishonest_at_da_cert_sent_numbers
247 .contains(&self.total_da_certs_sent_from_node)
248 {
249 let mut result = vec![HotShotEvent::DacSend(cert.clone(), sender.clone())];
250 for i in 1..=self.total_views_add_to_cert {
251 let mut bad_cert = cert.clone();
252 bad_cert.view_number = cert.view_number + i;
253 result.push(HotShotEvent::DacSend(bad_cert, sender.clone()));
254 }
255 return result;
256 }
257 }
258 vec![event.clone()]
259 }
260}
261
262#[derive(Debug)]
264pub struct ViewDelay<TYPES: NodeType> {
265 pub number_of_views_to_delay: u64,
267 pub events_for_view: HashMap<TYPES::View, Vec<HotShotEvent<TYPES>>>,
269 pub stop_view_delay_at_view_number: u64,
271}
272
273#[async_trait]
274impl<TYPES: NodeType, I: NodeImplementation<TYPES> + std::fmt::Debug, V: Versions>
275 EventTransformerState<TYPES, I, V> for ViewDelay<TYPES>
276{
277 async fn recv_handler(&mut self, event: &HotShotEvent<TYPES>) -> Vec<HotShotEvent<TYPES>> {
278 let correct_event = vec![event.clone()];
279 if let Some(view_number) = event.view_number() {
280 if *view_number >= self.stop_view_delay_at_view_number {
281 return correct_event;
282 }
283
284 let events_for_current_view = self.events_for_view.entry(view_number).or_default();
286 events_for_current_view.push(event.clone());
287
288 let view_diff = (*view_number).saturating_sub(self.number_of_views_to_delay);
290 if view_diff > 0 {
291 return match self
292 .events_for_view
293 .remove(&<TYPES as NodeType>::View::new(view_diff))
294 {
295 Some(lookback_events) => lookback_events.clone(),
296 None => vec![],
298 };
299 }
300 }
301
302 correct_event
303 }
304
305 async fn send_handler(
306 &mut self,
307 event: &HotShotEvent<TYPES>,
308 _public_key: &TYPES::SignatureKey,
309 _private_key: &<TYPES::SignatureKey as SignatureKey>::PrivateKey,
310 _upgrade_lock: &UpgradeLock<TYPES, V>,
311 _consensus: OuterConsensus<TYPES>,
312 _membership_coordinator: EpochMembershipCoordinator<TYPES>,
313 _network: Arc<I::Network>,
314 ) -> Vec<HotShotEvent<TYPES>> {
315 vec![event.clone()]
316 }
317}
318
319pub struct DishonestVoting<TYPES: NodeType> {
321 pub view_increment: u64,
323 pub modifier: Arc<ModifierClosure<TYPES>>,
325}
326
327#[async_trait]
328impl<TYPES: NodeType, I: NodeImplementation<TYPES> + std::fmt::Debug, V: Versions>
329 EventTransformerState<TYPES, I, V> for DishonestVoting<TYPES>
330{
331 async fn recv_handler(&mut self, event: &HotShotEvent<TYPES>) -> Vec<HotShotEvent<TYPES>> {
332 vec![event.clone()]
333 }
334
335 async fn send_handler(
336 &mut self,
337 event: &HotShotEvent<TYPES>,
338 public_key: &TYPES::SignatureKey,
339 private_key: &<TYPES::SignatureKey as SignatureKey>::PrivateKey,
340 upgrade_lock: &UpgradeLock<TYPES, V>,
341 _consensus: OuterConsensus<TYPES>,
342 _membership_coordinator: EpochMembershipCoordinator<TYPES>,
343 _network: Arc<I::Network>,
344 ) -> Vec<HotShotEvent<TYPES>> {
345 if let HotShotEvent::QuorumVoteSend(vote) = event {
346 let new_view = vote.view_number + self.view_increment;
347 let spoofed_vote = QuorumVote2::<TYPES>::create_signed_vote(
348 vote.data.clone(),
349 new_view,
350 public_key,
351 private_key,
352 upgrade_lock,
353 )
354 .await
355 .context("Failed to sign vote")
356 .unwrap();
357 tracing::debug!("Sending Quorum Vote for view: {new_view:?}");
358 return vec![HotShotEvent::QuorumVoteSend(spoofed_vote)];
359 }
360 vec![event.clone()]
361 }
362
363 fn add_network_event_task(
364 &self,
365 handle: &mut SystemContextHandle<TYPES, I, V>,
366 network: Arc<<I as NodeImplementation<TYPES>>::Network>,
367 ) {
368 let network_state: NetworkEventTaskState<_, V, _, _> = NetworkEventTaskState {
369 network,
370 view: TYPES::View::genesis(),
371 epoch: None,
372 membership_coordinator: handle.membership_coordinator.clone(),
373 storage: handle.storage(),
374 storage_metrics: handle.storage_metrics(),
375 consensus: OuterConsensus::new(handle.consensus()),
376 upgrade_lock: handle.hotshot.upgrade_lock.clone(),
377 transmit_tasks: BTreeMap::new(),
378 epoch_height: handle.epoch_height,
379 id: handle.hotshot.id,
380 };
381 let modified_network_state = NetworkEventTaskStateModifier {
382 network_event_task_state: network_state,
383 modifier: Arc::clone(&self.modifier),
384 };
385 handle.add_task(modified_network_state);
386 }
387}
388
389impl<TYPES: NodeType> std::fmt::Debug for DishonestVoting<TYPES> {
390 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
391 f.debug_struct("DishonestVoting")
392 .field("view_increment", &self.view_increment)
393 .finish_non_exhaustive()
394 }
395}
396
397#[derive(Debug)]
398pub struct DishonestVoter<TYPES: NodeType> {
400 pub votes_sent: Vec<QuorumVote2<TYPES>>,
402 pub dishonest_proposal_view_numbers: Arc<RwLock<HashSet<TYPES::View>>>,
404}
405
406#[async_trait]
407impl<TYPES: NodeType, I: NodeImplementation<TYPES> + std::fmt::Debug, V: Versions>
408 EventTransformerState<TYPES, I, V> for DishonestVoter<TYPES>
409{
410 async fn recv_handler(&mut self, event: &HotShotEvent<TYPES>) -> Vec<HotShotEvent<TYPES>> {
411 vec![event.clone()]
412 }
413
414 async fn send_handler(
415 &mut self,
416 event: &HotShotEvent<TYPES>,
417 public_key: &TYPES::SignatureKey,
418 private_key: &<TYPES::SignatureKey as SignatureKey>::PrivateKey,
419 upgrade_lock: &UpgradeLock<TYPES, V>,
420 _consensus: OuterConsensus<TYPES>,
421 _membership_coordinator: EpochMembershipCoordinator<TYPES>,
422 _network: Arc<I::Network>,
423 ) -> Vec<HotShotEvent<TYPES>> {
424 match event {
425 HotShotEvent::QuorumProposalRecv(proposal, _sender) => {
426 let dishonest_proposals = self.dishonest_proposal_view_numbers.read().await;
428 if dishonest_proposals.contains(&proposal.data.view_number()) {
429 let vote = QuorumVote2::<TYPES>::create_signed_vote(
433 self.votes_sent.last().unwrap().data.clone(),
434 event.view_number().unwrap(),
435 public_key,
436 private_key,
437 upgrade_lock,
438 )
439 .await
440 .context("Failed to sign vote")
441 .unwrap();
442 return vec![HotShotEvent::QuorumVoteSend(vote)];
443 }
444 },
445 HotShotEvent::TimeoutVoteSend(vote) => {
446 let dishonest_proposals = self.dishonest_proposal_view_numbers.read().await;
448 if dishonest_proposals.contains(&vote.view_number) {
449 return vec![];
452 }
453 },
454 HotShotEvent::QuorumVoteSend(vote) => {
455 self.votes_sent.push(vote.clone());
456 },
457 _ => {},
458 }
459 vec![event.clone()]
460 }
461}
462
463#[derive(Debug)]
478pub struct DishonestViewSyncRelay {
479 pub dishonest_proposal_view_numbers: Vec<u64>,
480 pub dishonest_vote_view_numbers: Vec<u64>,
481 pub first_f_honest_nodes: Vec<u64>,
482 pub second_f_honest_nodes: Vec<u64>,
483 pub one_honest_node: u64,
484 pub f_dishonest_nodes: Vec<u64>,
485}
486
487#[async_trait]
488impl<TYPES: NodeType, I: NodeImplementation<TYPES>, V: Versions> EventTransformerState<TYPES, I, V>
489 for DishonestViewSyncRelay
490{
491 async fn send_handler(
492 &mut self,
493 event: &HotShotEvent<TYPES>,
494 _public_key: &TYPES::SignatureKey,
495 _private_key: &<TYPES::SignatureKey as SignatureKey>::PrivateKey,
496 upgrade_lock: &UpgradeLock<TYPES, V>,
497 _consensus: OuterConsensus<TYPES>,
498 membership_coordinator: EpochMembershipCoordinator<TYPES>,
499 network: Arc<I::Network>,
500 ) -> Vec<HotShotEvent<TYPES>> {
501 match event {
502 HotShotEvent::QuorumProposalSend(proposal, sender) => {
503 let view_number = proposal.data.view_number();
504 if !self.dishonest_proposal_view_numbers.contains(&view_number) {
505 return vec![event.clone()];
506 }
507 let message_kind = if upgrade_lock.epochs_enabled(view_number).await {
508 MessageKind::<TYPES>::from_consensus_message(SequencingMessage::General(
509 GeneralConsensusMessage::Proposal2(convert_proposal(proposal.clone())),
510 ))
511 } else {
512 MessageKind::<TYPES>::from_consensus_message(SequencingMessage::General(
513 GeneralConsensusMessage::Proposal(convert_proposal(proposal.clone())),
514 ))
515 };
516 let message = Message {
517 sender: sender.clone(),
518 kind: message_kind,
519 };
520 let serialized_message = match upgrade_lock.serialize(&message).await {
521 Ok(serialized) => serialized,
522 Err(e) => {
523 panic!("Failed to serialize message: {e}");
524 },
525 };
526 let second_f_honest_it = self.second_f_honest_nodes.iter();
527 let f_dishonest_it = self.f_dishonest_nodes.iter();
528 let one_honest_it = once(&self.one_honest_node);
529 let chained_it: Box<dyn Iterator<Item = &u64> + Send> =
530 if &*view_number == self.dishonest_proposal_view_numbers.first().unwrap() {
531 Box::new(second_f_honest_it.chain(one_honest_it.chain(f_dishonest_it)))
533 } else {
534 Box::new(second_f_honest_it.chain(one_honest_it))
536 };
537 for node_id in chained_it {
538 let dummy_view = TYPES::View::new(*node_id);
539 let Ok(node) = membership_coordinator
540 .membership()
541 .read()
542 .await
543 .leader(dummy_view, proposal.data.epoch())
544 else {
545 panic!(
546 "Failed to find leader for view {} and epoch {:?}",
547 dummy_view,
548 proposal.data.epoch()
549 );
550 };
551 let transmit_result = network
552 .direct_message(
553 view_number.u64().into(),
554 serialized_message.clone(),
555 node.clone(),
556 )
557 .await;
558 match transmit_result {
559 Ok(()) => tracing::info!(
560 "Sent proposal for view {} to node {}",
561 proposal.data.view_number(),
562 node_id
563 ),
564 Err(e) => panic!("Failed to send message task: {e:?}"),
565 }
566 }
567 vec![]
568 },
569 HotShotEvent::QuorumVoteSend(vote) => {
570 if !self.dishonest_vote_view_numbers.contains(&vote.view_number) {
571 return vec![event.clone()];
572 }
573 vec![]
574 },
575 HotShotEvent::TimeoutVoteSend(vote) => {
576 if !self.dishonest_vote_view_numbers.contains(&vote.view_number) {
577 return vec![event.clone()];
578 }
579 vec![]
580 },
581 HotShotEvent::ViewSyncPreCommitVoteSend(vote) => {
582 if !self.dishonest_vote_view_numbers.contains(&vote.view_number) {
583 return vec![event.clone()];
584 }
585 vec![]
586 },
587 HotShotEvent::ViewSyncPreCommitCertificateSend(certificate, sender) => {
588 let view_number = certificate.data.round;
589 if !self.dishonest_proposal_view_numbers.contains(&view_number) {
590 return vec![event.clone()];
591 }
592 let message_kind = if upgrade_lock.epochs_enabled(view_number).await {
593 MessageKind::<TYPES>::from_consensus_message(SequencingMessage::General(
594 GeneralConsensusMessage::ViewSyncPreCommitCertificate2(certificate.clone()),
595 ))
596 } else {
597 MessageKind::<TYPES>::from_consensus_message(SequencingMessage::General(
598 GeneralConsensusMessage::ViewSyncPreCommitCertificate(
599 certificate.clone().to_vsc(),
600 ),
601 ))
602 };
603 let message = Message {
604 sender: sender.clone(),
605 kind: message_kind,
606 };
607 let serialized_message = match upgrade_lock.serialize(&message).await {
608 Ok(serialized) => serialized,
609 Err(e) => {
610 panic!("Failed to serialize message: {e}");
611 },
612 };
613 let second_f_honest_it = self.second_f_honest_nodes.iter();
614 let f_dishonest_it = self.f_dishonest_nodes.iter();
615 let one_honest_it = once(&self.one_honest_node);
616 let chained_it: Box<dyn Iterator<Item = &u64> + Send> =
618 Box::new(second_f_honest_it.chain(one_honest_it.chain(f_dishonest_it)));
619 for node_id in chained_it {
620 let dummy_view = TYPES::View::new(*node_id);
621 let Ok(node) = membership_coordinator
622 .membership()
623 .read()
624 .await
625 .leader(dummy_view, certificate.epoch())
626 else {
627 panic!(
628 "Failed to find leader for view {} and epoch {:?}",
629 dummy_view,
630 certificate.epoch()
631 );
632 };
633 let transmit_result = network
634 .direct_message(
635 view_number.u64().into(),
636 serialized_message.clone(),
637 node.clone(),
638 )
639 .await;
640 match transmit_result {
641 Ok(()) => tracing::info!(
642 "Sent ViewSyncPreCommitCertificate for view {} to node {}",
643 view_number,
644 node_id
645 ),
646 Err(e) => panic!("Failed to send message task: {e:?}"),
647 }
648 }
649 vec![]
650 },
651 HotShotEvent::ViewSyncCommitCertificateSend(certificate, sender) => {
652 let view_number = certificate.data.round;
653 if !self.dishonest_proposal_view_numbers.contains(&view_number) {
654 return vec![event.clone()];
655 }
656 let message_kind = if upgrade_lock.epochs_enabled(view_number).await {
657 MessageKind::<TYPES>::from_consensus_message(SequencingMessage::General(
658 GeneralConsensusMessage::ViewSyncCommitCertificate2(certificate.clone()),
659 ))
660 } else {
661 MessageKind::<TYPES>::from_consensus_message(SequencingMessage::General(
662 GeneralConsensusMessage::ViewSyncCommitCertificate(
663 certificate.clone().to_vsc(),
664 ),
665 ))
666 };
667 let message = Message {
668 sender: sender.clone(),
669 kind: message_kind,
670 };
671 let serialized_message = match upgrade_lock.serialize(&message).await {
672 Ok(serialized) => serialized,
673 Err(e) => {
674 panic!("Failed to serialize message: {e}");
675 },
676 };
677 let one_honest_it = once(&self.one_honest_node);
678 let chained_it: Box<dyn Iterator<Item = &u64> + Send> = Box::new(one_honest_it);
680 for node_id in chained_it {
681 let dummy_view = TYPES::View::new(*node_id);
682 let Ok(node) = membership_coordinator
683 .membership()
684 .read()
685 .await
686 .leader(dummy_view, certificate.epoch())
687 else {
688 panic!(
689 "Failed to find leader for view {} and epoch {:?}",
690 dummy_view,
691 certificate.epoch()
692 );
693 };
694 let transmit_result = network
695 .direct_message(
696 view_number.u64().into(),
697 serialized_message.clone(),
698 node.clone(),
699 )
700 .await;
701 match transmit_result {
702 Ok(()) => tracing::info!(
703 "Sent ViewSyncCommitCertificate for view {} to node {}",
704 view_number,
705 node_id
706 ),
707 Err(e) => panic!("Failed to send message task: {e:?}"),
708 }
709 }
710 vec![]
711 },
712 _ => vec![event.clone()],
713 }
714 }
715
716 async fn recv_handler(&mut self, event: &HotShotEvent<TYPES>) -> Vec<HotShotEvent<TYPES>> {
717 vec![event.clone()]
718 }
719}
720
721#[derive(Debug)]
722pub struct DishonestViewSyncWrongEpoch<TYPES: NodeType> {
723 pub first_dishonest_view_number: u64,
724 pub epoch_modifier: fn(TYPES::Epoch) -> TYPES::Epoch,
725}
726
727#[async_trait]
728impl<TYPES: NodeType, I: NodeImplementation<TYPES>, V: Versions> EventTransformerState<TYPES, I, V>
729 for DishonestViewSyncWrongEpoch<TYPES>
730{
731 async fn send_handler(
732 &mut self,
733 event: &HotShotEvent<TYPES>,
734 public_key: &TYPES::SignatureKey,
735 private_key: &<TYPES::SignatureKey as SignatureKey>::PrivateKey,
736 upgrade_lock: &UpgradeLock<TYPES, V>,
737 _consensus: OuterConsensus<TYPES>,
738 _membership_coordinator: EpochMembershipCoordinator<TYPES>,
739 _network: Arc<I::Network>,
740 ) -> Vec<HotShotEvent<TYPES>> {
741 match event {
742 HotShotEvent::QuorumProposalSend(proposal, _) => {
743 if self.first_dishonest_view_number > proposal.data.view_number().u64() {
744 return vec![event.clone()];
745 }
746 vec![]
747 },
748 HotShotEvent::QuorumVoteSend(vote) => {
749 if self.first_dishonest_view_number > vote.view_number().u64() {
750 return vec![event.clone()];
751 }
752 vec![]
753 },
754 HotShotEvent::TimeoutVoteSend(vote) => {
755 if self.first_dishonest_view_number > vote.view_number().u64() {
756 return vec![event.clone()];
757 }
758 vec![]
759 },
760 HotShotEvent::ViewSyncPreCommitVoteSend(vote) => {
761 if self.first_dishonest_view_number > vote.view_number().u64() {
762 return vec![event.clone()];
763 }
764 let view_number = vote.data.round;
765 let vote = if upgrade_lock.epochs_enabled(view_number).await {
766 ViewSyncPreCommitVote2::<TYPES>::create_signed_vote(
767 ViewSyncPreCommitData2 {
768 relay: 0,
769 round: view_number,
770 epoch: vote.data.epoch.map(self.epoch_modifier),
771 },
772 view_number,
773 public_key,
774 private_key,
775 upgrade_lock,
776 )
777 .await
778 .context("Failed to sign pre commit vote!")
779 .unwrap()
780 } else {
781 let vote = ViewSyncPreCommitVote::<TYPES>::create_signed_vote(
782 ViewSyncPreCommitData {
783 relay: 0,
784 round: view_number,
785 },
786 view_number,
787 public_key,
788 private_key,
789 upgrade_lock,
790 )
791 .await
792 .context("Failed to sign pre commit vote!")
793 .unwrap();
794 vote.to_vote2()
795 };
796 vec![HotShotEvent::ViewSyncPreCommitVoteSend(vote)]
797 },
798 _ => vec![event.clone()],
799 }
800 }
801
802 async fn recv_handler(&mut self, event: &HotShotEvent<TYPES>) -> Vec<HotShotEvent<TYPES>> {
803 vec![event.clone()]
804 }
805}