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