1use crate::{
4 simplex::signing_scheme::Scheme,
5 types::{Epoch, Round, View},
6 Epochable, Viewable,
7};
8use bytes::{Buf, BufMut};
9use commonware_codec::{varint::UInt, EncodeSize, Error, Read, ReadExt, ReadRangeExt, Write};
10use commonware_cryptography::{Digest, PublicKey};
11use commonware_utils::{max_faults, quorum, set::Ordered};
12use rand::{CryptoRng, Rng};
13use std::{collections::HashSet, fmt::Debug, hash::Hash};
14
15#[derive(Clone)]
18pub struct Context<D: Digest, P: PublicKey> {
19 pub round: Round,
21 pub leader: P,
23 pub parent: (View, D),
30}
31
32impl<D: Digest, P: PublicKey> Epochable for Context<D, P> {
33 type Epoch = Epoch;
34
35 fn epoch(&self) -> Epoch {
36 self.round.epoch()
37 }
38}
39
40impl<D: Digest, P: PublicKey> Viewable for Context<D, P> {
41 type View = View;
42
43 fn view(&self) -> View {
44 self.round.view()
45 }
46}
47
48pub trait Attributable {
51 fn signer(&self) -> u32;
53}
54
55pub struct AttributableVec<T: Attributable> {
58 data: Vec<Option<T>>,
59 added: usize,
60}
61
62impl<T: Attributable> AttributableVec<T> {
63 pub fn new(participants: usize) -> Self {
65 let mut data = Vec::with_capacity(participants);
67 data.resize_with(participants, || None);
68
69 Self { data, added: 0 }
70 }
71
72 pub fn push(&mut self, item: T) -> bool {
76 let index = item.signer() as usize;
77 if self.data[index].is_some() {
78 return false;
79 }
80 self.data[index] = Some(item);
81 self.added += 1;
82 true
83 }
84
85 pub fn len(&self) -> usize {
87 self.added
88 }
89
90 pub fn is_empty(&self) -> bool {
92 self.added == 0
93 }
94
95 pub fn iter(&self) -> impl Iterator<Item = &T> {
97 self.data.iter().filter_map(|o| o.as_ref())
98 }
99}
100
101#[derive(Copy, Clone)]
106pub enum VoteContext<'a, D: Digest> {
107 Notarize { proposal: &'a Proposal<D> },
109 Nullify { round: Round },
111 Finalize { proposal: &'a Proposal<D> },
113}
114
115impl<D: Digest> Viewable for VoteContext<'_, D> {
116 type View = View;
117
118 fn view(&self) -> View {
119 match self {
120 VoteContext::Notarize { proposal } => proposal.view(),
121 VoteContext::Nullify { round } => round.view(),
122 VoteContext::Finalize { proposal } => proposal.view(),
123 }
124 }
125}
126
127#[derive(Clone, Debug)]
129pub struct Vote<S: Scheme> {
130 pub signer: u32,
132 pub signature: S::Signature,
134}
135
136impl<S: Scheme> PartialEq for Vote<S> {
137 fn eq(&self, other: &Self) -> bool {
138 self.signer == other.signer && self.signature == other.signature
139 }
140}
141
142impl<S: Scheme> Eq for Vote<S> {}
143
144impl<S: Scheme> Hash for Vote<S> {
145 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
146 self.signer.hash(state);
147 self.signature.hash(state);
148 }
149}
150
151impl<S: Scheme> Write for Vote<S> {
152 fn write(&self, writer: &mut impl BufMut) {
153 self.signer.write(writer);
154 self.signature.write(writer);
155 }
156}
157
158impl<S: Scheme> EncodeSize for Vote<S> {
159 fn encode_size(&self) -> usize {
160 self.signer.encode_size() + self.signature.encode_size()
161 }
162}
163
164impl<S: Scheme> Read for Vote<S> {
165 type Cfg = ();
166
167 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
168 let signer = u32::read(reader)?;
169 let signature = S::Signature::read(reader)?;
170
171 Ok(Self { signer, signature })
172 }
173}
174
175pub struct VoteVerification<S: Scheme> {
177 pub verified: Vec<Vote<S>>,
179 pub invalid_signers: Vec<u32>,
181}
182
183impl<S: Scheme> VoteVerification<S> {
184 pub fn new(verified: Vec<Vote<S>>, invalid_signers: Vec<u32>) -> Self {
186 Self {
187 verified,
188 invalid_signers,
189 }
190 }
191}
192
193pub trait OrderedExt<P> {
195 fn quorum(&self) -> u32;
197
198 fn max_faults(&self) -> u32;
200
201 fn key(&self, index: u32) -> Option<&P>;
203
204 fn index(&self, key: &P) -> Option<u32>;
206}
207
208impl<P: PublicKey> OrderedExt<P> for Ordered<P> {
209 fn quorum(&self) -> u32 {
210 quorum(self.len() as u32)
211 }
212
213 fn max_faults(&self) -> u32 {
214 max_faults(self.len() as u32)
215 }
216
217 fn index(&self, key: &P) -> Option<u32> {
218 self.position(key).map(|index| index as u32)
219 }
220
221 fn key(&self, index: u32) -> Option<&P> {
222 self.get(index as usize)
223 }
224}
225
226pub struct BatchVerifier<S: Scheme, D: Digest> {
236 scheme: S,
238
239 quorum: Option<usize>,
241
242 leader: Option<u32>,
244 leader_proposal: Option<Proposal<D>>,
246
247 notarizes: Vec<Notarize<S, D>>,
249 notarizes_force: bool,
251 notarizes_verified: usize,
253
254 nullifies: Vec<Nullify<S>>,
256 nullifies_verified: usize,
258
259 finalizes: Vec<Finalize<S, D>>,
261 finalizes_verified: usize,
263}
264
265impl<S: Scheme, D: Digest> BatchVerifier<S, D> {
266 pub fn new(scheme: S, quorum: Option<u32>) -> Self {
275 Self {
276 scheme,
277
278 quorum: quorum.map(|q| q as usize),
280
281 leader: None,
282 leader_proposal: None,
283
284 notarizes: Vec::new(),
285 notarizes_force: false,
286 notarizes_verified: 0,
287
288 nullifies: Vec::new(),
289 nullifies_verified: 0,
290
291 finalizes: Vec::new(),
292 finalizes_verified: 0,
293 }
294 }
295
296 fn set_leader_proposal(&mut self, proposal: Proposal<D>) {
302 self.notarizes.retain(|n| n.proposal == proposal);
304 self.finalizes.retain(|f| f.proposal == proposal);
305
306 self.leader_proposal = Some(proposal);
308
309 self.notarizes_force = true;
311 }
312
313 pub fn add(&mut self, msg: Voter<S, D>, verified: bool) {
330 match msg {
331 Voter::Notarize(notarize) => {
332 if let Some(ref leader_proposal) = self.leader_proposal {
333 if leader_proposal != ¬arize.proposal {
335 return;
336 }
337 } else if let Some(leader) = self.leader {
338 if leader == notarize.signer() {
340 self.set_leader_proposal(notarize.proposal.clone());
342 }
343 }
344
345 if verified {
347 self.notarizes_verified += 1;
348 } else {
349 self.notarizes.push(notarize);
350 }
351 }
352 Voter::Nullify(nullify) => {
353 if verified {
354 self.nullifies_verified += 1;
355 } else {
356 self.nullifies.push(nullify);
357 }
358 }
359 Voter::Finalize(finalize) => {
360 if let Some(ref leader_proposal) = self.leader_proposal {
362 if leader_proposal != &finalize.proposal {
363 return;
364 }
365 }
366
367 if verified {
369 self.finalizes_verified += 1;
370 } else {
371 self.finalizes.push(finalize);
372 }
373 }
374 Voter::Notarization(_) | Voter::Nullification(_) | Voter::Finalization(_) => {
375 unreachable!("should not be adding recovered messages to partial verifier");
376 }
377 }
378 }
379
380 pub fn set_leader(&mut self, leader: u32) {
390 assert!(self.leader.is_none());
392 self.leader = Some(leader);
393
394 let Some(notarize) = self.notarizes.iter().find(|n| n.signer() == leader) else {
396 return;
397 };
398
399 self.set_leader_proposal(notarize.proposal.clone());
401 }
402
403 pub fn verify_notarizes<R: Rng + CryptoRng>(
418 &mut self,
419 rng: &mut R,
420 namespace: &[u8],
421 ) -> (Vec<Voter<S, D>>, Vec<u32>) {
422 self.notarizes_force = false;
423
424 let notarizes = std::mem::take(&mut self.notarizes);
425
426 if notarizes.is_empty() {
428 return (vec![], vec![]);
429 }
430
431 let (proposals, votes): (Vec<_>, Vec<_>) =
432 notarizes.into_iter().map(|n| (n.proposal, n.vote)).unzip();
433
434 let proposal = &proposals[0];
435
436 let VoteVerification {
437 verified,
438 invalid_signers,
439 } = self
440 .scheme
441 .verify_votes(rng, namespace, VoteContext::Notarize { proposal }, votes);
442
443 self.notarizes_verified += verified.len();
444
445 (
446 verified
447 .into_iter()
448 .zip(proposals)
449 .map(|(vote, proposal)| Voter::Notarize(Notarize { proposal, vote }))
450 .collect(),
451 invalid_signers,
452 )
453 }
454
455 pub fn ready_notarizes(&self) -> bool {
468 if self.notarizes.is_empty() {
470 return false;
471 }
472
473 if self.notarizes_force {
476 return true;
477 }
478
479 if self.leader.is_none() || self.leader_proposal.is_none() {
482 return false;
483 }
484
485 if let Some(quorum) = self.quorum {
487 if self.notarizes_verified >= quorum {
490 return false;
491 }
492
493 if self.notarizes_verified + self.notarizes.len() < quorum {
495 return false;
496 }
497 }
498
499 true
501 }
502
503 pub fn verify_nullifies<R: Rng + CryptoRng>(
518 &mut self,
519 rng: &mut R,
520 namespace: &[u8],
521 ) -> (Vec<Voter<S, D>>, Vec<u32>) {
522 let nullifies = std::mem::take(&mut self.nullifies);
523
524 if nullifies.is_empty() {
526 return (vec![], vec![]);
527 }
528
529 let round = nullifies[0].round;
530
531 let VoteVerification {
532 verified,
533 invalid_signers,
534 } = self.scheme.verify_votes::<_, D, _>(
535 rng,
536 namespace,
537 VoteContext::Nullify { round },
538 nullifies.into_iter().map(|nullify| nullify.vote),
539 );
540
541 self.nullifies_verified += verified.len();
542
543 (
544 verified
545 .into_iter()
546 .map(|vote| Voter::Nullify(Nullify { round, vote }))
547 .collect(),
548 invalid_signers,
549 )
550 }
551
552 pub fn ready_nullifies(&self) -> bool {
563 if self.nullifies.is_empty() {
565 return false;
566 }
567
568 if let Some(quorum) = self.quorum {
569 if self.nullifies_verified >= quorum {
572 return false;
573 }
574
575 if self.nullifies_verified + self.nullifies.len() < quorum {
577 return false;
578 }
579 }
580
581 true
583 }
584
585 pub fn verify_finalizes<R: Rng + CryptoRng>(
600 &mut self,
601 rng: &mut R,
602 namespace: &[u8],
603 ) -> (Vec<Voter<S, D>>, Vec<u32>) {
604 let finalizes = std::mem::take(&mut self.finalizes);
605
606 if finalizes.is_empty() {
608 return (vec![], vec![]);
609 }
610
611 let (proposals, votes): (Vec<_>, Vec<_>) =
612 finalizes.into_iter().map(|n| (n.proposal, n.vote)).unzip();
613
614 let proposal = &proposals[0];
615
616 let VoteVerification {
617 verified,
618 invalid_signers,
619 } = self
620 .scheme
621 .verify_votes(rng, namespace, VoteContext::Finalize { proposal }, votes);
622
623 self.finalizes_verified += verified.len();
624
625 (
626 verified
627 .into_iter()
628 .zip(proposals)
629 .map(|(vote, proposal)| Voter::Finalize(Finalize { proposal, vote }))
630 .collect(),
631 invalid_signers,
632 )
633 }
634
635 pub fn ready_finalizes(&self) -> bool {
647 if self.finalizes.is_empty() {
649 return false;
650 }
651
652 if self.leader.is_none() || self.leader_proposal.is_none() {
655 return false;
656 }
657 if let Some(quorum) = self.quorum {
658 if self.finalizes_verified >= quorum {
661 return false;
662 }
663
664 if self.finalizes_verified + self.finalizes.len() < quorum {
666 return false;
667 }
668 }
669
670 true
672 }
673}
674
675#[derive(Clone, Debug, PartialEq)]
678pub enum Voter<S: Scheme, D: Digest> {
679 Notarize(Notarize<S, D>),
681 Notarization(Notarization<S, D>),
683 Nullify(Nullify<S>),
685 Nullification(Nullification<S>),
687 Finalize(Finalize<S, D>),
689 Finalization(Finalization<S, D>),
691}
692
693impl<S: Scheme, D: Digest> Write for Voter<S, D> {
694 fn write(&self, writer: &mut impl BufMut) {
695 match self {
696 Voter::Notarize(v) => {
697 0u8.write(writer);
698 v.write(writer);
699 }
700 Voter::Notarization(v) => {
701 1u8.write(writer);
702 v.write(writer);
703 }
704 Voter::Nullify(v) => {
705 2u8.write(writer);
706 v.write(writer);
707 }
708 Voter::Nullification(v) => {
709 3u8.write(writer);
710 v.write(writer);
711 }
712 Voter::Finalize(v) => {
713 4u8.write(writer);
714 v.write(writer);
715 }
716 Voter::Finalization(v) => {
717 5u8.write(writer);
718 v.write(writer);
719 }
720 }
721 }
722}
723
724impl<S: Scheme, D: Digest> EncodeSize for Voter<S, D> {
725 fn encode_size(&self) -> usize {
726 1 + match self {
727 Voter::Notarize(v) => v.encode_size(),
728 Voter::Notarization(v) => v.encode_size(),
729 Voter::Nullify(v) => v.encode_size(),
730 Voter::Nullification(v) => v.encode_size(),
731 Voter::Finalize(v) => v.encode_size(),
732 Voter::Finalization(v) => v.encode_size(),
733 }
734 }
735}
736
737impl<S: Scheme, D: Digest> Read for Voter<S, D> {
738 type Cfg = <S::Certificate as Read>::Cfg;
739
740 fn read_cfg(reader: &mut impl Buf, cfg: &Self::Cfg) -> Result<Self, Error> {
741 let tag = <u8>::read(reader)?;
742 match tag {
743 0 => {
744 let v = Notarize::read(reader)?;
745 Ok(Voter::Notarize(v))
746 }
747 1 => {
748 let v = Notarization::read_cfg(reader, cfg)?;
749 Ok(Voter::Notarization(v))
750 }
751 2 => {
752 let v = Nullify::read(reader)?;
753 Ok(Voter::Nullify(v))
754 }
755 3 => {
756 let v = Nullification::read_cfg(reader, cfg)?;
757 Ok(Voter::Nullification(v))
758 }
759 4 => {
760 let v = Finalize::read(reader)?;
761 Ok(Voter::Finalize(v))
762 }
763 5 => {
764 let v = Finalization::read_cfg(reader, cfg)?;
765 Ok(Voter::Finalization(v))
766 }
767 _ => Err(Error::Invalid("consensus::simplex::Voter", "Invalid type")),
768 }
769 }
770}
771
772impl<S: Scheme, D: Digest> Epochable for Voter<S, D> {
773 type Epoch = Epoch;
774
775 fn epoch(&self) -> Epoch {
776 match self {
777 Voter::Notarize(v) => v.epoch(),
778 Voter::Notarization(v) => v.epoch(),
779 Voter::Nullify(v) => v.epoch(),
780 Voter::Nullification(v) => v.epoch(),
781 Voter::Finalize(v) => v.epoch(),
782 Voter::Finalization(v) => v.epoch(),
783 }
784 }
785}
786
787impl<S: Scheme, D: Digest> Viewable for Voter<S, D> {
788 type View = View;
789
790 fn view(&self) -> View {
791 match self {
792 Voter::Notarize(v) => v.view(),
793 Voter::Notarization(v) => v.view(),
794 Voter::Nullify(v) => v.view(),
795 Voter::Nullification(v) => v.view(),
796 Voter::Finalize(v) => v.view(),
797 Voter::Finalization(v) => v.view(),
798 }
799 }
800}
801
802#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
805pub struct Proposal<D: Digest> {
806 pub round: Round,
808 pub parent: View,
810 pub payload: D,
812}
813
814impl<D: Digest> Proposal<D> {
815 pub fn new(round: Round, parent: View, payload: D) -> Self {
817 Proposal {
818 round,
819 parent,
820 payload,
821 }
822 }
823}
824
825impl<D: Digest> Write for Proposal<D> {
826 fn write(&self, writer: &mut impl BufMut) {
827 self.round.write(writer);
828 UInt(self.parent).write(writer);
829 self.payload.write(writer)
830 }
831}
832
833impl<D: Digest> Read for Proposal<D> {
834 type Cfg = ();
835
836 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
837 let round = Round::read(reader)?;
838 let parent = UInt::read(reader)?.into();
839 let payload = D::read(reader)?;
840 Ok(Self {
841 round,
842 parent,
843 payload,
844 })
845 }
846}
847
848impl<D: Digest> EncodeSize for Proposal<D> {
849 fn encode_size(&self) -> usize {
850 self.round.encode_size() + UInt(self.parent).encode_size() + self.payload.encode_size()
851 }
852}
853
854impl<D: Digest> Epochable for Proposal<D> {
855 type Epoch = Epoch;
856
857 fn epoch(&self) -> Epoch {
858 self.round.epoch()
859 }
860}
861
862impl<D: Digest> Viewable for Proposal<D> {
863 type View = View;
864
865 fn view(&self) -> View {
866 self.round.view()
867 }
868}
869
870#[derive(Clone, Debug)]
872pub struct Notarize<S: Scheme, D: Digest> {
873 pub proposal: Proposal<D>,
875 pub vote: Vote<S>,
877}
878
879impl<S: Scheme, D: Digest> Notarize<S, D> {
880 pub fn round(&self) -> Round {
882 self.proposal.round
883 }
884}
885
886impl<S: Scheme, D: Digest> PartialEq for Notarize<S, D> {
887 fn eq(&self, other: &Self) -> bool {
888 self.proposal == other.proposal && self.vote == other.vote
889 }
890}
891
892impl<S: Scheme, D: Digest> Eq for Notarize<S, D> {}
893
894impl<S: Scheme, D: Digest> Hash for Notarize<S, D> {
895 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
896 self.proposal.hash(state);
897 self.vote.hash(state);
898 }
899}
900
901impl<S: Scheme, D: Digest> Notarize<S, D> {
902 pub fn sign(scheme: &S, namespace: &[u8], proposal: Proposal<D>) -> Option<Self> {
904 let vote = scheme.sign_vote(
905 namespace,
906 VoteContext::Notarize {
907 proposal: &proposal,
908 },
909 )?;
910
911 Some(Self { proposal, vote })
912 }
913
914 pub fn verify(&self, scheme: &S, namespace: &[u8]) -> bool {
918 scheme.verify_vote(
919 namespace,
920 VoteContext::Notarize {
921 proposal: &self.proposal,
922 },
923 &self.vote,
924 )
925 }
926}
927
928impl<S: Scheme, D: Digest> Write for Notarize<S, D> {
929 fn write(&self, writer: &mut impl BufMut) {
930 self.proposal.write(writer);
931 self.vote.write(writer);
932 }
933}
934
935impl<S: Scheme, D: Digest> EncodeSize for Notarize<S, D> {
936 fn encode_size(&self) -> usize {
937 self.proposal.encode_size() + self.vote.encode_size()
938 }
939}
940
941impl<S: Scheme, D: Digest> Read for Notarize<S, D> {
942 type Cfg = ();
943
944 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
945 let proposal = Proposal::read(reader)?;
946 let vote = Vote::read(reader)?;
947
948 Ok(Self { proposal, vote })
949 }
950}
951
952impl<S: Scheme, D: Digest> Attributable for Notarize<S, D> {
953 fn signer(&self) -> u32 {
954 self.vote.signer
955 }
956}
957
958impl<S: Scheme, D: Digest> Epochable for Notarize<S, D> {
959 type Epoch = Epoch;
960
961 fn epoch(&self) -> Epoch {
962 self.proposal.epoch()
963 }
964}
965
966impl<S: Scheme, D: Digest> Viewable for Notarize<S, D> {
967 type View = View;
968
969 fn view(&self) -> View {
970 self.proposal.view()
971 }
972}
973
974#[derive(Clone, Debug)]
980pub struct Notarization<S: Scheme, D: Digest> {
981 pub proposal: Proposal<D>,
983 pub certificate: S::Certificate,
985}
986
987impl<S: Scheme, D: Digest> Notarization<S, D> {
988 pub fn from_notarizes<'a>(
990 scheme: &S,
991 notarizes: impl IntoIterator<Item = &'a Notarize<S, D>>,
992 ) -> Option<Self> {
993 let mut iter = notarizes.into_iter().peekable();
994 let proposal = iter.peek()?.proposal.clone();
995 let certificate = scheme.assemble_certificate(iter.map(|n| n.vote.clone()))?;
996
997 Some(Self {
998 proposal,
999 certificate,
1000 })
1001 }
1002
1003 pub fn round(&self) -> Round {
1005 self.proposal.round
1006 }
1007}
1008
1009impl<S: Scheme, D: Digest> PartialEq for Notarization<S, D> {
1010 fn eq(&self, other: &Self) -> bool {
1011 self.proposal == other.proposal && self.certificate == other.certificate
1012 }
1013}
1014
1015impl<S: Scheme, D: Digest> Eq for Notarization<S, D> {}
1016
1017impl<S: Scheme, D: Digest> Hash for Notarization<S, D> {
1018 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1019 self.proposal.hash(state);
1020 self.certificate.hash(state);
1021 }
1022}
1023
1024impl<S: Scheme, D: Digest> Notarization<S, D> {
1025 pub fn verify<R: Rng + CryptoRng>(&self, rng: &mut R, scheme: &S, namespace: &[u8]) -> bool {
1029 scheme.verify_certificate(
1030 rng,
1031 namespace,
1032 VoteContext::Notarize {
1033 proposal: &self.proposal,
1034 },
1035 &self.certificate,
1036 )
1037 }
1038}
1039
1040impl<S: Scheme, D: Digest> Write for Notarization<S, D> {
1041 fn write(&self, writer: &mut impl BufMut) {
1042 self.proposal.write(writer);
1043 self.certificate.write(writer);
1044 }
1045}
1046
1047impl<S: Scheme, D: Digest> EncodeSize for Notarization<S, D> {
1048 fn encode_size(&self) -> usize {
1049 self.proposal.encode_size() + self.certificate.encode_size()
1050 }
1051}
1052
1053impl<S: Scheme, D: Digest> Read for Notarization<S, D> {
1054 type Cfg = <S::Certificate as Read>::Cfg;
1055
1056 fn read_cfg(reader: &mut impl Buf, cfg: &Self::Cfg) -> Result<Self, Error> {
1057 let proposal = Proposal::read(reader)?;
1058 let certificate = S::Certificate::read_cfg(reader, cfg)?;
1059
1060 Ok(Self {
1061 proposal,
1062 certificate,
1063 })
1064 }
1065}
1066
1067impl<S: Scheme, D: Digest> Epochable for Notarization<S, D> {
1068 type Epoch = Epoch;
1069
1070 fn epoch(&self) -> Epoch {
1071 self.proposal.epoch()
1072 }
1073}
1074
1075impl<S: Scheme, D: Digest> Viewable for Notarization<S, D> {
1076 type View = View;
1077
1078 fn view(&self) -> View {
1079 self.proposal.view()
1080 }
1081}
1082
1083#[derive(Clone, Debug)]
1086pub struct Nullify<S: Scheme> {
1087 pub round: Round,
1089 pub vote: Vote<S>,
1091}
1092
1093impl<S: Scheme> PartialEq for Nullify<S> {
1094 fn eq(&self, other: &Self) -> bool {
1095 self.round == other.round && self.vote == other.vote
1096 }
1097}
1098
1099impl<S: Scheme> Eq for Nullify<S> {}
1100
1101impl<S: Scheme> Hash for Nullify<S> {
1102 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1103 self.round.hash(state);
1104 self.vote.hash(state);
1105 }
1106}
1107
1108impl<S: Scheme> Nullify<S> {
1109 pub fn sign<D: Digest>(scheme: &S, namespace: &[u8], round: Round) -> Option<Self> {
1111 let vote = scheme.sign_vote::<D>(namespace, VoteContext::Nullify { round })?;
1112
1113 Some(Self { round, vote })
1114 }
1115
1116 pub fn verify<D: Digest>(&self, scheme: &S, namespace: &[u8]) -> bool {
1120 scheme.verify_vote::<D>(
1121 namespace,
1122 VoteContext::Nullify { round: self.round },
1123 &self.vote,
1124 )
1125 }
1126
1127 pub fn round(&self) -> Round {
1129 self.round
1130 }
1131}
1132
1133impl<S: Scheme> Write for Nullify<S> {
1134 fn write(&self, writer: &mut impl BufMut) {
1135 self.round.write(writer);
1136 self.vote.write(writer);
1137 }
1138}
1139
1140impl<S: Scheme> EncodeSize for Nullify<S> {
1141 fn encode_size(&self) -> usize {
1142 self.round.encode_size() + self.vote.encode_size()
1143 }
1144}
1145
1146impl<S: Scheme> Read for Nullify<S> {
1147 type Cfg = ();
1148
1149 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
1150 let round = Round::read(reader)?;
1151 let vote = Vote::read(reader)?;
1152
1153 Ok(Self { round, vote })
1154 }
1155}
1156
1157impl<S: Scheme> Attributable for Nullify<S> {
1158 fn signer(&self) -> u32 {
1159 self.vote.signer
1160 }
1161}
1162
1163impl<S: Scheme> Epochable for Nullify<S> {
1164 type Epoch = Epoch;
1165
1166 fn epoch(&self) -> Epoch {
1167 self.round.epoch()
1168 }
1169}
1170
1171impl<S: Scheme> Viewable for Nullify<S> {
1172 type View = View;
1173
1174 fn view(&self) -> View {
1175 self.round.view()
1176 }
1177}
1178
1179#[derive(Clone, Debug)]
1182pub struct Nullification<S: Scheme> {
1183 pub round: Round,
1185 pub certificate: S::Certificate,
1187}
1188
1189impl<S: Scheme> Nullification<S> {
1190 pub fn from_nullifies<'a>(
1192 scheme: &S,
1193 nullifies: impl IntoIterator<Item = &'a Nullify<S>>,
1194 ) -> Option<Self> {
1195 let mut iter = nullifies.into_iter().peekable();
1196 let round = iter.peek()?.round;
1197 let certificate = scheme.assemble_certificate(iter.map(|n| n.vote.clone()))?;
1198
1199 Some(Self { round, certificate })
1200 }
1201
1202 pub fn round(&self) -> Round {
1204 self.round
1205 }
1206}
1207
1208impl<S: Scheme> PartialEq for Nullification<S> {
1209 fn eq(&self, other: &Self) -> bool {
1210 self.round == other.round && self.certificate == other.certificate
1211 }
1212}
1213
1214impl<S: Scheme> Eq for Nullification<S> {}
1215
1216impl<S: Scheme> Hash for Nullification<S> {
1217 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1218 self.round.hash(state);
1219 self.certificate.hash(state);
1220 }
1221}
1222
1223impl<S: Scheme> Write for Nullification<S> {
1224 fn write(&self, writer: &mut impl BufMut) {
1225 self.round.write(writer);
1226 self.certificate.write(writer);
1227 }
1228}
1229
1230impl<S: Scheme> Nullification<S> {
1231 pub fn verify<R: Rng + CryptoRng, D: Digest>(
1235 &self,
1236 rng: &mut R,
1237 scheme: &S,
1238 namespace: &[u8],
1239 ) -> bool {
1240 scheme.verify_certificate::<_, D>(
1241 rng,
1242 namespace,
1243 VoteContext::Nullify { round: self.round },
1244 &self.certificate,
1245 )
1246 }
1247}
1248
1249impl<S: Scheme> EncodeSize for Nullification<S> {
1250 fn encode_size(&self) -> usize {
1251 self.round.encode_size() + self.certificate.encode_size()
1252 }
1253}
1254
1255impl<S: Scheme> Read for Nullification<S> {
1256 type Cfg = <S::Certificate as Read>::Cfg;
1257
1258 fn read_cfg(reader: &mut impl Buf, cfg: &Self::Cfg) -> Result<Self, Error> {
1259 let round = Round::read(reader)?;
1260 let certificate = S::Certificate::read_cfg(reader, cfg)?;
1261
1262 Ok(Self { round, certificate })
1263 }
1264}
1265
1266impl<S: Scheme> Epochable for Nullification<S> {
1267 type Epoch = Epoch;
1268
1269 fn epoch(&self) -> Epoch {
1270 self.round.epoch()
1271 }
1272}
1273
1274impl<S: Scheme> Viewable for Nullification<S> {
1275 type View = View;
1276
1277 fn view(&self) -> View {
1278 self.round.view()
1279 }
1280}
1281
1282#[derive(Clone, Debug)]
1286pub struct Finalize<S: Scheme, D: Digest> {
1287 pub proposal: Proposal<D>,
1289 pub vote: Vote<S>,
1291}
1292
1293impl<S: Scheme, D: Digest> Finalize<S, D> {
1294 pub fn round(&self) -> Round {
1296 self.proposal.round
1297 }
1298}
1299
1300impl<S: Scheme, D: Digest> PartialEq for Finalize<S, D> {
1301 fn eq(&self, other: &Self) -> bool {
1302 self.proposal == other.proposal && self.vote == other.vote
1303 }
1304}
1305
1306impl<S: Scheme, D: Digest> Eq for Finalize<S, D> {}
1307
1308impl<S: Scheme, D: Digest> Hash for Finalize<S, D> {
1309 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1310 self.proposal.hash(state);
1311 self.vote.hash(state);
1312 }
1313}
1314
1315impl<S: Scheme, D: Digest> Finalize<S, D> {
1316 pub fn sign(scheme: &S, namespace: &[u8], proposal: Proposal<D>) -> Option<Self> {
1318 let vote = scheme.sign_vote(
1319 namespace,
1320 VoteContext::Finalize {
1321 proposal: &proposal,
1322 },
1323 )?;
1324
1325 Some(Self { proposal, vote })
1326 }
1327
1328 pub fn verify(&self, scheme: &S, namespace: &[u8]) -> bool {
1332 scheme.verify_vote(
1333 namespace,
1334 VoteContext::Finalize {
1335 proposal: &self.proposal,
1336 },
1337 &self.vote,
1338 )
1339 }
1340}
1341
1342impl<S: Scheme, D: Digest> Write for Finalize<S, D> {
1343 fn write(&self, writer: &mut impl BufMut) {
1344 self.proposal.write(writer);
1345 self.vote.write(writer);
1346 }
1347}
1348
1349impl<S: Scheme, D: Digest> EncodeSize for Finalize<S, D> {
1350 fn encode_size(&self) -> usize {
1351 self.proposal.encode_size() + self.vote.encode_size()
1352 }
1353}
1354
1355impl<S: Scheme, D: Digest> Read for Finalize<S, D> {
1356 type Cfg = ();
1357
1358 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
1359 let proposal = Proposal::read(reader)?;
1360 let vote = Vote::read(reader)?;
1361
1362 Ok(Self { proposal, vote })
1363 }
1364}
1365
1366impl<S: Scheme, D: Digest> Attributable for Finalize<S, D> {
1367 fn signer(&self) -> u32 {
1368 self.vote.signer
1369 }
1370}
1371
1372impl<S: Scheme, D: Digest> Epochable for Finalize<S, D> {
1373 type Epoch = Epoch;
1374
1375 fn epoch(&self) -> Epoch {
1376 self.proposal.epoch()
1377 }
1378}
1379
1380impl<S: Scheme, D: Digest> Viewable for Finalize<S, D> {
1381 type View = View;
1382
1383 fn view(&self) -> View {
1384 self.proposal.view()
1385 }
1386}
1387
1388#[derive(Clone, Debug)]
1394pub struct Finalization<S: Scheme, D: Digest> {
1395 pub proposal: Proposal<D>,
1397 pub certificate: S::Certificate,
1399}
1400
1401impl<S: Scheme, D: Digest> Finalization<S, D> {
1402 pub fn from_finalizes<'a>(
1404 scheme: &S,
1405 finalizes: impl IntoIterator<Item = &'a Finalize<S, D>>,
1406 ) -> Option<Self> {
1407 let mut iter = finalizes.into_iter().peekable();
1408 let proposal = iter.peek()?.proposal.clone();
1409 let certificate = scheme.assemble_certificate(iter.map(|f| f.vote.clone()))?;
1410
1411 Some(Self {
1412 proposal,
1413 certificate,
1414 })
1415 }
1416
1417 pub fn round(&self) -> Round {
1419 self.proposal.round
1420 }
1421}
1422
1423impl<S: Scheme, D: Digest> PartialEq for Finalization<S, D> {
1424 fn eq(&self, other: &Self) -> bool {
1425 self.proposal == other.proposal && self.certificate == other.certificate
1426 }
1427}
1428
1429impl<S: Scheme, D: Digest> Eq for Finalization<S, D> {}
1430
1431impl<S: Scheme, D: Digest> Hash for Finalization<S, D> {
1432 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1433 self.proposal.hash(state);
1434 self.certificate.hash(state);
1435 }
1436}
1437
1438impl<S: Scheme, D: Digest> Finalization<S, D> {
1439 pub fn verify<R: Rng + CryptoRng>(&self, rng: &mut R, scheme: &S, namespace: &[u8]) -> bool {
1443 scheme.verify_certificate(
1444 rng,
1445 namespace,
1446 VoteContext::Finalize {
1447 proposal: &self.proposal,
1448 },
1449 &self.certificate,
1450 )
1451 }
1452}
1453
1454impl<S: Scheme, D: Digest> Write for Finalization<S, D> {
1455 fn write(&self, writer: &mut impl BufMut) {
1456 self.proposal.write(writer);
1457 self.certificate.write(writer);
1458 }
1459}
1460
1461impl<S: Scheme, D: Digest> EncodeSize for Finalization<S, D> {
1462 fn encode_size(&self) -> usize {
1463 self.proposal.encode_size() + self.certificate.encode_size()
1464 }
1465}
1466
1467impl<S: Scheme, D: Digest> Read for Finalization<S, D> {
1468 type Cfg = <S::Certificate as Read>::Cfg;
1469
1470 fn read_cfg(reader: &mut impl Buf, cfg: &Self::Cfg) -> Result<Self, Error> {
1471 let proposal = Proposal::read(reader)?;
1472 let certificate = S::Certificate::read_cfg(reader, cfg)?;
1473
1474 Ok(Self {
1475 proposal,
1476 certificate,
1477 })
1478 }
1479}
1480
1481impl<S: Scheme, D: Digest> Epochable for Finalization<S, D> {
1482 type Epoch = Epoch;
1483
1484 fn epoch(&self) -> Epoch {
1485 self.proposal.epoch()
1486 }
1487}
1488
1489impl<S: Scheme, D: Digest> Viewable for Finalization<S, D> {
1490 type View = View;
1491
1492 fn view(&self) -> View {
1493 self.proposal.view()
1494 }
1495}
1496
1497#[derive(Clone, Debug, PartialEq)]
1500pub enum Backfiller<S: Scheme, D: Digest> {
1501 Request(Request),
1503 Response(Response<S, D>),
1505}
1506
1507impl<S: Scheme, D: Digest> Write for Backfiller<S, D> {
1508 fn write(&self, writer: &mut impl BufMut) {
1509 match self {
1510 Backfiller::Request(request) => {
1511 0u8.write(writer);
1512 request.write(writer);
1513 }
1514 Backfiller::Response(response) => {
1515 1u8.write(writer);
1516 response.write(writer);
1517 }
1518 }
1519 }
1520}
1521
1522impl<S: Scheme, D: Digest> EncodeSize for Backfiller<S, D> {
1523 fn encode_size(&self) -> usize {
1524 1 + match self {
1525 Backfiller::Request(v) => v.encode_size(),
1526 Backfiller::Response(v) => v.encode_size(),
1527 }
1528 }
1529}
1530
1531impl<S: Scheme, D: Digest> Read for Backfiller<S, D> {
1532 type Cfg = (usize, <S::Certificate as Read>::Cfg);
1533
1534 fn read_cfg(reader: &mut impl Buf, cfg: &Self::Cfg) -> Result<Self, Error> {
1535 let tag = <u8>::read(reader)?;
1536 match tag {
1537 0 => {
1538 let (max_len, _) = cfg;
1539 let v = Request::read_cfg(reader, max_len)?;
1540 Ok(Backfiller::Request(v))
1541 }
1542 1 => {
1543 let v = Response::<S, D>::read_cfg(reader, cfg)?;
1544 Ok(Backfiller::Response(v))
1545 }
1546 _ => Err(Error::Invalid(
1547 "consensus::simplex::Backfiller",
1548 "Invalid type",
1549 )),
1550 }
1551 }
1552}
1553
1554#[derive(Clone, Debug, PartialEq)]
1557pub struct Request {
1558 pub id: u64,
1560 pub notarizations: Vec<View>,
1562 pub nullifications: Vec<View>,
1564}
1565
1566impl Request {
1567 pub fn new(id: u64, notarizations: Vec<View>, nullifications: Vec<View>) -> Self {
1569 Request {
1570 id,
1571 notarizations,
1572 nullifications,
1573 }
1574 }
1575}
1576
1577impl Write for Request {
1578 fn write(&self, writer: &mut impl BufMut) {
1579 UInt(self.id).write(writer);
1580 self.notarizations.write(writer);
1581 self.nullifications.write(writer);
1582 }
1583}
1584
1585impl EncodeSize for Request {
1586 fn encode_size(&self) -> usize {
1587 UInt(self.id).encode_size()
1588 + self.notarizations.encode_size()
1589 + self.nullifications.encode_size()
1590 }
1591}
1592
1593impl Read for Request {
1594 type Cfg = usize;
1595
1596 fn read_cfg(reader: &mut impl Buf, max_len: &usize) -> Result<Self, Error> {
1597 let id = UInt::read(reader)?.into();
1598 let mut views = HashSet::new();
1599 let notarizations = Vec::<View>::read_range(reader, ..=*max_len)?;
1600 for view in notarizations.iter() {
1601 if !views.insert(view) {
1602 return Err(Error::Invalid(
1603 "consensus::simplex::Request",
1604 "Duplicate notarization",
1605 ));
1606 }
1607 }
1608 let remaining = max_len - notarizations.len();
1609 views.clear();
1610 let nullifications = Vec::<View>::read_range(reader, ..=remaining)?;
1611 for view in nullifications.iter() {
1612 if !views.insert(view) {
1613 return Err(Error::Invalid(
1614 "consensus::simplex::Request",
1615 "Duplicate nullification",
1616 ));
1617 }
1618 }
1619 Ok(Request {
1620 id,
1621 notarizations,
1622 nullifications,
1623 })
1624 }
1625}
1626
1627#[derive(Clone, Debug, PartialEq)]
1630pub struct Response<S: Scheme, D: Digest> {
1631 pub id: u64,
1633 pub notarizations: Vec<Notarization<S, D>>,
1635 pub nullifications: Vec<Nullification<S>>,
1637}
1638
1639impl<S: Scheme, D: Digest> Response<S, D> {
1640 pub fn new(
1642 id: u64,
1643 notarizations: Vec<Notarization<S, D>>,
1644 nullifications: Vec<Nullification<S>>,
1645 ) -> Self {
1646 Response {
1647 id,
1648 notarizations,
1649 nullifications,
1650 }
1651 }
1652
1653 pub fn verify<R: Rng + CryptoRng>(&self, rng: &mut R, scheme: &S, namespace: &[u8]) -> bool {
1655 if self.notarizations.is_empty() && self.nullifications.is_empty() {
1657 return true;
1658 }
1659
1660 let notarizations = self.notarizations.iter().map(|notarization| {
1661 let context = VoteContext::Notarize {
1662 proposal: ¬arization.proposal,
1663 };
1664
1665 (context, ¬arization.certificate)
1666 });
1667
1668 let nullifications = self.nullifications.iter().map(|nullification| {
1669 let context = VoteContext::Nullify {
1670 round: nullification.round,
1671 };
1672
1673 (context, &nullification.certificate)
1674 });
1675
1676 scheme.verify_certificates(rng, namespace, notarizations.chain(nullifications))
1677 }
1678}
1679
1680impl<S: Scheme, D: Digest> Write for Response<S, D> {
1681 fn write(&self, writer: &mut impl BufMut) {
1682 UInt(self.id).write(writer);
1683 self.notarizations.write(writer);
1684 self.nullifications.write(writer);
1685 }
1686}
1687
1688impl<S: Scheme, D: Digest> EncodeSize for Response<S, D> {
1689 fn encode_size(&self) -> usize {
1690 UInt(self.id).encode_size()
1691 + self.notarizations.encode_size()
1692 + self.nullifications.encode_size()
1693 }
1694}
1695
1696impl<S: Scheme, D: Digest> Read for Response<S, D> {
1697 type Cfg = (usize, <S::Certificate as Read>::Cfg);
1698
1699 fn read_cfg(reader: &mut impl Buf, cfg: &Self::Cfg) -> Result<Self, Error> {
1700 let (max_len, certificate_cfg) = cfg;
1701 let id = UInt::read(reader)?.into();
1702 let mut views = HashSet::new();
1703 let notarizations = Vec::<Notarization<S, D>>::read_cfg(
1704 reader,
1705 &((..=*max_len).into(), certificate_cfg.clone()),
1706 )?;
1707 for notarization in notarizations.iter() {
1708 if !views.insert(notarization.view()) {
1709 return Err(Error::Invalid(
1710 "consensus::simplex::Response",
1711 "Duplicate notarization",
1712 ));
1713 }
1714 }
1715 let remaining = max_len - notarizations.len();
1716 views.clear();
1717 let nullifications = Vec::<Nullification<S>>::read_cfg(
1718 reader,
1719 &((..=remaining).into(), certificate_cfg.clone()),
1720 )?;
1721 for nullification in nullifications.iter() {
1722 if !views.insert(nullification.view()) {
1723 return Err(Error::Invalid(
1724 "consensus::simplex::Response",
1725 "Duplicate nullification",
1726 ));
1727 }
1728 }
1729 Ok(Response {
1730 id,
1731 notarizations,
1732 nullifications,
1733 })
1734 }
1735}
1736
1737#[derive(Clone, Debug)]
1755pub enum Activity<S: Scheme, D: Digest> {
1756 Notarize(Notarize<S, D>),
1758 Notarization(Notarization<S, D>),
1760 Nullify(Nullify<S>),
1762 Nullification(Nullification<S>),
1764 Finalize(Finalize<S, D>),
1766 Finalization(Finalization<S, D>),
1768 ConflictingNotarize(ConflictingNotarize<S, D>),
1770 ConflictingFinalize(ConflictingFinalize<S, D>),
1772 NullifyFinalize(NullifyFinalize<S, D>),
1774}
1775
1776impl<S: Scheme, D: Digest> PartialEq for Activity<S, D> {
1777 fn eq(&self, other: &Self) -> bool {
1778 match (self, other) {
1779 (Activity::Notarize(a), Activity::Notarize(b)) => a == b,
1780 (Activity::Notarization(a), Activity::Notarization(b)) => a == b,
1781 (Activity::Nullify(a), Activity::Nullify(b)) => a == b,
1782 (Activity::Nullification(a), Activity::Nullification(b)) => a == b,
1783 (Activity::Finalize(a), Activity::Finalize(b)) => a == b,
1784 (Activity::Finalization(a), Activity::Finalization(b)) => a == b,
1785 (Activity::ConflictingNotarize(a), Activity::ConflictingNotarize(b)) => a == b,
1786 (Activity::ConflictingFinalize(a), Activity::ConflictingFinalize(b)) => a == b,
1787 (Activity::NullifyFinalize(a), Activity::NullifyFinalize(b)) => a == b,
1788 _ => false,
1789 }
1790 }
1791}
1792
1793impl<S: Scheme, D: Digest> Eq for Activity<S, D> {}
1794
1795impl<S: Scheme, D: Digest> Hash for Activity<S, D> {
1796 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1797 match self {
1798 Activity::Notarize(v) => {
1799 0u8.hash(state);
1800 v.hash(state);
1801 }
1802 Activity::Notarization(v) => {
1803 1u8.hash(state);
1804 v.hash(state);
1805 }
1806 Activity::Nullify(v) => {
1807 2u8.hash(state);
1808 v.hash(state);
1809 }
1810 Activity::Nullification(v) => {
1811 3u8.hash(state);
1812 v.hash(state);
1813 }
1814 Activity::Finalize(v) => {
1815 4u8.hash(state);
1816 v.hash(state);
1817 }
1818 Activity::Finalization(v) => {
1819 5u8.hash(state);
1820 v.hash(state);
1821 }
1822 Activity::ConflictingNotarize(v) => {
1823 6u8.hash(state);
1824 v.hash(state);
1825 }
1826 Activity::ConflictingFinalize(v) => {
1827 7u8.hash(state);
1828 v.hash(state);
1829 }
1830 Activity::NullifyFinalize(v) => {
1831 8u8.hash(state);
1832 v.hash(state);
1833 }
1834 }
1835 }
1836}
1837
1838impl<S: Scheme, D: Digest> Activity<S, D> {
1839 pub fn verified(&self) -> bool {
1841 match self {
1842 Activity::Notarize(_) => false,
1843 Activity::Notarization(_) => true,
1844 Activity::Nullify(_) => false,
1845 Activity::Nullification(_) => true,
1846 Activity::Finalize(_) => false,
1847 Activity::Finalization(_) => true,
1848 Activity::ConflictingNotarize(_) => false,
1849 Activity::ConflictingFinalize(_) => false,
1850 Activity::NullifyFinalize(_) => false,
1851 }
1852 }
1853
1854 pub fn verify<R: Rng + CryptoRng>(&self, rng: &mut R, scheme: &S, namespace: &[u8]) -> bool {
1860 match self {
1861 Activity::Notarize(n) => n.verify(scheme, namespace),
1862 Activity::Notarization(n) => n.verify(rng, scheme, namespace),
1863 Activity::Nullify(n) => n.verify::<D>(scheme, namespace),
1864 Activity::Nullification(n) => n.verify::<R, D>(rng, scheme, namespace),
1865 Activity::Finalize(f) => f.verify(scheme, namespace),
1866 Activity::Finalization(f) => f.verify(rng, scheme, namespace),
1867 Activity::ConflictingNotarize(c) => c.verify(scheme, namespace),
1868 Activity::ConflictingFinalize(c) => c.verify(scheme, namespace),
1869 Activity::NullifyFinalize(c) => c.verify(scheme, namespace),
1870 }
1871 }
1872}
1873
1874impl<S: Scheme, D: Digest> Write for Activity<S, D> {
1875 fn write(&self, writer: &mut impl BufMut) {
1876 match self {
1877 Activity::Notarize(v) => {
1878 0u8.write(writer);
1879 v.write(writer);
1880 }
1881 Activity::Notarization(v) => {
1882 1u8.write(writer);
1883 v.write(writer);
1884 }
1885 Activity::Nullify(v) => {
1886 2u8.write(writer);
1887 v.write(writer);
1888 }
1889 Activity::Nullification(v) => {
1890 3u8.write(writer);
1891 v.write(writer);
1892 }
1893 Activity::Finalize(v) => {
1894 4u8.write(writer);
1895 v.write(writer);
1896 }
1897 Activity::Finalization(v) => {
1898 5u8.write(writer);
1899 v.write(writer);
1900 }
1901 Activity::ConflictingNotarize(v) => {
1902 6u8.write(writer);
1903 v.write(writer);
1904 }
1905 Activity::ConflictingFinalize(v) => {
1906 7u8.write(writer);
1907 v.write(writer);
1908 }
1909 Activity::NullifyFinalize(v) => {
1910 8u8.write(writer);
1911 v.write(writer);
1912 }
1913 }
1914 }
1915}
1916
1917impl<S: Scheme, D: Digest> EncodeSize for Activity<S, D> {
1918 fn encode_size(&self) -> usize {
1919 1 + match self {
1920 Activity::Notarize(v) => v.encode_size(),
1921 Activity::Notarization(v) => v.encode_size(),
1922 Activity::Nullify(v) => v.encode_size(),
1923 Activity::Nullification(v) => v.encode_size(),
1924 Activity::Finalize(v) => v.encode_size(),
1925 Activity::Finalization(v) => v.encode_size(),
1926 Activity::ConflictingNotarize(v) => v.encode_size(),
1927 Activity::ConflictingFinalize(v) => v.encode_size(),
1928 Activity::NullifyFinalize(v) => v.encode_size(),
1929 }
1930 }
1931}
1932
1933impl<S: Scheme, D: Digest> Read for Activity<S, D> {
1934 type Cfg = <S::Certificate as Read>::Cfg;
1935
1936 fn read_cfg(reader: &mut impl Buf, cfg: &Self::Cfg) -> Result<Self, Error> {
1937 let tag = <u8>::read(reader)?;
1938 match tag {
1939 0 => {
1940 let v = Notarize::<S, D>::read(reader)?;
1941 Ok(Activity::Notarize(v))
1942 }
1943 1 => {
1944 let v = Notarization::<S, D>::read_cfg(reader, cfg)?;
1945 Ok(Activity::Notarization(v))
1946 }
1947 2 => {
1948 let v = Nullify::<S>::read(reader)?;
1949 Ok(Activity::Nullify(v))
1950 }
1951 3 => {
1952 let v = Nullification::<S>::read_cfg(reader, cfg)?;
1953 Ok(Activity::Nullification(v))
1954 }
1955 4 => {
1956 let v = Finalize::<S, D>::read(reader)?;
1957 Ok(Activity::Finalize(v))
1958 }
1959 5 => {
1960 let v = Finalization::<S, D>::read_cfg(reader, cfg)?;
1961 Ok(Activity::Finalization(v))
1962 }
1963 6 => {
1964 let v = ConflictingNotarize::<S, D>::read(reader)?;
1965 Ok(Activity::ConflictingNotarize(v))
1966 }
1967 7 => {
1968 let v = ConflictingFinalize::<S, D>::read(reader)?;
1969 Ok(Activity::ConflictingFinalize(v))
1970 }
1971 8 => {
1972 let v = NullifyFinalize::<S, D>::read(reader)?;
1973 Ok(Activity::NullifyFinalize(v))
1974 }
1975 _ => Err(Error::Invalid(
1976 "consensus::simplex::Activity",
1977 "Invalid type",
1978 )),
1979 }
1980 }
1981}
1982
1983impl<S: Scheme, D: Digest> Epochable for Activity<S, D> {
1984 type Epoch = Epoch;
1985
1986 fn epoch(&self) -> Epoch {
1987 match self {
1988 Activity::Notarize(v) => v.epoch(),
1989 Activity::Notarization(v) => v.epoch(),
1990 Activity::Nullify(v) => v.epoch(),
1991 Activity::Nullification(v) => v.epoch(),
1992 Activity::Finalize(v) => v.epoch(),
1993 Activity::Finalization(v) => v.epoch(),
1994 Activity::ConflictingNotarize(v) => v.epoch(),
1995 Activity::ConflictingFinalize(v) => v.epoch(),
1996 Activity::NullifyFinalize(v) => v.epoch(),
1997 }
1998 }
1999}
2000
2001impl<S: Scheme, D: Digest> Viewable for Activity<S, D> {
2002 type View = View;
2003
2004 fn view(&self) -> View {
2005 match self {
2006 Activity::Notarize(v) => v.view(),
2007 Activity::Notarization(v) => v.view(),
2008 Activity::Nullify(v) => v.view(),
2009 Activity::Nullification(v) => v.view(),
2010 Activity::Finalize(v) => v.view(),
2011 Activity::Finalization(v) => v.view(),
2012 Activity::ConflictingNotarize(v) => v.view(),
2013 Activity::ConflictingFinalize(v) => v.view(),
2014 Activity::NullifyFinalize(v) => v.view(),
2015 }
2016 }
2017}
2018
2019#[derive(Clone, Debug)]
2022pub struct ConflictingNotarize<S: Scheme, D: Digest> {
2023 notarize_1: Notarize<S, D>,
2025 notarize_2: Notarize<S, D>,
2027}
2028
2029impl<S: Scheme, D: Digest> PartialEq for ConflictingNotarize<S, D> {
2030 fn eq(&self, other: &Self) -> bool {
2031 self.notarize_1 == other.notarize_1 && self.notarize_2 == other.notarize_2
2032 }
2033}
2034
2035impl<S: Scheme, D: Digest> Eq for ConflictingNotarize<S, D> {}
2036
2037impl<S: Scheme, D: Digest> Hash for ConflictingNotarize<S, D> {
2038 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
2039 self.notarize_1.hash(state);
2040 self.notarize_2.hash(state);
2041 }
2042}
2043
2044impl<S: Scheme, D: Digest> ConflictingNotarize<S, D> {
2045 pub fn new(notarize_1: Notarize<S, D>, notarize_2: Notarize<S, D>) -> Self {
2047 assert_eq!(notarize_1.round(), notarize_2.round());
2048 assert_eq!(notarize_1.signer(), notarize_2.signer());
2049
2050 ConflictingNotarize {
2051 notarize_1,
2052 notarize_2,
2053 }
2054 }
2055
2056 pub fn verify(&self, scheme: &S, namespace: &[u8]) -> bool {
2058 self.notarize_1.verify(scheme, namespace) && self.notarize_2.verify(scheme, namespace)
2059 }
2060}
2061
2062impl<S: Scheme, D: Digest> Attributable for ConflictingNotarize<S, D> {
2063 fn signer(&self) -> u32 {
2064 self.notarize_1.signer()
2065 }
2066}
2067
2068impl<S: Scheme, D: Digest> Epochable for ConflictingNotarize<S, D> {
2069 type Epoch = Epoch;
2070
2071 fn epoch(&self) -> Epoch {
2072 self.notarize_1.epoch()
2073 }
2074}
2075
2076impl<S: Scheme, D: Digest> Viewable for ConflictingNotarize<S, D> {
2077 type View = View;
2078
2079 fn view(&self) -> View {
2080 self.notarize_1.view()
2081 }
2082}
2083
2084impl<S: Scheme, D: Digest> Write for ConflictingNotarize<S, D> {
2085 fn write(&self, writer: &mut impl BufMut) {
2086 self.notarize_1.write(writer);
2087 self.notarize_2.write(writer);
2088 }
2089}
2090
2091impl<S: Scheme, D: Digest> Read for ConflictingNotarize<S, D> {
2092 type Cfg = ();
2093
2094 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
2095 let notarize_1 = Notarize::read(reader)?;
2096 let notarize_2 = Notarize::read(reader)?;
2097
2098 if notarize_1.signer() != notarize_2.signer() || notarize_1.round() != notarize_2.round() {
2099 return Err(Error::Invalid(
2100 "consensus::simplex::ConflictingNotarize",
2101 "invalid conflicting notarize",
2102 ));
2103 }
2104
2105 Ok(ConflictingNotarize {
2106 notarize_1,
2107 notarize_2,
2108 })
2109 }
2110}
2111
2112impl<S: Scheme, D: Digest> EncodeSize for ConflictingNotarize<S, D> {
2113 fn encode_size(&self) -> usize {
2114 self.notarize_1.encode_size() + self.notarize_2.encode_size()
2115 }
2116}
2117
2118#[derive(Clone, Debug)]
2121pub struct ConflictingFinalize<S: Scheme, D: Digest> {
2122 finalize_1: Finalize<S, D>,
2124 finalize_2: Finalize<S, D>,
2126}
2127
2128impl<S: Scheme, D: Digest> PartialEq for ConflictingFinalize<S, D> {
2129 fn eq(&self, other: &Self) -> bool {
2130 self.finalize_1 == other.finalize_1 && self.finalize_2 == other.finalize_2
2131 }
2132}
2133
2134impl<S: Scheme, D: Digest> Eq for ConflictingFinalize<S, D> {}
2135
2136impl<S: Scheme, D: Digest> Hash for ConflictingFinalize<S, D> {
2137 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
2138 self.finalize_1.hash(state);
2139 self.finalize_2.hash(state);
2140 }
2141}
2142
2143impl<S: Scheme, D: Digest> ConflictingFinalize<S, D> {
2144 pub fn new(finalize_1: Finalize<S, D>, finalize_2: Finalize<S, D>) -> Self {
2146 assert_eq!(finalize_1.round(), finalize_2.round());
2147 assert_eq!(finalize_1.signer(), finalize_2.signer());
2148
2149 ConflictingFinalize {
2150 finalize_1,
2151 finalize_2,
2152 }
2153 }
2154
2155 pub fn verify(&self, scheme: &S, namespace: &[u8]) -> bool {
2157 self.finalize_1.verify(scheme, namespace) && self.finalize_2.verify(scheme, namespace)
2158 }
2159}
2160
2161impl<S: Scheme, D: Digest> Attributable for ConflictingFinalize<S, D> {
2162 fn signer(&self) -> u32 {
2163 self.finalize_1.signer()
2164 }
2165}
2166
2167impl<S: Scheme, D: Digest> Epochable for ConflictingFinalize<S, D> {
2168 type Epoch = Epoch;
2169
2170 fn epoch(&self) -> Epoch {
2171 self.finalize_1.epoch()
2172 }
2173}
2174
2175impl<S: Scheme, D: Digest> Viewable for ConflictingFinalize<S, D> {
2176 type View = View;
2177
2178 fn view(&self) -> View {
2179 self.finalize_1.view()
2180 }
2181}
2182
2183impl<S: Scheme, D: Digest> Write for ConflictingFinalize<S, D> {
2184 fn write(&self, writer: &mut impl BufMut) {
2185 self.finalize_1.write(writer);
2186 self.finalize_2.write(writer);
2187 }
2188}
2189
2190impl<S: Scheme, D: Digest> Read for ConflictingFinalize<S, D> {
2191 type Cfg = ();
2192
2193 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
2194 let finalize_1 = Finalize::read(reader)?;
2195 let finalize_2 = Finalize::read(reader)?;
2196
2197 if finalize_1.signer() != finalize_2.signer() || finalize_1.round() != finalize_2.round() {
2198 return Err(Error::Invalid(
2199 "consensus::simplex::ConflictingFinalize",
2200 "invalid conflicting finalize",
2201 ));
2202 }
2203
2204 Ok(ConflictingFinalize {
2205 finalize_1,
2206 finalize_2,
2207 })
2208 }
2209}
2210
2211impl<S: Scheme, D: Digest> EncodeSize for ConflictingFinalize<S, D> {
2212 fn encode_size(&self) -> usize {
2213 self.finalize_1.encode_size() + self.finalize_2.encode_size()
2214 }
2215}
2216
2217#[derive(Clone, Debug)]
2221pub struct NullifyFinalize<S: Scheme, D: Digest> {
2222 nullify: Nullify<S>,
2224 finalize: Finalize<S, D>,
2226}
2227
2228impl<S: Scheme, D: Digest> PartialEq for NullifyFinalize<S, D> {
2229 fn eq(&self, other: &Self) -> bool {
2230 self.nullify == other.nullify && self.finalize == other.finalize
2231 }
2232}
2233
2234impl<S: Scheme, D: Digest> Eq for NullifyFinalize<S, D> {}
2235
2236impl<S: Scheme, D: Digest> Hash for NullifyFinalize<S, D> {
2237 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
2238 self.nullify.hash(state);
2239 self.finalize.hash(state);
2240 }
2241}
2242
2243impl<S: Scheme, D: Digest> NullifyFinalize<S, D> {
2244 pub fn new(nullify: Nullify<S>, finalize: Finalize<S, D>) -> Self {
2246 assert_eq!(nullify.round, finalize.round());
2247 assert_eq!(nullify.signer(), finalize.signer());
2248
2249 NullifyFinalize { nullify, finalize }
2250 }
2251
2252 pub fn verify(&self, scheme: &S, namespace: &[u8]) -> bool {
2254 self.nullify.verify::<D>(scheme, namespace) && self.finalize.verify(scheme, namespace)
2255 }
2256}
2257
2258impl<S: Scheme, D: Digest> Attributable for NullifyFinalize<S, D> {
2259 fn signer(&self) -> u32 {
2260 self.nullify.signer()
2261 }
2262}
2263
2264impl<S: Scheme, D: Digest> Epochable for NullifyFinalize<S, D> {
2265 type Epoch = Epoch;
2266
2267 fn epoch(&self) -> Epoch {
2268 self.nullify.epoch()
2269 }
2270}
2271
2272impl<S: Scheme, D: Digest> Viewable for NullifyFinalize<S, D> {
2273 type View = View;
2274
2275 fn view(&self) -> View {
2276 self.nullify.view()
2277 }
2278}
2279
2280impl<S: Scheme, D: Digest> Write for NullifyFinalize<S, D> {
2281 fn write(&self, writer: &mut impl BufMut) {
2282 self.nullify.write(writer);
2283 self.finalize.write(writer);
2284 }
2285}
2286
2287impl<S: Scheme, D: Digest> Read for NullifyFinalize<S, D> {
2288 type Cfg = ();
2289
2290 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
2291 let nullify = Nullify::read(reader)?;
2292 let finalize = Finalize::read(reader)?;
2293
2294 if nullify.signer() != finalize.signer() || nullify.round != finalize.round() {
2295 return Err(Error::Invalid(
2296 "consensus::simplex::NullifyFinalize",
2297 "mismatched signatures",
2298 ));
2299 }
2300
2301 Ok(NullifyFinalize { nullify, finalize })
2302 }
2303}
2304
2305impl<S: Scheme, D: Digest> EncodeSize for NullifyFinalize<S, D> {
2306 fn encode_size(&self) -> usize {
2307 self.nullify.encode_size() + self.finalize.encode_size()
2308 }
2309}
2310
2311#[cfg(test)]
2312mod tests {
2313 use super::*;
2314 use crate::simplex::signing_scheme::{bls12381_threshold, ed25519};
2315 use commonware_codec::{Decode, DecodeExt, Encode};
2316 use commonware_cryptography::{
2317 bls12381::{
2318 dkg::ops::{self},
2319 primitives::variant::MinSig,
2320 },
2321 ed25519::{PrivateKey as EdPrivateKey, PublicKey as EdPublicKey},
2322 sha256::Digest as Sha256,
2323 PrivateKeyExt, Signer,
2324 };
2325 use commonware_utils::quorum;
2326 use rand::{
2327 rngs::{OsRng, StdRng},
2328 SeedableRng,
2329 };
2330
2331 const NAMESPACE: &[u8] = b"test";
2332
2333 fn sample_digest(v: u8) -> Sha256 {
2335 Sha256::from([v; 32]) }
2337
2338 fn generate_bls12381_threshold_schemes(
2339 n: u32,
2340 seed: u64,
2341 ) -> Vec<bls12381_threshold::Scheme<EdPublicKey, MinSig>> {
2342 let mut rng = StdRng::seed_from_u64(seed);
2343 let t = quorum(n);
2344
2345 let participants: Vec<_> = (0..n)
2347 .map(|_| EdPrivateKey::from_rng(&mut rng).public_key())
2348 .collect();
2349 let (polynomial, shares) = ops::generate_shares::<_, MinSig>(&mut rng, None, n, t);
2350
2351 shares
2352 .into_iter()
2353 .map(|share| {
2354 bls12381_threshold::Scheme::new(participants.clone().into(), &polynomial, share)
2355 })
2356 .collect()
2357 }
2358
2359 fn generate_bls12381_threshold_verifier(
2360 n: u32,
2361 seed: u64,
2362 ) -> bls12381_threshold::Scheme<EdPublicKey, MinSig> {
2363 let mut rng = StdRng::seed_from_u64(seed);
2364 let t = quorum(n);
2365
2366 let participants: Vec<_> = (0..n)
2368 .map(|_| EdPrivateKey::from_rng(&mut rng).public_key())
2369 .collect();
2370
2371 let (polynomial, _) = ops::generate_shares::<_, MinSig>(&mut rng, None, n, t);
2372 bls12381_threshold::Scheme::verifier(participants.into(), &polynomial)
2373 }
2374
2375 fn generate_ed25519_schemes(n: usize, seed: u64) -> Vec<ed25519::Scheme> {
2376 let mut rng = StdRng::seed_from_u64(seed);
2377 let private_keys: Vec<_> = (0..n).map(|_| EdPrivateKey::from_rng(&mut rng)).collect();
2378
2379 let participants: Ordered<_> = private_keys.iter().map(|p| p.public_key()).collect();
2380
2381 private_keys
2382 .into_iter()
2383 .map(|sk| ed25519::Scheme::new(participants.clone(), sk))
2384 .collect()
2385 }
2386
2387 #[test]
2388 fn test_proposal_encode_decode() {
2389 let proposal = Proposal::new(Round::new(0, 10), 5, sample_digest(1));
2390 let encoded = proposal.encode();
2391 let decoded = Proposal::<Sha256>::decode(encoded).unwrap();
2392 assert_eq!(proposal, decoded);
2393 }
2394
2395 fn notarize_encode_decode<S: Scheme>(schemes: &[S]) {
2396 let round = Round::new(0, 10);
2397 let proposal = Proposal::new(round, 5, sample_digest(1));
2398 let notarize = Notarize::sign(&schemes[0], NAMESPACE, proposal).unwrap();
2399
2400 let encoded = notarize.encode();
2401 let decoded = Notarize::decode(encoded).unwrap();
2402
2403 assert_eq!(notarize, decoded);
2404 assert!(decoded.verify(&schemes[0], NAMESPACE));
2405 }
2406
2407 #[test]
2408 fn test_notarize_encode_decode() {
2409 let bls_threshold_schemes = generate_bls12381_threshold_schemes(5, 0);
2410 notarize_encode_decode(&bls_threshold_schemes);
2411
2412 let ed_schemes = generate_ed25519_schemes(5, 0);
2413 notarize_encode_decode(&ed_schemes);
2414 }
2415
2416 fn notarization_encode_decode<S: Scheme>(schemes: &[S]) {
2417 let proposal = Proposal::new(Round::new(0, 10), 5, sample_digest(1));
2418 let notarizes: Vec<_> = schemes
2419 .iter()
2420 .map(|scheme| Notarize::sign(scheme, NAMESPACE, proposal.clone()).unwrap())
2421 .collect();
2422 let notarization = Notarization::from_notarizes(&schemes[0], ¬arizes).unwrap();
2423 let encoded = notarization.encode();
2424 let cfg = schemes[0].certificate_codec_config();
2425 let decoded = Notarization::decode_cfg(encoded, &cfg).unwrap();
2426 assert_eq!(notarization, decoded);
2427 assert!(decoded.verify(&mut OsRng, &schemes[0], NAMESPACE));
2428 }
2429
2430 #[test]
2431 fn test_notarization_encode_decode() {
2432 let bls_threshold_schemes = generate_bls12381_threshold_schemes(5, 1);
2433 notarization_encode_decode(&bls_threshold_schemes);
2434
2435 let ed_schemes = generate_ed25519_schemes(5, 1);
2436 notarization_encode_decode(&ed_schemes);
2437 }
2438
2439 fn nullify_encode_decode<S: Scheme>(schemes: &[S]) {
2440 let round = Round::new(0, 10);
2441 let nullify = Nullify::sign::<Sha256>(&schemes[0], NAMESPACE, round).unwrap();
2442 let encoded = nullify.encode();
2443 let decoded = Nullify::decode(encoded).unwrap();
2444 assert_eq!(nullify, decoded);
2445 assert!(decoded.verify::<Sha256>(&schemes[0], NAMESPACE));
2446 }
2447
2448 #[test]
2449 fn test_nullify_encode_decode() {
2450 let bls_threshold_schemes = generate_bls12381_threshold_schemes(5, 2);
2451 nullify_encode_decode(&bls_threshold_schemes);
2452
2453 let ed_schemes = generate_ed25519_schemes(5, 2);
2454 nullify_encode_decode(&ed_schemes);
2455 }
2456
2457 fn nullification_encode_decode<S: Scheme>(schemes: &[S]) {
2458 let round = Round::new(333, 10);
2459 let nullifies: Vec<_> = schemes
2460 .iter()
2461 .map(|scheme| Nullify::sign::<Sha256>(scheme, NAMESPACE, round).unwrap())
2462 .collect();
2463 let nullification = Nullification::from_nullifies(&schemes[0], &nullifies).unwrap();
2464 let encoded = nullification.encode();
2465 let cfg = schemes[0].certificate_codec_config();
2466 let decoded = Nullification::decode_cfg(encoded, &cfg).unwrap();
2467 assert_eq!(nullification, decoded);
2468 assert!(decoded.verify::<_, Sha256>(&mut OsRng, &schemes[0], NAMESPACE));
2469 }
2470
2471 #[test]
2472 fn test_nullification_encode_decode() {
2473 let bls_threshold_schemes = generate_bls12381_threshold_schemes(5, 3);
2474 nullification_encode_decode(&bls_threshold_schemes);
2475
2476 let ed_schemes = generate_ed25519_schemes(5, 3);
2477 nullification_encode_decode(&ed_schemes);
2478 }
2479
2480 fn finalize_encode_decode<S: Scheme>(schemes: &[S]) {
2481 let round = Round::new(0, 10);
2482 let proposal = Proposal::new(round, 5, sample_digest(1));
2483 let finalize = Finalize::sign(&schemes[0], NAMESPACE, proposal).unwrap();
2484 let encoded = finalize.encode();
2485 let decoded = Finalize::decode(encoded).unwrap();
2486 assert_eq!(finalize, decoded);
2487 assert!(decoded.verify(&schemes[0], NAMESPACE));
2488 }
2489
2490 #[test]
2491 fn test_finalize_encode_decode() {
2492 let bls_threshold_schemes = generate_bls12381_threshold_schemes(5, 4);
2493 finalize_encode_decode(&bls_threshold_schemes);
2494
2495 let ed_schemes = generate_ed25519_schemes(5, 4);
2496 finalize_encode_decode(&ed_schemes);
2497 }
2498
2499 fn finalization_encode_decode<S: Scheme>(schemes: &[S]) {
2500 let round = Round::new(0, 10);
2501 let proposal = Proposal::new(round, 5, sample_digest(1));
2502 let finalizes: Vec<_> = schemes
2503 .iter()
2504 .map(|scheme| Finalize::sign(scheme, NAMESPACE, proposal.clone()).unwrap())
2505 .collect();
2506 let finalization = Finalization::from_finalizes(&schemes[0], &finalizes).unwrap();
2507 let encoded = finalization.encode();
2508 let cfg = schemes[0].certificate_codec_config();
2509 let decoded = Finalization::decode_cfg(encoded, &cfg).unwrap();
2510 assert_eq!(finalization, decoded);
2511 assert!(decoded.verify(&mut OsRng, &schemes[0], NAMESPACE));
2512 }
2513
2514 #[test]
2515 fn test_finalization_encode_decode() {
2516 let bls_threshold_schemes = generate_bls12381_threshold_schemes(5, 5);
2517 finalization_encode_decode(&bls_threshold_schemes);
2518
2519 let ed_schemes = generate_ed25519_schemes(5, 5);
2520 finalization_encode_decode(&ed_schemes);
2521 }
2522
2523 fn backfiller_encode_decode<S: Scheme>(schemes: &[S]) {
2524 let cfg = schemes[0].certificate_codec_config();
2525 let request = Request::new(1, vec![10, 11], vec![12, 13]);
2526 let encoded_request = Backfiller::<S, Sha256>::Request(request.clone()).encode();
2527 let decoded_request =
2528 Backfiller::<S, Sha256>::decode_cfg(encoded_request, &(usize::MAX, cfg.clone()))
2529 .unwrap();
2530 assert!(matches!(decoded_request, Backfiller::Request(r) if r == request));
2531
2532 let round = Round::new(0, 10);
2533 let proposal = Proposal::new(round, 5, sample_digest(1));
2534 let notarizes: Vec<_> = schemes
2535 .iter()
2536 .map(|scheme| Notarize::sign(scheme, NAMESPACE, proposal.clone()).unwrap())
2537 .collect();
2538 let notarization = Notarization::from_notarizes(&schemes[0], ¬arizes).unwrap();
2539
2540 let nullifies: Vec<_> = schemes
2541 .iter()
2542 .map(|scheme| Nullify::sign::<Sha256>(scheme, NAMESPACE, round).unwrap())
2543 .collect();
2544 let nullification = Nullification::from_nullifies(&schemes[0], &nullifies).unwrap();
2545
2546 let response = Response::<S, Sha256>::new(1, vec![notarization], vec![nullification]);
2547 let encoded_response = Backfiller::<S, Sha256>::Response(response.clone()).encode();
2548 let decoded_response =
2549 Backfiller::<S, Sha256>::decode_cfg(encoded_response, &(usize::MAX, cfg)).unwrap();
2550 assert!(matches!(decoded_response, Backfiller::Response(r) if r.id == response.id));
2551 }
2552
2553 #[test]
2554 fn test_backfiller_encode_decode() {
2555 let bls_threshold_schemes = generate_bls12381_threshold_schemes(5, 6);
2556 backfiller_encode_decode(&bls_threshold_schemes);
2557
2558 let ed_schemes = generate_ed25519_schemes(5, 6);
2559 backfiller_encode_decode(&ed_schemes);
2560 }
2561
2562 #[test]
2563 fn test_request_encode_decode() {
2564 let request = Request::new(1, vec![10, 11], vec![12, 13]);
2565 let encoded = request.encode();
2566 let decoded = Request::decode_cfg(encoded, &usize::MAX).unwrap();
2567 assert_eq!(request, decoded);
2568 }
2569
2570 fn response_encode_decode<S: Scheme>(schemes: &[S]) {
2571 let round = Round::new(0, 10);
2572 let proposal = Proposal::new(round, 5, sample_digest(1));
2573
2574 let notarizes: Vec<_> = schemes
2575 .iter()
2576 .map(|scheme| Notarize::sign(scheme, NAMESPACE, proposal.clone()).unwrap())
2577 .collect();
2578 let notarization = Notarization::from_notarizes(&schemes[0], ¬arizes).unwrap();
2579
2580 let nullifies: Vec<_> = schemes
2581 .iter()
2582 .map(|scheme| Nullify::sign::<Sha256>(scheme, NAMESPACE, round).unwrap())
2583 .collect();
2584 let nullification = Nullification::from_nullifies(&schemes[0], &nullifies).unwrap();
2585
2586 let response = Response::<S, Sha256>::new(1, vec![notarization], vec![nullification]);
2587 let cfg = schemes[0].certificate_codec_config();
2588 let mut decoded =
2589 Response::<S, Sha256>::decode_cfg(response.encode(), &(usize::MAX, cfg.clone()))
2590 .unwrap();
2591 assert_eq!(response.id, decoded.id);
2592 assert_eq!(response.notarizations.len(), decoded.notarizations.len());
2593 assert_eq!(response.nullifications.len(), decoded.nullifications.len());
2594
2595 let mut rng = OsRng;
2596 assert!(decoded.verify(&mut rng, &schemes[0], NAMESPACE));
2597
2598 decoded.nullifications[0].round = Round::new(
2599 decoded.nullifications[0].round.epoch(),
2600 decoded.nullifications[0].round.view() + 1,
2601 );
2602 assert!(!decoded.verify(&mut rng, &schemes[0], NAMESPACE));
2603 }
2604
2605 #[test]
2606 fn test_response_encode_decode() {
2607 let bls_threshold_schemes = generate_bls12381_threshold_schemes(5, 7);
2608 response_encode_decode(&bls_threshold_schemes);
2609
2610 let ed_schemes = generate_ed25519_schemes(5, 7);
2611 response_encode_decode(&ed_schemes);
2612 }
2613
2614 fn conflicting_notarize_encode_decode<S: Scheme>(schemes: &[S]) {
2615 let proposal1 = Proposal::new(Round::new(0, 10), 5, sample_digest(1));
2616 let proposal2 = Proposal::new(Round::new(0, 10), 5, sample_digest(2));
2617 let notarize1 = Notarize::sign(&schemes[0], NAMESPACE, proposal1).unwrap();
2618 let notarize2 = Notarize::sign(&schemes[0], NAMESPACE, proposal2).unwrap();
2619 let conflicting = ConflictingNotarize::new(notarize1, notarize2);
2620
2621 let encoded = conflicting.encode();
2622 let decoded = ConflictingNotarize::<S, Sha256>::decode(encoded).unwrap();
2623
2624 assert_eq!(conflicting, decoded);
2625 assert!(decoded.verify(&schemes[0], NAMESPACE));
2626 }
2627
2628 #[test]
2629 fn test_conflicting_notarize_encode_decode() {
2630 let bls_threshold_schemes = generate_bls12381_threshold_schemes(5, 8);
2631 conflicting_notarize_encode_decode(&bls_threshold_schemes);
2632
2633 let ed_schemes = generate_ed25519_schemes(5, 8);
2634 conflicting_notarize_encode_decode(&ed_schemes);
2635 }
2636
2637 fn conflicting_finalize_encode_decode<S: Scheme>(schemes: &[S]) {
2638 let proposal1 = Proposal::new(Round::new(0, 10), 5, sample_digest(1));
2639 let proposal2 = Proposal::new(Round::new(0, 10), 5, sample_digest(2));
2640 let finalize1 = Finalize::sign(&schemes[0], NAMESPACE, proposal1).unwrap();
2641 let finalize2 = Finalize::sign(&schemes[0], NAMESPACE, proposal2).unwrap();
2642 let conflicting = ConflictingFinalize::new(finalize1, finalize2);
2643
2644 let encoded = conflicting.encode();
2645 let decoded = ConflictingFinalize::<S, Sha256>::decode(encoded).unwrap();
2646
2647 assert_eq!(conflicting, decoded);
2648 assert!(decoded.verify(&schemes[0], NAMESPACE));
2649 }
2650
2651 #[test]
2652 fn test_conflicting_finalize_encode_decode() {
2653 let bls_threshold_schemes = generate_bls12381_threshold_schemes(5, 9);
2654 conflicting_finalize_encode_decode(&bls_threshold_schemes);
2655
2656 let ed_schemes = generate_ed25519_schemes(5, 9);
2657 conflicting_finalize_encode_decode(&ed_schemes);
2658 }
2659
2660 fn nullify_finalize_encode_decode<S: Scheme>(schemes: &[S]) {
2661 let round = Round::new(0, 10);
2662 let proposal = Proposal::new(round, 5, sample_digest(1));
2663 let nullify = Nullify::sign::<Sha256>(&schemes[0], NAMESPACE, round).unwrap();
2664 let finalize = Finalize::sign(&schemes[0], NAMESPACE, proposal).unwrap();
2665 let conflict = NullifyFinalize::new(nullify, finalize);
2666
2667 let encoded = conflict.encode();
2668 let decoded = NullifyFinalize::<S, Sha256>::decode(encoded).unwrap();
2669
2670 assert_eq!(conflict, decoded);
2671 assert!(decoded.verify(&schemes[0], NAMESPACE));
2672 }
2673
2674 #[test]
2675 fn test_nullify_finalize_encode_decode() {
2676 let bls_threshold_schemes = generate_bls12381_threshold_schemes(5, 10);
2677 nullify_finalize_encode_decode(&bls_threshold_schemes);
2678
2679 let ed_schemes = generate_ed25519_schemes(5, 10);
2680 nullify_finalize_encode_decode(&ed_schemes);
2681 }
2682
2683 fn notarize_verify_wrong_namespace<S: Scheme>(scheme: &S) {
2684 let round = Round::new(0, 10);
2685 let proposal = Proposal::new(round, 5, sample_digest(1));
2686 let notarize = Notarize::sign(scheme, NAMESPACE, proposal).unwrap();
2687
2688 assert!(notarize.verify(scheme, NAMESPACE));
2689 assert!(!notarize.verify(scheme, b"wrong_namespace"));
2690 }
2691
2692 #[test]
2693 fn test_notarize_verify_wrong_namespace() {
2694 let bls_threshold_schemes = generate_bls12381_threshold_schemes(5, 220);
2695 notarize_verify_wrong_namespace(&bls_threshold_schemes[0]);
2696
2697 let ed_schemes = generate_ed25519_schemes(5, 220);
2698 notarize_verify_wrong_namespace(&ed_schemes[0]);
2699 }
2700
2701 fn notarize_verify_wrong_scheme<S: Scheme>(scheme: &S, wrong_scheme: &S) {
2702 let round = Round::new(0, 10);
2703 let proposal = Proposal::new(round, 5, sample_digest(2));
2704 let notarize = Notarize::sign(scheme, NAMESPACE, proposal).unwrap();
2705
2706 assert!(notarize.verify(scheme, NAMESPACE));
2707 assert!(!notarize.verify(wrong_scheme, NAMESPACE));
2708 }
2709
2710 #[test]
2711 fn test_notarize_verify_wrong_scheme() {
2712 let bls_threshold_schemes = generate_bls12381_threshold_schemes(5, 221);
2713 let bls_threshold_wrong_scheme = generate_bls12381_threshold_verifier(5, 501);
2714 notarize_verify_wrong_scheme(&bls_threshold_schemes[0], &bls_threshold_wrong_scheme);
2715
2716 let ed_schemes = generate_ed25519_schemes(5, 221);
2717 let ed_wrong_scheme = generate_ed25519_schemes(5, 321);
2718 notarize_verify_wrong_scheme(&ed_schemes[0], &ed_wrong_scheme[0]);
2719 }
2720
2721 fn notarization_verify_wrong_scheme<S: Scheme>(schemes: &[S], wrong_scheme: &S) {
2722 let round = Round::new(0, 10);
2723 let proposal = Proposal::new(round, 5, sample_digest(3));
2724 let quorum = quorum(schemes.len() as u32);
2725 let notarizes: Vec<_> = schemes
2726 .iter()
2727 .take(quorum as usize)
2728 .map(|scheme| Notarize::sign(scheme, NAMESPACE, proposal.clone()).unwrap())
2729 .collect();
2730
2731 let notarization =
2732 Notarization::from_notarizes(&schemes[0], ¬arizes).expect("quorum notarization");
2733 let mut rng = OsRng;
2734 assert!(notarization.verify(&mut rng, &schemes[0], NAMESPACE));
2735
2736 let mut rng = OsRng;
2737 assert!(!notarization.verify(&mut rng, wrong_scheme, NAMESPACE));
2738 }
2739
2740 #[test]
2741 fn test_notarization_verify_wrong_scheme() {
2742 let bls_threshold_schemes = generate_bls12381_threshold_schemes(5, 222);
2743 let bls_threshold_wrong_scheme = generate_bls12381_threshold_verifier(5, 502);
2744 notarization_verify_wrong_scheme(&bls_threshold_schemes, &bls_threshold_wrong_scheme);
2745
2746 let ed_schemes = generate_ed25519_schemes(5, 222);
2747 let ed_wrong_scheme = generate_ed25519_schemes(5, 422);
2748 notarization_verify_wrong_scheme(&ed_schemes, &ed_wrong_scheme[0]);
2749 }
2750
2751 fn notarization_verify_wrong_namespace<S: Scheme>(schemes: &[S]) {
2752 let round = Round::new(0, 10);
2753 let proposal = Proposal::new(round, 5, sample_digest(4));
2754 let quorum = quorum(schemes.len() as u32);
2755 let notarizes: Vec<_> = schemes
2756 .iter()
2757 .take(quorum as usize)
2758 .map(|scheme| Notarize::sign(scheme, NAMESPACE, proposal.clone()).unwrap())
2759 .collect();
2760
2761 let notarization =
2762 Notarization::from_notarizes(&schemes[0], ¬arizes).expect("quorum notarization");
2763 let mut rng = OsRng;
2764 assert!(notarization.verify(&mut rng, &schemes[0], NAMESPACE));
2765
2766 let mut rng = OsRng;
2767 assert!(!notarization.verify(&mut rng, &schemes[0], b"wrong_namespace"));
2768 }
2769
2770 #[test]
2771 fn test_notarization_verify_wrong_namespace() {
2772 let bls_threshold_schemes = generate_bls12381_threshold_schemes(5, 223);
2773 notarization_verify_wrong_namespace(&bls_threshold_schemes);
2774
2775 let ed_schemes = generate_ed25519_schemes(5, 223);
2776 notarization_verify_wrong_namespace(&ed_schemes);
2777 }
2778
2779 fn notarization_recover_insufficient_signatures<S: Scheme>(schemes: &[S]) {
2780 let quorum = quorum(schemes.len() as u32);
2781 assert!(quorum > 1, "test requires quorum larger than one");
2782 let round = Round::new(0, 10);
2783 let proposal = Proposal::new(round, 5, sample_digest(5));
2784 let notarizes: Vec<_> = schemes
2785 .iter()
2786 .take((quorum - 1) as usize)
2787 .map(|scheme| Notarize::sign(scheme, NAMESPACE, proposal.clone()).unwrap())
2788 .collect();
2789
2790 assert!(
2791 Notarization::from_notarizes(&schemes[0], ¬arizes).is_none(),
2792 "insufficient votes should not form a notarization"
2793 );
2794 }
2795
2796 #[test]
2797 fn test_notarization_recover_insufficient_signatures() {
2798 let bls_threshold_schemes = generate_bls12381_threshold_schemes(5, 224);
2799 notarization_recover_insufficient_signatures(&bls_threshold_schemes);
2800
2801 let ed_schemes = generate_ed25519_schemes(5, 224);
2802 notarization_recover_insufficient_signatures(&ed_schemes);
2803 }
2804
2805 fn conflicting_notarize_detection<S: Scheme>(scheme: &S, wrong_scheme: &S) {
2806 let round = Round::new(0, 10);
2807 let proposal1 = Proposal::new(round, 5, sample_digest(6));
2808 let proposal2 = Proposal::new(round, 5, sample_digest(7));
2809
2810 let notarize1 = Notarize::sign(scheme, NAMESPACE, proposal1).unwrap();
2811 let notarize2 = Notarize::sign(scheme, NAMESPACE, proposal2).unwrap();
2812 let conflict = ConflictingNotarize::new(notarize1, notarize2);
2813
2814 assert!(conflict.verify(scheme, NAMESPACE));
2815 assert!(!conflict.verify(scheme, b"wrong_namespace"));
2816 assert!(!conflict.verify(wrong_scheme, NAMESPACE));
2817 }
2818
2819 #[test]
2820 fn test_conflicting_notarize_detection() {
2821 let bls_threshold_schemes = generate_bls12381_threshold_schemes(5, 225);
2822 let bls_threshold_wrong_scheme = generate_bls12381_threshold_verifier(5, 503);
2823 conflicting_notarize_detection(&bls_threshold_schemes[0], &bls_threshold_wrong_scheme);
2824
2825 let ed_schemes = generate_ed25519_schemes(5, 225);
2826 let ed_wrong_scheme = generate_ed25519_schemes(5, 425);
2827 conflicting_notarize_detection(&ed_schemes[0], &ed_wrong_scheme[0]);
2828 }
2829
2830 fn nullify_finalize_detection<S: Scheme>(scheme: &S, wrong_scheme: &S) {
2831 let round = Round::new(0, 10);
2832 let proposal = Proposal::new(round, 5, sample_digest(8));
2833
2834 let nullify = Nullify::sign::<Sha256>(scheme, NAMESPACE, round).unwrap();
2835 let finalize = Finalize::sign(scheme, NAMESPACE, proposal).unwrap();
2836 let conflict = NullifyFinalize::new(nullify, finalize);
2837
2838 assert!(conflict.verify(scheme, NAMESPACE));
2839 assert!(!conflict.verify(scheme, b"wrong_namespace"));
2840 assert!(!conflict.verify(wrong_scheme, NAMESPACE));
2841 }
2842
2843 #[test]
2844 fn test_nullify_finalize_detection() {
2845 let bls_threshold_schemes = generate_bls12381_threshold_schemes(5, 226);
2846 let bls_threshold_wrong_scheme = generate_bls12381_threshold_verifier(5, 504);
2847 nullify_finalize_detection(&bls_threshold_schemes[0], &bls_threshold_wrong_scheme);
2848
2849 let ed_schemes = generate_ed25519_schemes(5, 226);
2850 let ed_wrong_scheme = generate_ed25519_schemes(5, 426);
2851 nullify_finalize_detection(&ed_schemes[0], &ed_wrong_scheme[0]);
2852 }
2853
2854 fn finalization_verify_wrong_scheme<S: Scheme>(schemes: &[S], wrong_scheme: &S) {
2855 let round = Round::new(0, 10);
2856 let proposal = Proposal::new(round, 5, sample_digest(9));
2857 let quorum = quorum(schemes.len() as u32);
2858 let finalizes: Vec<_> = schemes
2859 .iter()
2860 .take(quorum as usize)
2861 .map(|scheme| Finalize::sign(scheme, NAMESPACE, proposal.clone()).unwrap())
2862 .collect();
2863
2864 let finalization =
2865 Finalization::from_finalizes(&schemes[0], &finalizes).expect("quorum finalization");
2866 let mut rng = OsRng;
2867 assert!(finalization.verify(&mut rng, &schemes[0], NAMESPACE));
2868
2869 let mut rng = OsRng;
2870 assert!(!finalization.verify(&mut rng, wrong_scheme, NAMESPACE));
2871 }
2872
2873 #[test]
2874 fn test_finalization_wrong_scheme() {
2875 let bls_threshold_schemes = generate_bls12381_threshold_schemes(5, 227);
2876 let bls_threshold_wrong_scheme = generate_bls12381_threshold_verifier(5, 505);
2877 finalization_verify_wrong_scheme(&bls_threshold_schemes, &bls_threshold_wrong_scheme);
2878
2879 let ed_schemes = generate_ed25519_schemes(5, 227);
2880 let ed_wrong_scheme = generate_ed25519_schemes(5, 427);
2881 finalization_verify_wrong_scheme(&ed_schemes, &ed_wrong_scheme[0]);
2882 }
2883
2884 fn create_notarize<S: Scheme>(
2886 scheme: &S,
2887 round: Round,
2888 parent_view: View,
2889 payload_val: u8,
2890 ) -> Notarize<S, Sha256> {
2891 let proposal = Proposal::new(round, parent_view, sample_digest(payload_val));
2892 Notarize::sign(scheme, NAMESPACE, proposal).unwrap()
2893 }
2894
2895 #[allow(dead_code)]
2897 fn create_nullify<S: Scheme>(scheme: &S, round: Round) -> Nullify<S> {
2898 Nullify::sign::<Sha256>(scheme, NAMESPACE, round).unwrap()
2899 }
2900
2901 #[allow(dead_code)]
2903 fn create_finalize<S: Scheme>(
2904 scheme: &S,
2905 round: Round,
2906 parent_view: View,
2907 payload_val: u8,
2908 ) -> Finalize<S, Sha256> {
2909 let proposal = Proposal::new(round, parent_view, sample_digest(payload_val));
2910 Finalize::sign(scheme, NAMESPACE, proposal).unwrap()
2911 }
2912
2913 fn create_notarization<S: Scheme>(
2914 schemes: &[S],
2915 round: Round,
2916 parent_view: View,
2917 payload_val: u8,
2918 quorum: u32,
2919 ) -> Notarization<S, Sha256> {
2920 let proposal = Proposal::new(round, parent_view, sample_digest(payload_val));
2921 let notarizes: Vec<_> = schemes
2922 .iter()
2923 .take(quorum as usize)
2924 .map(|scheme| Notarize::sign(scheme, NAMESPACE, proposal.clone()).unwrap())
2925 .collect();
2926 Notarization::from_notarizes(&schemes[0], ¬arizes).unwrap()
2927 }
2928
2929 fn batch_verifier_add_notarize<S: Scheme + Clone>(schemes: Vec<S>) {
2930 let quorum = quorum(schemes.len() as u32);
2931 let mut verifier = BatchVerifier::<S, Sha256>::new(schemes[0].clone(), Some(quorum));
2932
2933 let round = Round::new(0, 1);
2934 let notarize1 = create_notarize(&schemes[0], round, 0, 1);
2935 let notarize2 = create_notarize(&schemes[1], round, 0, 1);
2936 let notarize_diff = create_notarize(&schemes[2], round, 0, 2);
2937
2938 verifier.add(Voter::Notarize(notarize1.clone()), false);
2939 assert_eq!(verifier.notarizes.len(), 1);
2940 assert_eq!(verifier.notarizes_verified, 0);
2941
2942 verifier.add(Voter::Notarize(notarize1.clone()), true);
2943 assert_eq!(verifier.notarizes.len(), 1);
2944 assert_eq!(verifier.notarizes_verified, 1);
2945
2946 verifier.set_leader(notarize1.signer());
2947 assert!(verifier.leader_proposal.is_some());
2948 assert_eq!(
2949 verifier.leader_proposal.as_ref().unwrap(),
2950 ¬arize1.proposal
2951 );
2952 assert!(verifier.notarizes_force);
2953 assert_eq!(verifier.notarizes.len(), 1);
2954
2955 verifier.add(Voter::Notarize(notarize2.clone()), false);
2956 assert_eq!(verifier.notarizes.len(), 2);
2957
2958 verifier.add(Voter::Notarize(notarize_diff.clone()), false);
2959 assert_eq!(verifier.notarizes.len(), 2);
2960
2961 let mut verifier2 = BatchVerifier::<S, Sha256>::new(schemes[0].clone(), Some(quorum));
2962 let round2 = Round::new(0, 2);
2963 let notarize_non_leader = create_notarize(&schemes[1], round2, 1, 3);
2964 let notarize_leader = create_notarize(&schemes[0], round2, 1, 3);
2965
2966 verifier2.set_leader(notarize_leader.signer());
2967 verifier2.add(Voter::Notarize(notarize_non_leader.clone()), false);
2968 assert!(verifier2.leader_proposal.is_none());
2969 assert_eq!(verifier2.notarizes.len(), 1);
2970
2971 verifier2.add(Voter::Notarize(notarize_leader.clone()), false);
2972 assert!(verifier2.leader_proposal.is_some());
2973 assert_eq!(
2974 verifier2.leader_proposal.as_ref().unwrap(),
2975 ¬arize_leader.proposal
2976 );
2977 assert_eq!(verifier2.notarizes.len(), 2);
2978 }
2979
2980 #[test]
2981 fn test_batch_verifier_add_notarize() {
2982 batch_verifier_add_notarize(generate_bls12381_threshold_schemes(5, 123));
2983 batch_verifier_add_notarize(generate_ed25519_schemes(5, 123));
2984 }
2985
2986 fn batch_verifier_set_leader<S: Scheme + Clone>(schemes: Vec<S>) {
2987 let quorum = quorum(schemes.len() as u32);
2988 let mut verifier = BatchVerifier::<S, Sha256>::new(schemes[0].clone(), Some(quorum));
2989
2990 let round = Round::new(0, 1);
2991 let leader_notarize = create_notarize(&schemes[0], round, 0, 1);
2992 let other_notarize = create_notarize(&schemes[1], round, 0, 1);
2993
2994 verifier.add(Voter::Notarize(other_notarize.clone()), false);
2995 assert_eq!(verifier.notarizes.len(), 1);
2996
2997 let leader = leader_notarize.signer();
2998 verifier.set_leader(leader);
2999 assert_eq!(verifier.leader, Some(leader));
3000 assert!(verifier.leader_proposal.is_none());
3001 assert!(!verifier.notarizes_force);
3002 assert_eq!(verifier.notarizes.len(), 1);
3003
3004 verifier.add(Voter::Notarize(leader_notarize.clone()), false);
3005 assert!(verifier.leader_proposal.is_some());
3006 assert_eq!(
3007 verifier.leader_proposal.as_ref().unwrap(),
3008 &leader_notarize.proposal
3009 );
3010 assert!(verifier.notarizes_force);
3011 assert_eq!(verifier.notarizes.len(), 2);
3012 }
3013
3014 #[test]
3015 fn test_batch_verifier_set_leader() {
3016 batch_verifier_set_leader(generate_bls12381_threshold_schemes(5, 124));
3017 batch_verifier_set_leader(generate_ed25519_schemes(5, 124));
3018 }
3019
3020 fn batch_verifier_ready_and_verify_notarizes<S: Scheme + Clone>(schemes: Vec<S>) {
3021 let quorum = quorum(schemes.len() as u32);
3022 let mut verifier = BatchVerifier::<S, Sha256>::new(schemes[0].clone(), Some(quorum));
3023 let mut rng = OsRng;
3024 let round = Round::new(0, 1);
3025 let notarizes: Vec<_> = schemes
3026 .iter()
3027 .map(|scheme| create_notarize(scheme, round, 0, 1))
3028 .collect();
3029
3030 assert!(!verifier.ready_notarizes());
3031
3032 verifier.set_leader(notarizes[0].signer());
3033 verifier.add(Voter::Notarize(notarizes[0].clone()), false);
3034 assert!(verifier.ready_notarizes());
3035 assert_eq!(verifier.notarizes.len(), 1);
3036
3037 let (verified_once, failed_once) = verifier.verify_notarizes(&mut rng, NAMESPACE);
3038 assert_eq!(verified_once.len(), 1);
3039 assert!(failed_once.is_empty());
3040 assert_eq!(verifier.notarizes_verified, 1);
3041 assert!(verifier.notarizes.is_empty());
3042 assert!(!verifier.notarizes_force);
3043
3044 verifier.add(Voter::Notarize(notarizes[1].clone()), false);
3045 assert!(!verifier.ready_notarizes());
3046 verifier.add(Voter::Notarize(notarizes[2].clone()), false);
3047 assert!(!verifier.ready_notarizes());
3048 verifier.add(Voter::Notarize(notarizes[3].clone()), false);
3049 assert!(verifier.ready_notarizes());
3050 assert_eq!(verifier.notarizes.len(), 3);
3051
3052 let (verified_bulk, failed_bulk) = verifier.verify_notarizes(&mut rng, NAMESPACE);
3053 assert_eq!(verified_bulk.len(), 3);
3054 assert!(failed_bulk.is_empty());
3055 assert_eq!(verifier.notarizes_verified, 4);
3056 assert!(verifier.notarizes.is_empty());
3057 assert!(!verifier.ready_notarizes());
3058
3059 let mut verifier2 = BatchVerifier::<S, Sha256>::new(schemes[0].clone(), Some(quorum));
3060 let round2 = Round::new(0, 2);
3061 let leader_vote = create_notarize(&schemes[0], round2, 1, 10);
3062 let mut faulty_vote = create_notarize(&schemes[1], round2, 1, 10);
3063 verifier2.set_leader(leader_vote.signer());
3064 verifier2.add(Voter::Notarize(leader_vote.clone()), false);
3065 faulty_vote.vote.signer = (schemes.len() as u32) + 10;
3066 verifier2.add(Voter::Notarize(faulty_vote.clone()), false);
3067 assert!(verifier2.ready_notarizes());
3068
3069 let (verified_second, failed_second) = verifier2.verify_notarizes(&mut rng, NAMESPACE);
3070 assert_eq!(verified_second.len(), 1);
3071 assert!(verified_second
3072 .into_iter()
3073 .any(|v| matches!(v, Voter::Notarize(ref n) if n == &leader_vote)));
3074 assert_eq!(failed_second, vec![faulty_vote.signer()]);
3075 }
3076
3077 #[test]
3078 fn test_batch_verifier_ready_and_verify_notarizes() {
3079 batch_verifier_ready_and_verify_notarizes(generate_bls12381_threshold_schemes(5, 125));
3080 batch_verifier_ready_and_verify_notarizes(generate_ed25519_schemes(5, 125));
3081 }
3082
3083 fn batch_verifier_add_nullify<S: Scheme + Clone>(schemes: Vec<S>) {
3084 let quorum = quorum(schemes.len() as u32);
3085 let mut verifier = BatchVerifier::<S, Sha256>::new(schemes[0].clone(), Some(quorum));
3086 let round = Round::new(0, 1);
3087 let nullify = create_nullify(&schemes[0], round);
3088
3089 verifier.add(Voter::Nullify(nullify.clone()), false);
3090 assert_eq!(verifier.nullifies.len(), 1);
3091 assert_eq!(verifier.nullifies_verified, 0);
3092
3093 verifier.add(Voter::Nullify(nullify.clone()), true);
3094 assert_eq!(verifier.nullifies.len(), 1);
3095 assert_eq!(verifier.nullifies_verified, 1);
3096 }
3097
3098 #[test]
3099 fn test_batch_verifier_add_nullify() {
3100 batch_verifier_add_nullify(generate_bls12381_threshold_schemes(5, 127));
3101 batch_verifier_add_nullify(generate_ed25519_schemes(5, 127));
3102 }
3103
3104 fn batch_verifier_ready_and_verify_nullifies<S: Scheme + Clone>(schemes: Vec<S>) {
3105 let quorum = quorum(schemes.len() as u32);
3106 let mut verifier = BatchVerifier::<S, Sha256>::new(schemes[0].clone(), Some(quorum));
3107 let mut rng = OsRng;
3108 let round = Round::new(0, 1);
3109 let nullifies: Vec<_> = schemes
3110 .iter()
3111 .map(|scheme| create_nullify(scheme, round))
3112 .collect();
3113
3114 verifier.add(Voter::Nullify(nullifies[0].clone()), true);
3115 assert_eq!(verifier.nullifies_verified, 1);
3116
3117 verifier.add(Voter::Nullify(nullifies[1].clone()), false);
3118 assert!(!verifier.ready_nullifies());
3119 verifier.add(Voter::Nullify(nullifies[2].clone()), false);
3120 assert!(!verifier.ready_nullifies());
3121 verifier.add(Voter::Nullify(nullifies[3].clone()), false);
3122 assert!(verifier.ready_nullifies());
3123 assert_eq!(verifier.nullifies.len(), 3);
3124
3125 let (verified, failed) = verifier.verify_nullifies(&mut rng, NAMESPACE);
3126 assert_eq!(verified.len(), 3);
3127 assert!(failed.is_empty());
3128 assert_eq!(verifier.nullifies_verified, 4);
3129 assert!(verifier.nullifies.is_empty());
3130 assert!(!verifier.ready_nullifies());
3131 }
3132
3133 #[test]
3134 fn test_batch_verifier_ready_and_verify_nullifies() {
3135 batch_verifier_ready_and_verify_nullifies(generate_bls12381_threshold_schemes(5, 128));
3136 batch_verifier_ready_and_verify_nullifies(generate_ed25519_schemes(5, 128));
3137 }
3138
3139 fn batch_verifier_add_finalize<S: Scheme + Clone>(schemes: Vec<S>) {
3140 let quorum = quorum(schemes.len() as u32);
3141 let mut verifier = BatchVerifier::<S, Sha256>::new(schemes[0].clone(), Some(quorum));
3142 let round = Round::new(0, 1);
3143 let finalize_a = create_finalize(&schemes[0], round, 0, 1);
3144 let finalize_b = create_finalize(&schemes[1], round, 0, 2);
3145
3146 verifier.add(Voter::Finalize(finalize_b.clone()), false);
3147 assert_eq!(verifier.finalizes.len(), 1);
3148 assert_eq!(verifier.finalizes_verified, 0);
3149
3150 verifier.add(Voter::Finalize(finalize_a.clone()), false);
3151 assert_eq!(verifier.finalizes.len(), 2);
3152
3153 verifier.set_leader(finalize_a.signer());
3154 assert!(verifier.leader_proposal.is_none());
3155 verifier.set_leader_proposal(finalize_a.proposal.clone());
3156 assert_eq!(verifier.finalizes.len(), 1);
3157 assert_eq!(verifier.finalizes[0], finalize_a);
3158 assert_eq!(verifier.finalizes_verified, 0);
3159
3160 verifier.add(Voter::Finalize(finalize_a.clone()), true);
3161 assert_eq!(verifier.finalizes.len(), 1);
3162 assert_eq!(verifier.finalizes_verified, 1);
3163
3164 verifier.add(Voter::Finalize(finalize_b.clone()), false);
3165 assert_eq!(verifier.finalizes.len(), 1);
3166 assert_eq!(verifier.finalizes_verified, 1);
3167 }
3168
3169 #[test]
3170 fn test_batch_verifier_add_finalize() {
3171 batch_verifier_add_finalize(generate_bls12381_threshold_schemes(5, 129));
3172 batch_verifier_add_finalize(generate_ed25519_schemes(5, 129));
3173 }
3174
3175 fn batch_verifier_ready_and_verify_finalizes<S: Scheme + Clone>(schemes: Vec<S>) {
3176 let quorum = quorum(schemes.len() as u32);
3177 let mut verifier = BatchVerifier::<S, Sha256>::new(schemes[0].clone(), Some(quorum));
3178 let mut rng = OsRng;
3179 let round = Round::new(0, 1);
3180 let finalizes: Vec<_> = schemes
3181 .iter()
3182 .map(|scheme| create_finalize(scheme, round, 0, 1))
3183 .collect();
3184
3185 assert!(!verifier.ready_finalizes());
3186
3187 verifier.set_leader(finalizes[0].signer());
3188 verifier.set_leader_proposal(finalizes[0].proposal.clone());
3189
3190 verifier.add(Voter::Finalize(finalizes[0].clone()), true);
3191 assert_eq!(verifier.finalizes_verified, 1);
3192 assert!(verifier.finalizes.is_empty());
3193
3194 verifier.add(Voter::Finalize(finalizes[1].clone()), false);
3195 assert!(!verifier.ready_finalizes());
3196 verifier.add(Voter::Finalize(finalizes[2].clone()), false);
3197 assert!(!verifier.ready_finalizes());
3198 verifier.add(Voter::Finalize(finalizes[3].clone()), false);
3199 assert!(verifier.ready_finalizes());
3200
3201 let (verified, failed) = verifier.verify_finalizes(&mut rng, NAMESPACE);
3202 assert_eq!(verified.len(), 3);
3203 assert!(failed.is_empty());
3204 assert_eq!(verifier.finalizes_verified, 4);
3205 assert!(verifier.finalizes.is_empty());
3206 assert!(!verifier.ready_finalizes());
3207 }
3208
3209 #[test]
3210 fn test_batch_verifier_ready_and_verify_finalizes() {
3211 batch_verifier_ready_and_verify_finalizes(generate_bls12381_threshold_schemes(5, 130));
3212 batch_verifier_ready_and_verify_finalizes(generate_ed25519_schemes(5, 130));
3213 }
3214
3215 fn batch_verifier_quorum_none<S: Scheme + Clone>(schemes: Vec<S>) {
3216 let mut rng = OsRng;
3217 let round = Round::new(0, 1);
3218
3219 let mut verifier_notarize = BatchVerifier::<S, Sha256>::new(schemes[0].clone(), None);
3220 let notarize = create_notarize(&schemes[0], round, 0, 1);
3221 assert!(!verifier_notarize.ready_notarizes());
3222 verifier_notarize.set_leader(notarize.signer());
3223 verifier_notarize.add(Voter::Notarize(notarize.clone()), false);
3224 assert!(verifier_notarize.ready_notarizes());
3225 let (verified_notarize, failed_notarize) =
3226 verifier_notarize.verify_notarizes(&mut rng, NAMESPACE);
3227 assert_eq!(verified_notarize.len(), 1);
3228 assert!(failed_notarize.is_empty());
3229 assert_eq!(verifier_notarize.notarizes_verified, 1);
3230 assert!(!verifier_notarize.ready_notarizes());
3231
3232 let mut verifier_null = BatchVerifier::<S, Sha256>::new(schemes[0].clone(), None);
3233 let nullify = create_nullify(&schemes[0], round);
3234 assert!(!verifier_null.ready_nullifies());
3235 verifier_null.add(Voter::Nullify(nullify.clone()), false);
3236 assert!(verifier_null.ready_nullifies());
3237 let (verified_null, failed_null) = verifier_null.verify_nullifies(&mut rng, NAMESPACE);
3238 assert_eq!(verified_null.len(), 1);
3239 assert!(failed_null.is_empty());
3240 assert_eq!(verifier_null.nullifies_verified, 1);
3241 assert!(!verifier_null.ready_nullifies());
3242
3243 let mut verifier_final = BatchVerifier::<S, Sha256>::new(schemes[0].clone(), None);
3244 let finalize = create_finalize(&schemes[0], round, 0, 1);
3245 assert!(!verifier_final.ready_finalizes());
3246 verifier_final.set_leader(finalize.signer());
3247 verifier_final.set_leader_proposal(finalize.proposal.clone());
3248 verifier_final.add(Voter::Finalize(finalize.clone()), false);
3249 assert!(verifier_final.ready_finalizes());
3250 let (verified_fin, failed_fin) = verifier_final.verify_finalizes(&mut rng, NAMESPACE);
3251 assert_eq!(verified_fin.len(), 1);
3252 assert!(failed_fin.is_empty());
3253 assert_eq!(verifier_final.finalizes_verified, 1);
3254 assert!(!verifier_final.ready_finalizes());
3255 }
3256
3257 #[test]
3258 fn test_batch_verifier_quorum_none() {
3259 batch_verifier_quorum_none(generate_bls12381_threshold_schemes(3, 200));
3260 batch_verifier_quorum_none(generate_ed25519_schemes(3, 200));
3261 }
3262
3263 fn batch_verifier_leader_proposal_filters_messages<S: Scheme + Clone>(schemes: Vec<S>) {
3264 let quorum = quorum(schemes.len() as u32);
3265 let mut verifier = BatchVerifier::<S, Sha256>::new(schemes[0].clone(), Some(quorum));
3266 let round = Round::new(0, 1);
3267 let proposal_a = Proposal::new(round, 0, sample_digest(10));
3268 let proposal_b = Proposal::new(round, 0, sample_digest(20));
3269
3270 let notarize_a = Notarize::sign(&schemes[0], NAMESPACE, proposal_a.clone()).unwrap();
3271 let notarize_b = Notarize::sign(&schemes[1], NAMESPACE, proposal_b.clone()).unwrap();
3272 let finalize_a = Finalize::sign(&schemes[0], NAMESPACE, proposal_a.clone()).unwrap();
3273 let finalize_b = Finalize::sign(&schemes[1], NAMESPACE, proposal_b.clone()).unwrap();
3274
3275 verifier.add(Voter::Notarize(notarize_a.clone()), false);
3276 verifier.add(Voter::Notarize(notarize_b.clone()), false);
3277 verifier.add(Voter::Finalize(finalize_a.clone()), false);
3278 verifier.add(Voter::Finalize(finalize_b.clone()), false);
3279
3280 assert_eq!(verifier.notarizes.len(), 2);
3281 assert_eq!(verifier.finalizes.len(), 2);
3282
3283 verifier.set_leader(notarize_a.signer());
3284
3285 assert!(verifier.notarizes_force);
3286 assert_eq!(verifier.notarizes.len(), 1);
3287 assert_eq!(verifier.notarizes[0].proposal, proposal_a);
3288 assert_eq!(verifier.finalizes.len(), 1);
3289 assert_eq!(verifier.finalizes[0].proposal, proposal_a);
3290 }
3291
3292 #[test]
3293 fn test_batch_verifier_leader_proposal_filters_messages() {
3294 batch_verifier_leader_proposal_filters_messages(generate_bls12381_threshold_schemes(
3295 3, 201,
3296 ));
3297 batch_verifier_leader_proposal_filters_messages(generate_ed25519_schemes(3, 201));
3298 }
3299
3300 fn batch_verifier_set_leader_twice_panics<S: Scheme + Clone>(schemes: Vec<S>) {
3301 let mut verifier = BatchVerifier::<S, Sha256>::new(schemes[0].clone(), Some(3));
3302 verifier.set_leader(0);
3303 verifier.set_leader(1);
3304 }
3305
3306 #[test]
3307 #[should_panic(expected = "self.leader.is_none()")]
3308 fn test_batch_verifier_set_leader_twice_panics_bls() {
3309 batch_verifier_set_leader_twice_panics(generate_bls12381_threshold_schemes(3, 212));
3310 }
3311
3312 #[test]
3313 #[should_panic(expected = "self.leader.is_none()")]
3314 fn test_batch_verifier_set_leader_twice_panics_ed() {
3315 batch_verifier_set_leader_twice_panics(generate_ed25519_schemes(3, 213));
3316 }
3317
3318 fn batch_verifier_add_recovered_message_panics<S: Scheme + Clone>(schemes: Vec<S>) {
3319 let quorum = quorum(schemes.len() as u32);
3320 let mut verifier = BatchVerifier::<S, Sha256>::new(schemes[0].clone(), Some(quorum));
3321 let notarization = create_notarization(&schemes, Round::new(0, 1), 0, 1, quorum);
3322 verifier.add(Voter::Notarization(notarization), false);
3323 }
3324
3325 #[test]
3326 #[should_panic(expected = "should not be adding recovered messages to partial verifier")]
3327 fn test_batch_verifier_add_recovered_message_panics_bls() {
3328 batch_verifier_add_recovered_message_panics(generate_bls12381_threshold_schemes(3, 213));
3329 }
3330
3331 #[test]
3332 #[should_panic(expected = "should not be adding recovered messages to partial verifier")]
3333 fn test_batch_verifier_add_recovered_message_panics_ed() {
3334 batch_verifier_add_recovered_message_panics(generate_ed25519_schemes(3, 214));
3335 }
3336
3337 fn batch_verifier_notarizes_force_flag<S: Scheme + Clone>(schemes: Vec<S>) {
3338 let quorum = quorum(schemes.len() as u32);
3339 let mut verifier = BatchVerifier::<S, Sha256>::new(schemes[0].clone(), Some(quorum));
3340 let mut rng = OsRng;
3341 let round = Round::new(0, 1);
3342 let leader_vote = create_notarize(&schemes[0], round, 0, 1);
3343
3344 verifier.set_leader(leader_vote.signer());
3345 verifier.add(Voter::Notarize(leader_vote.clone()), false);
3346
3347 assert!(
3348 verifier.notarizes_force,
3349 "notarizes_force should be true after leader's proposal is set"
3350 );
3351 assert!(verifier.ready_notarizes());
3352
3353 let (verified, _) = verifier.verify_notarizes(&mut rng, NAMESPACE);
3354 assert_eq!(verified.len(), 1);
3355 assert!(
3356 !verifier.notarizes_force,
3357 "notarizes_force should be false after verification"
3358 );
3359 assert!(!verifier.ready_notarizes());
3360 }
3361
3362 #[test]
3363 fn test_ready_notarizes_behavior_with_force_flag() {
3364 batch_verifier_notarizes_force_flag(generate_bls12381_threshold_schemes(3, 203));
3365 batch_verifier_notarizes_force_flag(generate_ed25519_schemes(3, 203));
3366 }
3367
3368 fn batch_verifier_ready_notarizes_without_leader<S: Scheme + Clone>(schemes: Vec<S>) {
3369 let quorum = quorum(schemes.len() as u32);
3370 let mut verifier = BatchVerifier::<S, Sha256>::new(schemes[0].clone(), Some(quorum));
3371 let round = Round::new(0, 1);
3372
3373 let notarizes: Vec<_> = schemes
3374 .iter()
3375 .take(quorum as usize)
3376 .map(|scheme| create_notarize(scheme, round, 0, 1))
3377 .collect();
3378
3379 for vote in notarizes.iter() {
3380 verifier.add(Voter::Notarize(vote.clone()), false);
3381 }
3382
3383 assert!(
3384 !verifier.ready_notarizes(),
3385 "Should not be ready without leader/proposal set"
3386 );
3387
3388 verifier.set_leader(notarizes[0].signer());
3389 assert!(
3390 verifier.ready_notarizes(),
3391 "Should be ready once leader is set"
3392 );
3393 }
3394
3395 #[test]
3396 fn test_ready_notarizes_without_leader_or_proposal() {
3397 batch_verifier_ready_notarizes_without_leader(generate_bls12381_threshold_schemes(3, 204));
3398 batch_verifier_ready_notarizes_without_leader(generate_ed25519_schemes(3, 204));
3399 }
3400
3401 fn batch_verifier_ready_finalizes_without_leader<S: Scheme + Clone>(schemes: Vec<S>) {
3402 let quorum = quorum(schemes.len() as u32);
3403 let mut verifier = BatchVerifier::<S, Sha256>::new(schemes[0].clone(), Some(quorum));
3404 let round = Round::new(0, 1);
3405 let finalizes: Vec<_> = schemes
3406 .iter()
3407 .take(quorum as usize)
3408 .map(|scheme| create_finalize(scheme, round, 0, 1))
3409 .collect();
3410
3411 for finalize in finalizes.iter() {
3412 verifier.add(Voter::Finalize(finalize.clone()), false);
3413 }
3414
3415 assert!(
3416 !verifier.ready_finalizes(),
3417 "Should not be ready without leader/proposal set"
3418 );
3419
3420 verifier.set_leader(finalizes[0].signer());
3421 assert!(
3422 !verifier.ready_finalizes(),
3423 "Should not be ready without leader_proposal set"
3424 );
3425 }
3426
3427 #[test]
3428 fn test_ready_finalizes_without_leader_or_proposal() {
3429 batch_verifier_ready_finalizes_without_leader(generate_bls12381_threshold_schemes(3, 205));
3430 batch_verifier_ready_finalizes_without_leader(generate_ed25519_schemes(3, 205));
3431 }
3432
3433 fn batch_verifier_verify_notarizes_empty<S: Scheme + Clone>(schemes: Vec<S>) {
3434 let quorum = quorum(schemes.len() as u32);
3435 let mut verifier = BatchVerifier::<S, Sha256>::new(schemes[0].clone(), Some(quorum));
3436 let round = Round::new(0, 1);
3437 let leader_proposal = Proposal::new(round, 0, sample_digest(1));
3438 verifier.set_leader_proposal(leader_proposal);
3439 assert!(verifier.notarizes_force);
3440 assert!(verifier.notarizes.is_empty());
3441 assert!(!verifier.ready_notarizes());
3442 }
3443
3444 #[test]
3445 fn test_verify_notarizes_empty_pending_when_forced() {
3446 batch_verifier_verify_notarizes_empty(generate_bls12381_threshold_schemes(3, 206));
3447 batch_verifier_verify_notarizes_empty(generate_ed25519_schemes(3, 206));
3448 }
3449
3450 fn batch_verifier_verify_nullifies_empty<S: Scheme + Clone>(schemes: Vec<S>) {
3451 let quorum = quorum(schemes.len() as u32);
3452 let mut verifier = BatchVerifier::<S, Sha256>::new(schemes[0].clone(), Some(quorum));
3453 let mut rng = OsRng;
3454 assert!(verifier.nullifies.is_empty());
3455 assert!(!verifier.ready_nullifies());
3456 let (verified, failed) = verifier.verify_nullifies(&mut rng, NAMESPACE);
3457 assert!(verified.is_empty());
3458 assert!(failed.is_empty());
3459 assert_eq!(verifier.nullifies_verified, 0);
3460 }
3461
3462 #[test]
3463 fn test_verify_nullifies_empty_pending() {
3464 batch_verifier_verify_nullifies_empty(generate_bls12381_threshold_schemes(3, 207));
3465 batch_verifier_verify_nullifies_empty(generate_ed25519_schemes(3, 207));
3466 }
3467
3468 fn batch_verifier_verify_finalizes_empty<S: Scheme + Clone>(schemes: Vec<S>) {
3469 let quorum = quorum(schemes.len() as u32);
3470 let mut verifier = BatchVerifier::<S, Sha256>::new(schemes[0].clone(), Some(quorum));
3471 let mut rng = OsRng;
3472 verifier.set_leader(0);
3473 assert!(verifier.finalizes.is_empty());
3474 assert!(!verifier.ready_finalizes());
3475 let (verified, failed) = verifier.verify_finalizes(&mut rng, NAMESPACE);
3476 assert!(verified.is_empty());
3477 assert!(failed.is_empty());
3478 assert_eq!(verifier.finalizes_verified, 0);
3479 }
3480
3481 #[test]
3482 fn test_verify_finalizes_empty_pending() {
3483 batch_verifier_verify_finalizes_empty(generate_bls12381_threshold_schemes(3, 208));
3484 batch_verifier_verify_finalizes_empty(generate_ed25519_schemes(3, 208));
3485 }
3486
3487 fn batch_verifier_ready_notarizes_exact_quorum<S: Scheme + Clone>(schemes: Vec<S>) {
3488 let quorum = quorum(schemes.len() as u32);
3489 let mut verifier = BatchVerifier::<S, Sha256>::new(schemes[0].clone(), Some(quorum));
3490 let mut rng = OsRng;
3491 let round = Round::new(0, 1);
3492
3493 let leader_vote = create_notarize(&schemes[0], round, 0, 1);
3494 verifier.set_leader(leader_vote.signer());
3495 verifier.add(Voter::Notarize(leader_vote.clone()), true);
3496 assert_eq!(verifier.notarizes_verified, 1);
3497
3498 let second_vote = create_notarize(&schemes[1], round, 0, 1);
3499 verifier.add(Voter::Notarize(second_vote.clone()), false);
3500 assert!(verifier.ready_notarizes());
3501 let (verified_once, failed_once) = verifier.verify_notarizes(&mut rng, NAMESPACE);
3502 assert_eq!(verified_once.len(), 1);
3503 assert!(failed_once.is_empty());
3504 assert_eq!(verifier.notarizes_verified, 2);
3505
3506 for scheme in schemes.iter().take(quorum as usize).skip(2) {
3507 assert!(!verifier.ready_notarizes());
3508 verifier.add(Voter::Notarize(create_notarize(scheme, round, 0, 1)), false);
3509 }
3510
3511 assert!(verifier.ready_notarizes());
3512 }
3513
3514 #[test]
3515 fn test_ready_notarizes_exact_quorum() {
3516 batch_verifier_ready_notarizes_exact_quorum(generate_bls12381_threshold_schemes(5, 209));
3517 batch_verifier_ready_notarizes_exact_quorum(generate_ed25519_schemes(5, 209));
3518 }
3519
3520 fn batch_verifier_ready_nullifies_exact_quorum<S: Scheme + Clone>(schemes: Vec<S>) {
3521 let quorum = quorum(schemes.len() as u32);
3522 let mut verifier = BatchVerifier::<S, Sha256>::new(schemes[0].clone(), Some(quorum));
3523 let round = Round::new(0, 1);
3524
3525 verifier.add(Voter::Nullify(create_nullify(&schemes[0], round)), true);
3526 assert_eq!(verifier.nullifies_verified, 1);
3527
3528 for scheme in schemes.iter().take(quorum as usize).skip(1) {
3529 assert!(!verifier.ready_nullifies());
3530 verifier.add(Voter::Nullify(create_nullify(scheme, round)), false);
3531 }
3532
3533 assert!(verifier.ready_nullifies());
3534 }
3535
3536 #[test]
3537 fn test_ready_nullifies_exact_quorum() {
3538 batch_verifier_ready_nullifies_exact_quorum(generate_bls12381_threshold_schemes(5, 210));
3539 batch_verifier_ready_nullifies_exact_quorum(generate_ed25519_schemes(5, 210));
3540 }
3541
3542 fn batch_verifier_ready_finalizes_exact_quorum<S: Scheme + Clone>(schemes: Vec<S>) {
3543 let quorum = quorum(schemes.len() as u32);
3544 let mut verifier = BatchVerifier::<S, Sha256>::new(schemes[0].clone(), Some(quorum));
3545 let round = Round::new(0, 1);
3546 let leader_finalize = create_finalize(&schemes[0], round, 0, 1);
3547 verifier.set_leader(leader_finalize.signer());
3548 verifier.set_leader_proposal(leader_finalize.proposal.clone());
3549 verifier.add(Voter::Finalize(leader_finalize), true);
3550 assert_eq!(verifier.finalizes_verified, 1);
3551
3552 for scheme in schemes.iter().take(quorum as usize).skip(1) {
3553 assert!(!verifier.ready_finalizes());
3554 verifier.add(Voter::Finalize(create_finalize(scheme, round, 0, 1)), false);
3555 }
3556
3557 assert!(verifier.ready_finalizes());
3558 }
3559
3560 #[test]
3561 fn test_ready_finalizes_exact_quorum() {
3562 batch_verifier_ready_finalizes_exact_quorum(generate_bls12381_threshold_schemes(5, 211));
3563 batch_verifier_ready_finalizes_exact_quorum(generate_ed25519_schemes(5, 211));
3564 }
3565
3566 fn batch_verifier_ready_notarizes_quorum_already_met_by_verified<S: Scheme + Clone>(
3567 schemes: Vec<S>,
3568 ) {
3569 let quorum = quorum(schemes.len() as u32);
3570 assert!(
3571 schemes.len() > quorum as usize,
3572 "test requires more validators than the quorum"
3573 );
3574 let mut verifier = BatchVerifier::<S, Sha256>::new(schemes[0].clone(), Some(quorum));
3575 let round = Round::new(0, 1);
3576
3577 let leader_vote = create_notarize(&schemes[0], round, 0, 1);
3579 verifier.set_leader(leader_vote.signer());
3580 verifier.add(Voter::Notarize(leader_vote.clone()), false);
3581 verifier.notarizes_force = false;
3582
3583 for scheme in schemes.iter().take(quorum as usize) {
3585 verifier.add(Voter::Notarize(create_notarize(scheme, round, 0, 1)), true);
3586 }
3587 assert_eq!(verifier.notarizes_verified, quorum as usize);
3588 assert!(
3589 !verifier.ready_notarizes(),
3590 "Should not be ready if quorum already met by verified messages"
3591 );
3592
3593 let extra_vote = create_notarize(&schemes[quorum as usize], round, 0, 1);
3595 verifier.add(Voter::Notarize(extra_vote), false);
3596 assert!(
3597 !verifier.ready_notarizes(),
3598 "Should not be ready if quorum already met by verified messages"
3599 );
3600 }
3601
3602 #[test]
3603 fn test_ready_notarizes_quorum_already_met_by_verified() {
3604 batch_verifier_ready_notarizes_quorum_already_met_by_verified(
3605 generate_bls12381_threshold_schemes(5, 212),
3606 );
3607 batch_verifier_ready_notarizes_quorum_already_met_by_verified(generate_ed25519_schemes(
3608 5, 212,
3609 ));
3610 }
3611
3612 fn batch_verifier_ready_nullifies_quorum_already_met_by_verified<S: Scheme + Clone>(
3613 schemes: Vec<S>,
3614 ) {
3615 let quorum = quorum(schemes.len() as u32);
3616 assert!(
3617 schemes.len() > quorum as usize,
3618 "test requires more validators than the quorum"
3619 );
3620 let mut verifier = BatchVerifier::<S, Sha256>::new(schemes[0].clone(), Some(quorum));
3621 let round = Round::new(0, 1);
3622
3623 for scheme in schemes.iter().take(quorum as usize) {
3625 verifier.add(Voter::Nullify(create_nullify(scheme, round)), true);
3626 }
3627 assert_eq!(verifier.nullifies_verified, quorum as usize);
3628 assert!(
3629 !verifier.ready_nullifies(),
3630 "Should not be ready if quorum already met by verified messages"
3631 );
3632
3633 let extra_nullify = create_nullify(&schemes[quorum as usize], round);
3635 verifier.add(Voter::Nullify(extra_nullify), false);
3636 assert!(
3637 !verifier.ready_nullifies(),
3638 "Should not be ready if quorum already met by verified messages"
3639 );
3640 }
3641
3642 #[test]
3643 fn test_ready_nullifies_quorum_already_met_by_verified() {
3644 batch_verifier_ready_nullifies_quorum_already_met_by_verified(
3645 generate_bls12381_threshold_schemes(5, 213),
3646 );
3647 batch_verifier_ready_nullifies_quorum_already_met_by_verified(generate_ed25519_schemes(
3648 5, 213,
3649 ));
3650 }
3651
3652 fn batch_verifier_ready_finalizes_quorum_already_met_by_verified<S: Scheme + Clone>(
3653 schemes: Vec<S>,
3654 ) {
3655 let quorum = quorum(schemes.len() as u32);
3656 assert!(
3657 schemes.len() > quorum as usize,
3658 "test requires more validators than the quorum"
3659 );
3660 let mut verifier = BatchVerifier::<S, Sha256>::new(schemes[0].clone(), Some(quorum));
3661 let round = Round::new(0, 1);
3662
3663 let leader_finalize = create_finalize(&schemes[0], round, 0, 1);
3665 verifier.set_leader(leader_finalize.signer());
3666 verifier.set_leader_proposal(leader_finalize.proposal.clone());
3667
3668 for scheme in schemes.iter().take(quorum as usize) {
3670 verifier.add(Voter::Finalize(create_finalize(scheme, round, 0, 1)), true);
3671 }
3672 assert_eq!(verifier.finalizes_verified, quorum as usize);
3673 assert!(
3674 !verifier.ready_finalizes(),
3675 "Should not be ready if quorum already met by verified messages"
3676 );
3677
3678 let extra_finalize = create_finalize(&schemes[quorum as usize], round, 0, 1);
3680 verifier.add(Voter::Finalize(extra_finalize), false);
3681 assert!(
3682 !verifier.ready_finalizes(),
3683 "Should not be ready if quorum already met by verified messages"
3684 );
3685 }
3686
3687 #[test]
3688 fn test_ready_finalizes_quorum_already_met_by_verified() {
3689 batch_verifier_ready_finalizes_quorum_already_met_by_verified(
3690 generate_bls12381_threshold_schemes(5, 214),
3691 );
3692 batch_verifier_ready_finalizes_quorum_already_met_by_verified(generate_ed25519_schemes(
3693 5, 214,
3694 ));
3695 }
3696
3697 struct MockAttributable(u32);
3698
3699 impl Attributable for MockAttributable {
3700 fn signer(&self) -> u32 {
3701 self.0
3702 }
3703 }
3704
3705 #[test]
3706 fn test_attributable_vec() {
3707 let mut vec = AttributableVec::new(5);
3708 assert_eq!(vec.len(), 0);
3709 assert!(vec.is_empty());
3710
3711 assert!(vec.push(MockAttributable(3)));
3712 assert_eq!(vec.len(), 1);
3713 assert!(!vec.is_empty());
3714 let mut iter = vec.iter();
3715 assert!(matches!(iter.next(), Some(a) if a.signer() == 3));
3716 assert!(iter.next().is_none());
3717 drop(iter);
3718
3719 assert!(vec.push(MockAttributable(1)));
3720 assert_eq!(vec.len(), 2);
3721 assert!(!vec.is_empty());
3722 let mut iter = vec.iter();
3723 assert!(matches!(iter.next(), Some(a) if a.signer() == 1));
3724 assert!(matches!(iter.next(), Some(a) if a.signer() == 3));
3725 assert!(iter.next().is_none());
3726 drop(iter);
3727
3728 assert!(!vec.push(MockAttributable(3)));
3729 assert_eq!(vec.len(), 2);
3730 assert!(!vec.is_empty());
3731 let mut iter = vec.iter();
3732 assert!(matches!(iter.next(), Some(a) if a.signer() == 1));
3733 assert!(matches!(iter.next(), Some(a) if a.signer() == 3));
3734 assert!(iter.next().is_none());
3735 drop(iter);
3736 }
3737}