1use crate::{
4 simplex::scheme,
5 types::{Epoch, Participant, Round, View},
6 Epochable, Viewable,
7};
8use bytes::{Buf, BufMut};
9use commonware_codec::{varint::UInt, EncodeSize, Error, Read, ReadExt, ReadRangeExt, Write};
10use commonware_cryptography::{
11 certificate::{Attestation, Scheme},
12 Digest, PublicKey,
13};
14use commonware_parallel::Strategy;
15use commonware_utils::N3f1;
16use rand_core::CryptoRngCore;
17use std::{collections::HashSet, fmt::Debug, hash::Hash};
18
19#[derive(Clone, Debug, PartialEq, Eq)]
22pub struct Context<D: Digest, P: PublicKey> {
23 pub round: Round,
25 pub leader: P,
27 pub parent: (View, D),
34}
35
36impl<D: Digest, P: PublicKey> Epochable for Context<D, P> {
37 fn epoch(&self) -> Epoch {
38 self.round.epoch()
39 }
40}
41
42impl<D: Digest, P: PublicKey> Viewable for Context<D, P> {
43 fn view(&self) -> View {
44 self.round.view()
45 }
46}
47
48impl<D: Digest, P: PublicKey> Write for Context<D, P> {
49 fn write(&self, buf: &mut impl BufMut) {
50 self.round.write(buf);
51 self.leader.write(buf);
52 self.parent.write(buf);
53 }
54}
55
56impl<D: Digest, P: PublicKey> EncodeSize for Context<D, P> {
57 fn encode_size(&self) -> usize {
58 self.round.encode_size() + self.leader.encode_size() + self.parent.encode_size()
59 }
60}
61
62impl<D: Digest, P: PublicKey> Read for Context<D, P> {
63 type Cfg = ();
64
65 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
66 let round = Round::read(reader)?;
67 let leader = P::read(reader)?;
68 let parent = <(View, D)>::read_cfg(reader, &((), ()))?;
69
70 Ok(Self {
71 round,
72 leader,
73 parent,
74 })
75 }
76}
77
78#[cfg(feature = "arbitrary")]
79impl<D: Digest, P: PublicKey> arbitrary::Arbitrary<'_> for Context<D, P>
80where
81 D: for<'a> arbitrary::Arbitrary<'a>,
82 P: for<'a> arbitrary::Arbitrary<'a>,
83{
84 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
85 Ok(Self {
86 round: Round::arbitrary(u)?,
87 leader: P::arbitrary(u)?,
88 parent: (View::arbitrary(u)?, D::arbitrary(u)?),
89 })
90 }
91}
92
93pub trait Attributable {
96 fn signer(&self) -> Participant;
98}
99
100pub struct AttributableMap<T: Attributable> {
105 data: Vec<Option<T>>,
106 added: usize,
107}
108
109impl<T: Attributable> AttributableMap<T> {
110 pub fn new(participants: usize) -> Self {
112 let mut data = Vec::with_capacity(participants);
114 data.resize_with(participants, || None);
115
116 Self { data, added: 0 }
117 }
118
119 pub fn clear(&mut self) {
121 self.data.fill_with(|| None);
122 self.added = 0;
123 }
124
125 pub fn insert(&mut self, item: T) -> bool {
131 let index: usize = item.signer().into();
132 if index >= self.data.len() {
133 return false;
134 }
135 if self.data[index].is_some() {
136 return false;
137 }
138 self.data[index] = Some(item);
139 self.added += 1;
140 true
141 }
142
143 pub const fn len(&self) -> usize {
145 self.added
146 }
147
148 pub const fn is_empty(&self) -> bool {
150 self.added == 0
151 }
152
153 pub fn get(&self, signer: Participant) -> Option<&T> {
155 self.data.get(<usize>::from(signer))?.as_ref()
156 }
157
158 pub fn iter(&self) -> impl Iterator<Item = &T> {
161 self.data.iter().filter_map(|o| o.as_ref())
162 }
163}
164
165pub struct VoteTracker<S: Scheme, D: Digest> {
171 notarizes: AttributableMap<Notarize<S, D>>,
173 nullifies: AttributableMap<Nullify<S>>,
175 finalizes: AttributableMap<Finalize<S, D>>,
180}
181
182impl<S: Scheme, D: Digest> VoteTracker<S, D> {
183 pub fn new(participants: usize) -> Self {
185 Self {
186 notarizes: AttributableMap::new(participants),
187 nullifies: AttributableMap::new(participants),
188 finalizes: AttributableMap::new(participants),
189 }
190 }
191
192 pub fn insert_notarize(&mut self, vote: Notarize<S, D>) -> bool {
194 self.notarizes.insert(vote)
195 }
196
197 pub fn insert_nullify(&mut self, vote: Nullify<S>) -> bool {
199 self.nullifies.insert(vote)
200 }
201
202 pub fn insert_finalize(&mut self, vote: Finalize<S, D>) -> bool {
204 self.finalizes.insert(vote)
205 }
206
207 pub fn notarize(&self, signer: Participant) -> Option<&Notarize<S, D>> {
209 self.notarizes.get(signer)
210 }
211
212 pub fn nullify(&self, signer: Participant) -> Option<&Nullify<S>> {
214 self.nullifies.get(signer)
215 }
216
217 pub fn finalize(&self, signer: Participant) -> Option<&Finalize<S, D>> {
219 self.finalizes.get(signer)
220 }
221
222 pub fn iter_notarizes(&self) -> impl Iterator<Item = &Notarize<S, D>> {
224 self.notarizes.iter()
225 }
226
227 pub fn iter_nullifies(&self) -> impl Iterator<Item = &Nullify<S>> {
229 self.nullifies.iter()
230 }
231
232 pub fn iter_finalizes(&self) -> impl Iterator<Item = &Finalize<S, D>> {
234 self.finalizes.iter()
235 }
236
237 pub fn len_notarizes(&self) -> u32 {
239 u32::try_from(self.notarizes.len()).expect("too many notarize votes")
240 }
241
242 pub fn len_nullifies(&self) -> u32 {
244 u32::try_from(self.nullifies.len()).expect("too many nullify votes")
245 }
246
247 pub fn len_finalizes(&self) -> u32 {
249 u32::try_from(self.finalizes.len()).expect("too many finalize votes")
250 }
251
252 pub fn has_notarize(&self, signer: Participant) -> bool {
254 self.notarizes.get(signer).is_some()
255 }
256
257 pub fn has_nullify(&self, signer: Participant) -> bool {
259 self.nullifies.get(signer).is_some()
260 }
261
262 pub fn has_finalize(&self, signer: Participant) -> bool {
264 self.finalizes.get(signer).is_some()
265 }
266
267 pub fn clear_notarizes(&mut self) {
269 self.notarizes.clear();
270 }
271
272 pub fn clear_finalizes(&mut self) {
274 self.finalizes.clear();
275 }
276}
277
278#[derive(Copy, Clone, Debug)]
283pub enum Subject<'a, D: Digest> {
284 Notarize { proposal: &'a Proposal<D> },
286 Nullify { round: Round },
288 Finalize { proposal: &'a Proposal<D> },
290}
291
292impl<D: Digest> Viewable for Subject<'_, D> {
293 fn view(&self) -> View {
294 match self {
295 Subject::Notarize { proposal } => proposal.view(),
296 Subject::Nullify { round } => round.view(),
297 Subject::Finalize { proposal } => proposal.view(),
298 }
299 }
300}
301
302#[derive(Clone, Debug, PartialEq)]
304pub enum Vote<S: Scheme, D: Digest> {
305 Notarize(Notarize<S, D>),
307 Nullify(Nullify<S>),
309 Finalize(Finalize<S, D>),
311}
312
313impl<S: Scheme, D: Digest> Write for Vote<S, D> {
314 fn write(&self, writer: &mut impl BufMut) {
315 match self {
316 Self::Notarize(v) => {
317 0u8.write(writer);
318 v.write(writer);
319 }
320 Self::Nullify(v) => {
321 1u8.write(writer);
322 v.write(writer);
323 }
324 Self::Finalize(v) => {
325 2u8.write(writer);
326 v.write(writer);
327 }
328 }
329 }
330}
331
332impl<S: Scheme, D: Digest> EncodeSize for Vote<S, D> {
333 fn encode_size(&self) -> usize {
334 1 + match self {
335 Self::Notarize(v) => v.encode_size(),
336 Self::Nullify(v) => v.encode_size(),
337 Self::Finalize(v) => v.encode_size(),
338 }
339 }
340}
341
342impl<S: Scheme, D: Digest> Read for Vote<S, D> {
343 type Cfg = ();
344
345 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
346 let tag = <u8>::read(reader)?;
347 match tag {
348 0 => {
349 let v = Notarize::read(reader)?;
350 Ok(Self::Notarize(v))
351 }
352 1 => {
353 let v = Nullify::read(reader)?;
354 Ok(Self::Nullify(v))
355 }
356 2 => {
357 let v = Finalize::read(reader)?;
358 Ok(Self::Finalize(v))
359 }
360 _ => Err(Error::Invalid("consensus::simplex::Vote", "Invalid type")),
361 }
362 }
363}
364
365impl<S: Scheme, D: Digest> Epochable for Vote<S, D> {
366 fn epoch(&self) -> Epoch {
367 match self {
368 Self::Notarize(v) => v.epoch(),
369 Self::Nullify(v) => v.epoch(),
370 Self::Finalize(v) => v.epoch(),
371 }
372 }
373}
374
375impl<S: Scheme, D: Digest> Viewable for Vote<S, D> {
376 fn view(&self) -> View {
377 match self {
378 Self::Notarize(v) => v.view(),
379 Self::Nullify(v) => v.view(),
380 Self::Finalize(v) => v.view(),
381 }
382 }
383}
384
385#[cfg(feature = "arbitrary")]
386impl<S: Scheme, D: Digest> arbitrary::Arbitrary<'_> for Vote<S, D>
387where
388 S::Signature: for<'a> arbitrary::Arbitrary<'a>,
389 D: for<'a> arbitrary::Arbitrary<'a>,
390{
391 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
392 let tag = u.int_in_range(0..=2)?;
393 match tag {
394 0 => {
395 let v = Notarize::arbitrary(u)?;
396 Ok(Self::Notarize(v))
397 }
398 1 => {
399 let v = Nullify::arbitrary(u)?;
400 Ok(Self::Nullify(v))
401 }
402 2 => {
403 let v = Finalize::arbitrary(u)?;
404 Ok(Self::Finalize(v))
405 }
406 _ => unreachable!(),
407 }
408 }
409}
410
411#[derive(Clone, Debug, PartialEq)]
413pub enum Certificate<S: Scheme, D: Digest> {
414 Notarization(Notarization<S, D>),
416 Nullification(Nullification<S>),
418 Finalization(Finalization<S, D>),
420}
421
422impl<S: Scheme, D: Digest> Write for Certificate<S, D> {
423 fn write(&self, writer: &mut impl BufMut) {
424 match self {
425 Self::Notarization(v) => {
426 0u8.write(writer);
427 v.write(writer);
428 }
429 Self::Nullification(v) => {
430 1u8.write(writer);
431 v.write(writer);
432 }
433 Self::Finalization(v) => {
434 2u8.write(writer);
435 v.write(writer);
436 }
437 }
438 }
439}
440
441impl<S: Scheme, D: Digest> EncodeSize for Certificate<S, D> {
442 fn encode_size(&self) -> usize {
443 1 + match self {
444 Self::Notarization(v) => v.encode_size(),
445 Self::Nullification(v) => v.encode_size(),
446 Self::Finalization(v) => v.encode_size(),
447 }
448 }
449}
450
451impl<S: Scheme, D: Digest> Read for Certificate<S, D> {
452 type Cfg = <S::Certificate as Read>::Cfg;
453
454 fn read_cfg(reader: &mut impl Buf, cfg: &Self::Cfg) -> Result<Self, Error> {
455 let tag = <u8>::read(reader)?;
456 match tag {
457 0 => {
458 let v = Notarization::read_cfg(reader, cfg)?;
459 Ok(Self::Notarization(v))
460 }
461 1 => {
462 let v = Nullification::read_cfg(reader, cfg)?;
463 Ok(Self::Nullification(v))
464 }
465 2 => {
466 let v = Finalization::read_cfg(reader, cfg)?;
467 Ok(Self::Finalization(v))
468 }
469 _ => Err(Error::Invalid(
470 "consensus::simplex::Certificate",
471 "Invalid type",
472 )),
473 }
474 }
475}
476
477impl<S: Scheme, D: Digest> Epochable for Certificate<S, D> {
478 fn epoch(&self) -> Epoch {
479 match self {
480 Self::Notarization(v) => v.epoch(),
481 Self::Nullification(v) => v.epoch(),
482 Self::Finalization(v) => v.epoch(),
483 }
484 }
485}
486
487impl<S: Scheme, D: Digest> Viewable for Certificate<S, D> {
488 fn view(&self) -> View {
489 match self {
490 Self::Notarization(v) => v.view(),
491 Self::Nullification(v) => v.view(),
492 Self::Finalization(v) => v.view(),
493 }
494 }
495}
496
497#[cfg(feature = "arbitrary")]
498impl<S: Scheme, D: Digest> arbitrary::Arbitrary<'_> for Certificate<S, D>
499where
500 S::Certificate: for<'a> arbitrary::Arbitrary<'a>,
501 D: for<'a> arbitrary::Arbitrary<'a>,
502{
503 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
504 let tag = u.int_in_range(0..=2)?;
505 match tag {
506 0 => {
507 let v = Notarization::arbitrary(u)?;
508 Ok(Self::Notarization(v))
509 }
510 1 => {
511 let v = Nullification::arbitrary(u)?;
512 Ok(Self::Nullification(v))
513 }
514 2 => {
515 let v = Finalization::arbitrary(u)?;
516 Ok(Self::Finalization(v))
517 }
518 _ => unreachable!(),
519 }
520 }
521}
522
523#[derive(Clone, Debug, PartialEq)]
525pub enum Artifact<S: Scheme, D: Digest> {
526 Notarize(Notarize<S, D>),
528 Notarization(Notarization<S, D>),
530 Certification(Round, bool),
532 Nullify(Nullify<S>),
534 Nullification(Nullification<S>),
536 Finalize(Finalize<S, D>),
538 Finalization(Finalization<S, D>),
540}
541
542impl<S: Scheme, D: Digest> Write for Artifact<S, D> {
543 fn write(&self, writer: &mut impl BufMut) {
544 match self {
545 Self::Notarize(v) => {
546 0u8.write(writer);
547 v.write(writer);
548 }
549 Self::Notarization(v) => {
550 1u8.write(writer);
551 v.write(writer);
552 }
553 Self::Certification(r, b) => {
554 2u8.write(writer);
555 r.write(writer);
556 b.write(writer);
557 }
558 Self::Nullify(v) => {
559 3u8.write(writer);
560 v.write(writer);
561 }
562 Self::Nullification(v) => {
563 4u8.write(writer);
564 v.write(writer);
565 }
566 Self::Finalize(v) => {
567 5u8.write(writer);
568 v.write(writer);
569 }
570 Self::Finalization(v) => {
571 6u8.write(writer);
572 v.write(writer);
573 }
574 }
575 }
576}
577
578impl<S: Scheme, D: Digest> EncodeSize for Artifact<S, D> {
579 fn encode_size(&self) -> usize {
580 1 + match self {
581 Self::Notarize(v) => v.encode_size(),
582 Self::Notarization(v) => v.encode_size(),
583 Self::Certification(r, b) => r.encode_size() + b.encode_size(),
584 Self::Nullify(v) => v.encode_size(),
585 Self::Nullification(v) => v.encode_size(),
586 Self::Finalize(v) => v.encode_size(),
587 Self::Finalization(v) => v.encode_size(),
588 }
589 }
590}
591
592impl<S: Scheme, D: Digest> Read for Artifact<S, D> {
593 type Cfg = <S::Certificate as Read>::Cfg;
594
595 fn read_cfg(reader: &mut impl Buf, cfg: &Self::Cfg) -> Result<Self, Error> {
596 let tag = <u8>::read(reader)?;
597 match tag {
598 0 => {
599 let v = Notarize::read(reader)?;
600 Ok(Self::Notarize(v))
601 }
602 1 => {
603 let v = Notarization::read_cfg(reader, cfg)?;
604 Ok(Self::Notarization(v))
605 }
606 2 => {
607 let r = Round::read(reader)?;
608 let b = bool::read(reader)?;
609 Ok(Self::Certification(r, b))
610 }
611 3 => {
612 let v = Nullify::read(reader)?;
613 Ok(Self::Nullify(v))
614 }
615 4 => {
616 let v = Nullification::read_cfg(reader, cfg)?;
617 Ok(Self::Nullification(v))
618 }
619 5 => {
620 let v = Finalize::read(reader)?;
621 Ok(Self::Finalize(v))
622 }
623 6 => {
624 let v = Finalization::read_cfg(reader, cfg)?;
625 Ok(Self::Finalization(v))
626 }
627 _ => Err(Error::Invalid(
628 "consensus::simplex::Artifact",
629 "Invalid type",
630 )),
631 }
632 }
633}
634
635impl<S: Scheme, D: Digest> Epochable for Artifact<S, D> {
636 fn epoch(&self) -> Epoch {
637 match self {
638 Self::Notarize(v) => v.epoch(),
639 Self::Notarization(v) => v.epoch(),
640 Self::Certification(r, _) => r.epoch(),
641 Self::Nullify(v) => v.epoch(),
642 Self::Nullification(v) => v.epoch(),
643 Self::Finalize(v) => v.epoch(),
644 Self::Finalization(v) => v.epoch(),
645 }
646 }
647}
648
649impl<S: Scheme, D: Digest> Viewable for Artifact<S, D> {
650 fn view(&self) -> View {
651 match self {
652 Self::Notarize(v) => v.view(),
653 Self::Notarization(v) => v.view(),
654 Self::Certification(r, _) => r.view(),
655 Self::Nullify(v) => v.view(),
656 Self::Nullification(v) => v.view(),
657 Self::Finalize(v) => v.view(),
658 Self::Finalization(v) => v.view(),
659 }
660 }
661}
662
663impl<S: Scheme, D: Digest> From<Vote<S, D>> for Artifact<S, D> {
664 fn from(vote: Vote<S, D>) -> Self {
665 match vote {
666 Vote::Notarize(v) => Self::Notarize(v),
667 Vote::Nullify(v) => Self::Nullify(v),
668 Vote::Finalize(v) => Self::Finalize(v),
669 }
670 }
671}
672
673impl<S: Scheme, D: Digest> From<Certificate<S, D>> for Artifact<S, D> {
674 fn from(cert: Certificate<S, D>) -> Self {
675 match cert {
676 Certificate::Notarization(v) => Self::Notarization(v),
677 Certificate::Nullification(v) => Self::Nullification(v),
678 Certificate::Finalization(v) => Self::Finalization(v),
679 }
680 }
681}
682
683#[cfg(feature = "arbitrary")]
684impl<S: Scheme, D: Digest> arbitrary::Arbitrary<'_> for Artifact<S, D>
685where
686 S::Signature: for<'a> arbitrary::Arbitrary<'a>,
687 S::Certificate: for<'a> arbitrary::Arbitrary<'a>,
688 D: for<'a> arbitrary::Arbitrary<'a>,
689{
690 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
691 let tag = u.int_in_range(0..=6)?;
692 match tag {
693 0 => {
694 let v = Notarize::arbitrary(u)?;
695 Ok(Self::Notarize(v))
696 }
697 1 => {
698 let v = Notarization::arbitrary(u)?;
699 Ok(Self::Notarization(v))
700 }
701 2 => {
702 let r = Round::arbitrary(u)?;
703 let b = bool::arbitrary(u)?;
704 Ok(Self::Certification(r, b))
705 }
706 3 => {
707 let v = Nullify::arbitrary(u)?;
708 Ok(Self::Nullify(v))
709 }
710 4 => {
711 let v = Nullification::arbitrary(u)?;
712 Ok(Self::Nullification(v))
713 }
714 5 => {
715 let v = Finalize::arbitrary(u)?;
716 Ok(Self::Finalize(v))
717 }
718 6 => {
719 let v = Finalization::arbitrary(u)?;
720 Ok(Self::Finalization(v))
721 }
722 _ => unreachable!(),
723 }
724 }
725}
726
727#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
730pub struct Proposal<D: Digest> {
731 pub round: Round,
733 pub parent: View,
735 pub payload: D,
737}
738
739impl<D: Digest> Proposal<D> {
740 pub const fn new(round: Round, parent: View, payload: D) -> Self {
742 Self {
743 round,
744 parent,
745 payload,
746 }
747 }
748}
749
750impl<D: Digest> Write for Proposal<D> {
751 fn write(&self, writer: &mut impl BufMut) {
752 self.round.write(writer);
753 self.parent.write(writer);
754 self.payload.write(writer)
755 }
756}
757
758impl<D: Digest> Read for Proposal<D> {
759 type Cfg = ();
760
761 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
762 let round = Round::read(reader)?;
763 let parent = View::read(reader)?;
764 let payload = D::read(reader)?;
765 Ok(Self {
766 round,
767 parent,
768 payload,
769 })
770 }
771}
772
773impl<D: Digest> EncodeSize for Proposal<D> {
774 fn encode_size(&self) -> usize {
775 self.round.encode_size() + self.parent.encode_size() + self.payload.encode_size()
776 }
777}
778
779impl<D: Digest> Epochable for Proposal<D> {
780 fn epoch(&self) -> Epoch {
781 self.round.epoch()
782 }
783}
784
785impl<D: Digest> Viewable for Proposal<D> {
786 fn view(&self) -> View {
787 self.round.view()
788 }
789}
790
791#[cfg(feature = "arbitrary")]
792impl<D: Digest> arbitrary::Arbitrary<'_> for Proposal<D>
793where
794 D: for<'a> arbitrary::Arbitrary<'a>,
795{
796 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
797 let round = Round::arbitrary(u)?;
798 let parent = View::arbitrary(u)?;
799 let payload = D::arbitrary(u)?;
800 Ok(Self {
801 round,
802 parent,
803 payload,
804 })
805 }
806}
807
808#[derive(Clone, Debug)]
810pub struct Notarize<S: Scheme, D: Digest> {
811 pub proposal: Proposal<D>,
813 pub attestation: Attestation<S>,
815}
816
817impl<S: Scheme, D: Digest> Notarize<S, D> {
818 pub fn sign(scheme: &S, proposal: Proposal<D>) -> Option<Self>
820 where
821 S: scheme::Scheme<D>,
822 {
823 let attestation = scheme.sign::<D>(Subject::Notarize {
824 proposal: &proposal,
825 })?;
826
827 Some(Self {
828 proposal,
829 attestation,
830 })
831 }
832
833 pub fn verify<R>(&self, rng: &mut R, scheme: &S, strategy: &impl Strategy) -> bool
837 where
838 R: CryptoRngCore,
839 S: scheme::Scheme<D>,
840 {
841 scheme.verify_attestation::<_, D>(
842 rng,
843 Subject::Notarize {
844 proposal: &self.proposal,
845 },
846 &self.attestation,
847 strategy,
848 )
849 }
850
851 pub const fn round(&self) -> Round {
853 self.proposal.round
854 }
855}
856
857impl<S: Scheme, D: Digest> PartialEq for Notarize<S, D> {
858 fn eq(&self, other: &Self) -> bool {
859 self.proposal == other.proposal && self.attestation == other.attestation
860 }
861}
862
863impl<S: Scheme, D: Digest> Eq for Notarize<S, D> {}
864
865impl<S: Scheme, D: Digest> Hash for Notarize<S, D> {
866 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
867 self.proposal.hash(state);
868 self.attestation.hash(state);
869 }
870}
871
872impl<S: Scheme, D: Digest> Write for Notarize<S, D> {
873 fn write(&self, writer: &mut impl BufMut) {
874 self.proposal.write(writer);
875 self.attestation.write(writer);
876 }
877}
878
879impl<S: Scheme, D: Digest> EncodeSize for Notarize<S, D> {
880 fn encode_size(&self) -> usize {
881 self.proposal.encode_size() + self.attestation.encode_size()
882 }
883}
884
885impl<S: Scheme, D: Digest> Read for Notarize<S, D> {
886 type Cfg = ();
887
888 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
889 let proposal = Proposal::read(reader)?;
890 let attestation = Attestation::read(reader)?;
891
892 Ok(Self {
893 proposal,
894 attestation,
895 })
896 }
897}
898
899impl<S: Scheme, D: Digest> Attributable for Notarize<S, D> {
900 fn signer(&self) -> Participant {
901 self.attestation.signer
902 }
903}
904
905impl<S: Scheme, D: Digest> Epochable for Notarize<S, D> {
906 fn epoch(&self) -> Epoch {
907 self.proposal.epoch()
908 }
909}
910
911impl<S: Scheme, D: Digest> Viewable for Notarize<S, D> {
912 fn view(&self) -> View {
913 self.proposal.view()
914 }
915}
916
917#[cfg(feature = "arbitrary")]
918impl<S: Scheme, D: Digest> arbitrary::Arbitrary<'_> for Notarize<S, D>
919where
920 S::Signature: for<'a> arbitrary::Arbitrary<'a>,
921 D: for<'a> arbitrary::Arbitrary<'a>,
922{
923 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
924 let proposal = Proposal::arbitrary(u)?;
925 let attestation = Attestation::arbitrary(u)?;
926 Ok(Self {
927 proposal,
928 attestation,
929 })
930 }
931}
932
933#[derive(Clone, Debug)]
940pub struct Notarization<S: Scheme, D: Digest> {
941 pub proposal: Proposal<D>,
943 pub certificate: S::Certificate,
945}
946
947impl<S: Scheme, D: Digest> Notarization<S, D> {
948 pub fn from_notarizes<'a, I>(scheme: &S, notarizes: I, strategy: &impl Strategy) -> Option<Self>
950 where
951 I: IntoIterator<Item = &'a Notarize<S, D>>,
952 I::IntoIter: Send,
953 {
954 let mut iter = notarizes.into_iter().peekable();
955 let proposal = iter.peek()?.proposal.clone();
956 let certificate =
957 scheme.assemble::<_, N3f1>(iter.map(|n| n.attestation.clone()), strategy)?;
958
959 Some(Self {
960 proposal,
961 certificate,
962 })
963 }
964
965 pub fn verify<R: CryptoRngCore>(
969 &self,
970 rng: &mut R,
971 scheme: &S,
972 strategy: &impl Strategy,
973 ) -> bool
974 where
975 S: scheme::Scheme<D>,
976 {
977 scheme.verify_certificate::<_, D, N3f1>(
978 rng,
979 Subject::Notarize {
980 proposal: &self.proposal,
981 },
982 &self.certificate,
983 strategy,
984 )
985 }
986
987 pub const fn round(&self) -> Round {
989 self.proposal.round
990 }
991}
992
993impl<S: Scheme, D: Digest> PartialEq for Notarization<S, D> {
994 fn eq(&self, other: &Self) -> bool {
995 self.proposal == other.proposal && self.certificate == other.certificate
996 }
997}
998
999impl<S: Scheme, D: Digest> Eq for Notarization<S, D> {}
1000
1001impl<S: Scheme, D: Digest> Hash for Notarization<S, D> {
1002 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1003 self.proposal.hash(state);
1004 self.certificate.hash(state);
1005 }
1006}
1007
1008impl<S: Scheme, D: Digest> Write for Notarization<S, D> {
1009 fn write(&self, writer: &mut impl BufMut) {
1010 self.proposal.write(writer);
1011 self.certificate.write(writer);
1012 }
1013}
1014
1015impl<S: Scheme, D: Digest> EncodeSize for Notarization<S, D> {
1016 fn encode_size(&self) -> usize {
1017 self.proposal.encode_size() + self.certificate.encode_size()
1018 }
1019}
1020
1021impl<S: Scheme, D: Digest> Read for Notarization<S, D> {
1022 type Cfg = <S::Certificate as Read>::Cfg;
1023
1024 fn read_cfg(reader: &mut impl Buf, cfg: &Self::Cfg) -> Result<Self, Error> {
1025 let proposal = Proposal::read(reader)?;
1026 let certificate = S::Certificate::read_cfg(reader, cfg)?;
1027
1028 Ok(Self {
1029 proposal,
1030 certificate,
1031 })
1032 }
1033}
1034
1035impl<S: Scheme, D: Digest> Epochable for Notarization<S, D> {
1036 fn epoch(&self) -> Epoch {
1037 self.proposal.epoch()
1038 }
1039}
1040
1041impl<S: Scheme, D: Digest> Viewable for Notarization<S, D> {
1042 fn view(&self) -> View {
1043 self.proposal.view()
1044 }
1045}
1046
1047#[cfg(feature = "arbitrary")]
1048impl<S: Scheme, D: Digest> arbitrary::Arbitrary<'_> for Notarization<S, D>
1049where
1050 S::Certificate: for<'a> arbitrary::Arbitrary<'a>,
1051 D: for<'a> arbitrary::Arbitrary<'a>,
1052{
1053 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
1054 let proposal = Proposal::arbitrary(u)?;
1055 let certificate = S::Certificate::arbitrary(u)?;
1056 Ok(Self {
1057 proposal,
1058 certificate,
1059 })
1060 }
1061}
1062
1063#[derive(Clone, Debug)]
1066pub struct Nullify<S: Scheme> {
1067 pub round: Round,
1069 pub attestation: Attestation<S>,
1071}
1072
1073impl<S: Scheme> PartialEq for Nullify<S> {
1074 fn eq(&self, other: &Self) -> bool {
1075 self.round == other.round && self.attestation == other.attestation
1076 }
1077}
1078
1079impl<S: Scheme> Eq for Nullify<S> {}
1080
1081impl<S: Scheme> Hash for Nullify<S> {
1082 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1083 self.round.hash(state);
1084 self.attestation.hash(state);
1085 }
1086}
1087
1088impl<S: Scheme> Nullify<S> {
1089 pub fn sign<D: Digest>(scheme: &S, round: Round) -> Option<Self>
1091 where
1092 S: scheme::Scheme<D>,
1093 {
1094 let attestation = scheme.sign::<D>(Subject::Nullify { round })?;
1095
1096 Some(Self { round, attestation })
1097 }
1098
1099 pub fn verify<R, D: Digest>(&self, rng: &mut R, scheme: &S, strategy: &impl Strategy) -> bool
1103 where
1104 R: CryptoRngCore,
1105 S: scheme::Scheme<D>,
1106 {
1107 scheme.verify_attestation::<_, D>(
1108 rng,
1109 Subject::Nullify { round: self.round },
1110 &self.attestation,
1111 strategy,
1112 )
1113 }
1114
1115 pub const fn round(&self) -> Round {
1117 self.round
1118 }
1119}
1120
1121impl<S: Scheme> Write for Nullify<S> {
1122 fn write(&self, writer: &mut impl BufMut) {
1123 self.round.write(writer);
1124 self.attestation.write(writer);
1125 }
1126}
1127
1128impl<S: Scheme> EncodeSize for Nullify<S> {
1129 fn encode_size(&self) -> usize {
1130 self.round.encode_size() + self.attestation.encode_size()
1131 }
1132}
1133
1134impl<S: Scheme> Read for Nullify<S> {
1135 type Cfg = ();
1136
1137 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
1138 let round = Round::read(reader)?;
1139 let attestation = Attestation::read(reader)?;
1140
1141 Ok(Self { round, attestation })
1142 }
1143}
1144
1145impl<S: Scheme> Attributable for Nullify<S> {
1146 fn signer(&self) -> Participant {
1147 self.attestation.signer
1148 }
1149}
1150
1151impl<S: Scheme> Epochable for Nullify<S> {
1152 fn epoch(&self) -> Epoch {
1153 self.round.epoch()
1154 }
1155}
1156
1157impl<S: Scheme> Viewable for Nullify<S> {
1158 fn view(&self) -> View {
1159 self.round.view()
1160 }
1161}
1162
1163#[cfg(feature = "arbitrary")]
1164impl<S: Scheme> arbitrary::Arbitrary<'_> for Nullify<S>
1165where
1166 S::Signature: for<'a> arbitrary::Arbitrary<'a>,
1167{
1168 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
1169 let round = Round::arbitrary(u)?;
1170 let attestation = Attestation::arbitrary(u)?;
1171 Ok(Self { round, attestation })
1172 }
1173}
1174
1175#[derive(Clone, Debug)]
1178pub struct Nullification<S: Scheme> {
1179 pub round: Round,
1181 pub certificate: S::Certificate,
1183}
1184
1185impl<S: Scheme> Nullification<S> {
1186 pub fn from_nullifies<'a, I>(scheme: &S, nullifies: I, strategy: &impl Strategy) -> Option<Self>
1188 where
1189 I: IntoIterator<Item = &'a Nullify<S>>,
1190 I::IntoIter: Send,
1191 {
1192 let mut iter = nullifies.into_iter().peekable();
1193 let round = iter.peek()?.round;
1194 let certificate =
1195 scheme.assemble::<_, N3f1>(iter.map(|n| n.attestation.clone()), strategy)?;
1196
1197 Some(Self { round, certificate })
1198 }
1199
1200 pub fn verify<R: CryptoRngCore, D: Digest>(
1204 &self,
1205 rng: &mut R,
1206 scheme: &S,
1207 strategy: &impl Strategy,
1208 ) -> bool
1209 where
1210 S: scheme::Scheme<D>,
1211 {
1212 scheme.verify_certificate::<_, D, N3f1>(
1213 rng,
1214 Subject::Nullify { round: self.round },
1215 &self.certificate,
1216 strategy,
1217 )
1218 }
1219
1220 pub const fn round(&self) -> Round {
1222 self.round
1223 }
1224}
1225
1226impl<S: Scheme> PartialEq for Nullification<S> {
1227 fn eq(&self, other: &Self) -> bool {
1228 self.round == other.round && self.certificate == other.certificate
1229 }
1230}
1231
1232impl<S: Scheme> Eq for Nullification<S> {}
1233
1234impl<S: Scheme> Hash for Nullification<S> {
1235 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1236 self.round.hash(state);
1237 self.certificate.hash(state);
1238 }
1239}
1240
1241impl<S: Scheme> Write for Nullification<S> {
1242 fn write(&self, writer: &mut impl BufMut) {
1243 self.round.write(writer);
1244 self.certificate.write(writer);
1245 }
1246}
1247
1248impl<S: Scheme> EncodeSize for Nullification<S> {
1249 fn encode_size(&self) -> usize {
1250 self.round.encode_size() + self.certificate.encode_size()
1251 }
1252}
1253
1254impl<S: Scheme> Read for Nullification<S> {
1255 type Cfg = <S::Certificate as Read>::Cfg;
1256
1257 fn read_cfg(reader: &mut impl Buf, cfg: &Self::Cfg) -> Result<Self, Error> {
1258 let round = Round::read(reader)?;
1259 let certificate = S::Certificate::read_cfg(reader, cfg)?;
1260
1261 Ok(Self { round, certificate })
1262 }
1263}
1264
1265impl<S: Scheme> Epochable for Nullification<S> {
1266 fn epoch(&self) -> Epoch {
1267 self.round.epoch()
1268 }
1269}
1270
1271impl<S: Scheme> Viewable for Nullification<S> {
1272 fn view(&self) -> View {
1273 self.round.view()
1274 }
1275}
1276
1277#[cfg(feature = "arbitrary")]
1278impl<S: Scheme> arbitrary::Arbitrary<'_> for Nullification<S>
1279where
1280 S::Certificate: for<'a> arbitrary::Arbitrary<'a>,
1281{
1282 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
1283 let round = Round::arbitrary(u)?;
1284 let certificate = S::Certificate::arbitrary(u)?;
1285 Ok(Self { round, certificate })
1286 }
1287}
1288
1289#[derive(Clone, Debug)]
1293pub struct Finalize<S: Scheme, D: Digest> {
1294 pub proposal: Proposal<D>,
1296 pub attestation: Attestation<S>,
1298}
1299
1300impl<S: Scheme, D: Digest> Finalize<S, D> {
1301 pub fn sign(scheme: &S, proposal: Proposal<D>) -> Option<Self>
1303 where
1304 S: scheme::Scheme<D>,
1305 {
1306 let attestation = scheme.sign::<D>(Subject::Finalize {
1307 proposal: &proposal,
1308 })?;
1309
1310 Some(Self {
1311 proposal,
1312 attestation,
1313 })
1314 }
1315
1316 pub fn verify<R>(&self, rng: &mut R, scheme: &S, strategy: &impl Strategy) -> bool
1320 where
1321 R: CryptoRngCore,
1322 S: scheme::Scheme<D>,
1323 {
1324 scheme.verify_attestation::<_, D>(
1325 rng,
1326 Subject::Finalize {
1327 proposal: &self.proposal,
1328 },
1329 &self.attestation,
1330 strategy,
1331 )
1332 }
1333
1334 pub const fn round(&self) -> Round {
1336 self.proposal.round
1337 }
1338}
1339
1340impl<S: Scheme, D: Digest> PartialEq for Finalize<S, D> {
1341 fn eq(&self, other: &Self) -> bool {
1342 self.proposal == other.proposal && self.attestation == other.attestation
1343 }
1344}
1345
1346impl<S: Scheme, D: Digest> Eq for Finalize<S, D> {}
1347
1348impl<S: Scheme, D: Digest> Hash for Finalize<S, D> {
1349 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1350 self.proposal.hash(state);
1351 self.attestation.hash(state);
1352 }
1353}
1354
1355impl<S: Scheme, D: Digest> Write for Finalize<S, D> {
1356 fn write(&self, writer: &mut impl BufMut) {
1357 self.proposal.write(writer);
1358 self.attestation.write(writer);
1359 }
1360}
1361
1362impl<S: Scheme, D: Digest> EncodeSize for Finalize<S, D> {
1363 fn encode_size(&self) -> usize {
1364 self.proposal.encode_size() + self.attestation.encode_size()
1365 }
1366}
1367
1368impl<S: Scheme, D: Digest> Read for Finalize<S, D> {
1369 type Cfg = ();
1370
1371 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
1372 let proposal = Proposal::read(reader)?;
1373 let attestation = Attestation::read(reader)?;
1374
1375 Ok(Self {
1376 proposal,
1377 attestation,
1378 })
1379 }
1380}
1381
1382impl<S: Scheme, D: Digest> Attributable for Finalize<S, D> {
1383 fn signer(&self) -> Participant {
1384 self.attestation.signer
1385 }
1386}
1387
1388impl<S: Scheme, D: Digest> Epochable for Finalize<S, D> {
1389 fn epoch(&self) -> Epoch {
1390 self.proposal.epoch()
1391 }
1392}
1393
1394impl<S: Scheme, D: Digest> Viewable for Finalize<S, D> {
1395 fn view(&self) -> View {
1396 self.proposal.view()
1397 }
1398}
1399
1400#[cfg(feature = "arbitrary")]
1401impl<S: Scheme, D: Digest> arbitrary::Arbitrary<'_> for Finalize<S, D>
1402where
1403 S::Signature: for<'a> arbitrary::Arbitrary<'a>,
1404 D: for<'a> arbitrary::Arbitrary<'a>,
1405{
1406 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
1407 let proposal = Proposal::arbitrary(u)?;
1408 let attestation = Attestation::arbitrary(u)?;
1409 Ok(Self {
1410 proposal,
1411 attestation,
1412 })
1413 }
1414}
1415
1416#[derive(Clone, Debug)]
1423pub struct Finalization<S: Scheme, D: Digest> {
1424 pub proposal: Proposal<D>,
1426 pub certificate: S::Certificate,
1428}
1429
1430impl<S: Scheme, D: Digest> Finalization<S, D> {
1431 pub fn from_finalizes<'a, I>(scheme: &S, finalizes: I, strategy: &impl Strategy) -> Option<Self>
1433 where
1434 I: IntoIterator<Item = &'a Finalize<S, D>>,
1435 I::IntoIter: Send,
1436 {
1437 let mut iter = finalizes.into_iter().peekable();
1438 let proposal = iter.peek()?.proposal.clone();
1439 let certificate =
1440 scheme.assemble::<_, N3f1>(iter.map(|f| f.attestation.clone()), strategy)?;
1441
1442 Some(Self {
1443 proposal,
1444 certificate,
1445 })
1446 }
1447
1448 pub fn verify<R: CryptoRngCore>(
1452 &self,
1453 rng: &mut R,
1454 scheme: &S,
1455 strategy: &impl Strategy,
1456 ) -> bool
1457 where
1458 S: scheme::Scheme<D>,
1459 {
1460 scheme.verify_certificate::<_, D, N3f1>(
1461 rng,
1462 Subject::Finalize {
1463 proposal: &self.proposal,
1464 },
1465 &self.certificate,
1466 strategy,
1467 )
1468 }
1469
1470 pub const fn round(&self) -> Round {
1472 self.proposal.round
1473 }
1474}
1475
1476impl<S: Scheme, D: Digest> PartialEq for Finalization<S, D> {
1477 fn eq(&self, other: &Self) -> bool {
1478 self.proposal == other.proposal && self.certificate == other.certificate
1479 }
1480}
1481
1482impl<S: Scheme, D: Digest> Eq for Finalization<S, D> {}
1483
1484impl<S: Scheme, D: Digest> Hash for Finalization<S, D> {
1485 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1486 self.proposal.hash(state);
1487 self.certificate.hash(state);
1488 }
1489}
1490
1491impl<S: Scheme, D: Digest> Write for Finalization<S, D> {
1492 fn write(&self, writer: &mut impl BufMut) {
1493 self.proposal.write(writer);
1494 self.certificate.write(writer);
1495 }
1496}
1497
1498impl<S: Scheme, D: Digest> EncodeSize for Finalization<S, D> {
1499 fn encode_size(&self) -> usize {
1500 self.proposal.encode_size() + self.certificate.encode_size()
1501 }
1502}
1503
1504impl<S: Scheme, D: Digest> Read for Finalization<S, D> {
1505 type Cfg = <S::Certificate as Read>::Cfg;
1506
1507 fn read_cfg(reader: &mut impl Buf, cfg: &Self::Cfg) -> Result<Self, Error> {
1508 let proposal = Proposal::read(reader)?;
1509 let certificate = S::Certificate::read_cfg(reader, cfg)?;
1510
1511 Ok(Self {
1512 proposal,
1513 certificate,
1514 })
1515 }
1516}
1517
1518impl<S: Scheme, D: Digest> Epochable for Finalization<S, D> {
1519 fn epoch(&self) -> Epoch {
1520 self.proposal.epoch()
1521 }
1522}
1523
1524impl<S: Scheme, D: Digest> Viewable for Finalization<S, D> {
1525 fn view(&self) -> View {
1526 self.proposal.view()
1527 }
1528}
1529
1530#[cfg(feature = "arbitrary")]
1531impl<S: Scheme, D: Digest> arbitrary::Arbitrary<'_> for Finalization<S, D>
1532where
1533 S::Certificate: for<'a> arbitrary::Arbitrary<'a>,
1534 D: for<'a> arbitrary::Arbitrary<'a>,
1535{
1536 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
1537 let proposal = Proposal::arbitrary(u)?;
1538 let certificate = S::Certificate::arbitrary(u)?;
1539 Ok(Self {
1540 proposal,
1541 certificate,
1542 })
1543 }
1544}
1545
1546#[derive(Clone, Debug, PartialEq)]
1549pub enum Backfiller<S: Scheme, D: Digest> {
1550 Request(Request),
1552 Response(Response<S, D>),
1554}
1555
1556impl<S: Scheme, D: Digest> Write for Backfiller<S, D> {
1557 fn write(&self, writer: &mut impl BufMut) {
1558 match self {
1559 Self::Request(request) => {
1560 0u8.write(writer);
1561 request.write(writer);
1562 }
1563 Self::Response(response) => {
1564 1u8.write(writer);
1565 response.write(writer);
1566 }
1567 }
1568 }
1569}
1570
1571impl<S: Scheme, D: Digest> EncodeSize for Backfiller<S, D> {
1572 fn encode_size(&self) -> usize {
1573 1 + match self {
1574 Self::Request(v) => v.encode_size(),
1575 Self::Response(v) => v.encode_size(),
1576 }
1577 }
1578}
1579
1580impl<S: Scheme, D: Digest> Read for Backfiller<S, D> {
1581 type Cfg = (usize, <S::Certificate as Read>::Cfg);
1582
1583 fn read_cfg(reader: &mut impl Buf, cfg: &Self::Cfg) -> Result<Self, Error> {
1584 let tag = <u8>::read(reader)?;
1585 match tag {
1586 0 => {
1587 let (max_len, _) = cfg;
1588 let v = Request::read_cfg(reader, max_len)?;
1589 Ok(Self::Request(v))
1590 }
1591 1 => {
1592 let v = Response::<S, D>::read_cfg(reader, cfg)?;
1593 Ok(Self::Response(v))
1594 }
1595 _ => Err(Error::Invalid(
1596 "consensus::simplex::Backfiller",
1597 "Invalid type",
1598 )),
1599 }
1600 }
1601}
1602
1603#[cfg(feature = "arbitrary")]
1604impl<S: Scheme, D: Digest> arbitrary::Arbitrary<'_> for Backfiller<S, D>
1605where
1606 S::Certificate: for<'a> arbitrary::Arbitrary<'a>,
1607 D: for<'a> arbitrary::Arbitrary<'a>,
1608{
1609 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
1610 let tag = u.int_in_range(0..=1)?;
1611 match tag {
1612 0 => {
1613 let v = Request::arbitrary(u)?;
1614 Ok(Self::Request(v))
1615 }
1616 1 => {
1617 let v = Response::<S, D>::arbitrary(u)?;
1618 Ok(Self::Response(v))
1619 }
1620 _ => unreachable!(),
1621 }
1622 }
1623}
1624
1625#[derive(Clone, Debug, PartialEq)]
1628#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1629pub struct Request {
1630 pub id: u64,
1632 pub notarizations: Vec<View>,
1634 pub nullifications: Vec<View>,
1636}
1637
1638impl Request {
1639 pub const fn new(id: u64, notarizations: Vec<View>, nullifications: Vec<View>) -> Self {
1641 Self {
1642 id,
1643 notarizations,
1644 nullifications,
1645 }
1646 }
1647}
1648
1649impl Write for Request {
1650 fn write(&self, writer: &mut impl BufMut) {
1651 UInt(self.id).write(writer);
1652 self.notarizations.write(writer);
1653 self.nullifications.write(writer);
1654 }
1655}
1656
1657impl EncodeSize for Request {
1658 fn encode_size(&self) -> usize {
1659 UInt(self.id).encode_size()
1660 + self.notarizations.encode_size()
1661 + self.nullifications.encode_size()
1662 }
1663}
1664
1665impl Read for Request {
1666 type Cfg = usize;
1667
1668 fn read_cfg(reader: &mut impl Buf, max_len: &usize) -> Result<Self, Error> {
1669 let id = UInt::read(reader)?.into();
1670 let mut views = HashSet::new();
1671 let notarizations = Vec::<View>::read_range(reader, ..=*max_len)?;
1672 for view in notarizations.iter() {
1673 if !views.insert(view) {
1674 return Err(Error::Invalid(
1675 "consensus::simplex::Request",
1676 "Duplicate notarization",
1677 ));
1678 }
1679 }
1680 let remaining = max_len - notarizations.len();
1681 views.clear();
1682 let nullifications = Vec::<View>::read_range(reader, ..=remaining)?;
1683 for view in nullifications.iter() {
1684 if !views.insert(view) {
1685 return Err(Error::Invalid(
1686 "consensus::simplex::Request",
1687 "Duplicate nullification",
1688 ));
1689 }
1690 }
1691 Ok(Self {
1692 id,
1693 notarizations,
1694 nullifications,
1695 })
1696 }
1697}
1698
1699#[derive(Clone, Debug, PartialEq)]
1702pub struct Response<S: Scheme, D: Digest> {
1703 pub id: u64,
1705 pub notarizations: Vec<Notarization<S, D>>,
1707 pub nullifications: Vec<Nullification<S>>,
1709}
1710
1711impl<S: Scheme, D: Digest> Response<S, D> {
1712 pub const fn new(
1714 id: u64,
1715 notarizations: Vec<Notarization<S, D>>,
1716 nullifications: Vec<Nullification<S>>,
1717 ) -> Self {
1718 Self {
1719 id,
1720 notarizations,
1721 nullifications,
1722 }
1723 }
1724
1725 pub fn verify<R: CryptoRngCore>(
1727 &self,
1728 rng: &mut R,
1729 scheme: &S,
1730 strategy: &impl Strategy,
1731 ) -> bool
1732 where
1733 S: scheme::Scheme<D>,
1734 {
1735 if self.notarizations.is_empty() && self.nullifications.is_empty() {
1737 return true;
1738 }
1739
1740 let notarizations = self.notarizations.iter().map(|notarization| {
1741 let context = Subject::Notarize {
1742 proposal: ¬arization.proposal,
1743 };
1744
1745 (context, ¬arization.certificate)
1746 });
1747
1748 let nullifications = self.nullifications.iter().map(|nullification| {
1749 let context = Subject::Nullify {
1750 round: nullification.round,
1751 };
1752
1753 (context, &nullification.certificate)
1754 });
1755
1756 scheme.verify_certificates::<_, D, _, N3f1>(
1757 rng,
1758 notarizations.chain(nullifications),
1759 strategy,
1760 )
1761 }
1762}
1763
1764impl<S: Scheme, D: Digest> Write for Response<S, D> {
1765 fn write(&self, writer: &mut impl BufMut) {
1766 UInt(self.id).write(writer);
1767 self.notarizations.write(writer);
1768 self.nullifications.write(writer);
1769 }
1770}
1771
1772impl<S: Scheme, D: Digest> EncodeSize for Response<S, D> {
1773 fn encode_size(&self) -> usize {
1774 UInt(self.id).encode_size()
1775 + self.notarizations.encode_size()
1776 + self.nullifications.encode_size()
1777 }
1778}
1779
1780impl<S: Scheme, D: Digest> Read for Response<S, D> {
1781 type Cfg = (usize, <S::Certificate as Read>::Cfg);
1782
1783 fn read_cfg(reader: &mut impl Buf, cfg: &Self::Cfg) -> Result<Self, Error> {
1784 let (max_len, certificate_cfg) = cfg;
1785 let id = UInt::read(reader)?.into();
1786 let mut views = HashSet::new();
1787 let notarizations = Vec::<Notarization<S, D>>::read_cfg(
1788 reader,
1789 &((..=*max_len).into(), certificate_cfg.clone()),
1790 )?;
1791 for notarization in notarizations.iter() {
1792 if !views.insert(notarization.view()) {
1793 return Err(Error::Invalid(
1794 "consensus::simplex::Response",
1795 "Duplicate notarization",
1796 ));
1797 }
1798 }
1799 let remaining = max_len - notarizations.len();
1800 views.clear();
1801 let nullifications = Vec::<Nullification<S>>::read_cfg(
1802 reader,
1803 &((..=remaining).into(), certificate_cfg.clone()),
1804 )?;
1805 for nullification in nullifications.iter() {
1806 if !views.insert(nullification.view()) {
1807 return Err(Error::Invalid(
1808 "consensus::simplex::Response",
1809 "Duplicate nullification",
1810 ));
1811 }
1812 }
1813 Ok(Self {
1814 id,
1815 notarizations,
1816 nullifications,
1817 })
1818 }
1819}
1820
1821#[cfg(feature = "arbitrary")]
1822impl<S: Scheme, D: Digest> arbitrary::Arbitrary<'_> for Response<S, D>
1823where
1824 S::Certificate: for<'a> arbitrary::Arbitrary<'a>,
1825 D: for<'a> arbitrary::Arbitrary<'a>,
1826{
1827 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
1828 let id = u.arbitrary()?;
1829 let notarizations = u.arbitrary()?;
1830 let nullifications = u.arbitrary()?;
1831 Ok(Self {
1832 id,
1833 notarizations,
1834 nullifications,
1835 })
1836 }
1837}
1838
1839#[derive(Clone, Debug)]
1857pub enum Activity<S: Scheme, D: Digest> {
1858 Notarize(Notarize<S, D>),
1860 Notarization(Notarization<S, D>),
1862 Certification(Notarization<S, D>),
1864 Nullify(Nullify<S>),
1866 Nullification(Nullification<S>),
1868 Finalize(Finalize<S, D>),
1870 Finalization(Finalization<S, D>),
1872 ConflictingNotarize(ConflictingNotarize<S, D>),
1874 ConflictingFinalize(ConflictingFinalize<S, D>),
1876 NullifyFinalize(NullifyFinalize<S, D>),
1878}
1879
1880impl<S: Scheme, D: Digest> PartialEq for Activity<S, D> {
1881 fn eq(&self, other: &Self) -> bool {
1882 match (self, other) {
1883 (Self::Notarize(a), Self::Notarize(b)) => a == b,
1884 (Self::Notarization(a), Self::Notarization(b)) => a == b,
1885 (Self::Certification(a), Self::Certification(b)) => a == b,
1886 (Self::Nullify(a), Self::Nullify(b)) => a == b,
1887 (Self::Nullification(a), Self::Nullification(b)) => a == b,
1888 (Self::Finalize(a), Self::Finalize(b)) => a == b,
1889 (Self::Finalization(a), Self::Finalization(b)) => a == b,
1890 (Self::ConflictingNotarize(a), Self::ConflictingNotarize(b)) => a == b,
1891 (Self::ConflictingFinalize(a), Self::ConflictingFinalize(b)) => a == b,
1892 (Self::NullifyFinalize(a), Self::NullifyFinalize(b)) => a == b,
1893 _ => false,
1894 }
1895 }
1896}
1897
1898impl<S: Scheme, D: Digest> Eq for Activity<S, D> {}
1899
1900impl<S: Scheme, D: Digest> Hash for Activity<S, D> {
1901 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1902 match self {
1903 Self::Notarize(v) => {
1904 0u8.hash(state);
1905 v.hash(state);
1906 }
1907 Self::Notarization(v) => {
1908 1u8.hash(state);
1909 v.hash(state);
1910 }
1911 Self::Certification(v) => {
1912 2u8.hash(state);
1913 v.hash(state);
1914 }
1915 Self::Nullify(v) => {
1916 3u8.hash(state);
1917 v.hash(state);
1918 }
1919 Self::Nullification(v) => {
1920 4u8.hash(state);
1921 v.hash(state);
1922 }
1923 Self::Finalize(v) => {
1924 5u8.hash(state);
1925 v.hash(state);
1926 }
1927 Self::Finalization(v) => {
1928 6u8.hash(state);
1929 v.hash(state);
1930 }
1931 Self::ConflictingNotarize(v) => {
1932 7u8.hash(state);
1933 v.hash(state);
1934 }
1935 Self::ConflictingFinalize(v) => {
1936 8u8.hash(state);
1937 v.hash(state);
1938 }
1939 Self::NullifyFinalize(v) => {
1940 9u8.hash(state);
1941 v.hash(state);
1942 }
1943 }
1944 }
1945}
1946
1947impl<S: Scheme, D: Digest> Activity<S, D> {
1948 pub const fn verified(&self) -> bool {
1950 match self {
1951 Self::Notarize(_) => false,
1952 Self::Notarization(_) => true,
1953 Self::Certification(_) => false,
1954 Self::Nullify(_) => false,
1955 Self::Nullification(_) => true,
1956 Self::Finalize(_) => false,
1957 Self::Finalization(_) => true,
1958 Self::ConflictingNotarize(_) => false,
1959 Self::ConflictingFinalize(_) => false,
1960 Self::NullifyFinalize(_) => false,
1961 }
1962 }
1963
1964 pub fn verify<R: CryptoRngCore>(
1970 &self,
1971 rng: &mut R,
1972 scheme: &S,
1973 strategy: &impl Strategy,
1974 ) -> bool
1975 where
1976 S: scheme::Scheme<D>,
1977 {
1978 match self {
1979 Self::Notarize(n) => n.verify(rng, scheme, strategy),
1980 Self::Notarization(n) => n.verify(rng, scheme, strategy),
1981 Self::Certification(n) => n.verify(rng, scheme, strategy),
1982 Self::Nullify(n) => n.verify(rng, scheme, strategy),
1983 Self::Nullification(n) => n.verify(rng, scheme, strategy),
1984 Self::Finalize(f) => f.verify(rng, scheme, strategy),
1985 Self::Finalization(f) => f.verify(rng, scheme, strategy),
1986 Self::ConflictingNotarize(c) => c.verify(rng, scheme, strategy),
1987 Self::ConflictingFinalize(c) => c.verify(rng, scheme, strategy),
1988 Self::NullifyFinalize(c) => c.verify(rng, scheme, strategy),
1989 }
1990 }
1991}
1992
1993impl<S: Scheme, D: Digest> Write for Activity<S, D> {
1994 fn write(&self, writer: &mut impl BufMut) {
1995 match self {
1996 Self::Notarize(v) => {
1997 0u8.write(writer);
1998 v.write(writer);
1999 }
2000 Self::Notarization(v) => {
2001 1u8.write(writer);
2002 v.write(writer);
2003 }
2004 Self::Certification(v) => {
2005 2u8.write(writer);
2006 v.write(writer);
2007 }
2008 Self::Nullify(v) => {
2009 3u8.write(writer);
2010 v.write(writer);
2011 }
2012 Self::Nullification(v) => {
2013 4u8.write(writer);
2014 v.write(writer);
2015 }
2016 Self::Finalize(v) => {
2017 5u8.write(writer);
2018 v.write(writer);
2019 }
2020 Self::Finalization(v) => {
2021 6u8.write(writer);
2022 v.write(writer);
2023 }
2024 Self::ConflictingNotarize(v) => {
2025 7u8.write(writer);
2026 v.write(writer);
2027 }
2028 Self::ConflictingFinalize(v) => {
2029 8u8.write(writer);
2030 v.write(writer);
2031 }
2032 Self::NullifyFinalize(v) => {
2033 9u8.write(writer);
2034 v.write(writer);
2035 }
2036 }
2037 }
2038}
2039
2040impl<S: Scheme, D: Digest> EncodeSize for Activity<S, D> {
2041 fn encode_size(&self) -> usize {
2042 1 + match self {
2043 Self::Notarize(v) => v.encode_size(),
2044 Self::Notarization(v) => v.encode_size(),
2045 Self::Certification(v) => v.encode_size(),
2046 Self::Nullify(v) => v.encode_size(),
2047 Self::Nullification(v) => v.encode_size(),
2048 Self::Finalize(v) => v.encode_size(),
2049 Self::Finalization(v) => v.encode_size(),
2050 Self::ConflictingNotarize(v) => v.encode_size(),
2051 Self::ConflictingFinalize(v) => v.encode_size(),
2052 Self::NullifyFinalize(v) => v.encode_size(),
2053 }
2054 }
2055}
2056
2057impl<S: Scheme, D: Digest> Read for Activity<S, D> {
2058 type Cfg = <S::Certificate as Read>::Cfg;
2059
2060 fn read_cfg(reader: &mut impl Buf, cfg: &Self::Cfg) -> Result<Self, Error> {
2061 let tag = <u8>::read(reader)?;
2062 match tag {
2063 0 => {
2064 let v = Notarize::<S, D>::read(reader)?;
2065 Ok(Self::Notarize(v))
2066 }
2067 1 => {
2068 let v = Notarization::<S, D>::read_cfg(reader, cfg)?;
2069 Ok(Self::Notarization(v))
2070 }
2071 2 => {
2072 let v = Notarization::<S, D>::read_cfg(reader, cfg)?;
2073 Ok(Self::Certification(v))
2074 }
2075 3 => {
2076 let v = Nullify::<S>::read(reader)?;
2077 Ok(Self::Nullify(v))
2078 }
2079 4 => {
2080 let v = Nullification::<S>::read_cfg(reader, cfg)?;
2081 Ok(Self::Nullification(v))
2082 }
2083 5 => {
2084 let v = Finalize::<S, D>::read(reader)?;
2085 Ok(Self::Finalize(v))
2086 }
2087 6 => {
2088 let v = Finalization::<S, D>::read_cfg(reader, cfg)?;
2089 Ok(Self::Finalization(v))
2090 }
2091 7 => {
2092 let v = ConflictingNotarize::<S, D>::read(reader)?;
2093 Ok(Self::ConflictingNotarize(v))
2094 }
2095 8 => {
2096 let v = ConflictingFinalize::<S, D>::read(reader)?;
2097 Ok(Self::ConflictingFinalize(v))
2098 }
2099 9 => {
2100 let v = NullifyFinalize::<S, D>::read(reader)?;
2101 Ok(Self::NullifyFinalize(v))
2102 }
2103 _ => Err(Error::Invalid(
2104 "consensus::simplex::Activity",
2105 "Invalid type",
2106 )),
2107 }
2108 }
2109}
2110
2111impl<S: Scheme, D: Digest> Epochable for Activity<S, D> {
2112 fn epoch(&self) -> Epoch {
2113 match self {
2114 Self::Notarize(v) => v.epoch(),
2115 Self::Notarization(v) => v.epoch(),
2116 Self::Certification(v) => v.epoch(),
2117 Self::Nullify(v) => v.epoch(),
2118 Self::Nullification(v) => v.epoch(),
2119 Self::Finalize(v) => v.epoch(),
2120 Self::Finalization(v) => v.epoch(),
2121 Self::ConflictingNotarize(v) => v.epoch(),
2122 Self::ConflictingFinalize(v) => v.epoch(),
2123 Self::NullifyFinalize(v) => v.epoch(),
2124 }
2125 }
2126}
2127
2128impl<S: Scheme, D: Digest> Viewable for Activity<S, D> {
2129 fn view(&self) -> View {
2130 match self {
2131 Self::Notarize(v) => v.view(),
2132 Self::Notarization(v) => v.view(),
2133 Self::Certification(v) => v.view(),
2134 Self::Nullify(v) => v.view(),
2135 Self::Nullification(v) => v.view(),
2136 Self::Finalize(v) => v.view(),
2137 Self::Finalization(v) => v.view(),
2138 Self::ConflictingNotarize(v) => v.view(),
2139 Self::ConflictingFinalize(v) => v.view(),
2140 Self::NullifyFinalize(v) => v.view(),
2141 }
2142 }
2143}
2144
2145#[cfg(feature = "arbitrary")]
2146impl<S: Scheme, D: Digest> arbitrary::Arbitrary<'_> for Activity<S, D>
2147where
2148 S::Signature: for<'a> arbitrary::Arbitrary<'a>,
2149 S::Certificate: for<'a> arbitrary::Arbitrary<'a>,
2150 D: for<'a> arbitrary::Arbitrary<'a>,
2151{
2152 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
2153 let tag = u.int_in_range(0..=9)?;
2154 match tag {
2155 0 => {
2156 let v = Notarize::<S, D>::arbitrary(u)?;
2157 Ok(Self::Notarize(v))
2158 }
2159 1 => {
2160 let v = Notarization::<S, D>::arbitrary(u)?;
2161 Ok(Self::Notarization(v))
2162 }
2163 2 => {
2164 let v = Notarization::<S, D>::arbitrary(u)?;
2165 Ok(Self::Certification(v))
2166 }
2167 3 => {
2168 let v = Nullify::<S>::arbitrary(u)?;
2169 Ok(Self::Nullify(v))
2170 }
2171 4 => {
2172 let v = Nullification::<S>::arbitrary(u)?;
2173 Ok(Self::Nullification(v))
2174 }
2175 5 => {
2176 let v = Finalize::<S, D>::arbitrary(u)?;
2177 Ok(Self::Finalize(v))
2178 }
2179 6 => {
2180 let v = Finalization::<S, D>::arbitrary(u)?;
2181 Ok(Self::Finalization(v))
2182 }
2183 7 => {
2184 let v = ConflictingNotarize::<S, D>::arbitrary(u)?;
2185 Ok(Self::ConflictingNotarize(v))
2186 }
2187 8 => {
2188 let v = ConflictingFinalize::<S, D>::arbitrary(u)?;
2189 Ok(Self::ConflictingFinalize(v))
2190 }
2191 9 => {
2192 let v = NullifyFinalize::<S, D>::arbitrary(u)?;
2193 Ok(Self::NullifyFinalize(v))
2194 }
2195 _ => unreachable!(),
2196 }
2197 }
2198}
2199
2200#[derive(Clone, Debug)]
2203pub struct ConflictingNotarize<S: Scheme, D: Digest> {
2204 notarize_1: Notarize<S, D>,
2206 notarize_2: Notarize<S, D>,
2208}
2209
2210impl<S: Scheme, D: Digest> PartialEq for ConflictingNotarize<S, D> {
2211 fn eq(&self, other: &Self) -> bool {
2212 self.notarize_1 == other.notarize_1 && self.notarize_2 == other.notarize_2
2213 }
2214}
2215
2216impl<S: Scheme, D: Digest> Eq for ConflictingNotarize<S, D> {}
2217
2218impl<S: Scheme, D: Digest> Hash for ConflictingNotarize<S, D> {
2219 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
2220 self.notarize_1.hash(state);
2221 self.notarize_2.hash(state);
2222 }
2223}
2224
2225impl<S: Scheme, D: Digest> ConflictingNotarize<S, D> {
2226 pub fn new(notarize_1: Notarize<S, D>, notarize_2: Notarize<S, D>) -> Self {
2233 assert_eq!(notarize_1.round(), notarize_2.round());
2234 assert_eq!(notarize_1.signer(), notarize_2.signer());
2235 assert_ne!(
2236 notarize_1.proposal, notarize_2.proposal,
2237 "proposals must differ to constitute conflicting evidence"
2238 );
2239
2240 Self {
2241 notarize_1,
2242 notarize_2,
2243 }
2244 }
2245
2246 pub fn verify<R>(&self, rng: &mut R, scheme: &S, strategy: &impl Strategy) -> bool
2248 where
2249 R: CryptoRngCore,
2250 S: scheme::Scheme<D>,
2251 {
2252 self.notarize_1.verify(rng, scheme, strategy)
2253 && self.notarize_2.verify(rng, scheme, strategy)
2254 }
2255}
2256
2257impl<S: Scheme, D: Digest> Attributable for ConflictingNotarize<S, D> {
2258 fn signer(&self) -> Participant {
2259 self.notarize_1.signer()
2260 }
2261}
2262
2263impl<S: Scheme, D: Digest> Epochable for ConflictingNotarize<S, D> {
2264 fn epoch(&self) -> Epoch {
2265 self.notarize_1.epoch()
2266 }
2267}
2268
2269impl<S: Scheme, D: Digest> Viewable for ConflictingNotarize<S, D> {
2270 fn view(&self) -> View {
2271 self.notarize_1.view()
2272 }
2273}
2274
2275impl<S: Scheme, D: Digest> Write for ConflictingNotarize<S, D> {
2276 fn write(&self, writer: &mut impl BufMut) {
2277 self.notarize_1.write(writer);
2278 self.notarize_2.write(writer);
2279 }
2280}
2281
2282impl<S: Scheme, D: Digest> Read for ConflictingNotarize<S, D> {
2283 type Cfg = ();
2284
2285 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
2286 let notarize_1 = Notarize::read(reader)?;
2287 let notarize_2 = Notarize::read(reader)?;
2288
2289 if notarize_1.signer() != notarize_2.signer()
2290 || notarize_1.round() != notarize_2.round()
2291 || notarize_1.proposal == notarize_2.proposal
2292 {
2293 return Err(Error::Invalid(
2294 "consensus::simplex::ConflictingNotarize",
2295 "invalid conflicting notarize",
2296 ));
2297 }
2298
2299 Ok(Self {
2300 notarize_1,
2301 notarize_2,
2302 })
2303 }
2304}
2305
2306impl<S: Scheme, D: Digest> EncodeSize for ConflictingNotarize<S, D> {
2307 fn encode_size(&self) -> usize {
2308 self.notarize_1.encode_size() + self.notarize_2.encode_size()
2309 }
2310}
2311
2312#[cfg(feature = "arbitrary")]
2313impl<S: Scheme, D: Digest> arbitrary::Arbitrary<'_> for ConflictingNotarize<S, D>
2314where
2315 S::Signature: for<'a> arbitrary::Arbitrary<'a>,
2316 D: for<'a> arbitrary::Arbitrary<'a>,
2317{
2318 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
2319 let notarize_1 = Notarize::arbitrary(u)?;
2320 let notarize_2 = Notarize::arbitrary(u)?;
2321 Ok(Self {
2322 notarize_1,
2323 notarize_2,
2324 })
2325 }
2326}
2327
2328#[derive(Clone, Debug)]
2331pub struct ConflictingFinalize<S: Scheme, D: Digest> {
2332 finalize_1: Finalize<S, D>,
2334 finalize_2: Finalize<S, D>,
2336}
2337
2338impl<S: Scheme, D: Digest> PartialEq for ConflictingFinalize<S, D> {
2339 fn eq(&self, other: &Self) -> bool {
2340 self.finalize_1 == other.finalize_1 && self.finalize_2 == other.finalize_2
2341 }
2342}
2343
2344impl<S: Scheme, D: Digest> Eq for ConflictingFinalize<S, D> {}
2345
2346impl<S: Scheme, D: Digest> Hash for ConflictingFinalize<S, D> {
2347 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
2348 self.finalize_1.hash(state);
2349 self.finalize_2.hash(state);
2350 }
2351}
2352
2353impl<S: Scheme, D: Digest> ConflictingFinalize<S, D> {
2354 pub fn new(finalize_1: Finalize<S, D>, finalize_2: Finalize<S, D>) -> Self {
2361 assert_eq!(finalize_1.round(), finalize_2.round());
2362 assert_eq!(finalize_1.signer(), finalize_2.signer());
2363 assert_ne!(
2364 finalize_1.proposal, finalize_2.proposal,
2365 "proposals must differ to constitute conflicting evidence"
2366 );
2367
2368 Self {
2369 finalize_1,
2370 finalize_2,
2371 }
2372 }
2373
2374 pub fn verify<R>(&self, rng: &mut R, scheme: &S, strategy: &impl Strategy) -> bool
2376 where
2377 R: CryptoRngCore,
2378 S: scheme::Scheme<D>,
2379 {
2380 self.finalize_1.verify(rng, scheme, strategy)
2381 && self.finalize_2.verify(rng, scheme, strategy)
2382 }
2383}
2384
2385impl<S: Scheme, D: Digest> Attributable for ConflictingFinalize<S, D> {
2386 fn signer(&self) -> Participant {
2387 self.finalize_1.signer()
2388 }
2389}
2390
2391impl<S: Scheme, D: Digest> Epochable for ConflictingFinalize<S, D> {
2392 fn epoch(&self) -> Epoch {
2393 self.finalize_1.epoch()
2394 }
2395}
2396
2397impl<S: Scheme, D: Digest> Viewable for ConflictingFinalize<S, D> {
2398 fn view(&self) -> View {
2399 self.finalize_1.view()
2400 }
2401}
2402
2403impl<S: Scheme, D: Digest> Write for ConflictingFinalize<S, D> {
2404 fn write(&self, writer: &mut impl BufMut) {
2405 self.finalize_1.write(writer);
2406 self.finalize_2.write(writer);
2407 }
2408}
2409
2410impl<S: Scheme, D: Digest> Read for ConflictingFinalize<S, D> {
2411 type Cfg = ();
2412
2413 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
2414 let finalize_1 = Finalize::read(reader)?;
2415 let finalize_2 = Finalize::read(reader)?;
2416
2417 if finalize_1.signer() != finalize_2.signer()
2418 || finalize_1.round() != finalize_2.round()
2419 || finalize_1.proposal == finalize_2.proposal
2420 {
2421 return Err(Error::Invalid(
2422 "consensus::simplex::ConflictingFinalize",
2423 "invalid conflicting finalize",
2424 ));
2425 }
2426
2427 Ok(Self {
2428 finalize_1,
2429 finalize_2,
2430 })
2431 }
2432}
2433
2434impl<S: Scheme, D: Digest> EncodeSize for ConflictingFinalize<S, D> {
2435 fn encode_size(&self) -> usize {
2436 self.finalize_1.encode_size() + self.finalize_2.encode_size()
2437 }
2438}
2439
2440#[cfg(feature = "arbitrary")]
2441impl<S: Scheme, D: Digest> arbitrary::Arbitrary<'_> for ConflictingFinalize<S, D>
2442where
2443 S::Signature: for<'a> arbitrary::Arbitrary<'a>,
2444 D: for<'a> arbitrary::Arbitrary<'a>,
2445{
2446 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
2447 let finalize_1 = Finalize::arbitrary(u)?;
2448 let finalize_2 = Finalize::arbitrary(u)?;
2449 Ok(Self {
2450 finalize_1,
2451 finalize_2,
2452 })
2453 }
2454}
2455
2456#[derive(Clone, Debug)]
2460pub struct NullifyFinalize<S: Scheme, D: Digest> {
2461 nullify: Nullify<S>,
2463 finalize: Finalize<S, D>,
2465}
2466
2467impl<S: Scheme, D: Digest> PartialEq for NullifyFinalize<S, D> {
2468 fn eq(&self, other: &Self) -> bool {
2469 self.nullify == other.nullify && self.finalize == other.finalize
2470 }
2471}
2472
2473impl<S: Scheme, D: Digest> Eq for NullifyFinalize<S, D> {}
2474
2475impl<S: Scheme, D: Digest> Hash for NullifyFinalize<S, D> {
2476 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
2477 self.nullify.hash(state);
2478 self.finalize.hash(state);
2479 }
2480}
2481
2482impl<S: Scheme, D: Digest> NullifyFinalize<S, D> {
2483 pub fn new(nullify: Nullify<S>, finalize: Finalize<S, D>) -> Self {
2485 assert_eq!(nullify.round, finalize.round());
2486 assert_eq!(nullify.signer(), finalize.signer());
2487
2488 Self { nullify, finalize }
2489 }
2490
2491 pub fn verify<R>(&self, rng: &mut R, scheme: &S, strategy: &impl Strategy) -> bool
2493 where
2494 R: CryptoRngCore,
2495 S: scheme::Scheme<D>,
2496 {
2497 self.nullify.verify(rng, scheme, strategy) && self.finalize.verify(rng, scheme, strategy)
2498 }
2499}
2500
2501impl<S: Scheme, D: Digest> Attributable for NullifyFinalize<S, D> {
2502 fn signer(&self) -> Participant {
2503 self.nullify.signer()
2504 }
2505}
2506
2507impl<S: Scheme, D: Digest> Epochable for NullifyFinalize<S, D> {
2508 fn epoch(&self) -> Epoch {
2509 self.nullify.epoch()
2510 }
2511}
2512
2513impl<S: Scheme, D: Digest> Viewable for NullifyFinalize<S, D> {
2514 fn view(&self) -> View {
2515 self.nullify.view()
2516 }
2517}
2518
2519impl<S: Scheme, D: Digest> Write for NullifyFinalize<S, D> {
2520 fn write(&self, writer: &mut impl BufMut) {
2521 self.nullify.write(writer);
2522 self.finalize.write(writer);
2523 }
2524}
2525
2526impl<S: Scheme, D: Digest> Read for NullifyFinalize<S, D> {
2527 type Cfg = ();
2528
2529 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
2530 let nullify = Nullify::read(reader)?;
2531 let finalize = Finalize::read(reader)?;
2532
2533 if nullify.signer() != finalize.signer() || nullify.round != finalize.round() {
2534 return Err(Error::Invalid(
2535 "consensus::simplex::NullifyFinalize",
2536 "mismatched signatures",
2537 ));
2538 }
2539
2540 Ok(Self { nullify, finalize })
2541 }
2542}
2543
2544impl<S: Scheme, D: Digest> EncodeSize for NullifyFinalize<S, D> {
2545 fn encode_size(&self) -> usize {
2546 self.nullify.encode_size() + self.finalize.encode_size()
2547 }
2548}
2549
2550#[cfg(feature = "arbitrary")]
2551impl<S: Scheme, D: Digest> arbitrary::Arbitrary<'_> for NullifyFinalize<S, D>
2552where
2553 S::Signature: for<'a> arbitrary::Arbitrary<'a>,
2554 D: for<'a> arbitrary::Arbitrary<'a>,
2555{
2556 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
2557 let nullify = Nullify::arbitrary(u)?;
2558 let finalize = Finalize::arbitrary(u)?;
2559 Ok(Self { nullify, finalize })
2560 }
2561}
2562
2563#[cfg(test)]
2564mod tests {
2565 use super::*;
2566 use crate::simplex::{
2567 quorum,
2568 scheme::{
2569 bls12381_multisig,
2570 bls12381_threshold::{
2571 standard as bls12381_threshold_std, vrf as bls12381_threshold_vrf,
2572 },
2573 ed25519, secp256r1, Scheme,
2574 },
2575 };
2576 use bytes::Bytes;
2577 use commonware_codec::{Decode, DecodeExt, Encode};
2578 use commonware_cryptography::{
2579 bls12381::primitives::variant::{MinPk, MinSig},
2580 certificate::mocks::Fixture,
2581 sha256::Digest as Sha256,
2582 };
2583 use commonware_parallel::Sequential;
2584 use commonware_utils::{test_rng, Faults, N3f1};
2585 use rand::{rngs::StdRng, SeedableRng};
2586
2587 const NAMESPACE: &[u8] = b"test";
2588
2589 fn sample_digest(v: u8) -> Sha256 {
2591 Sha256::from([v; 32]) }
2593
2594 fn setup_seeded<S, F>(n: u32, seed: u64, fixture: F) -> Fixture<S>
2596 where
2597 F: FnOnce(&mut StdRng, &[u8], u32) -> Fixture<S>,
2598 {
2599 setup_seeded_ns(n, seed, NAMESPACE, fixture)
2600 }
2601
2602 fn setup_seeded_ns<S, F>(n: u32, seed: u64, namespace: &[u8], fixture: F) -> Fixture<S>
2604 where
2605 F: FnOnce(&mut StdRng, &[u8], u32) -> Fixture<S>,
2606 {
2607 let mut rng = StdRng::seed_from_u64(seed);
2608 fixture(&mut rng, namespace, n)
2609 }
2610
2611 #[test]
2612 fn test_proposal_encode_decode() {
2613 let proposal = Proposal::new(
2614 Round::new(Epoch::new(0), View::new(10)),
2615 View::new(5),
2616 sample_digest(1),
2617 );
2618 let encoded = proposal.encode();
2619 let decoded = Proposal::<Sha256>::decode(encoded).unwrap();
2620 assert_eq!(proposal, decoded);
2621 }
2622
2623 fn notarize_encode_decode<S, F>(fixture: F)
2624 where
2625 S: Scheme<Sha256>,
2626 F: FnOnce(&mut StdRng, &[u8], u32) -> Fixture<S>,
2627 {
2628 let mut rng = test_rng();
2629 let fixture = fixture(&mut rng, NAMESPACE, 5);
2630 let round = Round::new(Epoch::new(0), View::new(10));
2631 let proposal = Proposal::new(round, View::new(5), sample_digest(1));
2632 let notarize = Notarize::sign(&fixture.schemes[0], proposal).unwrap();
2633
2634 let encoded = notarize.encode();
2635 let decoded = Notarize::decode(encoded).unwrap();
2636
2637 assert_eq!(notarize, decoded);
2638 assert!(decoded.verify(&mut rng, &fixture.schemes[0], &Sequential));
2639 }
2640
2641 #[test]
2642 fn test_notarize_encode_decode() {
2643 notarize_encode_decode(ed25519::fixture);
2644 notarize_encode_decode(secp256r1::fixture);
2645 notarize_encode_decode(bls12381_multisig::fixture::<MinPk, _>);
2646 notarize_encode_decode(bls12381_multisig::fixture::<MinSig, _>);
2647 notarize_encode_decode(bls12381_threshold_vrf::fixture::<MinPk, _>);
2648 notarize_encode_decode(bls12381_threshold_vrf::fixture::<MinSig, _>);
2649 notarize_encode_decode(bls12381_threshold_std::fixture::<MinPk, _>);
2650 notarize_encode_decode(bls12381_threshold_std::fixture::<MinSig, _>);
2651 }
2652
2653 fn notarization_encode_decode<S, F>(fixture: F)
2654 where
2655 S: Scheme<Sha256>,
2656 F: FnOnce(&mut StdRng, &[u8], u32) -> Fixture<S>,
2657 {
2658 let mut rng = test_rng();
2659 let fixture = fixture(&mut rng, NAMESPACE, 5);
2660 let proposal = Proposal::new(
2661 Round::new(Epoch::new(0), View::new(10)),
2662 View::new(5),
2663 sample_digest(1),
2664 );
2665 let notarizes: Vec<_> = fixture
2666 .schemes
2667 .iter()
2668 .map(|scheme| Notarize::sign(scheme, proposal.clone()).unwrap())
2669 .collect();
2670 let notarization =
2671 Notarization::from_notarizes(&fixture.schemes[0], ¬arizes, &Sequential).unwrap();
2672 let encoded = notarization.encode();
2673 let cfg = fixture.schemes[0].certificate_codec_config();
2674 let decoded = Notarization::decode_cfg(encoded, &cfg).unwrap();
2675 assert_eq!(notarization, decoded);
2676 assert!(decoded.verify(&mut rng, &fixture.schemes[0], &Sequential));
2677 }
2678
2679 #[test]
2680 fn test_notarization_encode_decode() {
2681 notarization_encode_decode(ed25519::fixture);
2682 notarization_encode_decode(secp256r1::fixture);
2683 notarization_encode_decode(bls12381_multisig::fixture::<MinPk, _>);
2684 notarization_encode_decode(bls12381_multisig::fixture::<MinSig, _>);
2685 notarization_encode_decode(bls12381_threshold_vrf::fixture::<MinPk, _>);
2686 notarization_encode_decode(bls12381_threshold_vrf::fixture::<MinSig, _>);
2687 notarization_encode_decode(bls12381_threshold_std::fixture::<MinPk, _>);
2688 notarization_encode_decode(bls12381_threshold_std::fixture::<MinSig, _>);
2689 }
2690
2691 fn nullify_encode_decode<S, F>(fixture: F)
2692 where
2693 S: Scheme<Sha256>,
2694 F: FnOnce(&mut StdRng, &[u8], u32) -> Fixture<S>,
2695 {
2696 let mut rng = test_rng();
2697 let fixture = fixture(&mut rng, NAMESPACE, 5);
2698 let round = Round::new(Epoch::new(0), View::new(10));
2699 let nullify = Nullify::sign::<Sha256>(&fixture.schemes[0], round).unwrap();
2700 let encoded = nullify.encode();
2701 let decoded = Nullify::decode(encoded).unwrap();
2702 assert_eq!(nullify, decoded);
2703 assert!(decoded.verify::<_, Sha256>(&mut rng, &fixture.schemes[0], &Sequential));
2704 }
2705
2706 #[test]
2707 fn test_nullify_encode_decode() {
2708 nullify_encode_decode(ed25519::fixture);
2709 nullify_encode_decode(secp256r1::fixture);
2710 nullify_encode_decode(bls12381_multisig::fixture::<MinPk, _>);
2711 nullify_encode_decode(bls12381_multisig::fixture::<MinSig, _>);
2712 nullify_encode_decode(bls12381_threshold_vrf::fixture::<MinPk, _>);
2713 nullify_encode_decode(bls12381_threshold_vrf::fixture::<MinSig, _>);
2714 nullify_encode_decode(bls12381_threshold_std::fixture::<MinPk, _>);
2715 nullify_encode_decode(bls12381_threshold_std::fixture::<MinSig, _>);
2716 }
2717
2718 fn nullification_encode_decode<S, F>(fixture: F)
2719 where
2720 S: Scheme<Sha256>,
2721 F: FnOnce(&mut StdRng, &[u8], u32) -> Fixture<S>,
2722 {
2723 let mut rng = test_rng();
2724 let fixture = fixture(&mut rng, NAMESPACE, 5);
2725 let round = Round::new(Epoch::new(333), View::new(10));
2726 let nullifies: Vec<_> = fixture
2727 .schemes
2728 .iter()
2729 .map(|scheme| Nullify::sign::<Sha256>(scheme, round).unwrap())
2730 .collect();
2731 let nullification =
2732 Nullification::from_nullifies(&fixture.schemes[0], &nullifies, &Sequential).unwrap();
2733 let encoded = nullification.encode();
2734 let cfg = fixture.schemes[0].certificate_codec_config();
2735 let decoded = Nullification::decode_cfg(encoded, &cfg).unwrap();
2736 assert_eq!(nullification, decoded);
2737 assert!(decoded.verify::<_, Sha256>(&mut rng, &fixture.schemes[0], &Sequential));
2738 }
2739
2740 #[test]
2741 fn test_nullification_encode_decode() {
2742 nullification_encode_decode(ed25519::fixture);
2743 nullification_encode_decode(secp256r1::fixture);
2744 nullification_encode_decode(bls12381_multisig::fixture::<MinPk, _>);
2745 nullification_encode_decode(bls12381_multisig::fixture::<MinSig, _>);
2746 nullification_encode_decode(bls12381_threshold_vrf::fixture::<MinPk, _>);
2747 nullification_encode_decode(bls12381_threshold_vrf::fixture::<MinSig, _>);
2748 nullification_encode_decode(bls12381_threshold_std::fixture::<MinPk, _>);
2749 nullification_encode_decode(bls12381_threshold_std::fixture::<MinSig, _>);
2750 }
2751
2752 fn finalize_encode_decode<S, F>(fixture: F)
2753 where
2754 S: Scheme<Sha256>,
2755 F: FnOnce(&mut StdRng, &[u8], u32) -> Fixture<S>,
2756 {
2757 let mut rng = test_rng();
2758 let fixture = fixture(&mut rng, NAMESPACE, 5);
2759 let round = Round::new(Epoch::new(0), View::new(10));
2760 let proposal = Proposal::new(round, View::new(5), sample_digest(1));
2761 let finalize = Finalize::sign(&fixture.schemes[0], proposal).unwrap();
2762 let encoded = finalize.encode();
2763 let decoded = Finalize::decode(encoded).unwrap();
2764 assert_eq!(finalize, decoded);
2765 assert!(decoded.verify(&mut rng, &fixture.schemes[0], &Sequential));
2766 }
2767
2768 #[test]
2769 fn test_finalize_encode_decode() {
2770 finalize_encode_decode(ed25519::fixture);
2771 finalize_encode_decode(secp256r1::fixture);
2772 finalize_encode_decode(bls12381_multisig::fixture::<MinPk, _>);
2773 finalize_encode_decode(bls12381_multisig::fixture::<MinSig, _>);
2774 finalize_encode_decode(bls12381_threshold_vrf::fixture::<MinPk, _>);
2775 finalize_encode_decode(bls12381_threshold_vrf::fixture::<MinSig, _>);
2776 finalize_encode_decode(bls12381_threshold_std::fixture::<MinPk, _>);
2777 finalize_encode_decode(bls12381_threshold_std::fixture::<MinSig, _>);
2778 }
2779
2780 fn finalization_encode_decode<S, F>(fixture: F)
2781 where
2782 S: Scheme<Sha256>,
2783 F: FnOnce(&mut StdRng, &[u8], u32) -> Fixture<S>,
2784 {
2785 let mut rng = test_rng();
2786 let fixture = fixture(&mut rng, NAMESPACE, 5);
2787 let round = Round::new(Epoch::new(0), View::new(10));
2788 let proposal = Proposal::new(round, View::new(5), sample_digest(1));
2789 let finalizes: Vec<_> = fixture
2790 .schemes
2791 .iter()
2792 .map(|scheme| Finalize::sign(scheme, proposal.clone()).unwrap())
2793 .collect();
2794 let finalization =
2795 Finalization::from_finalizes(&fixture.schemes[0], &finalizes, &Sequential).unwrap();
2796 let encoded = finalization.encode();
2797 let cfg = fixture.schemes[0].certificate_codec_config();
2798 let decoded = Finalization::decode_cfg(encoded, &cfg).unwrap();
2799 assert_eq!(finalization, decoded);
2800 assert!(decoded.verify(&mut rng, &fixture.schemes[0], &Sequential));
2801 }
2802
2803 #[test]
2804 fn test_finalization_encode_decode() {
2805 finalization_encode_decode(ed25519::fixture);
2806 finalization_encode_decode(secp256r1::fixture);
2807 finalization_encode_decode(bls12381_multisig::fixture::<MinPk, _>);
2808 finalization_encode_decode(bls12381_multisig::fixture::<MinSig, _>);
2809 finalization_encode_decode(bls12381_threshold_vrf::fixture::<MinPk, _>);
2810 finalization_encode_decode(bls12381_threshold_vrf::fixture::<MinSig, _>);
2811 finalization_encode_decode(bls12381_threshold_std::fixture::<MinPk, _>);
2812 finalization_encode_decode(bls12381_threshold_std::fixture::<MinSig, _>);
2813 }
2814
2815 fn backfiller_encode_decode<S, F>(fixture: F)
2816 where
2817 S: Scheme<Sha256>,
2818 F: FnOnce(&mut StdRng, &[u8], u32) -> Fixture<S>,
2819 {
2820 let mut rng = test_rng();
2821 let fixture = fixture(&mut rng, NAMESPACE, 5);
2822 let cfg = fixture.schemes[0].certificate_codec_config();
2823 let request = Request::new(
2824 1,
2825 vec![View::new(10), View::new(11)],
2826 vec![View::new(12), View::new(13)],
2827 );
2828 let encoded_request = Backfiller::<S, Sha256>::Request(request.clone()).encode();
2829 let decoded_request =
2830 Backfiller::<S, Sha256>::decode_cfg(encoded_request, &(usize::MAX, cfg.clone()))
2831 .unwrap();
2832 assert!(matches!(decoded_request, Backfiller::Request(r) if r == request));
2833
2834 let round = Round::new(Epoch::new(0), View::new(10));
2835 let proposal = Proposal::new(round, View::new(5), sample_digest(1));
2836 let notarizes: Vec<_> = fixture
2837 .schemes
2838 .iter()
2839 .map(|scheme| Notarize::sign(scheme, proposal.clone()).unwrap())
2840 .collect();
2841 let notarization =
2842 Notarization::from_notarizes(&fixture.schemes[0], ¬arizes, &Sequential).unwrap();
2843
2844 let nullifies: Vec<_> = fixture
2845 .schemes
2846 .iter()
2847 .map(|scheme| Nullify::sign::<Sha256>(scheme, round).unwrap())
2848 .collect();
2849 let nullification =
2850 Nullification::from_nullifies(&fixture.schemes[0], &nullifies, &Sequential).unwrap();
2851
2852 let response = Response::<S, Sha256>::new(1, vec![notarization], vec![nullification]);
2853 let encoded_response = Backfiller::<S, Sha256>::Response(response.clone()).encode();
2854 let decoded_response =
2855 Backfiller::<S, Sha256>::decode_cfg(encoded_response, &(usize::MAX, cfg)).unwrap();
2856 assert!(matches!(decoded_response, Backfiller::Response(r) if r.id == response.id));
2857 }
2858
2859 #[test]
2860 fn test_backfiller_encode_decode() {
2861 backfiller_encode_decode(ed25519::fixture);
2862 backfiller_encode_decode(secp256r1::fixture);
2863 backfiller_encode_decode(bls12381_multisig::fixture::<MinPk, _>);
2864 backfiller_encode_decode(bls12381_multisig::fixture::<MinSig, _>);
2865 backfiller_encode_decode(bls12381_threshold_vrf::fixture::<MinPk, _>);
2866 backfiller_encode_decode(bls12381_threshold_vrf::fixture::<MinSig, _>);
2867 backfiller_encode_decode(bls12381_threshold_std::fixture::<MinPk, _>);
2868 backfiller_encode_decode(bls12381_threshold_std::fixture::<MinSig, _>);
2869 }
2870
2871 #[test]
2872 fn test_request_encode_decode() {
2873 let request = Request::new(
2874 1,
2875 vec![View::new(10), View::new(11)],
2876 vec![View::new(12), View::new(13)],
2877 );
2878 let encoded = request.encode();
2879 let decoded = Request::decode_cfg(encoded, &usize::MAX).unwrap();
2880 assert_eq!(request, decoded);
2881 }
2882
2883 fn response_encode_decode<S, F>(fixture: F)
2884 where
2885 S: Scheme<Sha256>,
2886 F: FnOnce(&mut StdRng, &[u8], u32) -> Fixture<S>,
2887 {
2888 let mut rng = test_rng();
2889 let fixture = fixture(&mut rng, NAMESPACE, 5);
2890 let round = Round::new(Epoch::new(0), View::new(10));
2891 let proposal = Proposal::new(round, View::new(5), sample_digest(1));
2892
2893 let notarizes: Vec<_> = fixture
2894 .schemes
2895 .iter()
2896 .map(|scheme| Notarize::sign(scheme, proposal.clone()).unwrap())
2897 .collect();
2898 let notarization =
2899 Notarization::from_notarizes(&fixture.schemes[0], ¬arizes, &Sequential).unwrap();
2900
2901 let nullifies: Vec<_> = fixture
2902 .schemes
2903 .iter()
2904 .map(|scheme| Nullify::sign::<Sha256>(scheme, round).unwrap())
2905 .collect();
2906 let nullification =
2907 Nullification::from_nullifies(&fixture.schemes[0], &nullifies, &Sequential).unwrap();
2908
2909 let response = Response::<S, Sha256>::new(1, vec![notarization], vec![nullification]);
2910 let cfg = fixture.schemes[0].certificate_codec_config();
2911 let mut decoded =
2912 Response::<S, Sha256>::decode_cfg(response.encode(), &(usize::MAX, cfg)).unwrap();
2913 assert_eq!(response.id, decoded.id);
2914 assert_eq!(response.notarizations.len(), decoded.notarizations.len());
2915 assert_eq!(response.nullifications.len(), decoded.nullifications.len());
2916
2917 assert!(decoded.verify(&mut rng, &fixture.schemes[0], &Sequential));
2918
2919 decoded.nullifications[0].round = Round::new(
2920 decoded.nullifications[0].round.epoch(),
2921 decoded.nullifications[0].round.view().next(),
2922 );
2923 assert!(!decoded.verify(&mut rng, &fixture.schemes[0], &Sequential));
2924 }
2925
2926 #[test]
2927 fn test_response_encode_decode() {
2928 response_encode_decode(ed25519::fixture);
2929 response_encode_decode(secp256r1::fixture);
2930 response_encode_decode(bls12381_multisig::fixture::<MinPk, _>);
2931 response_encode_decode(bls12381_multisig::fixture::<MinSig, _>);
2932 response_encode_decode(bls12381_threshold_vrf::fixture::<MinPk, _>);
2933 response_encode_decode(bls12381_threshold_vrf::fixture::<MinSig, _>);
2934 response_encode_decode(bls12381_threshold_std::fixture::<MinPk, _>);
2935 response_encode_decode(bls12381_threshold_std::fixture::<MinSig, _>);
2936 }
2937
2938 fn conflicting_notarize_encode_decode<S, F>(fixture: F)
2939 where
2940 S: Scheme<Sha256>,
2941 F: FnOnce(&mut StdRng, &[u8], u32) -> Fixture<S>,
2942 {
2943 let mut rng = test_rng();
2944 let fixture = fixture(&mut rng, NAMESPACE, 5);
2945 let proposal1 = Proposal::new(
2946 Round::new(Epoch::new(0), View::new(10)),
2947 View::new(5),
2948 sample_digest(1),
2949 );
2950 let proposal2 = Proposal::new(
2951 Round::new(Epoch::new(0), View::new(10)),
2952 View::new(5),
2953 sample_digest(2),
2954 );
2955 let notarize1 = Notarize::sign(&fixture.schemes[0], proposal1).unwrap();
2956 let notarize2 = Notarize::sign(&fixture.schemes[0], proposal2).unwrap();
2957 let conflicting = ConflictingNotarize::new(notarize1, notarize2);
2958
2959 let encoded = conflicting.encode();
2960 let decoded = ConflictingNotarize::<S, Sha256>::decode(encoded).unwrap();
2961
2962 assert_eq!(conflicting, decoded);
2963 assert!(decoded.verify(&mut rng, &fixture.schemes[0], &Sequential));
2964 }
2965
2966 #[test]
2967 fn test_conflicting_notarize_encode_decode() {
2968 conflicting_notarize_encode_decode(ed25519::fixture);
2969 conflicting_notarize_encode_decode(secp256r1::fixture);
2970 conflicting_notarize_encode_decode(bls12381_multisig::fixture::<MinPk, _>);
2971 conflicting_notarize_encode_decode(bls12381_multisig::fixture::<MinSig, _>);
2972 conflicting_notarize_encode_decode(bls12381_threshold_vrf::fixture::<MinPk, _>);
2973 conflicting_notarize_encode_decode(bls12381_threshold_vrf::fixture::<MinSig, _>);
2974 conflicting_notarize_encode_decode(bls12381_threshold_std::fixture::<MinPk, _>);
2975 conflicting_notarize_encode_decode(bls12381_threshold_std::fixture::<MinSig, _>);
2976 }
2977
2978 fn conflicting_finalize_encode_decode<S, F>(fixture: F)
2979 where
2980 S: Scheme<Sha256>,
2981 F: FnOnce(&mut StdRng, &[u8], u32) -> Fixture<S>,
2982 {
2983 let mut rng = test_rng();
2984 let fixture = fixture(&mut rng, NAMESPACE, 5);
2985 let proposal1 = Proposal::new(
2986 Round::new(Epoch::new(0), View::new(10)),
2987 View::new(5),
2988 sample_digest(1),
2989 );
2990 let proposal2 = Proposal::new(
2991 Round::new(Epoch::new(0), View::new(10)),
2992 View::new(5),
2993 sample_digest(2),
2994 );
2995 let finalize1 = Finalize::sign(&fixture.schemes[0], proposal1).unwrap();
2996 let finalize2 = Finalize::sign(&fixture.schemes[0], proposal2).unwrap();
2997 let conflicting = ConflictingFinalize::new(finalize1, finalize2);
2998
2999 let encoded = conflicting.encode();
3000 let decoded = ConflictingFinalize::<S, Sha256>::decode(encoded).unwrap();
3001
3002 assert_eq!(conflicting, decoded);
3003 assert!(decoded.verify(&mut rng, &fixture.schemes[0], &Sequential));
3004 }
3005
3006 #[test]
3007 fn test_conflicting_finalize_encode_decode() {
3008 conflicting_finalize_encode_decode(ed25519::fixture);
3009 conflicting_finalize_encode_decode(secp256r1::fixture);
3010 conflicting_finalize_encode_decode(bls12381_multisig::fixture::<MinPk, _>);
3011 conflicting_finalize_encode_decode(bls12381_multisig::fixture::<MinSig, _>);
3012 conflicting_finalize_encode_decode(bls12381_threshold_vrf::fixture::<MinPk, _>);
3013 conflicting_finalize_encode_decode(bls12381_threshold_vrf::fixture::<MinSig, _>);
3014 conflicting_finalize_encode_decode(bls12381_threshold_std::fixture::<MinPk, _>);
3015 conflicting_finalize_encode_decode(bls12381_threshold_std::fixture::<MinSig, _>);
3016 }
3017
3018 fn nullify_finalize_encode_decode<S, F>(fixture: F)
3019 where
3020 S: Scheme<Sha256>,
3021 F: FnOnce(&mut StdRng, &[u8], u32) -> Fixture<S>,
3022 {
3023 let mut rng = test_rng();
3024 let fixture = fixture(&mut rng, NAMESPACE, 5);
3025 let round = Round::new(Epoch::new(0), View::new(10));
3026 let proposal = Proposal::new(round, View::new(5), sample_digest(1));
3027 let nullify = Nullify::sign::<Sha256>(&fixture.schemes[0], round).unwrap();
3028 let finalize = Finalize::sign(&fixture.schemes[0], proposal).unwrap();
3029 let conflict = NullifyFinalize::new(nullify, finalize);
3030
3031 let encoded = conflict.encode();
3032 let decoded = NullifyFinalize::<S, Sha256>::decode(encoded).unwrap();
3033
3034 assert_eq!(conflict, decoded);
3035 assert!(decoded.verify(&mut rng, &fixture.schemes[0], &Sequential));
3036 }
3037
3038 #[test]
3039 fn test_nullify_finalize_encode_decode() {
3040 nullify_finalize_encode_decode(ed25519::fixture);
3041 nullify_finalize_encode_decode(secp256r1::fixture);
3042 nullify_finalize_encode_decode(bls12381_multisig::fixture::<MinPk, _>);
3043 nullify_finalize_encode_decode(bls12381_multisig::fixture::<MinSig, _>);
3044 nullify_finalize_encode_decode(bls12381_threshold_vrf::fixture::<MinPk, _>);
3045 nullify_finalize_encode_decode(bls12381_threshold_vrf::fixture::<MinSig, _>);
3046 nullify_finalize_encode_decode(bls12381_threshold_std::fixture::<MinPk, _>);
3047 nullify_finalize_encode_decode(bls12381_threshold_std::fixture::<MinSig, _>);
3048 }
3049
3050 fn notarize_verify_wrong_namespace<S, F>(f: F)
3051 where
3052 S: Scheme<Sha256>,
3053 F: Fn(&mut StdRng, &[u8], u32) -> Fixture<S>,
3054 {
3055 let mut rng = test_rng();
3057 let fixture = setup_seeded_ns(5, 0, NAMESPACE, &f);
3058 let wrong_fixture = setup_seeded_ns(5, 0, b"wrong_namespace", &f);
3059 let round = Round::new(Epoch::new(0), View::new(10));
3060 let proposal = Proposal::new(round, View::new(5), sample_digest(1));
3061 let notarize = Notarize::sign(&fixture.schemes[0], proposal).unwrap();
3062
3063 assert!(notarize.verify(&mut rng, &fixture.schemes[0], &Sequential));
3064 assert!(!notarize.verify(&mut rng, &wrong_fixture.schemes[0], &Sequential));
3065 }
3066
3067 #[test]
3068 fn test_notarize_verify_wrong_namespace() {
3069 notarize_verify_wrong_namespace(ed25519::fixture);
3070 notarize_verify_wrong_namespace(secp256r1::fixture);
3071 notarize_verify_wrong_namespace(bls12381_multisig::fixture::<MinPk, _>);
3072 notarize_verify_wrong_namespace(bls12381_multisig::fixture::<MinSig, _>);
3073 notarize_verify_wrong_namespace(bls12381_threshold_vrf::fixture::<MinPk, _>);
3074 notarize_verify_wrong_namespace(bls12381_threshold_vrf::fixture::<MinSig, _>);
3075 notarize_verify_wrong_namespace(bls12381_threshold_std::fixture::<MinPk, _>);
3076 notarize_verify_wrong_namespace(bls12381_threshold_std::fixture::<MinSig, _>);
3077 }
3078
3079 fn notarize_verify_wrong_scheme<S, F>(f: F)
3080 where
3081 S: Scheme<Sha256>,
3082 F: Fn(&mut StdRng, &[u8], u32) -> Fixture<S>,
3083 {
3084 let mut rng = test_rng();
3085 let fixture = setup_seeded(5, 0, &f);
3086 let wrong_fixture = setup_seeded(5, 1, &f);
3087 let round = Round::new(Epoch::new(0), View::new(10));
3088 let proposal = Proposal::new(round, View::new(5), sample_digest(2));
3089 let notarize = Notarize::sign(&fixture.schemes[0], proposal).unwrap();
3090
3091 assert!(notarize.verify(&mut rng, &fixture.schemes[0], &Sequential));
3092 assert!(!notarize.verify(&mut rng, &wrong_fixture.verifier, &Sequential));
3093 }
3094
3095 #[test]
3096 fn test_notarize_verify_wrong_scheme() {
3097 notarize_verify_wrong_scheme(ed25519::fixture);
3098 notarize_verify_wrong_scheme(secp256r1::fixture);
3099 notarize_verify_wrong_scheme(bls12381_multisig::fixture::<MinPk, _>);
3100 notarize_verify_wrong_scheme(bls12381_multisig::fixture::<MinSig, _>);
3101 notarize_verify_wrong_scheme(bls12381_threshold_vrf::fixture::<MinPk, _>);
3102 notarize_verify_wrong_scheme(bls12381_threshold_vrf::fixture::<MinSig, _>);
3103 notarize_verify_wrong_scheme(bls12381_threshold_std::fixture::<MinPk, _>);
3104 notarize_verify_wrong_scheme(bls12381_threshold_std::fixture::<MinSig, _>);
3105 }
3106
3107 fn notarization_verify_wrong_scheme<S, F>(f: F)
3108 where
3109 S: Scheme<Sha256>,
3110 F: Fn(&mut StdRng, &[u8], u32) -> Fixture<S>,
3111 {
3112 let mut rng = test_rng();
3113 let fixture = setup_seeded(5, 0, &f);
3114 let wrong_fixture = setup_seeded(5, 1, &f);
3115 let round = Round::new(Epoch::new(0), View::new(10));
3116 let proposal = Proposal::new(round, View::new(5), sample_digest(3));
3117 let quorum = N3f1::quorum(fixture.schemes.len()) as usize;
3118 let notarizes: Vec<_> = fixture
3119 .schemes
3120 .iter()
3121 .take(quorum)
3122 .map(|scheme| Notarize::sign(scheme, proposal.clone()).unwrap())
3123 .collect();
3124
3125 let notarization =
3126 Notarization::from_notarizes(&fixture.schemes[0], ¬arizes, &Sequential)
3127 .expect("quorum notarization");
3128 assert!(notarization.verify(&mut rng, &fixture.schemes[0], &Sequential));
3129 assert!(!notarization.verify(&mut rng, &wrong_fixture.verifier, &Sequential));
3130 }
3131
3132 #[test]
3133 fn test_notarization_verify_wrong_scheme() {
3134 notarization_verify_wrong_scheme(ed25519::fixture);
3135 notarization_verify_wrong_scheme(secp256r1::fixture);
3136 notarization_verify_wrong_scheme(bls12381_multisig::fixture::<MinPk, _>);
3137 notarization_verify_wrong_scheme(bls12381_multisig::fixture::<MinSig, _>);
3138 notarization_verify_wrong_scheme(bls12381_threshold_vrf::fixture::<MinPk, _>);
3139 notarization_verify_wrong_scheme(bls12381_threshold_vrf::fixture::<MinSig, _>);
3140 notarization_verify_wrong_scheme(bls12381_threshold_std::fixture::<MinPk, _>);
3141 notarization_verify_wrong_scheme(bls12381_threshold_std::fixture::<MinSig, _>);
3142 }
3143
3144 fn notarization_verify_wrong_namespace<S, F>(f: F)
3145 where
3146 S: Scheme<Sha256>,
3147 F: Fn(&mut StdRng, &[u8], u32) -> Fixture<S>,
3148 {
3149 let fixture = setup_seeded_ns(5, 0, NAMESPACE, &f);
3151 let wrong_fixture = setup_seeded_ns(5, 0, b"wrong_namespace", &f);
3152 let mut rng = test_rng();
3153 let round = Round::new(Epoch::new(0), View::new(10));
3154 let proposal = Proposal::new(round, View::new(5), sample_digest(4));
3155 let quorum = N3f1::quorum(fixture.schemes.len()) as usize;
3156 let notarizes: Vec<_> = fixture
3157 .schemes
3158 .iter()
3159 .take(quorum)
3160 .map(|scheme| Notarize::sign(scheme, proposal.clone()).unwrap())
3161 .collect();
3162
3163 let notarization =
3164 Notarization::from_notarizes(&fixture.schemes[0], ¬arizes, &Sequential)
3165 .expect("quorum notarization");
3166 assert!(notarization.verify(&mut rng, &fixture.schemes[0], &Sequential));
3167
3168 assert!(!notarization.verify(&mut rng, &wrong_fixture.schemes[0], &Sequential));
3169 }
3170
3171 #[test]
3172 fn test_notarization_verify_wrong_namespace() {
3173 notarization_verify_wrong_namespace(ed25519::fixture);
3174 notarization_verify_wrong_namespace(secp256r1::fixture);
3175 notarization_verify_wrong_namespace(bls12381_multisig::fixture::<MinPk, _>);
3176 notarization_verify_wrong_namespace(bls12381_multisig::fixture::<MinSig, _>);
3177 notarization_verify_wrong_namespace(bls12381_threshold_vrf::fixture::<MinPk, _>);
3178 notarization_verify_wrong_namespace(bls12381_threshold_vrf::fixture::<MinSig, _>);
3179 notarization_verify_wrong_namespace(bls12381_threshold_std::fixture::<MinPk, _>);
3180 notarization_verify_wrong_namespace(bls12381_threshold_std::fixture::<MinSig, _>);
3181 }
3182
3183 fn notarization_recover_insufficient_signatures<S, F>(fixture: F)
3184 where
3185 S: Scheme<Sha256>,
3186 F: FnOnce(&mut StdRng, &[u8], u32) -> Fixture<S>,
3187 {
3188 let mut rng = test_rng();
3189 let fixture = fixture(&mut rng, NAMESPACE, 5);
3190 let quorum_size = quorum(fixture.schemes.len() as u32) as usize;
3191 assert!(quorum_size > 1, "test requires quorum larger than one");
3192 let round = Round::new(Epoch::new(0), View::new(10));
3193 let proposal = Proposal::new(round, View::new(5), sample_digest(5));
3194 let notarizes: Vec<_> = fixture
3195 .schemes
3196 .iter()
3197 .take(quorum_size - 1)
3198 .map(|scheme| Notarize::sign(scheme, proposal.clone()).unwrap())
3199 .collect();
3200
3201 assert!(
3202 Notarization::from_notarizes(&fixture.schemes[0], ¬arizes, &Sequential).is_none(),
3203 "insufficient votes should not form a notarization"
3204 );
3205 }
3206
3207 #[test]
3208 fn test_notarization_recover_insufficient_signatures() {
3209 notarization_recover_insufficient_signatures(ed25519::fixture);
3210 notarization_recover_insufficient_signatures(secp256r1::fixture);
3211 notarization_recover_insufficient_signatures(bls12381_multisig::fixture::<MinPk, _>);
3212 notarization_recover_insufficient_signatures(bls12381_multisig::fixture::<MinSig, _>);
3213 notarization_recover_insufficient_signatures(bls12381_threshold_vrf::fixture::<MinPk, _>);
3214 notarization_recover_insufficient_signatures(bls12381_threshold_vrf::fixture::<MinSig, _>);
3215 notarization_recover_insufficient_signatures(bls12381_threshold_std::fixture::<MinPk, _>);
3216 notarization_recover_insufficient_signatures(bls12381_threshold_std::fixture::<MinSig, _>);
3217 }
3218
3219 fn conflicting_notarize_detection<S, F>(f: F)
3220 where
3221 S: Scheme<Sha256>,
3222 F: Fn(&mut StdRng, &[u8], u32) -> Fixture<S>,
3223 {
3224 let mut rng = test_rng();
3225 let fixture = setup_seeded(5, 0, &f);
3226 let wrong_ns_fixture = setup_seeded_ns(5, 0, b"wrong_namespace", &f);
3227 let wrong_scheme_fixture = setup_seeded(5, 1, &f);
3228
3229 let round = Round::new(Epoch::new(0), View::new(10));
3230 let proposal1 = Proposal::new(round, View::new(5), sample_digest(6));
3231 let proposal2 = Proposal::new(round, View::new(5), sample_digest(7));
3232
3233 let notarize1 = Notarize::sign(&fixture.schemes[0], proposal1).unwrap();
3234 let notarize2 = Notarize::sign(&fixture.schemes[0], proposal2).unwrap();
3235 let conflict = ConflictingNotarize::new(notarize1, notarize2);
3236
3237 assert!(conflict.verify(&mut rng, &fixture.schemes[0], &Sequential));
3238 assert!(!conflict.verify(&mut rng, &wrong_ns_fixture.schemes[0], &Sequential));
3239 assert!(!conflict.verify(&mut rng, &wrong_scheme_fixture.verifier, &Sequential));
3240 }
3241
3242 #[test]
3243 fn test_conflicting_notarize_detection() {
3244 conflicting_notarize_detection(ed25519::fixture);
3245 conflicting_notarize_detection(secp256r1::fixture);
3246 conflicting_notarize_detection(bls12381_multisig::fixture::<MinPk, _>);
3247 conflicting_notarize_detection(bls12381_multisig::fixture::<MinSig, _>);
3248 conflicting_notarize_detection(bls12381_threshold_vrf::fixture::<MinPk, _>);
3249 conflicting_notarize_detection(bls12381_threshold_vrf::fixture::<MinSig, _>);
3250 conflicting_notarize_detection(bls12381_threshold_std::fixture::<MinPk, _>);
3251 conflicting_notarize_detection(bls12381_threshold_std::fixture::<MinSig, _>);
3252 }
3253
3254 fn nullify_finalize_detection<S, F>(f: F)
3255 where
3256 S: Scheme<Sha256>,
3257 F: Fn(&mut StdRng, &[u8], u32) -> Fixture<S>,
3258 {
3259 let mut rng = test_rng();
3260 let fixture = setup_seeded(5, 0, &f);
3261 let wrong_ns_fixture = setup_seeded_ns(5, 0, b"wrong_namespace", &f);
3262 let wrong_scheme_fixture = setup_seeded(5, 1, &f);
3263
3264 let round = Round::new(Epoch::new(0), View::new(10));
3265 let proposal = Proposal::new(round, View::new(5), sample_digest(8));
3266
3267 let nullify = Nullify::sign::<Sha256>(&fixture.schemes[0], round).unwrap();
3268 let finalize = Finalize::sign(&fixture.schemes[0], proposal).unwrap();
3269 let conflict = NullifyFinalize::new(nullify, finalize);
3270
3271 assert!(conflict.verify(&mut rng, &fixture.schemes[0], &Sequential));
3272 assert!(!conflict.verify(&mut rng, &wrong_ns_fixture.schemes[0], &Sequential));
3273 assert!(!conflict.verify(&mut rng, &wrong_scheme_fixture.verifier, &Sequential));
3274 }
3275
3276 #[test]
3277 fn test_nullify_finalize_detection() {
3278 nullify_finalize_detection(ed25519::fixture);
3279 nullify_finalize_detection(secp256r1::fixture);
3280 nullify_finalize_detection(bls12381_multisig::fixture::<MinPk, _>);
3281 nullify_finalize_detection(bls12381_multisig::fixture::<MinSig, _>);
3282 nullify_finalize_detection(bls12381_threshold_vrf::fixture::<MinPk, _>);
3283 nullify_finalize_detection(bls12381_threshold_vrf::fixture::<MinSig, _>);
3284 nullify_finalize_detection(bls12381_threshold_std::fixture::<MinPk, _>);
3285 nullify_finalize_detection(bls12381_threshold_std::fixture::<MinSig, _>);
3286 }
3287
3288 fn finalization_verify_wrong_scheme<S, F>(f: F)
3289 where
3290 S: Scheme<Sha256>,
3291 F: Fn(&mut StdRng, &[u8], u32) -> Fixture<S>,
3292 {
3293 let mut rng = test_rng();
3294 let fixture = setup_seeded(5, 0, &f);
3295 let wrong_fixture = setup_seeded(5, 1, &f);
3296 let round = Round::new(Epoch::new(0), View::new(10));
3297 let proposal = Proposal::new(round, View::new(5), sample_digest(9));
3298 let quorum = N3f1::quorum(fixture.schemes.len()) as usize;
3299 let finalizes: Vec<_> = fixture
3300 .schemes
3301 .iter()
3302 .take(quorum)
3303 .map(|scheme| Finalize::sign(scheme, proposal.clone()).unwrap())
3304 .collect();
3305
3306 let finalization =
3307 Finalization::from_finalizes(&fixture.schemes[0], &finalizes, &Sequential)
3308 .expect("quorum finalization");
3309 assert!(finalization.verify(&mut rng, &fixture.schemes[0], &Sequential));
3310 assert!(!finalization.verify(&mut rng, &wrong_fixture.verifier, &Sequential));
3311 }
3312
3313 #[test]
3314 fn test_finalization_wrong_scheme() {
3315 finalization_verify_wrong_scheme(ed25519::fixture);
3316 finalization_verify_wrong_scheme(secp256r1::fixture);
3317 finalization_verify_wrong_scheme(bls12381_multisig::fixture::<MinPk, _>);
3318 finalization_verify_wrong_scheme(bls12381_multisig::fixture::<MinSig, _>);
3319 finalization_verify_wrong_scheme(bls12381_threshold_vrf::fixture::<MinPk, _>);
3320 finalization_verify_wrong_scheme(bls12381_threshold_vrf::fixture::<MinSig, _>);
3321 finalization_verify_wrong_scheme(bls12381_threshold_std::fixture::<MinPk, _>);
3322 finalization_verify_wrong_scheme(bls12381_threshold_std::fixture::<MinSig, _>);
3323 }
3324
3325 struct MockAttributable(Participant);
3326
3327 impl Attributable for MockAttributable {
3328 fn signer(&self) -> Participant {
3329 self.0
3330 }
3331 }
3332
3333 #[test]
3334 fn test_attributable_map() {
3335 let mut map = AttributableMap::new(5);
3336 assert_eq!(map.len(), 0);
3337 assert!(map.is_empty());
3338
3339 for i in 0..5 {
3341 assert!(map.get(Participant::new(i)).is_none());
3342 }
3343
3344 assert!(map.insert(MockAttributable(Participant::new(3))));
3345 assert_eq!(map.len(), 1);
3346 assert!(!map.is_empty());
3347 let mut iter = map.iter();
3348 assert!(matches!(iter.next(), Some(a) if a.signer() == Participant::new(3)));
3349 assert!(iter.next().is_none());
3350 drop(iter);
3351
3352 assert!(
3354 matches!(map.get(Participant::new(3)), Some(a) if a.signer() == Participant::new(3))
3355 );
3356
3357 assert!(map.insert(MockAttributable(Participant::new(1))));
3358 assert_eq!(map.len(), 2);
3359 assert!(!map.is_empty());
3360 let mut iter = map.iter();
3361 assert!(matches!(iter.next(), Some(a) if a.signer() == Participant::new(1)));
3362 assert!(matches!(iter.next(), Some(a) if a.signer() == Participant::new(3)));
3363 assert!(iter.next().is_none());
3364 drop(iter);
3365
3366 assert!(
3368 matches!(map.get(Participant::new(1)), Some(a) if a.signer() == Participant::new(1))
3369 );
3370 assert!(
3371 matches!(map.get(Participant::new(3)), Some(a) if a.signer() == Participant::new(3))
3372 );
3373
3374 assert!(map.get(Participant::new(0)).is_none());
3376 assert!(map.get(Participant::new(2)).is_none());
3377 assert!(map.get(Participant::new(4)).is_none());
3378
3379 assert!(!map.insert(MockAttributable(Participant::new(3))));
3380 assert_eq!(map.len(), 2);
3381 assert!(!map.is_empty());
3382 let mut iter = map.iter();
3383 assert!(matches!(iter.next(), Some(a) if a.signer() == Participant::new(1)));
3384 assert!(matches!(iter.next(), Some(a) if a.signer() == Participant::new(3)));
3385 assert!(iter.next().is_none());
3386 drop(iter);
3387
3388 assert!(!map.insert(MockAttributable(Participant::new(5))));
3390 assert!(!map.insert(MockAttributable(Participant::new(100))));
3391 assert_eq!(map.len(), 2);
3392
3393 map.clear();
3395 assert_eq!(map.len(), 0);
3396 assert!(map.is_empty());
3397 assert!(map.iter().next().is_none());
3398
3399 assert!(map.insert(MockAttributable(Participant::new(2))));
3401 assert_eq!(map.len(), 1);
3402 let mut iter = map.iter();
3403 assert!(matches!(iter.next(), Some(a) if a.signer() == Participant::new(2)));
3404 assert!(iter.next().is_none());
3405 }
3406
3407 #[test]
3408 #[should_panic(expected = "proposals must differ")]
3409 fn issue_2944_regression_conflicting_notarize_new() {
3410 let mut rng = test_rng();
3411 let fixture = ed25519::fixture(&mut rng, NAMESPACE, 1);
3412 let proposal = Proposal::new(
3413 Round::new(Epoch::new(0), View::new(10)),
3414 View::new(5),
3415 sample_digest(1),
3416 );
3417 let notarize = Notarize::sign(&fixture.schemes[0], proposal).unwrap();
3418 let _ = ConflictingNotarize::new(notarize.clone(), notarize);
3419 }
3420
3421 #[test]
3422 fn issue_2944_regression_conflicting_notarize_decode() {
3423 let mut rng = test_rng();
3424 let fixture = ed25519::fixture(&mut rng, NAMESPACE, 1);
3425 let proposal = Proposal::new(
3426 Round::new(Epoch::new(0), View::new(10)),
3427 View::new(5),
3428 sample_digest(1),
3429 );
3430 let notarize = Notarize::sign(&fixture.schemes[0], proposal).unwrap();
3431
3432 let mut buf = Vec::new();
3434 notarize.write(&mut buf);
3435 notarize.write(&mut buf);
3436
3437 let result = ConflictingNotarize::<ed25519::Scheme, Sha256>::decode(Bytes::from(buf));
3439 assert!(result.is_err());
3440 }
3441
3442 #[test]
3443 #[should_panic(expected = "proposals must differ")]
3444 fn issue_2944_regression_conflicting_finalize_new() {
3445 let mut rng = test_rng();
3446 let fixture = ed25519::fixture(&mut rng, NAMESPACE, 1);
3447 let proposal = Proposal::new(
3448 Round::new(Epoch::new(0), View::new(10)),
3449 View::new(5),
3450 sample_digest(1),
3451 );
3452 let finalize = Finalize::sign(&fixture.schemes[0], proposal).unwrap();
3453 let _ = ConflictingFinalize::new(finalize.clone(), finalize);
3454 }
3455
3456 #[test]
3457 fn issue_2944_regression_conflicting_finalize_decode() {
3458 let mut rng = test_rng();
3459 let fixture = ed25519::fixture(&mut rng, NAMESPACE, 1);
3460 let proposal = Proposal::new(
3461 Round::new(Epoch::new(0), View::new(10)),
3462 View::new(5),
3463 sample_digest(1),
3464 );
3465 let finalize = Finalize::sign(&fixture.schemes[0], proposal).unwrap();
3466
3467 let mut buf = Vec::new();
3469 finalize.write(&mut buf);
3470 finalize.write(&mut buf);
3471
3472 let result = ConflictingFinalize::<ed25519::Scheme, Sha256>::decode(Bytes::from(buf));
3474 assert!(result.is_err());
3475 }
3476
3477 #[cfg(feature = "arbitrary")]
3478 mod conformance {
3479 use super::*;
3480 use crate::simplex::scheme::bls12381_threshold::vrf as bls12381_threshold_vrf;
3481 use commonware_codec::conformance::CodecConformance;
3482 use commonware_cryptography::{ed25519::PublicKey, sha256::Digest as Sha256Digest};
3483
3484 type Scheme = bls12381_threshold_vrf::Scheme<PublicKey, MinSig>;
3485
3486 commonware_conformance::conformance_tests! {
3487 CodecConformance<Vote<Scheme, Sha256Digest>>,
3488 CodecConformance<Certificate<Scheme, Sha256Digest>>,
3489 CodecConformance<Artifact<Scheme, Sha256Digest>>,
3490 CodecConformance<Proposal<Sha256Digest>>,
3491 CodecConformance<Notarize<Scheme, Sha256Digest>>,
3492 CodecConformance<Notarization<Scheme, Sha256Digest>>,
3493 CodecConformance<Nullify<Scheme>>,
3494 CodecConformance<Nullification<Scheme>>,
3495 CodecConformance<Finalize<Scheme, Sha256Digest>>,
3496 CodecConformance<Finalization<Scheme, Sha256Digest>>,
3497 CodecConformance<Backfiller<Scheme, Sha256Digest>>,
3498 CodecConformance<Request>,
3499 CodecConformance<Response<Scheme, Sha256Digest>>,
3500 CodecConformance<Activity<Scheme, Sha256Digest>>,
3501 CodecConformance<ConflictingNotarize<Scheme, Sha256Digest>>,
3502 CodecConformance<ConflictingFinalize<Scheme, Sha256Digest>>,
3503 CodecConformance<NullifyFinalize<Scheme, Sha256Digest>>,
3504 CodecConformance<Context<Sha256Digest, PublicKey>>
3505 }
3506 }
3507}