1use crate::Viewable;
4use bytes::{Buf, BufMut};
5use commonware_codec::{
6 varint::UInt, Encode, EncodeSize, Error, Read, ReadExt, ReadRangeExt, Write,
7};
8use commonware_cryptography::{
9 bls12381::primitives::{
10 group::Share,
11 ops::{
12 aggregate_signatures, aggregate_verify_multiple_messages, partial_sign_message,
13 partial_verify_multiple_public_keys_precomputed, verify_message,
14 },
15 poly::PartialSignature,
16 variant::Variant,
17 },
18 Digest,
19};
20use commonware_utils::union;
21use std::{
22 collections::{BTreeSet, HashMap, HashSet},
23 hash::Hash,
24};
25
26pub type View = u64;
30
31#[derive(Clone)]
34pub struct Context<D: Digest> {
35 pub view: View,
37
38 pub parent: (View, D),
45}
46
47pub trait Attributable {
50 fn signer(&self) -> u32;
52}
53
54pub trait Seedable<V: Variant> {
56 fn seed(&self) -> Seed<V>;
58}
59
60pub const SEED_SUFFIX: &[u8] = b"_SEED";
63pub const NOTARIZE_SUFFIX: &[u8] = b"_NOTARIZE";
64pub const NULLIFY_SUFFIX: &[u8] = b"_NULLIFY";
65pub const FINALIZE_SUFFIX: &[u8] = b"_FINALIZE";
66
67#[inline]
69pub fn view_message(view: View) -> Vec<u8> {
70 View::encode(&view).into()
71}
72
73#[inline]
76pub fn seed_namespace(namespace: &[u8]) -> Vec<u8> {
77 union(namespace, SEED_SUFFIX)
78}
79
80#[inline]
83pub fn notarize_namespace(namespace: &[u8]) -> Vec<u8> {
84 union(namespace, NOTARIZE_SUFFIX)
85}
86
87#[inline]
90pub fn nullify_namespace(namespace: &[u8]) -> Vec<u8> {
91 union(namespace, NULLIFY_SUFFIX)
92}
93
94#[inline]
97pub fn finalize_namespace(namespace: &[u8]) -> Vec<u8> {
98 union(namespace, FINALIZE_SUFFIX)
99}
100
101pub struct BatchVerifier<V: Variant, D: Digest> {
111 quorum: Option<usize>,
112
113 leader: Option<u32>,
114 leader_proposal: Option<Proposal<D>>,
115
116 notarizes: Vec<Notarize<V, D>>,
117 notarizes_force: bool,
118 notarizes_verified: usize,
119
120 nullifies: Vec<Nullify<V>>,
121 nullifies_verified: usize,
122
123 finalizes: Vec<Finalize<V, D>>,
124 finalizes_verified: usize,
125}
126
127impl<V: Variant, D: Digest> BatchVerifier<V, D> {
128 pub fn new(quorum: Option<u32>) -> Self {
136 Self {
137 quorum: quorum.map(|q| q as usize),
138
139 leader: None,
140 leader_proposal: None,
141
142 notarizes: Vec::new(),
143 notarizes_force: false,
144 notarizes_verified: 0,
145
146 nullifies: Vec::new(),
147 nullifies_verified: 0,
148
149 finalizes: Vec::new(),
150 finalizes_verified: 0,
151 }
152 }
153
154 fn set_leader_proposal(&mut self, proposal: Proposal<D>) {
160 self.notarizes.retain(|n| n.proposal == proposal);
162 self.finalizes.retain(|f| f.proposal == proposal);
163
164 self.leader_proposal = Some(proposal);
166
167 self.notarizes_force = true;
169 }
170
171 pub fn add(&mut self, msg: Voter<V, D>, verified: bool) {
188 match msg {
189 Voter::Notarize(notarize) => {
190 if let Some(ref leader_proposal) = self.leader_proposal {
191 if leader_proposal != ¬arize.proposal {
193 return;
194 }
195 } else if let Some(leader) = self.leader {
196 if leader == notarize.signer() {
198 self.set_leader_proposal(notarize.proposal.clone());
200 }
201 }
202
203 if verified {
205 self.notarizes_verified += 1;
206 } else {
207 self.notarizes.push(notarize);
208 }
209 }
210 Voter::Nullify(nullify) => {
211 if verified {
212 self.nullifies_verified += 1;
213 } else {
214 self.nullifies.push(nullify);
215 }
216 }
217 Voter::Finalize(finalize) => {
218 if let Some(ref leader_proposal) = self.leader_proposal {
220 if leader_proposal != &finalize.proposal {
221 return;
222 }
223 }
224
225 if verified {
227 self.finalizes_verified += 1;
228 } else {
229 self.finalizes.push(finalize);
230 }
231 }
232 Voter::Notarization(_) | Voter::Nullification(_) | Voter::Finalization(_) => {
233 unreachable!("should not be adding recovered messages to partial verifier");
234 }
235 }
236 }
237
238 pub fn set_leader(&mut self, leader: u32) {
248 assert!(self.leader.is_none());
250 self.leader = Some(leader);
251
252 let Some(notarize) = self.notarizes.iter().find(|n| n.signer() == leader) else {
254 return;
255 };
256
257 self.set_leader_proposal(notarize.proposal.clone());
259 }
260
261 pub fn verify_notarizes(
277 &mut self,
278 namespace: &[u8],
279 polynomial: &[V::Public],
280 ) -> (Vec<Voter<V, D>>, Vec<u32>) {
281 self.notarizes_force = false;
282 let (notarizes, failed) =
283 Notarize::verify_multiple(namespace, polynomial, std::mem::take(&mut self.notarizes));
284 self.notarizes_verified += notarizes.len();
285 (notarizes.into_iter().map(Voter::Notarize).collect(), failed)
286 }
287
288 pub fn ready_notarizes(&self) -> bool {
301 if self.notarizes.is_empty() {
303 return false;
304 }
305
306 if self.notarizes_force {
309 return true;
310 }
311
312 if self.leader.is_none() || self.leader_proposal.is_none() {
315 return false;
316 }
317
318 if let Some(quorum) = self.quorum {
320 if self.notarizes_verified >= quorum {
323 return false;
324 }
325
326 if self.notarizes_verified + self.notarizes.len() < quorum {
328 return false;
329 }
330 }
331
332 true
334 }
335
336 pub fn verify_nullifies(
352 &mut self,
353 namespace: &[u8],
354 polynomial: &[V::Public],
355 ) -> (Vec<Voter<V, D>>, Vec<u32>) {
356 let (nullifies, failed) =
357 Nullify::verify_multiple(namespace, polynomial, std::mem::take(&mut self.nullifies));
358 self.nullifies_verified += nullifies.len();
359 (nullifies.into_iter().map(Voter::Nullify).collect(), failed)
360 }
361
362 pub fn ready_nullifies(&self) -> bool {
373 if self.nullifies.is_empty() {
375 return false;
376 }
377
378 if let Some(quorum) = self.quorum {
379 if self.nullifies_verified >= quorum {
382 return false;
383 }
384
385 if self.nullifies_verified + self.nullifies.len() < quorum {
387 return false;
388 }
389 }
390
391 true
393 }
394
395 pub fn verify_finalizes(
411 &mut self,
412 namespace: &[u8],
413 polynomial: &[V::Public],
414 ) -> (Vec<Voter<V, D>>, Vec<u32>) {
415 let (finalizes, failed) =
416 Finalize::verify_multiple(namespace, polynomial, std::mem::take(&mut self.finalizes));
417 self.finalizes_verified += finalizes.len();
418 (finalizes.into_iter().map(Voter::Finalize).collect(), failed)
419 }
420
421 pub fn ready_finalizes(&self) -> bool {
433 if self.finalizes.is_empty() {
435 return false;
436 }
437
438 if self.leader.is_none() || self.leader_proposal.is_none() {
441 return false;
442 }
443 if let Some(quorum) = self.quorum {
444 if self.finalizes_verified >= quorum {
447 return false;
448 }
449
450 if self.finalizes_verified + self.finalizes.len() < quorum {
452 return false;
453 }
454 }
455
456 true
458 }
459}
460
461#[derive(Clone, Debug, PartialEq)]
464pub enum Voter<V: Variant, D: Digest> {
465 Notarize(Notarize<V, D>),
467 Notarization(Notarization<V, D>),
469 Nullify(Nullify<V>),
471 Nullification(Nullification<V>),
473 Finalize(Finalize<V, D>),
475 Finalization(Finalization<V, D>),
477}
478
479impl<V: Variant, D: Digest> Write for Voter<V, D> {
480 fn write(&self, writer: &mut impl BufMut) {
481 match self {
482 Voter::Notarize(v) => {
483 0u8.write(writer);
484 v.write(writer);
485 }
486 Voter::Notarization(v) => {
487 1u8.write(writer);
488 v.write(writer);
489 }
490 Voter::Nullify(v) => {
491 2u8.write(writer);
492 v.write(writer);
493 }
494 Voter::Nullification(v) => {
495 3u8.write(writer);
496 v.write(writer);
497 }
498 Voter::Finalize(v) => {
499 4u8.write(writer);
500 v.write(writer);
501 }
502 Voter::Finalization(v) => {
503 5u8.write(writer);
504 v.write(writer);
505 }
506 }
507 }
508}
509
510impl<V: Variant, D: Digest> EncodeSize for Voter<V, D> {
511 fn encode_size(&self) -> usize {
512 1 + match self {
513 Voter::Notarize(v) => v.encode_size(),
514 Voter::Notarization(v) => v.encode_size(),
515 Voter::Nullify(v) => v.encode_size(),
516 Voter::Nullification(v) => v.encode_size(),
517 Voter::Finalize(v) => v.encode_size(),
518 Voter::Finalization(v) => v.encode_size(),
519 }
520 }
521}
522
523impl<V: Variant, D: Digest> Read for Voter<V, D> {
524 type Cfg = ();
525
526 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
527 let tag = <u8>::read(reader)?;
528 match tag {
529 0 => {
530 let v = Notarize::read(reader)?;
531 Ok(Voter::Notarize(v))
532 }
533 1 => {
534 let v = Notarization::read(reader)?;
535 Ok(Voter::Notarization(v))
536 }
537 2 => {
538 let v = Nullify::read(reader)?;
539 Ok(Voter::Nullify(v))
540 }
541 3 => {
542 let v = Nullification::read(reader)?;
543 Ok(Voter::Nullification(v))
544 }
545 4 => {
546 let v = Finalize::read(reader)?;
547 Ok(Voter::Finalize(v))
548 }
549 5 => {
550 let v = Finalization::read(reader)?;
551 Ok(Voter::Finalization(v))
552 }
553 _ => Err(Error::Invalid(
554 "consensus::threshold_simplex::Voter",
555 "Invalid type",
556 )),
557 }
558 }
559}
560
561impl<V: Variant, D: Digest> Viewable for Voter<V, D> {
562 type View = View;
563
564 fn view(&self) -> View {
565 match self {
566 Voter::Notarize(v) => v.view(),
567 Voter::Notarization(v) => v.view(),
568 Voter::Nullify(v) => v.view(),
569 Voter::Nullification(v) => v.view(),
570 Voter::Finalize(v) => v.view(),
571 Voter::Finalization(v) => v.view(),
572 }
573 }
574}
575
576#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
579pub struct Proposal<D: Digest> {
580 pub view: View,
582 pub parent: View,
584 pub payload: D,
586}
587
588impl<D: Digest> Proposal<D> {
589 pub fn new(view: View, parent: View, payload: D) -> Self {
591 Proposal {
592 view,
593 parent,
594 payload,
595 }
596 }
597}
598
599impl<D: Digest> Write for Proposal<D> {
600 fn write(&self, writer: &mut impl BufMut) {
601 UInt(self.view).write(writer);
602 UInt(self.parent).write(writer);
603 self.payload.write(writer)
604 }
605}
606
607impl<D: Digest> Read for Proposal<D> {
608 type Cfg = ();
609
610 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
611 let view = UInt::read(reader)?.into();
612 let parent = UInt::read(reader)?.into();
613 let payload = D::read(reader)?;
614 Ok(Self {
615 view,
616 parent,
617 payload,
618 })
619 }
620}
621
622impl<D: Digest> EncodeSize for Proposal<D> {
623 fn encode_size(&self) -> usize {
624 UInt(self.view).encode_size() + UInt(self.parent).encode_size() + self.payload.encode_size()
625 }
626}
627
628impl<D: Digest> Viewable for Proposal<D> {
629 type View = View;
630
631 fn view(&self) -> View {
632 self.view
633 }
634}
635
636#[derive(Clone, Debug, PartialEq, Hash, Eq)]
640pub struct Notarize<V: Variant, D: Digest> {
641 pub proposal: Proposal<D>,
643 pub proposal_signature: PartialSignature<V>,
645 pub seed_signature: PartialSignature<V>,
647}
648
649impl<V: Variant, D: Digest> Notarize<V, D> {
650 pub fn new(
652 proposal: Proposal<D>,
653 proposal_signature: PartialSignature<V>,
654 seed_signature: PartialSignature<V>,
655 ) -> Self {
656 Notarize {
657 proposal,
658 proposal_signature,
659 seed_signature,
660 }
661 }
662
663 pub fn verify(&self, namespace: &[u8], polynomial: &[V::Public]) -> bool {
670 let notarize_namespace = notarize_namespace(namespace);
671 let notarize_message = self.proposal.encode();
672 let notarize_message = (Some(notarize_namespace.as_ref()), notarize_message.as_ref());
673 let seed_namespace = seed_namespace(namespace);
674 let seed_message = view_message(self.proposal.view);
675 let seed_message = (Some(seed_namespace.as_ref()), seed_message.as_ref());
676 let Some(evaluated) = polynomial.get(self.signer() as usize) else {
677 return false;
678 };
679 let signature = aggregate_signatures::<V, _>(&[
680 self.proposal_signature.value,
681 self.seed_signature.value,
682 ]);
683 aggregate_verify_multiple_messages::<V, _>(
684 evaluated,
685 &[notarize_message, seed_message],
686 &signature,
687 1,
688 )
689 .is_ok()
690 }
691
692 pub fn verify_multiple(
699 namespace: &[u8],
700 polynomial: &[V::Public],
701 notarizes: Vec<Notarize<V, D>>,
702 ) -> (Vec<Notarize<V, D>>, Vec<u32>) {
703 if notarizes.is_empty() {
705 return (notarizes, vec![]);
706 } else if notarizes.len() == 1 {
707 let valid = notarizes[0].verify(namespace, polynomial);
710 if valid {
711 return (notarizes, vec![]);
712 } else {
713 return (vec![], vec![notarizes[0].signer()]);
714 }
715 }
716 let proposal = ¬arizes[0].proposal;
717 let mut invalid = BTreeSet::new();
718
719 let notarize_namespace = notarize_namespace(namespace);
721 let notarize_message = proposal.encode();
722 let notarize_signatures = notarizes.iter().map(|n| &n.proposal_signature);
723 if let Err(err) = partial_verify_multiple_public_keys_precomputed::<V, _>(
724 polynomial,
725 Some(¬arize_namespace),
726 ¬arize_message,
727 notarize_signatures,
728 ) {
729 for signature in err.iter() {
730 invalid.insert(signature.index);
731 }
732 }
733
734 let seed_namespace = seed_namespace(namespace);
736 let seed_message = view_message(proposal.view);
737 let seed_signatures = notarizes
738 .iter()
739 .filter(|n| !invalid.contains(&n.seed_signature.index))
740 .map(|n| &n.seed_signature);
741 if let Err(err) = partial_verify_multiple_public_keys_precomputed::<V, _>(
742 polynomial,
743 Some(&seed_namespace),
744 &seed_message,
745 seed_signatures,
746 ) {
747 for signature in err.iter() {
748 invalid.insert(signature.index);
749 }
750 }
751
752 (
754 notarizes
755 .into_iter()
756 .filter(|n| !invalid.contains(&n.signer()))
757 .collect(),
758 invalid.into_iter().collect(),
759 )
760 }
761
762 pub fn sign(namespace: &[u8], share: &Share, proposal: Proposal<D>) -> Self {
764 let notarize_namespace = notarize_namespace(namespace);
765 let proposal_message = proposal.encode();
766 let proposal_signature =
767 partial_sign_message::<V>(share, Some(notarize_namespace.as_ref()), &proposal_message);
768 let seed_namespace = seed_namespace(namespace);
769 let seed_message = view_message(proposal.view);
770 let seed_signature =
771 partial_sign_message::<V>(share, Some(seed_namespace.as_ref()), &seed_message);
772 Notarize::new(proposal, proposal_signature, seed_signature)
773 }
774}
775
776impl<V: Variant, D: Digest> Attributable for Notarize<V, D> {
777 fn signer(&self) -> u32 {
778 self.proposal_signature.index
779 }
780}
781
782impl<V: Variant, D: Digest> Viewable for Notarize<V, D> {
783 type View = View;
784
785 fn view(&self) -> View {
786 self.proposal.view()
787 }
788}
789
790impl<V: Variant, D: Digest> Write for Notarize<V, D> {
791 fn write(&self, writer: &mut impl BufMut) {
792 self.proposal.write(writer);
793 self.proposal_signature.write(writer);
794 self.seed_signature.write(writer);
795 }
796}
797
798impl<V: Variant, D: Digest> Read for Notarize<V, D> {
799 type Cfg = ();
800
801 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
802 let proposal = Proposal::read(reader)?;
803 let proposal_signature = PartialSignature::<V>::read(reader)?;
804 let seed_signature = PartialSignature::<V>::read(reader)?;
805 if proposal_signature.index != seed_signature.index {
806 return Err(Error::Invalid(
807 "consensus::threshold_simplex::Notarize",
808 "mismatched signatures",
809 ));
810 }
811 Ok(Notarize {
812 proposal,
813 proposal_signature,
814 seed_signature,
815 })
816 }
817}
818
819impl<V: Variant, D: Digest> EncodeSize for Notarize<V, D> {
820 fn encode_size(&self) -> usize {
821 self.proposal.encode_size()
822 + self.proposal_signature.encode_size()
823 + self.seed_signature.encode_size()
824 }
825}
826
827#[derive(Clone, Debug, PartialEq, Hash, Eq)]
831pub struct Notarization<V: Variant, D: Digest> {
832 pub proposal: Proposal<D>,
834 pub proposal_signature: V::Signature,
836 pub seed_signature: V::Signature,
838}
839
840impl<V: Variant, D: Digest> Notarization<V, D> {
841 pub fn new(
843 proposal: Proposal<D>,
844 proposal_signature: V::Signature,
845 seed_signature: V::Signature,
846 ) -> Self {
847 Notarization {
848 proposal,
849 proposal_signature,
850 seed_signature,
851 }
852 }
853
854 pub fn verify(&self, namespace: &[u8], identity: &V::Public) -> bool {
860 let notarize_namespace = notarize_namespace(namespace);
861 let notarize_message = self.proposal.encode();
862 let notarize_message = (Some(notarize_namespace.as_ref()), notarize_message.as_ref());
863 let seed_namespace = seed_namespace(namespace);
864 let seed_message = view_message(self.proposal.view);
865 let seed_message = (Some(seed_namespace.as_ref()), seed_message.as_ref());
866 let signature =
867 aggregate_signatures::<V, _>(&[self.proposal_signature, self.seed_signature]);
868 aggregate_verify_multiple_messages::<V, _>(
869 identity,
870 &[notarize_message, seed_message],
871 &signature,
872 1,
873 )
874 .is_ok()
875 }
876}
877
878impl<V: Variant, D: Digest> Viewable for Notarization<V, D> {
879 type View = View;
880
881 fn view(&self) -> View {
882 self.proposal.view()
883 }
884}
885
886impl<V: Variant, D: Digest> Write for Notarization<V, D> {
887 fn write(&self, writer: &mut impl BufMut) {
888 self.proposal.write(writer);
889 self.proposal_signature.write(writer);
890 self.seed_signature.write(writer)
891 }
892}
893
894impl<V: Variant, D: Digest> Read for Notarization<V, D> {
895 type Cfg = ();
896
897 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
898 let proposal = Proposal::read(reader)?;
899 let proposal_signature = V::Signature::read(reader)?;
900 let seed_signature = V::Signature::read(reader)?;
901 Ok(Notarization {
902 proposal,
903 proposal_signature,
904 seed_signature,
905 })
906 }
907}
908
909impl<V: Variant, D: Digest> EncodeSize for Notarization<V, D> {
910 fn encode_size(&self) -> usize {
911 self.proposal.encode_size()
912 + self.proposal_signature.encode_size()
913 + self.seed_signature.encode_size()
914 }
915}
916
917impl<V: Variant, D: Digest> Seedable<V> for Notarization<V, D> {
918 fn seed(&self) -> Seed<V> {
919 Seed::new(self.view(), self.seed_signature)
920 }
921}
922
923#[derive(Clone, Debug, PartialEq, Hash, Eq)]
927pub struct Nullify<V: Variant> {
928 pub view: View,
930 pub view_signature: PartialSignature<V>,
932 pub seed_signature: PartialSignature<V>,
934}
935
936impl<V: Variant> Nullify<V> {
937 pub fn new(
939 view: View,
940 view_signature: PartialSignature<V>,
941 seed_signature: PartialSignature<V>,
942 ) -> Self {
943 Nullify {
944 view,
945 view_signature,
946 seed_signature,
947 }
948 }
949
950 pub fn verify(&self, namespace: &[u8], polynomial: &[V::Public]) -> bool {
957 let nullify_namespace = nullify_namespace(namespace);
958 let view_message = view_message(self.view);
959 let nullify_message = (Some(nullify_namespace.as_ref()), view_message.as_ref());
960 let seed_namespace = seed_namespace(namespace);
961 let seed_message = (Some(seed_namespace.as_ref()), view_message.as_ref());
962 let Some(evaluated) = polynomial.get(self.signer() as usize) else {
963 return false;
964 };
965 let signature =
966 aggregate_signatures::<V, _>(&[self.view_signature.value, self.seed_signature.value]);
967 aggregate_verify_multiple_messages::<V, _>(
968 evaluated,
969 &[nullify_message, seed_message],
970 &signature,
971 1,
972 )
973 .is_ok()
974 }
975
976 pub fn verify_multiple(
983 namespace: &[u8],
984 polynomial: &[V::Public],
985 nullifies: Vec<Nullify<V>>,
986 ) -> (Vec<Nullify<V>>, Vec<u32>) {
987 if nullifies.is_empty() {
989 return (nullifies, vec![]);
990 } else if nullifies.len() == 1 {
991 let valid = nullifies[0].verify(namespace, polynomial);
992 if valid {
993 return (nullifies, vec![]);
994 } else {
995 return (vec![], vec![nullifies[0].signer()]);
996 }
997 }
998 let selected = &nullifies[0];
999 let mut invalid = BTreeSet::new();
1000
1001 let nullify_namespace = nullify_namespace(namespace);
1003 let view_message = view_message(selected.view);
1004 let view_signatures = nullifies.iter().map(|n| &n.view_signature);
1005 if let Err(err) = partial_verify_multiple_public_keys_precomputed::<V, _>(
1006 polynomial,
1007 Some(&nullify_namespace),
1008 &view_message,
1009 view_signatures,
1010 ) {
1011 for signature in err.iter() {
1012 invalid.insert(signature.index);
1013 }
1014 }
1015
1016 let seed_namespace = seed_namespace(namespace);
1018 let seed_signatures = nullifies
1019 .iter()
1020 .filter(|n| !invalid.contains(&n.seed_signature.index))
1021 .map(|n| &n.seed_signature);
1022 if let Err(err) = partial_verify_multiple_public_keys_precomputed::<V, _>(
1023 polynomial,
1024 Some(&seed_namespace),
1025 &view_message,
1026 seed_signatures,
1027 ) {
1028 for signature in err.iter() {
1029 invalid.insert(signature.index);
1030 }
1031 }
1032
1033 (
1035 nullifies
1036 .into_iter()
1037 .filter(|n| !invalid.contains(&n.signer()))
1038 .collect(),
1039 invalid.into_iter().collect(),
1040 )
1041 }
1042
1043 pub fn sign(namespace: &[u8], share: &Share, view: View) -> Self {
1045 let nullify_namespace = nullify_namespace(namespace);
1046 let view_message = view_message(view);
1047 let view_signature =
1048 partial_sign_message::<V>(share, Some(nullify_namespace.as_ref()), &view_message);
1049 let seed_namespace = seed_namespace(namespace);
1050 let seed_signature =
1051 partial_sign_message::<V>(share, Some(seed_namespace.as_ref()), &view_message);
1052 Nullify::new(view, view_signature, seed_signature)
1053 }
1054}
1055
1056impl<V: Variant> Attributable for Nullify<V> {
1057 fn signer(&self) -> u32 {
1058 self.view_signature.index
1059 }
1060}
1061
1062impl<V: Variant> Viewable for Nullify<V> {
1063 type View = View;
1064
1065 fn view(&self) -> View {
1066 self.view
1067 }
1068}
1069
1070impl<V: Variant> Write for Nullify<V> {
1071 fn write(&self, writer: &mut impl BufMut) {
1072 UInt(self.view).write(writer);
1073 self.view_signature.write(writer);
1074 self.seed_signature.write(writer);
1075 }
1076}
1077
1078impl<V: Variant> Read for Nullify<V> {
1079 type Cfg = ();
1080
1081 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
1082 let view = UInt::read(reader)?.into();
1083 let view_signature = PartialSignature::<V>::read(reader)?;
1084 let seed_signature = PartialSignature::<V>::read(reader)?;
1085 if view_signature.index != seed_signature.index {
1086 return Err(Error::Invalid(
1087 "consensus::threshold_simplex::Nullify",
1088 "mismatched signatures",
1089 ));
1090 }
1091 Ok(Nullify {
1092 view,
1093 view_signature,
1094 seed_signature,
1095 })
1096 }
1097}
1098
1099impl<V: Variant> EncodeSize for Nullify<V> {
1100 fn encode_size(&self) -> usize {
1101 UInt(self.view).encode_size()
1102 + self.view_signature.encode_size()
1103 + self.seed_signature.encode_size()
1104 }
1105}
1106
1107#[derive(Clone, Debug, PartialEq, Hash, Eq)]
1111pub struct Nullification<V: Variant> {
1112 pub view: View,
1114 pub view_signature: V::Signature,
1116 pub seed_signature: V::Signature,
1118}
1119
1120impl<V: Variant> Nullification<V> {
1121 pub fn new(view: View, view_signature: V::Signature, seed_signature: V::Signature) -> Self {
1123 Nullification {
1124 view,
1125 view_signature,
1126 seed_signature,
1127 }
1128 }
1129
1130 pub fn verify(&self, namespace: &[u8], identity: &V::Public) -> bool {
1136 let nullify_namespace = nullify_namespace(namespace);
1137 let view_message = view_message(self.view);
1138 let nullify_message = (Some(nullify_namespace.as_ref()), view_message.as_ref());
1139 let seed_namespace = seed_namespace(namespace);
1140 let seed_message = (Some(seed_namespace.as_ref()), view_message.as_ref());
1141 let signature = aggregate_signatures::<V, _>(&[self.view_signature, self.seed_signature]);
1142 aggregate_verify_multiple_messages::<V, _>(
1143 identity,
1144 &[nullify_message, seed_message],
1145 &signature,
1146 1,
1147 )
1148 .is_ok()
1149 }
1150}
1151
1152impl<V: Variant> Viewable for Nullification<V> {
1153 type View = View;
1154
1155 fn view(&self) -> View {
1156 self.view
1157 }
1158}
1159
1160impl<V: Variant> Write for Nullification<V> {
1161 fn write(&self, writer: &mut impl BufMut) {
1162 UInt(self.view).write(writer);
1163 self.view_signature.write(writer);
1164 self.seed_signature.write(writer);
1165 }
1166}
1167
1168impl<V: Variant> Read for Nullification<V> {
1169 type Cfg = ();
1170
1171 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
1172 let view = UInt::read(reader)?.into();
1173 let view_signature = V::Signature::read(reader)?;
1174 let seed_signature = V::Signature::read(reader)?;
1175 Ok(Nullification {
1176 view,
1177 view_signature,
1178 seed_signature,
1179 })
1180 }
1181}
1182
1183impl<V: Variant> EncodeSize for Nullification<V> {
1184 fn encode_size(&self) -> usize {
1185 UInt(self.view).encode_size()
1186 + self.view_signature.encode_size()
1187 + self.seed_signature.encode_size()
1188 }
1189}
1190
1191impl<V: Variant> Seedable<V> for Nullification<V> {
1192 fn seed(&self) -> Seed<V> {
1193 Seed::new(self.view(), self.seed_signature)
1194 }
1195}
1196
1197#[derive(Clone, Debug, PartialEq, Hash, Eq)]
1201pub struct Finalize<V: Variant, D: Digest> {
1202 pub proposal: Proposal<D>,
1204 pub proposal_signature: PartialSignature<V>,
1206}
1207
1208impl<V: Variant, D: Digest> Finalize<V, D> {
1209 pub fn new(proposal: Proposal<D>, proposal_signature: PartialSignature<V>) -> Self {
1211 Finalize {
1212 proposal,
1213 proposal_signature,
1214 }
1215 }
1216
1217 pub fn verify(&self, namespace: &[u8], polynomial: &[V::Public]) -> bool {
1221 let finalize_namespace = finalize_namespace(namespace);
1222 let message = self.proposal.encode();
1223 let Some(evaluated) = polynomial.get(self.signer() as usize) else {
1224 return false;
1225 };
1226 verify_message::<V>(
1227 evaluated,
1228 Some(finalize_namespace.as_ref()),
1229 &message,
1230 &self.proposal_signature.value,
1231 )
1232 .is_ok()
1233 }
1234
1235 pub fn verify_multiple(
1242 namespace: &[u8],
1243 polynomial: &[V::Public],
1244 finalizes: Vec<Finalize<V, D>>,
1245 ) -> (Vec<Finalize<V, D>>, Vec<u32>) {
1246 if finalizes.is_empty() {
1248 return (finalizes, vec![]);
1249 } else if finalizes.len() == 1 {
1250 let valid = finalizes[0].verify(namespace, polynomial);
1251 if valid {
1252 return (finalizes, vec![]);
1253 } else {
1254 return (vec![], vec![finalizes[0].signer()]);
1255 }
1256 }
1257 let proposal = &finalizes[0].proposal;
1258 let mut invalid = BTreeSet::new();
1259
1260 let finalize_namespace = finalize_namespace(namespace);
1262 let finalize_message = proposal.encode();
1263 let finalize_signatures = finalizes.iter().map(|f| &f.proposal_signature);
1264 if let Err(err) = partial_verify_multiple_public_keys_precomputed::<V, _>(
1265 polynomial,
1266 Some(&finalize_namespace),
1267 &finalize_message,
1268 finalize_signatures,
1269 ) {
1270 for signature in err.iter() {
1271 invalid.insert(signature.index);
1272 }
1273 }
1274
1275 (
1277 finalizes
1278 .into_iter()
1279 .filter(|f| !invalid.contains(&f.signer()))
1280 .collect(),
1281 invalid.into_iter().collect(),
1282 )
1283 }
1284
1285 pub fn sign(namespace: &[u8], share: &Share, proposal: Proposal<D>) -> Self {
1287 let finalize_namespace = finalize_namespace(namespace);
1288 let message = proposal.encode();
1289 let proposal_signature =
1290 partial_sign_message::<V>(share, Some(finalize_namespace.as_ref()), &message);
1291 Finalize::new(proposal, proposal_signature)
1292 }
1293}
1294
1295impl<V: Variant, D: Digest> Attributable for Finalize<V, D> {
1296 fn signer(&self) -> u32 {
1297 self.proposal_signature.index
1298 }
1299}
1300
1301impl<V: Variant, D: Digest> Viewable for Finalize<V, D> {
1302 type View = View;
1303
1304 fn view(&self) -> View {
1305 self.proposal.view()
1306 }
1307}
1308
1309impl<V: Variant, D: Digest> Write for Finalize<V, D> {
1310 fn write(&self, writer: &mut impl BufMut) {
1311 self.proposal.write(writer);
1312 self.proposal_signature.write(writer);
1313 }
1314}
1315
1316impl<V: Variant, D: Digest> Read for Finalize<V, D> {
1317 type Cfg = ();
1318
1319 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
1320 let proposal = Proposal::read(reader)?;
1321 let proposal_signature = PartialSignature::<V>::read(reader)?;
1322 Ok(Finalize {
1323 proposal,
1324 proposal_signature,
1325 })
1326 }
1327}
1328
1329impl<V: Variant, D: Digest> EncodeSize for Finalize<V, D> {
1330 fn encode_size(&self) -> usize {
1331 self.proposal.encode_size() + self.proposal_signature.encode_size()
1332 }
1333}
1334
1335#[derive(Clone, Debug, PartialEq, Hash, Eq)]
1339pub struct Finalization<V: Variant, D: Digest> {
1340 pub proposal: Proposal<D>,
1342 pub proposal_signature: V::Signature,
1344 pub seed_signature: V::Signature,
1346}
1347
1348impl<V: Variant, D: Digest> Finalization<V, D> {
1349 pub fn new(
1351 proposal: Proposal<D>,
1352 proposal_signature: V::Signature,
1353 seed_signature: V::Signature,
1354 ) -> Self {
1355 Finalization {
1356 proposal,
1357 proposal_signature,
1358 seed_signature,
1359 }
1360 }
1361
1362 pub fn verify(&self, namespace: &[u8], identity: &V::Public) -> bool {
1368 let finalize_namespace = finalize_namespace(namespace);
1369 let finalize_message = self.proposal.encode();
1370 let finalize_message = (Some(finalize_namespace.as_ref()), finalize_message.as_ref());
1371 let seed_namespace = seed_namespace(namespace);
1372 let seed_message = view_message(self.proposal.view);
1373 let seed_message = (Some(seed_namespace.as_ref()), seed_message.as_ref());
1374 let signature =
1375 aggregate_signatures::<V, _>(&[self.proposal_signature, self.seed_signature]);
1376 aggregate_verify_multiple_messages::<V, _>(
1377 identity,
1378 &[finalize_message, seed_message],
1379 &signature,
1380 1,
1381 )
1382 .is_ok()
1383 }
1384}
1385
1386impl<V: Variant, D: Digest> Viewable for Finalization<V, D> {
1387 type View = View;
1388
1389 fn view(&self) -> View {
1390 self.proposal.view()
1391 }
1392}
1393
1394impl<V: Variant, D: Digest> Write for Finalization<V, D> {
1395 fn write(&self, writer: &mut impl BufMut) {
1396 self.proposal.write(writer);
1397 self.proposal_signature.write(writer);
1398 self.seed_signature.write(writer);
1399 }
1400}
1401
1402impl<V: Variant, D: Digest> Read for Finalization<V, D> {
1403 type Cfg = ();
1404
1405 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
1406 let proposal = Proposal::read(reader)?;
1407 let proposal_signature = V::Signature::read(reader)?;
1408 let seed_signature = V::Signature::read(reader)?;
1409 Ok(Finalization {
1410 proposal,
1411 proposal_signature,
1412 seed_signature,
1413 })
1414 }
1415}
1416
1417impl<V: Variant, D: Digest> EncodeSize for Finalization<V, D> {
1418 fn encode_size(&self) -> usize {
1419 self.proposal.encode_size()
1420 + self.proposal_signature.encode_size()
1421 + self.seed_signature.encode_size()
1422 }
1423}
1424
1425impl<V: Variant, D: Digest> Seedable<V> for Finalization<V, D> {
1426 fn seed(&self) -> Seed<V> {
1427 Seed::new(self.view(), self.seed_signature)
1428 }
1429}
1430
1431#[derive(Clone, Debug, PartialEq)]
1434pub enum Backfiller<V: Variant, D: Digest> {
1435 Request(Request),
1437 Response(Response<V, D>),
1439}
1440
1441impl<V: Variant, D: Digest> Write for Backfiller<V, D> {
1442 fn write(&self, writer: &mut impl BufMut) {
1443 match self {
1444 Backfiller::Request(v) => {
1445 0u8.write(writer);
1446 v.write(writer);
1447 }
1448 Backfiller::Response(v) => {
1449 1u8.write(writer);
1450 v.write(writer);
1451 }
1452 }
1453 }
1454}
1455
1456impl<V: Variant, D: Digest> EncodeSize for Backfiller<V, D> {
1457 fn encode_size(&self) -> usize {
1458 1 + match self {
1459 Backfiller::Request(v) => v.encode_size(),
1460 Backfiller::Response(v) => v.encode_size(),
1461 }
1462 }
1463}
1464
1465impl<V: Variant, D: Digest> Read for Backfiller<V, D> {
1466 type Cfg = usize;
1467
1468 fn read_cfg(reader: &mut impl Buf, cfg: &usize) -> Result<Self, Error> {
1469 let tag = <u8>::read(reader)?;
1470 match tag {
1471 0 => {
1472 let v = Request::read_cfg(reader, cfg)?;
1473 Ok(Backfiller::Request(v))
1474 }
1475 1 => {
1476 let v = Response::<V, D>::read_cfg(reader, cfg)?;
1477 Ok(Backfiller::Response(v))
1478 }
1479 _ => Err(Error::Invalid(
1480 "consensus::threshold_simplex::Backfiller",
1481 "Invalid type",
1482 )),
1483 }
1484 }
1485}
1486
1487#[derive(Clone, Debug, PartialEq)]
1490pub struct Request {
1491 pub id: u64,
1493 pub notarizations: Vec<View>,
1495 pub nullifications: Vec<View>,
1497}
1498
1499impl Request {
1500 pub fn new(id: u64, notarizations: Vec<View>, nullifications: Vec<View>) -> Self {
1502 Request {
1503 id,
1504 notarizations,
1505 nullifications,
1506 }
1507 }
1508}
1509
1510impl Write for Request {
1511 fn write(&self, writer: &mut impl BufMut) {
1512 UInt(self.id).write(writer);
1513 self.notarizations.write(writer);
1514 self.nullifications.write(writer);
1515 }
1516}
1517
1518impl EncodeSize for Request {
1519 fn encode_size(&self) -> usize {
1520 UInt(self.id).encode_size()
1521 + self.notarizations.encode_size()
1522 + self.nullifications.encode_size()
1523 }
1524}
1525
1526impl Read for Request {
1527 type Cfg = usize;
1528
1529 fn read_cfg(reader: &mut impl Buf, max_len: &usize) -> Result<Self, Error> {
1530 let id = UInt::read(reader)?.into();
1531 let mut views = HashSet::new();
1532 let notarizations = Vec::<View>::read_range(reader, ..=*max_len)?;
1533 for view in notarizations.iter() {
1534 if !views.insert(view) {
1535 return Err(Error::Invalid(
1536 "consensus::threshold_simplex::Request",
1537 "Duplicate notarization",
1538 ));
1539 }
1540 }
1541 let remaining = max_len - notarizations.len();
1542 views.clear();
1543 let nullifications = Vec::<View>::read_range(reader, ..=remaining)?;
1544 for view in nullifications.iter() {
1545 if !views.insert(view) {
1546 return Err(Error::Invalid(
1547 "consensus::threshold_simplex::Request",
1548 "Duplicate nullification",
1549 ));
1550 }
1551 }
1552 Ok(Request {
1553 id,
1554 notarizations,
1555 nullifications,
1556 })
1557 }
1558}
1559
1560#[derive(Clone, Debug, PartialEq)]
1563pub struct Response<V: Variant, D: Digest> {
1564 pub id: u64,
1566 pub notarizations: Vec<Notarization<V, D>>,
1568 pub nullifications: Vec<Nullification<V>>,
1570}
1571
1572impl<V: Variant, D: Digest> Response<V, D> {
1573 pub fn new(
1575 id: u64,
1576 notarizations: Vec<Notarization<V, D>>,
1577 nullifications: Vec<Nullification<V>>,
1578 ) -> Self {
1579 Response {
1580 id,
1581 notarizations,
1582 nullifications,
1583 }
1584 }
1585
1586 pub fn verify(&self, namespace: &[u8], identity: &V::Public) -> bool {
1588 if self.notarizations.is_empty() && self.nullifications.is_empty() {
1590 return true;
1591 }
1592 let mut seeds = HashMap::new();
1593 let mut messages = Vec::new();
1594 let mut signatures = Vec::new();
1595
1596 let notarize_namespace = notarize_namespace(namespace);
1598 let seed_namespace = seed_namespace(namespace);
1599 for notarization in self.notarizations.iter() {
1600 let notarize_message = notarization.proposal.encode().to_vec();
1602 let notarize_message = (Some(notarize_namespace.as_slice()), notarize_message);
1603 messages.push(notarize_message);
1604 signatures.push(¬arization.proposal_signature);
1605
1606 if let Some(previous) = seeds.get(¬arization.proposal.view) {
1608 if *previous != ¬arization.seed_signature {
1609 return false;
1610 }
1611 } else {
1612 let seed_message = view_message(notarization.proposal.view);
1613 let seed_message = (Some(seed_namespace.as_slice()), seed_message);
1614 messages.push(seed_message);
1615 signatures.push(¬arization.seed_signature);
1616 seeds.insert(notarization.proposal.view, ¬arization.seed_signature);
1617 }
1618 }
1619
1620 let nullify_namespace = nullify_namespace(namespace);
1622 for nullification in self.nullifications.iter() {
1623 let nullify_message = view_message(nullification.view);
1625 let nullify_message = (Some(nullify_namespace.as_slice()), nullify_message);
1626 messages.push(nullify_message);
1627 signatures.push(&nullification.view_signature);
1628
1629 if let Some(previous) = seeds.get(&nullification.view) {
1631 if *previous != &nullification.seed_signature {
1632 return false;
1633 }
1634 } else {
1635 let seed_message = view_message(nullification.view);
1636 let seed_message = (Some(seed_namespace.as_slice()), seed_message);
1637 messages.push(seed_message);
1638 signatures.push(&nullification.seed_signature);
1639 seeds.insert(nullification.view, &nullification.seed_signature);
1640 }
1641 }
1642
1643 let signature = aggregate_signatures::<V, _>(signatures);
1645 aggregate_verify_multiple_messages::<V, _>(
1646 identity,
1647 &messages
1648 .iter()
1649 .map(|(namespace, message)| (namespace.as_deref(), message.as_ref()))
1650 .collect::<Vec<_>>(),
1651 &signature,
1652 1,
1653 )
1654 .is_ok()
1655 }
1656}
1657
1658impl<V: Variant, D: Digest> Write for Response<V, D> {
1659 fn write(&self, writer: &mut impl BufMut) {
1660 UInt(self.id).write(writer);
1661 self.notarizations.write(writer);
1662 self.nullifications.write(writer);
1663 }
1664}
1665
1666impl<V: Variant, D: Digest> EncodeSize for Response<V, D> {
1667 fn encode_size(&self) -> usize {
1668 UInt(self.id).encode_size()
1669 + self.notarizations.encode_size()
1670 + self.nullifications.encode_size()
1671 }
1672}
1673
1674impl<V: Variant, D: Digest> Read for Response<V, D> {
1675 type Cfg = usize;
1676
1677 fn read_cfg(reader: &mut impl Buf, max_len: &usize) -> Result<Self, Error> {
1678 let id = UInt::read(reader)?.into();
1679 let mut views = HashSet::new();
1680 let notarizations = Vec::<Notarization<V, D>>::read_range(reader, ..=*max_len)?;
1681 for notarization in notarizations.iter() {
1682 if !views.insert(notarization.proposal.view) {
1683 return Err(Error::Invalid(
1684 "consensus::threshold_simplex::Response",
1685 "Duplicate notarization",
1686 ));
1687 }
1688 }
1689 let remaining = max_len - notarizations.len();
1690 views.clear();
1691 let nullifications = Vec::<Nullification<V>>::read_range(reader, ..=remaining)?;
1692 for nullification in nullifications.iter() {
1693 if !views.insert(nullification.view) {
1694 return Err(Error::Invalid(
1695 "consensus::threshold_simplex::Response",
1696 "Duplicate nullification",
1697 ));
1698 }
1699 }
1700 Ok(Response {
1701 id,
1702 notarizations,
1703 nullifications,
1704 })
1705 }
1706}
1707
1708#[derive(Clone, Debug, PartialEq, Hash, Eq)]
1722pub enum Activity<V: Variant, D: Digest> {
1723 Notarize(Notarize<V, D>),
1725 Notarization(Notarization<V, D>),
1727 Nullify(Nullify<V>),
1729 Nullification(Nullification<V>),
1731 Finalize(Finalize<V, D>),
1733 Finalization(Finalization<V, D>),
1735 ConflictingNotarize(ConflictingNotarize<V, D>),
1737 ConflictingFinalize(ConflictingFinalize<V, D>),
1739 NullifyFinalize(NullifyFinalize<V, D>),
1741}
1742
1743impl<V: Variant, D: Digest> Activity<V, D> {
1744 pub fn verified(&self) -> bool {
1746 match self {
1747 Activity::Notarize(_) => false,
1748 Activity::Notarization(_) => true,
1749 Activity::Nullify(_) => false,
1750 Activity::Nullification(_) => true,
1751 Activity::Finalize(_) => false,
1752 Activity::Finalization(_) => true,
1753 Activity::ConflictingNotarize(_) => false,
1754 Activity::ConflictingFinalize(_) => false,
1755 Activity::NullifyFinalize(_) => false,
1756 }
1757 }
1758}
1759
1760impl<V: Variant, D: Digest> Write for Activity<V, D> {
1761 fn write(&self, writer: &mut impl BufMut) {
1762 match self {
1763 Activity::Notarize(v) => {
1764 0u8.write(writer);
1765 v.write(writer);
1766 }
1767 Activity::Notarization(v) => {
1768 1u8.write(writer);
1769 v.write(writer);
1770 }
1771 Activity::Nullify(v) => {
1772 2u8.write(writer);
1773 v.write(writer);
1774 }
1775 Activity::Nullification(v) => {
1776 3u8.write(writer);
1777 v.write(writer);
1778 }
1779 Activity::Finalize(v) => {
1780 4u8.write(writer);
1781 v.write(writer);
1782 }
1783 Activity::Finalization(v) => {
1784 5u8.write(writer);
1785 v.write(writer);
1786 }
1787 Activity::ConflictingNotarize(v) => {
1788 6u8.write(writer);
1789 v.write(writer);
1790 }
1791 Activity::ConflictingFinalize(v) => {
1792 7u8.write(writer);
1793 v.write(writer);
1794 }
1795 Activity::NullifyFinalize(v) => {
1796 8u8.write(writer);
1797 v.write(writer);
1798 }
1799 }
1800 }
1801}
1802
1803impl<V: Variant, D: Digest> EncodeSize for Activity<V, D> {
1804 fn encode_size(&self) -> usize {
1805 1 + match self {
1806 Activity::Notarize(v) => v.encode_size(),
1807 Activity::Notarization(v) => v.encode_size(),
1808 Activity::Nullify(v) => v.encode_size(),
1809 Activity::Nullification(v) => v.encode_size(),
1810 Activity::Finalize(v) => v.encode_size(),
1811 Activity::Finalization(v) => v.encode_size(),
1812 Activity::ConflictingNotarize(v) => v.encode_size(),
1813 Activity::ConflictingFinalize(v) => v.encode_size(),
1814 Activity::NullifyFinalize(v) => v.encode_size(),
1815 }
1816 }
1817}
1818
1819impl<V: Variant, D: Digest> Read for Activity<V, D> {
1820 type Cfg = ();
1821
1822 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
1823 let tag = <u8>::read(reader)?;
1824 match tag {
1825 0 => {
1826 let v = Notarize::<V, D>::read(reader)?;
1827 Ok(Activity::Notarize(v))
1828 }
1829 1 => {
1830 let v = Notarization::<V, D>::read(reader)?;
1831 Ok(Activity::Notarization(v))
1832 }
1833 2 => {
1834 let v = Nullify::<V>::read(reader)?;
1835 Ok(Activity::Nullify(v))
1836 }
1837 3 => {
1838 let v = Nullification::<V>::read(reader)?;
1839 Ok(Activity::Nullification(v))
1840 }
1841 4 => {
1842 let v = Finalize::<V, D>::read(reader)?;
1843 Ok(Activity::Finalize(v))
1844 }
1845 5 => {
1846 let v = Finalization::<V, D>::read(reader)?;
1847 Ok(Activity::Finalization(v))
1848 }
1849 6 => {
1850 let v = ConflictingNotarize::<V, D>::read(reader)?;
1851 Ok(Activity::ConflictingNotarize(v))
1852 }
1853 7 => {
1854 let v = ConflictingFinalize::<V, D>::read(reader)?;
1855 Ok(Activity::ConflictingFinalize(v))
1856 }
1857 8 => {
1858 let v = NullifyFinalize::<V, D>::read(reader)?;
1859 Ok(Activity::NullifyFinalize(v))
1860 }
1861 _ => Err(Error::Invalid(
1862 "consensus::threshold_simplex::Activity",
1863 "Invalid type",
1864 )),
1865 }
1866 }
1867}
1868
1869impl<V: Variant, D: Digest> Viewable for Activity<V, D> {
1870 type View = View;
1871
1872 fn view(&self) -> View {
1873 match self {
1874 Activity::Notarize(v) => v.view(),
1875 Activity::Notarization(v) => v.view(),
1876 Activity::Nullify(v) => v.view(),
1877 Activity::Nullification(v) => v.view(),
1878 Activity::Finalize(v) => v.view(),
1879 Activity::Finalization(v) => v.view(),
1880 Activity::ConflictingNotarize(v) => v.view(),
1881 Activity::ConflictingFinalize(v) => v.view(),
1882 Activity::NullifyFinalize(v) => v.view(),
1883 }
1884 }
1885}
1886
1887#[derive(Clone, Debug, PartialEq, Hash, Eq)]
1889pub struct Seed<V: Variant> {
1890 pub view: View,
1892 pub signature: V::Signature,
1894}
1895
1896impl<V: Variant> Seed<V> {
1897 pub fn new(view: View, signature: V::Signature) -> Self {
1899 Seed { view, signature }
1900 }
1901
1902 pub fn verify(&self, namespace: &[u8], identity: &V::Public) -> bool {
1904 let seed_namespace = seed_namespace(namespace);
1905 let message = view_message(self.view);
1906 verify_message::<V>(identity, Some(&seed_namespace), &message, &self.signature).is_ok()
1907 }
1908}
1909
1910impl<V: Variant> Viewable for Seed<V> {
1911 type View = View;
1912
1913 fn view(&self) -> View {
1914 self.view
1915 }
1916}
1917
1918impl<V: Variant> Write for Seed<V> {
1919 fn write(&self, writer: &mut impl BufMut) {
1920 UInt(self.view).write(writer);
1921 self.signature.write(writer);
1922 }
1923}
1924
1925impl<V: Variant> Read for Seed<V> {
1926 type Cfg = ();
1927
1928 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
1929 let view = UInt::read(reader)?.into();
1930 let signature = V::Signature::read(reader)?;
1931 Ok(Seed { view, signature })
1932 }
1933}
1934
1935impl<V: Variant> EncodeSize for Seed<V> {
1936 fn encode_size(&self) -> usize {
1937 UInt(self.view).encode_size() + self.signature.encode_size()
1938 }
1939}
1940
1941#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1944pub struct ConflictingNotarize<V: Variant, D: Digest> {
1945 pub view: View,
1947 pub parent_1: View,
1949 pub payload_1: D,
1951 pub signature_1: PartialSignature<V>,
1953 pub parent_2: View,
1955 pub payload_2: D,
1957 pub signature_2: PartialSignature<V>,
1959}
1960
1961impl<V: Variant, D: Digest> ConflictingNotarize<V, D> {
1962 pub fn new(notarize_1: Notarize<V, D>, notarize_2: Notarize<V, D>) -> Self {
1964 assert_eq!(notarize_1.view(), notarize_2.view());
1965 assert_eq!(notarize_1.signer(), notarize_2.signer());
1966 ConflictingNotarize {
1967 view: notarize_1.view(),
1968 parent_1: notarize_1.proposal.parent,
1969 payload_1: notarize_1.proposal.payload,
1970 signature_1: notarize_1.proposal_signature,
1971 parent_2: notarize_2.proposal.parent,
1972 payload_2: notarize_2.proposal.payload,
1973 signature_2: notarize_2.proposal_signature,
1974 }
1975 }
1976
1977 pub fn proposals(&self) -> (Proposal<D>, Proposal<D>) {
1979 (
1980 Proposal::new(self.view, self.parent_1, self.payload_1),
1981 Proposal::new(self.view, self.parent_2, self.payload_2),
1982 )
1983 }
1984
1985 pub fn verify(&self, namespace: &[u8], polynomial: &[V::Public]) -> bool {
1987 let (proposal_1, proposal_2) = self.proposals();
1988 let notarize_namespace = notarize_namespace(namespace);
1989 let notarize_message_1 = proposal_1.encode();
1990 let notarize_message_1 = (
1991 Some(notarize_namespace.as_ref()),
1992 notarize_message_1.as_ref(),
1993 );
1994 let notarize_message_2 = proposal_2.encode();
1995 let notarize_message_2 = (
1996 Some(notarize_namespace.as_ref()),
1997 notarize_message_2.as_ref(),
1998 );
1999 let Some(evaluated) = polynomial.get(self.signer() as usize) else {
2000 return false;
2001 };
2002 let signature =
2003 aggregate_signatures::<V, _>(&[self.signature_1.value, self.signature_2.value]);
2004 aggregate_verify_multiple_messages::<V, _>(
2005 evaluated,
2006 &[notarize_message_1, notarize_message_2],
2007 &signature,
2008 1,
2009 )
2010 .is_ok()
2011 }
2012}
2013
2014impl<V: Variant, D: Digest> Attributable for ConflictingNotarize<V, D> {
2015 fn signer(&self) -> u32 {
2016 self.signature_1.index
2017 }
2018}
2019
2020impl<V: Variant, D: Digest> Viewable for ConflictingNotarize<V, D> {
2021 type View = View;
2022
2023 fn view(&self) -> View {
2024 self.view
2025 }
2026}
2027
2028impl<V: Variant, D: Digest> Write for ConflictingNotarize<V, D> {
2029 fn write(&self, writer: &mut impl BufMut) {
2030 UInt(self.view).write(writer);
2031 UInt(self.parent_1).write(writer);
2032 self.payload_1.write(writer);
2033 self.signature_1.write(writer);
2034 UInt(self.parent_2).write(writer);
2035 self.payload_2.write(writer);
2036 self.signature_2.write(writer);
2037 }
2038}
2039
2040impl<V: Variant, D: Digest> Read for ConflictingNotarize<V, D> {
2041 type Cfg = ();
2042
2043 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
2044 let view = UInt::read(reader)?.into();
2045 let parent_1 = UInt::read(reader)?.into();
2046 let payload_1 = D::read(reader)?;
2047 let signature_1 = PartialSignature::<V>::read(reader)?;
2048 let parent_2 = UInt::read(reader)?.into();
2049 let payload_2 = D::read(reader)?;
2050 let signature_2 = PartialSignature::<V>::read(reader)?;
2051 if signature_1.index != signature_2.index {
2052 return Err(Error::Invalid(
2053 "consensus::threshold_simplex::ConflictingNotarize",
2054 "mismatched signatures",
2055 ));
2056 }
2057 Ok(ConflictingNotarize {
2058 view,
2059 parent_1,
2060 payload_1,
2061 signature_1,
2062 parent_2,
2063 payload_2,
2064 signature_2,
2065 })
2066 }
2067}
2068
2069impl<V: Variant, D: Digest> EncodeSize for ConflictingNotarize<V, D> {
2070 fn encode_size(&self) -> usize {
2071 UInt(self.view).encode_size()
2072 + UInt(self.parent_1).encode_size()
2073 + self.payload_1.encode_size()
2074 + self.signature_1.encode_size()
2075 + UInt(self.parent_2).encode_size()
2076 + self.payload_2.encode_size()
2077 + self.signature_2.encode_size()
2078 }
2079}
2080
2081#[derive(Clone, Debug, PartialEq, Eq, Hash)]
2084pub struct ConflictingFinalize<V: Variant, D: Digest> {
2085 pub view: View,
2087 pub parent_1: View,
2089 pub payload_1: D,
2091 pub signature_1: PartialSignature<V>,
2093 pub parent_2: View,
2095 pub payload_2: D,
2097 pub signature_2: PartialSignature<V>,
2099}
2100
2101impl<V: Variant, D: Digest> ConflictingFinalize<V, D> {
2102 pub fn new(finalize_1: Finalize<V, D>, finalize_2: Finalize<V, D>) -> Self {
2104 assert_eq!(finalize_1.view(), finalize_2.view());
2105 assert_eq!(finalize_1.signer(), finalize_2.signer());
2106 ConflictingFinalize {
2107 view: finalize_1.view(),
2108 parent_1: finalize_1.proposal.parent,
2109 payload_1: finalize_1.proposal.payload,
2110 signature_1: finalize_1.proposal_signature,
2111 parent_2: finalize_2.proposal.parent,
2112 payload_2: finalize_2.proposal.payload,
2113 signature_2: finalize_2.proposal_signature,
2114 }
2115 }
2116
2117 pub fn proposals(&self) -> (Proposal<D>, Proposal<D>) {
2119 (
2120 Proposal::new(self.view, self.parent_1, self.payload_1),
2121 Proposal::new(self.view, self.parent_2, self.payload_2),
2122 )
2123 }
2124
2125 pub fn verify(&self, namespace: &[u8], polynomial: &[V::Public]) -> bool {
2127 let (proposal_1, proposal_2) = self.proposals();
2128 let finalize_namespace = finalize_namespace(namespace);
2129 let finalize_message_1 = proposal_1.encode();
2130 let finalize_message_1 = (
2131 Some(finalize_namespace.as_ref()),
2132 finalize_message_1.as_ref(),
2133 );
2134 let finalize_message_2 = proposal_2.encode();
2135 let finalize_message_2 = (
2136 Some(finalize_namespace.as_ref()),
2137 finalize_message_2.as_ref(),
2138 );
2139 let Some(evaluated) = polynomial.get(self.signer() as usize) else {
2140 return false;
2141 };
2142 let signature =
2143 aggregate_signatures::<V, _>(&[self.signature_1.value, self.signature_2.value]);
2144 aggregate_verify_multiple_messages::<V, _>(
2145 evaluated,
2146 &[finalize_message_1, finalize_message_2],
2147 &signature,
2148 1,
2149 )
2150 .is_ok()
2151 }
2152}
2153
2154impl<V: Variant, D: Digest> Attributable for ConflictingFinalize<V, D> {
2155 fn signer(&self) -> u32 {
2156 self.signature_1.index
2157 }
2158}
2159
2160impl<V: Variant, D: Digest> Viewable for ConflictingFinalize<V, D> {
2161 type View = View;
2162
2163 fn view(&self) -> View {
2164 self.view
2165 }
2166}
2167
2168impl<V: Variant, D: Digest> Write for ConflictingFinalize<V, D> {
2169 fn write(&self, writer: &mut impl BufMut) {
2170 UInt(self.view).write(writer);
2171 UInt(self.parent_1).write(writer);
2172 self.payload_1.write(writer);
2173 self.signature_1.write(writer);
2174 UInt(self.parent_2).write(writer);
2175 self.payload_2.write(writer);
2176 self.signature_2.write(writer);
2177 }
2178}
2179
2180impl<V: Variant, D: Digest> Read for ConflictingFinalize<V, D> {
2181 type Cfg = ();
2182
2183 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
2184 let view = UInt::read(reader)?.into();
2185 let parent_1 = UInt::read(reader)?.into();
2186 let payload_1 = D::read(reader)?;
2187 let signature_1 = PartialSignature::<V>::read(reader)?;
2188 let parent_2 = UInt::read(reader)?.into();
2189 let payload_2 = D::read(reader)?;
2190 let signature_2 = PartialSignature::<V>::read(reader)?;
2191 if signature_1.index != signature_2.index {
2192 return Err(Error::Invalid(
2193 "consensus::threshold_simplex::ConflictingFinalize",
2194 "mismatched signatures",
2195 ));
2196 }
2197 Ok(ConflictingFinalize {
2198 view,
2199 parent_1,
2200 payload_1,
2201 signature_1,
2202 parent_2,
2203 payload_2,
2204 signature_2,
2205 })
2206 }
2207}
2208
2209impl<V: Variant, D: Digest> EncodeSize for ConflictingFinalize<V, D> {
2210 fn encode_size(&self) -> usize {
2211 UInt(self.view).encode_size()
2212 + UInt(self.parent_1).encode_size()
2213 + self.payload_1.encode_size()
2214 + self.signature_1.encode_size()
2215 + UInt(self.parent_2).encode_size()
2216 + self.payload_2.encode_size()
2217 + self.signature_2.encode_size()
2218 }
2219}
2220
2221#[derive(Clone, Debug, PartialEq, Eq, Hash)]
2225pub struct NullifyFinalize<V: Variant, D: Digest> {
2226 pub proposal: Proposal<D>,
2228 pub view_signature: PartialSignature<V>,
2230 pub finalize_signature: PartialSignature<V>,
2232}
2233
2234impl<V: Variant, D: Digest> NullifyFinalize<V, D> {
2235 pub fn new(nullify: Nullify<V>, finalize: Finalize<V, D>) -> Self {
2237 assert_eq!(nullify.view(), finalize.view());
2238 assert_eq!(nullify.signer(), finalize.signer());
2239 NullifyFinalize {
2240 proposal: finalize.proposal,
2241 view_signature: nullify.view_signature,
2242 finalize_signature: finalize.proposal_signature,
2243 }
2244 }
2245
2246 pub fn verify(&self, namespace: &[u8], polynomial: &[V::Public]) -> bool {
2248 let nullify_namespace = nullify_namespace(namespace);
2249 let nullify_message = view_message(self.proposal.view);
2250 let nullify_message = (Some(nullify_namespace.as_ref()), nullify_message.as_ref());
2251 let finalize_namespace = finalize_namespace(namespace);
2252 let finalize_message = self.proposal.encode();
2253 let finalize_message = (Some(finalize_namespace.as_ref()), finalize_message.as_ref());
2254 let Some(evaluated) = polynomial.get(self.signer() as usize) else {
2255 return false;
2256 };
2257 let signature = aggregate_signatures::<V, _>(&[
2258 self.view_signature.value,
2259 self.finalize_signature.value,
2260 ]);
2261 aggregate_verify_multiple_messages::<V, _>(
2262 evaluated,
2263 &[nullify_message, finalize_message],
2264 &signature,
2265 1,
2266 )
2267 .is_ok()
2268 }
2269}
2270
2271impl<V: Variant, D: Digest> Attributable for NullifyFinalize<V, D> {
2272 fn signer(&self) -> u32 {
2273 self.view_signature.index
2274 }
2275}
2276
2277impl<V: Variant, D: Digest> Viewable for NullifyFinalize<V, D> {
2278 type View = View;
2279
2280 fn view(&self) -> View {
2281 self.proposal.view()
2282 }
2283}
2284
2285impl<V: Variant, D: Digest> Write for NullifyFinalize<V, D> {
2286 fn write(&self, writer: &mut impl BufMut) {
2287 self.proposal.write(writer);
2288 self.view_signature.write(writer);
2289 self.finalize_signature.write(writer);
2290 }
2291}
2292
2293impl<V: Variant, D: Digest> Read for NullifyFinalize<V, D> {
2294 type Cfg = ();
2295
2296 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
2297 let proposal = Proposal::read(reader)?;
2298 let view_signature = PartialSignature::<V>::read(reader)?;
2299 let finalize_signature = PartialSignature::<V>::read(reader)?;
2300 if view_signature.index != finalize_signature.index {
2301 return Err(Error::Invalid(
2302 "consensus::threshold_simplex::NullifyFinalize",
2303 "mismatched signatures",
2304 ));
2305 }
2306 Ok(NullifyFinalize {
2307 proposal,
2308 view_signature,
2309 finalize_signature,
2310 })
2311 }
2312}
2313
2314impl<V: Variant, D: Digest> EncodeSize for NullifyFinalize<V, D> {
2315 fn encode_size(&self) -> usize {
2316 self.proposal.encode_size()
2317 + self.view_signature.encode_size()
2318 + self.finalize_signature.encode_size()
2319 }
2320}
2321
2322#[cfg(test)]
2323mod tests {
2324 use super::*;
2325 use commonware_codec::{Decode, DecodeExt, Encode};
2326 use commonware_cryptography::{
2327 bls12381::{
2328 dkg::ops::{self, evaluate_all},
2329 primitives::{
2330 group::{Element, Share},
2331 ops::threshold_signature_recover,
2332 poly,
2333 variant::MinSig,
2334 },
2335 },
2336 sha256::Digest as Sha256,
2337 };
2338 use commonware_utils::quorum;
2339 use rand::{rngs::StdRng, SeedableRng};
2340
2341 const NAMESPACE: &[u8] = b"test";
2342
2343 fn sample_digest(v: u8) -> Sha256 {
2345 Sha256::from([v; 32]) }
2347
2348 fn generate_test_data(
2350 n: u32,
2351 t: u32,
2352 seed: u64,
2353 ) -> (
2354 <MinSig as Variant>::Public,
2355 Vec<<MinSig as Variant>::Public>,
2356 Vec<Share>,
2357 ) {
2358 let mut rng = StdRng::seed_from_u64(seed);
2359 let (polynomial, shares) = ops::generate_shares::<_, MinSig>(&mut rng, None, n, t);
2360 let identity = poly::public::<MinSig>(&polynomial);
2361 let polynomial = evaluate_all::<MinSig>(&polynomial, n);
2362 (*identity, polynomial, shares)
2363 }
2364
2365 #[test]
2366 fn test_proposal_encode_decode() {
2367 let proposal = Proposal::new(10, 5, sample_digest(1));
2368 let encoded = proposal.encode();
2369 let decoded = Proposal::<Sha256>::decode(encoded).unwrap();
2370 assert_eq!(proposal, decoded);
2371 }
2372
2373 #[test]
2374 fn test_notarize_encode_decode() {
2375 let n = 5;
2376 let t = quorum(n);
2377 let (_, polynomial, shares) = generate_test_data(n, t, 0);
2378
2379 let proposal = Proposal::new(10, 5, sample_digest(1));
2380 let notarize = Notarize::<MinSig, _>::sign(NAMESPACE, &shares[0], proposal);
2381
2382 let encoded = notarize.encode();
2383 let decoded = Notarize::<MinSig, Sha256>::decode(encoded).unwrap();
2384
2385 assert_eq!(notarize, decoded);
2386 assert!(decoded.verify(NAMESPACE, &polynomial));
2387 }
2388
2389 #[test]
2390 fn test_notarization_encode_decode() {
2391 let n = 5;
2392 let t = quorum(n);
2393 let (identity, _, shares) = generate_test_data(n, t, 0);
2394
2395 let proposal = Proposal::new(10, 5, sample_digest(1));
2396
2397 let notarizes: Vec<_> = shares
2399 .iter()
2400 .map(|s| Notarize::<MinSig, _>::sign(NAMESPACE, s, proposal.clone()))
2401 .collect();
2402
2403 let proposal_partials = notarizes.iter().map(|n| &n.proposal_signature);
2405 let proposal_signature =
2406 threshold_signature_recover::<MinSig, _>(t, proposal_partials).unwrap();
2407 let seed_partials = notarizes.iter().map(|n| &n.seed_signature);
2408 let seed_signature = threshold_signature_recover::<MinSig, _>(t, seed_partials).unwrap();
2409
2410 let notarization = Notarization::new(proposal, proposal_signature, seed_signature);
2412 let encoded = notarization.encode();
2413 let decoded = Notarization::<MinSig, Sha256>::decode(encoded).unwrap();
2414 assert_eq!(notarization, decoded);
2415
2416 assert!(decoded.verify(NAMESPACE, &identity));
2418
2419 let seed = notarization.seed();
2421 let encoded = seed.encode();
2422 let decoded = Seed::<MinSig>::decode(encoded).unwrap();
2423 assert_eq!(seed, decoded);
2424
2425 assert!(decoded.verify(NAMESPACE, &identity));
2427 }
2428
2429 #[test]
2430 fn test_nullify_encode_decode() {
2431 let n = 5;
2432 let t = quorum(n);
2433 let (_, polynomial, shares) = generate_test_data(n, t, 0);
2434
2435 let nullify = Nullify::<MinSig>::sign(NAMESPACE, &shares[0], 10);
2436
2437 let encoded = nullify.encode();
2438 let decoded = Nullify::<MinSig>::decode(encoded).unwrap();
2439
2440 assert_eq!(nullify, decoded);
2441 assert!(decoded.verify(NAMESPACE, &polynomial));
2442 }
2443
2444 #[test]
2445 fn test_nullification_encode_decode() {
2446 let n = 5;
2447 let t = quorum(n);
2448 let (identity, _, shares) = generate_test_data(n, t, 0);
2449
2450 let nullifies: Vec<_> = shares
2452 .iter()
2453 .map(|s| Nullify::<MinSig>::sign(NAMESPACE, s, 10))
2454 .collect();
2455
2456 let view_partials = nullifies.iter().map(|n| &n.view_signature);
2458 let view_signature = threshold_signature_recover::<MinSig, _>(t, view_partials).unwrap();
2459 let seed_partials = nullifies.iter().map(|n| &n.seed_signature);
2460 let seed_signature = threshold_signature_recover::<MinSig, _>(t, seed_partials).unwrap();
2461
2462 let nullification = Nullification::new(10, view_signature, seed_signature);
2464 let encoded = nullification.encode();
2465 let decoded = Nullification::<MinSig>::decode(encoded).unwrap();
2466 assert_eq!(nullification, decoded);
2467
2468 assert!(decoded.verify(NAMESPACE, &identity));
2470
2471 let seed = nullification.seed();
2473 let encoded = seed.encode();
2474 let decoded = Seed::<MinSig>::decode(encoded).unwrap();
2475 assert_eq!(seed, decoded);
2476
2477 assert!(decoded.verify(NAMESPACE, &identity));
2479 }
2480
2481 #[test]
2482 fn test_finalize_encode_decode() {
2483 let n = 5;
2484 let t = quorum(n);
2485 let (_, polynomial, shares) = generate_test_data(n, t, 0);
2486
2487 let proposal = Proposal::new(10, 5, sample_digest(1));
2488 let finalize = Finalize::<MinSig, _>::sign(NAMESPACE, &shares[0], proposal);
2489
2490 let encoded = finalize.encode();
2491 let decoded = Finalize::<MinSig, Sha256>::decode(encoded).unwrap();
2492
2493 assert_eq!(finalize, decoded);
2494 assert!(decoded.verify(NAMESPACE, &polynomial));
2495 }
2496
2497 #[test]
2498 fn test_finalization_encode_decode() {
2499 let n = 5;
2500 let t = quorum(n);
2501 let (identity, _, shares) = generate_test_data(n, t, 0);
2502
2503 let proposal = Proposal::new(10, 5, sample_digest(1));
2504
2505 let notarizes: Vec<_> = shares
2507 .iter()
2508 .map(|s| Notarize::<MinSig, _>::sign(NAMESPACE, s, proposal.clone()))
2509 .collect();
2510 let finalizes: Vec<_> = shares
2511 .iter()
2512 .map(|s| Finalize::<MinSig, _>::sign(NAMESPACE, s, proposal.clone()))
2513 .collect();
2514
2515 let proposal_partials = finalizes.iter().map(|f| &f.proposal_signature);
2517 let proposal_signature =
2518 threshold_signature_recover::<MinSig, _>(t, proposal_partials).unwrap();
2519 let seed_partials = notarizes.iter().map(|n| &n.seed_signature);
2520 let seed_signature = threshold_signature_recover::<MinSig, _>(t, seed_partials).unwrap();
2521
2522 let finalization = Finalization::new(proposal, proposal_signature, seed_signature);
2524 let encoded = finalization.encode();
2525 let decoded = Finalization::<MinSig, Sha256>::decode(encoded).unwrap();
2526 assert_eq!(finalization, decoded);
2527
2528 assert!(decoded.verify(NAMESPACE, &identity));
2530
2531 let seed = finalization.seed();
2533 let encoded = seed.encode();
2534 let decoded = Seed::<MinSig>::decode(encoded).unwrap();
2535 assert_eq!(seed, decoded);
2536
2537 assert!(decoded.verify(NAMESPACE, &identity));
2539 }
2540
2541 #[test]
2542 fn test_backfiller_encode_decode() {
2543 let request = Request::new(1, vec![10, 11], vec![12, 13]);
2545 let backfiller = Backfiller::<MinSig, Sha256>::Request(request.clone());
2546 let encoded = backfiller.encode();
2547 let decoded = Backfiller::<MinSig, Sha256>::decode_cfg(encoded, &usize::MAX).unwrap();
2548 assert!(matches!(decoded, Backfiller::Request(r) if r == request));
2549
2550 let n = 5;
2552 let t = quorum(n);
2553 let (_, _, shares) = generate_test_data(n, t, 0);
2554
2555 let proposal = Proposal::new(10, 5, sample_digest(1));
2557 let notarizes: Vec<_> = shares
2558 .iter()
2559 .map(|s| Notarize::<MinSig, _>::sign(NAMESPACE, s, proposal.clone()))
2560 .collect();
2561
2562 let proposal_partials = notarizes.iter().map(|n| &n.proposal_signature);
2563 let proposal_signature =
2564 threshold_signature_recover::<MinSig, _>(t, proposal_partials).unwrap();
2565 let seed_partials = notarizes.iter().map(|n| &n.seed_signature);
2566 let seed_signature = threshold_signature_recover::<MinSig, _>(t, seed_partials).unwrap();
2567
2568 let notarization = Notarization::new(proposal, proposal_signature, seed_signature);
2569
2570 let nullifies: Vec<_> = shares
2572 .iter()
2573 .map(|s| Nullify::<MinSig>::sign(NAMESPACE, s, 11))
2574 .collect();
2575
2576 let view_partials = nullifies.iter().map(|n| &n.view_signature);
2577 let view_signature = threshold_signature_recover::<MinSig, _>(t, view_partials).unwrap();
2578 let seed_partials = nullifies.iter().map(|n| &n.seed_signature);
2579 let seed_signature = threshold_signature_recover::<MinSig, _>(t, seed_partials).unwrap();
2580
2581 let nullification = Nullification::new(11, view_signature, seed_signature);
2582
2583 let response = Response::new(1, vec![notarization], vec![nullification]);
2585 let backfiller = Backfiller::<MinSig, Sha256>::Response(response.clone());
2586 let encoded = backfiller.encode();
2587 let decoded = Backfiller::<MinSig, Sha256>::decode_cfg(encoded, &usize::MAX).unwrap();
2588 assert!(matches!(decoded, Backfiller::Response(r) if r.id == response.id));
2589 }
2590
2591 #[test]
2592 fn test_request_encode_decode() {
2593 let request = Request::new(1, vec![10, 11], vec![12, 13]);
2594 let encoded = request.encode();
2595 let decoded = Request::decode_cfg(encoded, &usize::MAX).unwrap();
2596 assert_eq!(request, decoded);
2597 }
2598
2599 #[test]
2600 fn test_response_encode_decode() {
2601 let n = 5;
2602 let t = quorum(n);
2603 let (identity, _, shares) = generate_test_data(n, t, 0);
2604
2605 let proposal = Proposal::new(10, 5, sample_digest(1));
2607 let notarizes: Vec<_> = shares
2608 .iter()
2609 .map(|s| Notarize::<MinSig, _>::sign(NAMESPACE, s, proposal.clone()))
2610 .collect();
2611
2612 let proposal_partials = notarizes.iter().map(|n| &n.proposal_signature);
2613 let proposal_signature =
2614 threshold_signature_recover::<MinSig, _>(t, proposal_partials).unwrap();
2615 let seed_partials = notarizes.iter().map(|n| &n.seed_signature);
2616 let seed_signature = threshold_signature_recover::<MinSig, _>(t, seed_partials).unwrap();
2617
2618 let notarization = Notarization::new(proposal, proposal_signature, seed_signature);
2619
2620 let nullifies: Vec<_> = shares
2622 .iter()
2623 .map(|s| Nullify::<MinSig>::sign(NAMESPACE, s, 11))
2624 .collect();
2625
2626 let view_partials = nullifies.iter().map(|n| &n.view_signature);
2627 let view_signature = threshold_signature_recover::<MinSig, _>(t, view_partials).unwrap();
2628 let seed_partials = nullifies.iter().map(|n| &n.seed_signature);
2629 let seed_signature = threshold_signature_recover::<MinSig, _>(t, seed_partials).unwrap();
2630
2631 let nullification = Nullification::new(11, view_signature, seed_signature);
2632
2633 let response = Response::<MinSig, Sha256>::new(1, vec![notarization], vec![nullification]);
2635 let encoded = response.encode();
2636 let mut decoded = Response::<MinSig, Sha256>::decode_cfg(encoded, &usize::MAX).unwrap();
2637 assert_eq!(response.id, decoded.id);
2638 assert_eq!(response.notarizations.len(), decoded.notarizations.len());
2639 assert_eq!(response.nullifications.len(), decoded.nullifications.len());
2640
2641 assert!(decoded.verify(NAMESPACE, &identity));
2643
2644 decoded.nullifications[0]
2646 .view_signature
2647 .add(&<MinSig as Variant>::Signature::one());
2648
2649 assert!(!decoded.verify(NAMESPACE, &identity));
2651 }
2652
2653 #[test]
2654 fn test_conflicting_notarize_encode_decode() {
2655 let n = 5;
2656 let t = quorum(n);
2657 let (_, polynomial, shares) = generate_test_data(n, t, 0);
2658
2659 let proposal1 = Proposal::new(10, 5, sample_digest(1));
2660 let proposal2 = Proposal::new(10, 5, sample_digest(2));
2661 let notarize1 = Notarize::<MinSig, _>::sign(NAMESPACE, &shares[0], proposal1);
2662 let notarize2 = Notarize::<MinSig, _>::sign(NAMESPACE, &shares[0], proposal2);
2663 let conflicting_notarize = ConflictingNotarize::new(notarize1, notarize2);
2664
2665 let encoded = conflicting_notarize.encode();
2666 let decoded = ConflictingNotarize::<MinSig, Sha256>::decode(encoded).unwrap();
2667
2668 assert_eq!(conflicting_notarize, decoded);
2669 assert!(decoded.verify(NAMESPACE, &polynomial));
2670 }
2671
2672 #[test]
2673 fn test_conflicting_finalize_encode_decode() {
2674 let n = 5;
2675 let t = quorum(n);
2676 let (_, polynomial, shares) = generate_test_data(n, t, 0);
2677
2678 let proposal1 = Proposal::new(10, 5, sample_digest(1));
2679 let proposal2 = Proposal::new(10, 5, sample_digest(2));
2680 let finalize1 = Finalize::<MinSig, _>::sign(NAMESPACE, &shares[0], proposal1);
2681 let finalize2 = Finalize::<MinSig, _>::sign(NAMESPACE, &shares[0], proposal2);
2682 let conflicting_finalize = ConflictingFinalize::new(finalize1, finalize2);
2683
2684 let encoded = conflicting_finalize.encode();
2685 let decoded = ConflictingFinalize::<MinSig, Sha256>::decode(encoded).unwrap();
2686
2687 assert_eq!(conflicting_finalize, decoded);
2688 assert!(decoded.verify(NAMESPACE, &polynomial));
2689 }
2690
2691 #[test]
2692 fn test_nullify_finalize_encode_decode() {
2693 let n = 5;
2694 let t = quorum(n);
2695 let (_, polynomial, shares) = generate_test_data(n, t, 0);
2696
2697 let proposal = Proposal::new(10, 5, sample_digest(1));
2698 let nullify = Nullify::<MinSig>::sign(NAMESPACE, &shares[0], 10);
2699 let finalize = Finalize::<MinSig, _>::sign(NAMESPACE, &shares[0], proposal);
2700 let nullify_finalize = NullifyFinalize::new(nullify, finalize);
2701
2702 let encoded = nullify_finalize.encode();
2703 let decoded = NullifyFinalize::<MinSig, Sha256>::decode(encoded).unwrap();
2704
2705 assert_eq!(nullify_finalize, decoded);
2706 assert!(decoded.verify(NAMESPACE, &polynomial));
2707 }
2708
2709 #[test]
2710 fn test_notarize_verify_wrong_namespace() {
2711 let n = 5;
2712 let t = quorum(n);
2713 let (_, polynomial, shares) = generate_test_data(n, t, 0);
2714
2715 let proposal = Proposal::new(10, 5, sample_digest(1));
2716 let notarize = Notarize::<MinSig, _>::sign(NAMESPACE, &shares[0], proposal);
2717
2718 assert!(notarize.verify(NAMESPACE, &polynomial));
2720
2721 assert!(!notarize.verify(b"wrong_namespace", &polynomial));
2723 }
2724
2725 #[test]
2726 fn test_notarize_verify_wrong_polynomial() {
2727 let n = 5;
2728 let t = quorum(n);
2729 let (_, polynomial1, shares1) = generate_test_data(n, t, 0);
2730
2731 let (_, polynomial2, _) = generate_test_data(n, t, 1);
2733
2734 let proposal = Proposal::new(10, 5, sample_digest(1));
2735 let notarize = Notarize::<MinSig, _>::sign(NAMESPACE, &shares1[0], proposal);
2736
2737 assert!(notarize.verify(NAMESPACE, &polynomial1));
2739
2740 assert!(!notarize.verify(NAMESPACE, &polynomial2));
2742 }
2743
2744 #[test]
2745 fn test_notarization_verify_wrong_keys() {
2746 let n = 5;
2747 let t = quorum(n);
2748 let (identity, _, shares) = generate_test_data(n, t, 0);
2749
2750 let proposal = Proposal::new(10, 5, sample_digest(1));
2751
2752 let notarizes: Vec<_> = shares
2754 .iter()
2755 .map(|s| Notarize::<MinSig, _>::sign(NAMESPACE, s, proposal.clone()))
2756 .collect();
2757
2758 let proposal_partials = notarizes.iter().map(|n| &n.proposal_signature);
2760 let proposal_signature =
2761 threshold_signature_recover::<MinSig, _>(t, proposal_partials).unwrap();
2762 let seed_partials = notarizes.iter().map(|n| &n.seed_signature);
2763 let seed_signature = threshold_signature_recover::<MinSig, _>(t, seed_partials).unwrap();
2764
2765 let notarization =
2767 Notarization::<MinSig, _>::new(proposal, proposal_signature, seed_signature);
2768
2769 assert!(notarization.verify(NAMESPACE, &identity));
2771
2772 let (wrong_identity, _, _) = generate_test_data(n, t, 1);
2774
2775 assert!(!notarization.verify(NAMESPACE, &wrong_identity));
2777 }
2778
2779 #[test]
2780 fn test_notarization_verify_wrong_namespace() {
2781 let n = 5;
2782 let t = quorum(n);
2783 let (identity, _, shares) = generate_test_data(n, t, 0);
2784
2785 let proposal = Proposal::new(10, 5, sample_digest(1));
2786
2787 let notarizes: Vec<_> = shares
2789 .iter()
2790 .map(|s| Notarize::<MinSig, _>::sign(NAMESPACE, s, proposal.clone()))
2791 .collect();
2792
2793 let proposal_partials = notarizes.iter().map(|n| &n.proposal_signature);
2795 let proposal_signature =
2796 threshold_signature_recover::<MinSig, _>(t, proposal_partials).unwrap();
2797 let seed_partials = notarizes.iter().map(|n| &n.seed_signature);
2798 let seed_signature = threshold_signature_recover::<MinSig, _>(t, seed_partials).unwrap();
2799
2800 let notarization =
2802 Notarization::<MinSig, _>::new(proposal, proposal_signature, seed_signature);
2803
2804 assert!(notarization.verify(NAMESPACE, &identity));
2806
2807 assert!(!notarization.verify(b"wrong_namespace", &identity));
2809 }
2810
2811 #[test]
2812 fn test_threshold_recover_insufficient_signatures() {
2813 let n = 5;
2814 let t = quorum(n); let (_, _, shares) = generate_test_data(n, t, 0);
2816
2817 let proposal = Proposal::new(10, 5, sample_digest(1));
2818
2819 let notarizes: Vec<_> = shares
2821 .iter()
2822 .take((t as usize) - 1) .map(|s| Notarize::<MinSig, _>::sign(NAMESPACE, s, proposal.clone()))
2824 .collect();
2825
2826 let proposal_partials = notarizes.iter().map(|n| &n.proposal_signature);
2828 let result = threshold_signature_recover::<MinSig, _>(t, proposal_partials);
2829
2830 assert!(result.is_err());
2832 }
2833
2834 #[test]
2835 fn test_conflicting_notarize_detection() {
2836 let n = 5;
2837 let t = quorum(n);
2838 let (_, polynomial, shares) = generate_test_data(n, t, 0);
2839
2840 let proposal1 = Proposal::new(10, 5, sample_digest(1));
2842 let proposal2 = Proposal::new(10, 5, sample_digest(2)); let notarize1 = Notarize::<MinSig, _>::sign(NAMESPACE, &shares[0], proposal1.clone());
2846 let notarize2 = Notarize::<MinSig, _>::sign(NAMESPACE, &shares[0], proposal2);
2847
2848 let conflict = ConflictingNotarize::new(notarize1, notarize2.clone());
2850
2851 assert!(conflict.verify(NAMESPACE, &polynomial));
2853
2854 let notarize3 = Notarize::<MinSig, _>::sign(NAMESPACE, &shares[1], proposal1.clone());
2856
2857 let invalid_conflict: ConflictingNotarize<MinSig, Sha256> = ConflictingNotarize {
2860 view: conflict.view,
2861 parent_1: conflict.parent_1,
2862 payload_1: conflict.payload_1,
2863 signature_1: conflict.signature_1.clone(),
2864 parent_2: notarize3.proposal.parent,
2865 payload_2: notarize3.proposal.payload,
2866 signature_2: notarize3.proposal_signature,
2867 };
2868
2869 assert!(!invalid_conflict.verify(NAMESPACE, &polynomial));
2871 }
2872
2873 #[test]
2874 fn test_nullify_finalize_detection() {
2875 let n = 5;
2876 let t = quorum(n);
2877 let (_, polynomial, shares) = generate_test_data(n, t, 0);
2878
2879 let view = 10;
2880
2881 let nullify = Nullify::<MinSig>::sign(NAMESPACE, &shares[0], view);
2883
2884 let proposal = Proposal::new(view, 5, sample_digest(1));
2886 let finalize = Finalize::<MinSig, _>::sign(NAMESPACE, &shares[0], proposal);
2887
2888 let conflict = NullifyFinalize::new(nullify, finalize.clone());
2890
2891 assert!(conflict.verify(NAMESPACE, &polynomial));
2893
2894 assert!(!conflict.verify(b"wrong_namespace", &polynomial));
2896
2897 let nullify2 = Nullify::<MinSig>::sign(NAMESPACE, &shares[1], view);
2899
2900 let invalid_conflict: NullifyFinalize<MinSig, Sha256> = NullifyFinalize {
2902 proposal: finalize.proposal.clone(),
2903 view_signature: conflict.view_signature.clone(),
2904 finalize_signature: nullify2.view_signature,
2905 };
2906
2907 assert!(!invalid_conflict.verify(NAMESPACE, &polynomial));
2909 }
2910
2911 #[test]
2912 fn test_finalization_wrong_signature() {
2913 let n = 5;
2914 let t = quorum(n);
2915 let (identity, _, shares) = generate_test_data(n, t, 0);
2916
2917 let (wrong_identity, _, _) = generate_test_data(n, t, 1);
2919
2920 let proposal = Proposal::new(10, 5, sample_digest(1));
2921
2922 let finalizes: Vec<_> = shares
2924 .iter()
2925 .map(|s| Finalize::<MinSig, _>::sign(NAMESPACE, s, proposal.clone()))
2926 .collect();
2927 let notarizes: Vec<_> = shares
2928 .iter()
2929 .map(|s| Notarize::<MinSig, _>::sign(NAMESPACE, s, proposal.clone()))
2930 .collect();
2931
2932 let proposal_partials = finalizes.iter().map(|f| &f.proposal_signature);
2934 let proposal_signature =
2935 threshold_signature_recover::<MinSig, _>(t, proposal_partials).unwrap();
2936 let seed_partials = notarizes.iter().map(|n| &n.seed_signature);
2937 let seed_signature = threshold_signature_recover::<MinSig, _>(t, seed_partials).unwrap();
2938
2939 let finalization =
2941 Finalization::<MinSig, _>::new(proposal, proposal_signature, seed_signature);
2942
2943 assert!(finalization.verify(NAMESPACE, &identity));
2945
2946 assert!(!finalization.verify(NAMESPACE, &wrong_identity));
2948 }
2949
2950 fn create_notarize(
2952 share: &Share,
2953 view: View,
2954 parent_view: View,
2955 payload_val: u8,
2956 ) -> Notarize<MinSig, Sha256> {
2957 let proposal = Proposal::new(view, parent_view, sample_digest(payload_val));
2958 Notarize::<MinSig, _>::sign(NAMESPACE, share, proposal)
2959 }
2960
2961 fn create_nullify(share: &Share, view: View) -> Nullify<MinSig> {
2963 Nullify::<MinSig>::sign(NAMESPACE, share, view)
2964 }
2965
2966 fn create_finalize(
2968 share: &Share,
2969 view: View,
2970 parent_view: View,
2971 payload_val: u8,
2972 ) -> Finalize<MinSig, Sha256> {
2973 let proposal = Proposal::new(view, parent_view, sample_digest(payload_val));
2974 Finalize::<MinSig, _>::sign(NAMESPACE, share, proposal)
2975 }
2976
2977 fn create_notarization(
2979 proposal_view: View,
2980 parent_view: View,
2981 payload_val: u8,
2982 shares: &[Share],
2983 threshold: u32,
2984 ) -> Notarization<MinSig, Sha256> {
2985 let proposal = Proposal::new(proposal_view, parent_view, sample_digest(payload_val));
2986 let notarizes: Vec<_> = shares
2987 .iter()
2988 .take(threshold as usize)
2989 .map(|s| Notarize::<MinSig, _>::sign(NAMESPACE, s, proposal.clone()))
2990 .collect();
2991 let proposal_partials = notarizes.iter().map(|n| &n.proposal_signature);
2992 let proposal_signature =
2993 threshold_signature_recover::<MinSig, _>(threshold, proposal_partials).unwrap();
2994 let seed_partials = notarizes.iter().map(|n| &n.seed_signature);
2995 let seed_signature =
2996 threshold_signature_recover::<MinSig, _>(threshold, seed_partials).unwrap();
2997 Notarization::new(proposal, proposal_signature, seed_signature)
2998 }
2999
3000 #[test]
3001 fn test_batch_verifier_add_notarize() {
3002 let n_validators = 5;
3003 let threshold = quorum(n_validators);
3004 let (_, _, shares) = generate_test_data(n_validators, threshold, 123);
3005
3006 let mut verifier = BatchVerifier::<MinSig, Sha256>::new(Some(threshold));
3007
3008 let notarize1_s0 = create_notarize(&shares[0], 1, 0, 1); let notarize2_s1 = create_notarize(&shares[1], 1, 0, 1); let notarize_diff_prop_s2 = create_notarize(&shares[2], 1, 0, 2); verifier.add(Voter::Notarize(notarize1_s0.clone()), false);
3014 assert_eq!(verifier.notarizes.len(), 1);
3015 assert_eq!(verifier.notarizes_verified, 0);
3016
3017 verifier.add(Voter::Notarize(notarize1_s0.clone()), true);
3019 assert_eq!(verifier.notarizes.len(), 1); assert_eq!(verifier.notarizes_verified, 1); verifier.set_leader(shares[0].index);
3025 assert!(verifier.leader_proposal.is_some());
3026 assert_eq!(
3027 verifier.leader_proposal.as_ref().unwrap(),
3028 ¬arize1_s0.proposal
3029 );
3030 assert!(verifier.notarizes_force); assert_eq!(verifier.notarizes.len(), 1); verifier.add(Voter::Notarize(notarize2_s1.clone()), false);
3035 assert_eq!(verifier.notarizes.len(), 2);
3036
3037 verifier.add(Voter::Notarize(notarize_diff_prop_s2.clone()), false);
3039 assert_eq!(verifier.notarizes.len(), 2); let mut verifier2 = BatchVerifier::<MinSig, Sha256>::new(Some(threshold));
3043 let notarize_s1_v2 = create_notarize(&shares[1], 2, 1, 3); let notarize_s0_v2_leader = create_notarize(&shares[0], 2, 1, 3); verifier2.set_leader(shares[0].index); verifier2.add(Voter::Notarize(notarize_s1_v2.clone()), false); assert!(verifier2.leader_proposal.is_none()); assert_eq!(verifier2.notarizes.len(), 1);
3050
3051 verifier2.add(Voter::Notarize(notarize_s0_v2_leader.clone()), false); assert!(verifier2.leader_proposal.is_some()); assert_eq!(
3054 verifier2.leader_proposal.as_ref().unwrap(),
3055 ¬arize_s0_v2_leader.proposal
3056 );
3057 assert_eq!(verifier2.notarizes.len(), 2); }
3059
3060 #[test]
3061 fn test_batch_verifier_set_leader() {
3062 let n_validators = 5;
3063 let threshold = quorum(n_validators);
3064 let (_, _, shares) = generate_test_data(n_validators, threshold, 124);
3065 let mut verifier = BatchVerifier::<MinSig, Sha256>::new(Some(threshold));
3066
3067 let notarize_s0 = create_notarize(&shares[0], 1, 0, 1);
3068 let notarize_s1 = create_notarize(&shares[1], 1, 0, 1);
3069
3070 verifier.add(Voter::Notarize(notarize_s1.clone()), false);
3072 assert_eq!(verifier.notarizes.len(), 1);
3073
3074 verifier.set_leader(shares[0].index);
3076 assert_eq!(verifier.leader, Some(shares[0].index));
3077 assert!(verifier.leader_proposal.is_none()); assert!(!verifier.notarizes_force);
3079 assert_eq!(verifier.notarizes.len(), 1); verifier.add(Voter::Notarize(notarize_s0.clone()), false);
3083 assert!(verifier.leader_proposal.is_some()); assert_eq!(
3085 verifier.leader_proposal.as_ref().unwrap(),
3086 ¬arize_s0.proposal
3087 );
3088 assert!(verifier.notarizes_force); assert_eq!(verifier.notarizes.len(), 2); }
3091
3092 #[test]
3093 fn test_batch_verifier_ready_and_verify_notarizes() {
3094 let n_validators = 5;
3095 let threshold = quorum(n_validators); let (_, polynomial, shares) = generate_test_data(n_validators, threshold, 125);
3097
3098 let mut verifier = BatchVerifier::<MinSig, Sha256>::new(Some(threshold));
3099 let proposal = Proposal::new(1, 0, sample_digest(1));
3100
3101 let notarize_s0 = Notarize::<MinSig, _>::sign(NAMESPACE, &shares[0], proposal.clone());
3102 let notarize_s1 = Notarize::<MinSig, _>::sign(NAMESPACE, &shares[1], proposal.clone());
3103 let notarize_s2 = Notarize::<MinSig, _>::sign(NAMESPACE, &shares[2], proposal.clone());
3104 let notarize_s3 = Notarize::<MinSig, _>::sign(NAMESPACE, &shares[3], proposal.clone()); assert!(!verifier.ready_notarizes());
3108
3109 verifier.set_leader(shares[0].index);
3111 verifier.add(Voter::Notarize(notarize_s0.clone()), false);
3112 assert!(verifier.ready_notarizes()); assert_eq!(verifier.notarizes.len(), 1);
3114
3115 let (verified_n, failed_n) = verifier.verify_notarizes(NAMESPACE, &polynomial);
3116 assert_eq!(verified_n.len(), 1);
3117 assert!(failed_n.is_empty());
3118 assert_eq!(verifier.notarizes_verified, 1);
3119 assert!(verifier.notarizes.is_empty());
3120 assert!(!verifier.notarizes_force); verifier.add(Voter::Notarize(notarize_s1.clone()), false); assert!(!verifier.ready_notarizes());
3125 verifier.add(Voter::Notarize(notarize_s2.clone()), false); assert!(!verifier.ready_notarizes());
3127 verifier.add(Voter::Notarize(notarize_s3.clone()), false); assert!(verifier.ready_notarizes()); assert_eq!(verifier.notarizes.len(), 3);
3130
3131 let (verified_n, failed_n) = verifier.verify_notarizes(NAMESPACE, &polynomial);
3132 assert_eq!(verified_n.len(), 3);
3133 assert!(failed_n.is_empty());
3134 assert_eq!(verifier.notarizes_verified, 1 + 3); assert!(verifier.notarizes.is_empty());
3136
3137 assert!(!verifier.ready_notarizes());
3139
3140 let mut verifier2 = BatchVerifier::<MinSig, Sha256>::new(Some(threshold));
3142 verifier2.set_leader(shares[0].index); let leader_notarize = create_notarize(&shares[0], 2, 1, 10);
3144 verifier2.add(Voter::Notarize(leader_notarize.clone()), false); let mut faulty_notarize = create_notarize(&shares[1], 2, 1, 10); let (_, _, other_shares) = generate_test_data(n_validators, threshold, 126);
3149 faulty_notarize.proposal_signature = Notarize::<MinSig, _>::sign(
3150 NAMESPACE,
3151 &other_shares[1],
3152 faulty_notarize.proposal.clone(),
3153 ) .proposal_signature;
3155
3156 verifier2.add(Voter::Notarize(faulty_notarize.clone()), false); assert!(verifier2.ready_notarizes()); let (verified_n, failed_n) = verifier2.verify_notarizes(NAMESPACE, &polynomial);
3160 assert_eq!(verified_n.len(), 1); assert!(verified_n.contains(&Voter::Notarize(leader_notarize)));
3162 assert_eq!(failed_n.len(), 1);
3163 assert_eq!(failed_n[0], shares[1].index); }
3165
3166 #[test]
3167 fn test_batch_verifier_add_nullify() {
3168 let n_validators = 5;
3169 let threshold = quorum(n_validators);
3170 let (_, _, shares) = generate_test_data(n_validators, threshold, 127);
3171 let mut verifier = BatchVerifier::<MinSig, Sha256>::new(Some(threshold));
3172
3173 let nullify1_s0 = create_nullify(&shares[0], 1);
3174
3175 verifier.add(Voter::Nullify(nullify1_s0.clone()), false);
3177 assert_eq!(verifier.nullifies.len(), 1);
3178 assert_eq!(verifier.nullifies_verified, 0);
3179
3180 verifier.add(Voter::Nullify(nullify1_s0.clone()), true);
3182 assert_eq!(verifier.nullifies.len(), 1);
3183 assert_eq!(verifier.nullifies_verified, 1);
3184 }
3185
3186 #[test]
3187 fn test_batch_verifier_ready_and_verify_nullifies() {
3188 let n_validators = 5;
3189 let threshold = quorum(n_validators); let (_, polynomial, shares) = generate_test_data(n_validators, threshold, 128);
3191 let mut verifier = BatchVerifier::<MinSig, Sha256>::new(Some(threshold));
3192
3193 let nullify_s0 = create_nullify(&shares[0], 1);
3194 let nullify_s1 = create_nullify(&shares[1], 1);
3195 let nullify_s2 = create_nullify(&shares[2], 1);
3196 let nullify_s3 = create_nullify(&shares[3], 1); verifier.add(Voter::Nullify(nullify_s0.clone()), true); assert_eq!(verifier.nullifies_verified, 1);
3201 verifier.add(Voter::Nullify(nullify_s1.clone()), false); assert!(!verifier.ready_nullifies());
3203 verifier.add(Voter::Nullify(nullify_s2.clone()), false); assert!(!verifier.ready_nullifies());
3205
3206 verifier.add(Voter::Nullify(nullify_s3.clone()), false); assert!(verifier.ready_nullifies());
3209 assert_eq!(verifier.nullifies.len(), 3);
3210
3211 let (verified_null, failed_null) = verifier.verify_nullifies(NAMESPACE, &polynomial);
3212 assert_eq!(verified_null.len(), 3);
3213 assert!(failed_null.is_empty());
3214 assert_eq!(verifier.nullifies_verified, 1 + 3);
3215
3216 assert!(verifier.nullifies.is_empty());
3218 assert!(!verifier.ready_nullifies());
3219 }
3220
3221 #[test]
3222 fn test_batch_verifier_add_finalize() {
3223 let n_validators = 5;
3224 let threshold = quorum(n_validators);
3225 let (_, _, shares) = generate_test_data(n_validators, threshold, 129);
3226 let mut verifier = BatchVerifier::<MinSig, Sha256>::new(Some(threshold));
3227
3228 let finalize_s0_prop_a = create_finalize(&shares[0], 1, 0, 1); let finalize_s1_prop_b = create_finalize(&shares[1], 1, 0, 2); verifier.add(Voter::Finalize(finalize_s1_prop_b.clone()), false);
3233 assert_eq!(verifier.finalizes.len(), 1);
3234 assert_eq!(verifier.finalizes_verified, 0);
3235
3236 verifier.add(Voter::Finalize(finalize_s0_prop_a.clone()), false);
3238 assert_eq!(verifier.finalizes.len(), 2); verifier.set_leader(shares[0].index);
3243 assert!(verifier.leader_proposal.is_none());
3244 verifier.set_leader_proposal(finalize_s0_prop_a.proposal.clone());
3246 assert_eq!(verifier.finalizes.len(), 1);
3248 assert_eq!(verifier.finalizes[0], finalize_s0_prop_a);
3249 assert_eq!(verifier.finalizes_verified, 0);
3250
3251 verifier.add(Voter::Finalize(finalize_s0_prop_a.clone()), true);
3253 assert_eq!(verifier.finalizes.len(), 1); assert_eq!(verifier.finalizes_verified, 1); verifier.add(Voter::Finalize(finalize_s1_prop_b.clone()), false);
3258 assert_eq!(verifier.finalizes.len(), 1); assert_eq!(verifier.finalizes_verified, 1);
3260 }
3261
3262 #[test]
3263 fn test_batch_verifier_ready_and_verify_finalizes() {
3264 let n_validators = 5;
3265 let threshold = quorum(n_validators); let (_, polynomial, shares) = generate_test_data(n_validators, threshold, 130);
3267 let mut verifier = BatchVerifier::<MinSig, Sha256>::new(Some(threshold));
3268 let leader_proposal = Proposal::new(1, 0, sample_digest(1));
3269
3270 let finalize_s0 =
3271 Finalize::<MinSig, _>::sign(NAMESPACE, &shares[0], leader_proposal.clone());
3272 let finalize_s1 =
3273 Finalize::<MinSig, _>::sign(NAMESPACE, &shares[1], leader_proposal.clone());
3274 let finalize_s2 =
3275 Finalize::<MinSig, _>::sign(NAMESPACE, &shares[2], leader_proposal.clone());
3276 let finalize_s3 =
3277 Finalize::<MinSig, _>::sign(NAMESPACE, &shares[3], leader_proposal.clone());
3278
3279 assert!(!verifier.ready_finalizes());
3281
3282 verifier.set_leader(shares[0].index); verifier.set_leader_proposal(leader_proposal.clone());
3286
3287 verifier.add(Voter::Finalize(finalize_s0.clone()), true); assert_eq!(verifier.finalizes_verified, 1);
3290 assert_eq!(verifier.finalizes.len(), 0);
3291
3292 verifier.add(Voter::Finalize(finalize_s1.clone()), false); assert!(!verifier.ready_finalizes());
3294 verifier.add(Voter::Finalize(finalize_s2.clone()), false); assert!(!verifier.ready_finalizes());
3296
3297 verifier.add(Voter::Finalize(finalize_s3.clone()), false); assert!(verifier.ready_finalizes()); let (verified_fin, failed_fin) = verifier.verify_finalizes(NAMESPACE, &polynomial);
3302 assert_eq!(verified_fin.len(), 3);
3303 assert!(failed_fin.is_empty());
3304 assert_eq!(verifier.finalizes_verified, 1 + 3);
3305 assert!(verifier.finalizes.is_empty());
3306
3307 assert!(!verifier.ready_finalizes());
3309 }
3310
3311 #[test]
3312 fn test_batch_verifier_quorum_none() {
3313 let n_validators = 3;
3314 let threshold = quorum(n_validators); let (_, polynomial, shares) = generate_test_data(n_validators, threshold, 200);
3316
3317 let mut verifier_n = BatchVerifier::<MinSig, Sha256>::new(None);
3319 let prop1 = Proposal::new(1, 0, sample_digest(1));
3320 let notarize1 = create_notarize(&shares[0], 1, 0, 1);
3321
3322 assert!(!verifier_n.ready_notarizes()); verifier_n.set_leader(shares[0].index);
3324 verifier_n.add(Voter::Notarize(notarize1.clone()), false); assert!(verifier_n.ready_notarizes()); let (verified, failed) = verifier_n.verify_notarizes(NAMESPACE, &polynomial);
3328 assert_eq!(verified.len(), 1);
3329 assert!(failed.is_empty());
3330 assert_eq!(verifier_n.notarizes_verified, 1);
3331 assert!(!verifier_n.ready_notarizes()); let mut verifier_null = BatchVerifier::<MinSig, Sha256>::new(None);
3335 let nullify1 = create_nullify(&shares[0], 1);
3336 assert!(!verifier_null.ready_nullifies()); verifier_null.add(Voter::Nullify(nullify1.clone()), false);
3338 assert!(verifier_null.ready_nullifies()); let (verified, failed) = verifier_null.verify_nullifies(NAMESPACE, &polynomial);
3340 assert_eq!(verified.len(), 1);
3341 assert!(failed.is_empty());
3342 assert_eq!(verifier_null.nullifies_verified, 1);
3343 assert!(!verifier_null.ready_nullifies()); let mut verifier_f = BatchVerifier::<MinSig, Sha256>::new(None);
3347 let finalize1 = create_finalize(&shares[0], 1, 0, 1);
3348 assert!(!verifier_f.ready_finalizes()); verifier_f.set_leader(shares[0].index);
3350 verifier_f.set_leader_proposal(prop1.clone()); verifier_f.add(Voter::Finalize(finalize1.clone()), false);
3352 assert!(verifier_f.ready_finalizes()); let (verified, failed) = verifier_f.verify_finalizes(NAMESPACE, &polynomial);
3354 assert_eq!(verified.len(), 1);
3355 assert!(failed.is_empty());
3356 assert_eq!(verifier_f.finalizes_verified, 1);
3357 assert!(!verifier_f.ready_finalizes()); }
3359
3360 #[test]
3361 fn test_batch_verifier_leader_proposal_filters_messages() {
3362 let n_validators = 3;
3363 let threshold = quorum(n_validators);
3364 let (_, _, shares) = generate_test_data(n_validators, threshold, 201);
3365 let mut verifier = BatchVerifier::<MinSig, Sha256>::new(Some(threshold));
3366
3367 let proposal_a = Proposal::new(1, 0, sample_digest(10));
3368 let proposal_b = Proposal::new(1, 0, sample_digest(20));
3369
3370 let notarize_a_s0 = Notarize::<MinSig, _>::sign(NAMESPACE, &shares[0], proposal_a.clone());
3371 let notarize_b_s1 = Notarize::<MinSig, _>::sign(NAMESPACE, &shares[1], proposal_b.clone());
3372 let finalize_a_s0 = Finalize::<MinSig, _>::sign(NAMESPACE, &shares[0], proposal_a.clone());
3373 let finalize_b_s1 = Finalize::<MinSig, _>::sign(NAMESPACE, &shares[1], proposal_b.clone());
3374
3375 verifier.add(Voter::Notarize(notarize_a_s0.clone()), false);
3376 verifier.add(Voter::Notarize(notarize_b_s1.clone()), false);
3377 verifier.add(Voter::Finalize(finalize_a_s0.clone()), false);
3378 verifier.add(Voter::Finalize(finalize_b_s1.clone()), false);
3379
3380 assert_eq!(verifier.notarizes.len(), 2);
3381 assert_eq!(verifier.finalizes.len(), 2);
3382
3383 verifier.set_leader(shares[0].index);
3387
3388 assert!(verifier.notarizes_force);
3389 assert_eq!(verifier.notarizes.len(), 1);
3390 assert_eq!(verifier.notarizes[0].proposal, proposal_a);
3391 assert_eq!(verifier.finalizes.len(), 1);
3392 assert_eq!(verifier.finalizes[0].proposal, proposal_a);
3393 }
3394
3395 #[test]
3396 #[should_panic(expected = "self.leader.is_none()")]
3397 fn test_batch_verifier_set_leader_twice_panics() {
3398 let mut verifier = BatchVerifier::<MinSig, Sha256>::new(Some(3));
3399 verifier.set_leader(0);
3400 verifier.set_leader(1); }
3402
3403 #[test]
3404 #[should_panic(expected = "should not be adding recovered messages to partial verifier")]
3405 fn test_batch_verifier_add_recovered_message_panics() {
3406 let n_validators = 3;
3407 let threshold = quorum(n_validators);
3408 let (_, _, shares) = generate_test_data(n_validators, threshold, 202);
3409 let mut verifier = BatchVerifier::<MinSig, Sha256>::new(Some(threshold));
3410
3411 let notarization = create_notarization(1, 0, 1, &shares, threshold);
3412 verifier.add(Voter::Notarization(notarization), false); }
3414
3415 #[test]
3416 fn test_ready_notarizes_behavior_with_force_flag() {
3417 let n_validators = 3;
3418 let threshold = quorum(n_validators);
3419 let (_, polynomial, shares) = generate_test_data(n_validators, threshold, 203);
3420 let mut verifier = BatchVerifier::<MinSig, Sha256>::new(Some(threshold));
3421
3422 let leader_notarize = create_notarize(&shares[0], 1, 0, 1);
3423
3424 verifier.set_leader(shares[0].index);
3426 verifier.add(Voter::Notarize(leader_notarize.clone()), false);
3428
3429 assert!(
3430 verifier.notarizes_force,
3431 "notarizes_force should be true after leader's proposal is set"
3432 );
3433 assert!(
3434 verifier.ready_notarizes(),
3435 "Ready should be true when notarizes_force is true"
3436 );
3437
3438 let (verified, _) = verifier.verify_notarizes(NAMESPACE, &polynomial);
3440 assert_eq!(verified.len(), 1);
3441
3442 assert!(
3443 !verifier.notarizes_force,
3444 "notarizes_force should be false after verification"
3445 );
3446 assert!(
3447 !verifier.ready_notarizes(),
3448 "Ready should be false now (no pending, quorum not met by verified alone)"
3449 );
3450 }
3451
3452 #[test]
3453 fn test_ready_notarizes_without_leader_or_proposal() {
3454 let n_validators = 3;
3455 let threshold = quorum(n_validators);
3456 let (_, _, shares) = generate_test_data(n_validators, threshold, 204);
3457 let mut verifier = BatchVerifier::<MinSig, Sha256>::new(Some(threshold));
3458
3459 for i in 0..threshold {
3461 verifier.add(
3462 Voter::Notarize(create_notarize(&shares[i as usize], 1, 0, 1)),
3463 false,
3464 );
3465 }
3466 assert!(
3467 !verifier.ready_notarizes(),
3468 "Should not be ready without leader/proposal set"
3469 );
3470
3471 verifier.set_leader(shares[0].index);
3473 assert!(
3474 verifier.ready_notarizes(),
3475 "Should be ready once leader is set"
3476 );
3477 }
3478
3479 #[test]
3480 fn test_ready_finalizes_without_leader_or_proposal() {
3481 let n_validators = 3;
3482 let threshold = quorum(n_validators);
3483 let (_, _, shares) = generate_test_data(n_validators, threshold, 205);
3484 let mut verifier = BatchVerifier::<MinSig, Sha256>::new(Some(threshold));
3485
3486 for i in 0..threshold {
3487 verifier.add(
3488 Voter::Finalize(create_finalize(&shares[i as usize], 1, 0, 1)),
3489 false,
3490 );
3491 }
3492 assert!(
3493 !verifier.ready_finalizes(),
3494 "Should not be ready without leader/proposal set"
3495 );
3496
3497 verifier.set_leader(shares[0].index);
3499 assert!(
3500 !verifier.ready_finalizes(),
3501 "Should not be ready without leader_proposal set"
3502 );
3503 }
3504
3505 #[test]
3506 fn test_verify_notarizes_empty_pending_when_forced() {
3507 let n_validators = 3;
3508 let threshold = quorum(n_validators);
3509 let mut verifier = BatchVerifier::<MinSig, Sha256>::new(Some(threshold));
3510
3511 let leader_proposal = Proposal::new(1, 0, sample_digest(1));
3512 verifier.set_leader_proposal(leader_proposal); assert!(verifier.notarizes_force);
3515 assert!(verifier.notarizes.is_empty());
3516 assert!(!verifier.ready_notarizes());
3517 }
3518
3519 #[test]
3520 fn test_verify_nullifies_empty_pending() {
3521 let n_validators = 3;
3522 let threshold = quorum(n_validators);
3523 let (_, polynomial, _) = generate_test_data(n_validators, threshold, 207);
3524 let mut verifier = BatchVerifier::<MinSig, Sha256>::new(Some(threshold));
3525
3526 assert!(verifier.nullifies.is_empty());
3527 assert!(!verifier.ready_nullifies());
3529
3530 let (verified, failed) = verifier.verify_nullifies(NAMESPACE, &polynomial);
3531 assert!(verified.is_empty());
3532 assert!(failed.is_empty());
3533 assert_eq!(verifier.nullifies_verified, 0);
3534 }
3535
3536 #[test]
3537 fn test_verify_finalizes_empty_pending() {
3538 let n_validators = 3;
3539 let threshold = quorum(n_validators);
3540 let (_, polynomial, shares) = generate_test_data(n_validators, threshold, 208);
3541 let mut verifier = BatchVerifier::<MinSig, Sha256>::new(Some(threshold));
3542
3543 verifier.set_leader(shares[0].index);
3545 assert!(verifier.finalizes.is_empty());
3546 assert!(!verifier.ready_finalizes());
3547
3548 let (verified, failed) = verifier.verify_finalizes(NAMESPACE, &polynomial);
3549 assert!(verified.is_empty());
3550 assert!(failed.is_empty());
3551 assert_eq!(verifier.finalizes_verified, 0);
3552 }
3553
3554 #[test]
3555 fn test_ready_notarizes_exact_quorum() {
3556 let n_validators = 5;
3557 let threshold = quorum(n_validators); let (_, polynomial, shares) = generate_test_data(n_validators, threshold, 209);
3559 let mut verifier = BatchVerifier::<MinSig, Sha256>::new(Some(threshold));
3560
3561 let leader_notarize = create_notarize(&shares[0], 1, 0, 1);
3562 verifier.set_leader(shares[0].index);
3563 verifier.add(Voter::Notarize(leader_notarize), true); assert_eq!(verifier.notarizes_verified, 1);
3565
3566 verifier.add(Voter::Notarize(create_notarize(&shares[1], 1, 0, 1)), false);
3568
3569 assert!(verifier.ready_notarizes());
3571 let (verified, failed) = verifier.verify_notarizes(NAMESPACE, &polynomial);
3572 assert_eq!(verified.len(), 1);
3573 assert!(failed.is_empty());
3574 assert_eq!(verifier.notarizes_verified, 1 + 1);
3575
3576 for share in shares.iter().take(threshold as usize).skip(2) {
3578 assert!(!verifier.ready_notarizes());
3579 verifier.add(Voter::Notarize(create_notarize(share, 1, 0, 1)), false);
3580 }
3581
3582 assert!(verifier.ready_notarizes());
3584 }
3585
3586 #[test]
3587 fn test_ready_nullifies_exact_quorum() {
3588 let n_validators = 5;
3589 let threshold = quorum(n_validators); let (_, _, shares) = generate_test_data(n_validators, threshold, 210);
3591 let mut verifier = BatchVerifier::<MinSig, Sha256>::new(Some(threshold));
3592
3593 verifier.add(Voter::Nullify(create_nullify(&shares[0], 1)), true); assert_eq!(verifier.nullifies_verified, 1);
3595
3596 for share in shares.iter().take(threshold as usize).skip(1) {
3597 assert!(!verifier.ready_nullifies());
3598 verifier.add(Voter::Nullify(create_nullify(share, 1)), false);
3599 }
3600 assert!(verifier.ready_nullifies());
3601 }
3602
3603 #[test]
3604 fn test_ready_finalizes_exact_quorum() {
3605 let n_validators = 5;
3606 let threshold = quorum(n_validators); let (_, _, shares) = generate_test_data(n_validators, threshold, 211);
3608 let mut verifier = BatchVerifier::<MinSig, Sha256>::new(Some(threshold));
3609
3610 let leader_proposal = Proposal::new(1, 0, sample_digest(1));
3611 verifier.set_leader(shares[0].index);
3612 verifier.set_leader_proposal(leader_proposal.clone());
3613
3614 verifier.add(Voter::Finalize(create_finalize(&shares[0], 1, 0, 1)), true); assert_eq!(verifier.finalizes_verified, 1);
3616
3617 for share in shares.iter().take(threshold as usize).skip(1) {
3618 assert!(!verifier.ready_finalizes());
3619 verifier.add(Voter::Finalize(create_finalize(share, 1, 0, 1)), false);
3620 }
3621 assert!(verifier.ready_finalizes());
3622 }
3623
3624 #[test]
3625 fn test_ready_notarizes_quorum_already_met_by_verified() {
3626 let n_validators = 5;
3627 let threshold = quorum(n_validators); let (_, _, shares) = generate_test_data(n_validators, threshold, 212);
3629 let mut verifier = BatchVerifier::<MinSig, Sha256>::new(Some(threshold));
3630
3631 let leader_notarize = create_notarize(&shares[0], 1, 0, 1);
3632 verifier.set_leader(shares[0].index);
3633 verifier.add(Voter::Notarize(leader_notarize), false); verifier.notarizes_force = false;
3636
3637 for share in shares.iter().take(threshold as usize) {
3638 verifier.add(Voter::Notarize(create_notarize(share, 1, 0, 1)), true);
3639 }
3640 assert_eq!(verifier.notarizes_verified as u32, threshold);
3641 assert!(
3642 !verifier.ready_notarizes(),
3643 "Should not be ready if quorum already met by verified messages"
3644 );
3645
3646 verifier.add(
3648 Voter::Notarize(create_notarize(&shares[threshold as usize], 1, 0, 1)),
3649 false,
3650 );
3651 assert!(!verifier.ready_notarizes());
3652 }
3653
3654 #[test]
3655 fn test_ready_nullifies_quorum_already_met_by_verified() {
3656 let n_validators = 5;
3657 let threshold = quorum(n_validators); let (_, _, shares) = generate_test_data(n_validators, threshold, 213);
3659 let mut verifier = BatchVerifier::<MinSig, Sha256>::new(Some(threshold));
3660
3661 for share in shares.iter().take(threshold as usize) {
3662 verifier.add(Voter::Nullify(create_nullify(share, 1)), true);
3663 }
3664 assert_eq!(verifier.nullifies_verified as u32, threshold);
3665 assert!(!verifier.ready_nullifies());
3666
3667 verifier.add(
3668 Voter::Nullify(create_nullify(&shares[threshold as usize], 1)),
3669 false,
3670 );
3671 assert!(!verifier.ready_nullifies());
3672 }
3673
3674 #[test]
3675 fn test_ready_finalizes_quorum_already_met_by_verified() {
3676 let n_validators = 5;
3677 let threshold = quorum(n_validators); let (_, _, shares) = generate_test_data(n_validators, threshold, 214);
3679 let mut verifier = BatchVerifier::<MinSig, Sha256>::new(Some(threshold));
3680
3681 let leader_proposal = Proposal::new(1, 0, sample_digest(1));
3682 verifier.set_leader(shares[0].index);
3683 verifier.set_leader_proposal(leader_proposal.clone());
3684
3685 for share in shares.iter().take(threshold as usize) {
3686 verifier.add(Voter::Finalize(create_finalize(share, 1, 0, 1)), true);
3687 }
3688 assert_eq!(verifier.finalizes_verified as u32, threshold);
3689 assert!(!verifier.ready_finalizes());
3690
3691 verifier.add(
3692 Voter::Finalize(create_finalize(&shares[threshold as usize], 1, 0, 1)),
3693 false,
3694 );
3695 assert!(!verifier.ready_finalizes());
3696 }
3697}