1use crate::{
4 simplex::scheme::{self, CertificateVerifier},
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::CryptoRng;
17use std::{collections::HashSet, fmt::Debug, hash::Hash, iter::once};
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
422#[cfg(not(target_arch = "wasm32"))]
423impl<S: Scheme, D: Digest> Certificate<S, D> {
424 pub(crate) const fn kind(&self) -> &'static str {
426 match self {
427 Self::Notarization(_) => "notarization",
428 Self::Nullification(_) => "nullification",
429 Self::Finalization(_) => "finalization",
430 }
431 }
432}
433
434impl<S: Scheme, D: Digest> Write for Certificate<S, D> {
435 fn write(&self, writer: &mut impl BufMut) {
436 match self {
437 Self::Notarization(v) => {
438 0u8.write(writer);
439 v.write(writer);
440 }
441 Self::Nullification(v) => {
442 1u8.write(writer);
443 v.write(writer);
444 }
445 Self::Finalization(v) => {
446 2u8.write(writer);
447 v.write(writer);
448 }
449 }
450 }
451}
452
453impl<S: Scheme, D: Digest> EncodeSize for Certificate<S, D> {
454 fn encode_size(&self) -> usize {
455 1 + match self {
456 Self::Notarization(v) => v.encode_size(),
457 Self::Nullification(v) => v.encode_size(),
458 Self::Finalization(v) => v.encode_size(),
459 }
460 }
461}
462
463impl<S: Scheme, D: Digest> Read for Certificate<S, D> {
464 type Cfg = <S::Certificate as Read>::Cfg;
465
466 fn read_cfg(reader: &mut impl Buf, cfg: &Self::Cfg) -> Result<Self, Error> {
467 let tag = <u8>::read(reader)?;
468 match tag {
469 0 => {
470 let v = Notarization::read_cfg(reader, cfg)?;
471 Ok(Self::Notarization(v))
472 }
473 1 => {
474 let v = Nullification::read_cfg(reader, cfg)?;
475 Ok(Self::Nullification(v))
476 }
477 2 => {
478 let v = Finalization::read_cfg(reader, cfg)?;
479 Ok(Self::Finalization(v))
480 }
481 _ => Err(Error::Invalid(
482 "consensus::simplex::Certificate",
483 "Invalid type",
484 )),
485 }
486 }
487}
488
489impl<S: Scheme, D: Digest> Epochable for Certificate<S, D> {
490 fn epoch(&self) -> Epoch {
491 match self {
492 Self::Notarization(v) => v.epoch(),
493 Self::Nullification(v) => v.epoch(),
494 Self::Finalization(v) => v.epoch(),
495 }
496 }
497}
498
499impl<S: Scheme, D: Digest> Viewable for Certificate<S, D> {
500 fn view(&self) -> View {
501 match self {
502 Self::Notarization(v) => v.view(),
503 Self::Nullification(v) => v.view(),
504 Self::Finalization(v) => v.view(),
505 }
506 }
507}
508
509#[cfg(feature = "arbitrary")]
510impl<S: Scheme, D: Digest> arbitrary::Arbitrary<'_> for Certificate<S, D>
511where
512 S::Certificate: for<'a> arbitrary::Arbitrary<'a>,
513 D: for<'a> arbitrary::Arbitrary<'a>,
514{
515 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
516 let tag = u.int_in_range(0..=2)?;
517 match tag {
518 0 => {
519 let v = Notarization::arbitrary(u)?;
520 Ok(Self::Notarization(v))
521 }
522 1 => {
523 let v = Nullification::arbitrary(u)?;
524 Ok(Self::Nullification(v))
525 }
526 2 => {
527 let v = Finalization::arbitrary(u)?;
528 Ok(Self::Finalization(v))
529 }
530 _ => unreachable!(),
531 }
532 }
533}
534
535#[derive(Clone, Debug, PartialEq)]
537pub enum Artifact<S: Scheme, D: Digest> {
538 Notarize(Notarize<S, D>),
540 Notarization(Notarization<S, D>),
542 Certification(Round, bool),
544 Nullify(Nullify<S>),
546 Nullification(Nullification<S>),
548 Finalize(Finalize<S, D>),
550 Finalization(Finalization<S, D>),
552}
553
554impl<S: Scheme, D: Digest> Write for Artifact<S, D> {
555 fn write(&self, writer: &mut impl BufMut) {
556 match self {
557 Self::Notarize(v) => {
558 0u8.write(writer);
559 v.write(writer);
560 }
561 Self::Notarization(v) => {
562 1u8.write(writer);
563 v.write(writer);
564 }
565 Self::Certification(r, b) => {
566 2u8.write(writer);
567 r.write(writer);
568 b.write(writer);
569 }
570 Self::Nullify(v) => {
571 3u8.write(writer);
572 v.write(writer);
573 }
574 Self::Nullification(v) => {
575 4u8.write(writer);
576 v.write(writer);
577 }
578 Self::Finalize(v) => {
579 5u8.write(writer);
580 v.write(writer);
581 }
582 Self::Finalization(v) => {
583 6u8.write(writer);
584 v.write(writer);
585 }
586 }
587 }
588}
589
590impl<S: Scheme, D: Digest> EncodeSize for Artifact<S, D> {
591 fn encode_size(&self) -> usize {
592 1 + match self {
593 Self::Notarize(v) => v.encode_size(),
594 Self::Notarization(v) => v.encode_size(),
595 Self::Certification(r, b) => r.encode_size() + b.encode_size(),
596 Self::Nullify(v) => v.encode_size(),
597 Self::Nullification(v) => v.encode_size(),
598 Self::Finalize(v) => v.encode_size(),
599 Self::Finalization(v) => v.encode_size(),
600 }
601 }
602}
603
604impl<S: Scheme, D: Digest> Read for Artifact<S, D> {
605 type Cfg = <S::Certificate as Read>::Cfg;
606
607 fn read_cfg(reader: &mut impl Buf, cfg: &Self::Cfg) -> Result<Self, Error> {
608 let tag = <u8>::read(reader)?;
609 match tag {
610 0 => {
611 let v = Notarize::read(reader)?;
612 Ok(Self::Notarize(v))
613 }
614 1 => {
615 let v = Notarization::read_cfg(reader, cfg)?;
616 Ok(Self::Notarization(v))
617 }
618 2 => {
619 let r = Round::read(reader)?;
620 let b = bool::read(reader)?;
621 Ok(Self::Certification(r, b))
622 }
623 3 => {
624 let v = Nullify::read(reader)?;
625 Ok(Self::Nullify(v))
626 }
627 4 => {
628 let v = Nullification::read_cfg(reader, cfg)?;
629 Ok(Self::Nullification(v))
630 }
631 5 => {
632 let v = Finalize::read(reader)?;
633 Ok(Self::Finalize(v))
634 }
635 6 => {
636 let v = Finalization::read_cfg(reader, cfg)?;
637 Ok(Self::Finalization(v))
638 }
639 _ => Err(Error::Invalid(
640 "consensus::simplex::Artifact",
641 "Invalid type",
642 )),
643 }
644 }
645}
646
647impl<S: Scheme, D: Digest> Epochable for Artifact<S, D> {
648 fn epoch(&self) -> Epoch {
649 match self {
650 Self::Notarize(v) => v.epoch(),
651 Self::Notarization(v) => v.epoch(),
652 Self::Certification(r, _) => r.epoch(),
653 Self::Nullify(v) => v.epoch(),
654 Self::Nullification(v) => v.epoch(),
655 Self::Finalize(v) => v.epoch(),
656 Self::Finalization(v) => v.epoch(),
657 }
658 }
659}
660
661impl<S: Scheme, D: Digest> Viewable for Artifact<S, D> {
662 fn view(&self) -> View {
663 match self {
664 Self::Notarize(v) => v.view(),
665 Self::Notarization(v) => v.view(),
666 Self::Certification(r, _) => r.view(),
667 Self::Nullify(v) => v.view(),
668 Self::Nullification(v) => v.view(),
669 Self::Finalize(v) => v.view(),
670 Self::Finalization(v) => v.view(),
671 }
672 }
673}
674
675impl<S: Scheme, D: Digest> From<Vote<S, D>> for Artifact<S, D> {
676 fn from(vote: Vote<S, D>) -> Self {
677 match vote {
678 Vote::Notarize(v) => Self::Notarize(v),
679 Vote::Nullify(v) => Self::Nullify(v),
680 Vote::Finalize(v) => Self::Finalize(v),
681 }
682 }
683}
684
685impl<S: Scheme, D: Digest> From<Certificate<S, D>> for Artifact<S, D> {
686 fn from(cert: Certificate<S, D>) -> Self {
687 match cert {
688 Certificate::Notarization(v) => Self::Notarization(v),
689 Certificate::Nullification(v) => Self::Nullification(v),
690 Certificate::Finalization(v) => Self::Finalization(v),
691 }
692 }
693}
694
695#[cfg(feature = "arbitrary")]
696impl<S: Scheme, D: Digest> arbitrary::Arbitrary<'_> for Artifact<S, D>
697where
698 S::Signature: for<'a> arbitrary::Arbitrary<'a>,
699 S::Certificate: for<'a> arbitrary::Arbitrary<'a>,
700 D: for<'a> arbitrary::Arbitrary<'a>,
701{
702 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
703 let tag = u.int_in_range(0..=6)?;
704 match tag {
705 0 => {
706 let v = Notarize::arbitrary(u)?;
707 Ok(Self::Notarize(v))
708 }
709 1 => {
710 let v = Notarization::arbitrary(u)?;
711 Ok(Self::Notarization(v))
712 }
713 2 => {
714 let r = Round::arbitrary(u)?;
715 let b = bool::arbitrary(u)?;
716 Ok(Self::Certification(r, b))
717 }
718 3 => {
719 let v = Nullify::arbitrary(u)?;
720 Ok(Self::Nullify(v))
721 }
722 4 => {
723 let v = Nullification::arbitrary(u)?;
724 Ok(Self::Nullification(v))
725 }
726 5 => {
727 let v = Finalize::arbitrary(u)?;
728 Ok(Self::Finalize(v))
729 }
730 6 => {
731 let v = Finalization::arbitrary(u)?;
732 Ok(Self::Finalization(v))
733 }
734 _ => unreachable!(),
735 }
736 }
737}
738
739#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
742pub struct Proposal<D: Digest> {
743 pub round: Round,
745 pub parent: View,
747 pub payload: D,
749}
750
751impl<D: Digest> Proposal<D> {
752 pub const fn new(round: Round, parent: View, payload: D) -> Self {
754 Self {
755 round,
756 parent,
757 payload,
758 }
759 }
760}
761
762impl<D: Digest> Write for Proposal<D> {
763 fn write(&self, writer: &mut impl BufMut) {
764 self.round.write(writer);
765 self.parent.write(writer);
766 self.payload.write(writer)
767 }
768}
769
770impl<D: Digest> Read for Proposal<D> {
771 type Cfg = ();
772
773 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
774 let round = Round::read(reader)?;
775 let parent = View::read(reader)?;
776 let payload = D::read(reader)?;
777 Ok(Self {
778 round,
779 parent,
780 payload,
781 })
782 }
783}
784
785impl<D: Digest> EncodeSize for Proposal<D> {
786 fn encode_size(&self) -> usize {
787 self.round.encode_size() + self.parent.encode_size() + self.payload.encode_size()
788 }
789}
790
791impl<D: Digest> Epochable for Proposal<D> {
792 fn epoch(&self) -> Epoch {
793 self.round.epoch()
794 }
795}
796
797impl<D: Digest> Viewable for Proposal<D> {
798 fn view(&self) -> View {
799 self.round.view()
800 }
801}
802
803#[cfg(feature = "arbitrary")]
804impl<D: Digest> arbitrary::Arbitrary<'_> for Proposal<D>
805where
806 D: for<'a> arbitrary::Arbitrary<'a>,
807{
808 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
809 let round = Round::arbitrary(u)?;
810 let parent = View::arbitrary(u)?;
811 let payload = D::arbitrary(u)?;
812 Ok(Self {
813 round,
814 parent,
815 payload,
816 })
817 }
818}
819
820#[derive(Clone, Debug)]
822pub struct Notarize<S: Scheme, D: Digest> {
823 pub proposal: Proposal<D>,
825 pub attestation: Attestation<S>,
827}
828
829impl<S: Scheme, D: Digest> Notarize<S, D> {
830 pub fn sign(scheme: &S, proposal: Proposal<D>) -> Option<Self>
832 where
833 S: scheme::Scheme<D>,
834 {
835 let attestation = scheme.sign::<D>(Subject::Notarize {
836 proposal: &proposal,
837 })?;
838
839 Some(Self {
840 proposal,
841 attestation,
842 })
843 }
844
845 pub fn verify<R>(&self, rng: &mut R, scheme: &S, strategy: &impl Strategy) -> bool
849 where
850 R: CryptoRng,
851 S: scheme::Scheme<D>,
852 {
853 scheme.verify_attestation::<_, D>(
854 rng,
855 Subject::Notarize {
856 proposal: &self.proposal,
857 },
858 &self.attestation,
859 strategy,
860 )
861 }
862
863 pub const fn round(&self) -> Round {
865 self.proposal.round
866 }
867}
868
869impl<S: Scheme, D: Digest> PartialEq for Notarize<S, D> {
870 fn eq(&self, other: &Self) -> bool {
871 self.proposal == other.proposal && self.attestation == other.attestation
872 }
873}
874
875impl<S: Scheme, D: Digest> Eq for Notarize<S, D> {}
876
877impl<S: Scheme, D: Digest> Hash for Notarize<S, D> {
878 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
879 self.proposal.hash(state);
880 self.attestation.hash(state);
881 }
882}
883
884impl<S: Scheme, D: Digest> Write for Notarize<S, D> {
885 fn write(&self, writer: &mut impl BufMut) {
886 self.proposal.write(writer);
887 self.attestation.write(writer);
888 }
889}
890
891impl<S: Scheme, D: Digest> EncodeSize for Notarize<S, D> {
892 fn encode_size(&self) -> usize {
893 self.proposal.encode_size() + self.attestation.encode_size()
894 }
895}
896
897impl<S: Scheme, D: Digest> Read for Notarize<S, D> {
898 type Cfg = ();
899
900 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
901 let proposal = Proposal::read(reader)?;
902 let attestation = Attestation::read(reader)?;
903
904 Ok(Self {
905 proposal,
906 attestation,
907 })
908 }
909}
910
911impl<S: Scheme, D: Digest> Attributable for Notarize<S, D> {
912 fn signer(&self) -> Participant {
913 self.attestation.signer
914 }
915}
916
917impl<S: Scheme, D: Digest> Epochable for Notarize<S, D> {
918 fn epoch(&self) -> Epoch {
919 self.proposal.epoch()
920 }
921}
922
923impl<S: Scheme, D: Digest> Viewable for Notarize<S, D> {
924 fn view(&self) -> View {
925 self.proposal.view()
926 }
927}
928
929#[cfg(feature = "arbitrary")]
930impl<S: Scheme, D: Digest> arbitrary::Arbitrary<'_> for Notarize<S, D>
931where
932 S::Signature: for<'a> arbitrary::Arbitrary<'a>,
933 D: for<'a> arbitrary::Arbitrary<'a>,
934{
935 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
936 let proposal = Proposal::arbitrary(u)?;
937 let attestation = Attestation::arbitrary(u)?;
938 Ok(Self {
939 proposal,
940 attestation,
941 })
942 }
943}
944
945pub fn verify_certificates<'a, R, S, D>(
950 rng: &mut R,
951 scheme: &S,
952 certificates: &[(Subject<'a, D>, &'a S::Certificate)],
953 strategy: &impl Strategy,
954) -> Vec<bool>
955where
956 R: CryptoRng,
957 S: CertificateVerifier<D>,
958 D: Digest,
959{
960 scheme.verify_certificates_bisect::<_, D, N3f1>(rng, certificates, strategy)
961}
962
963#[derive(Clone, Debug)]
970pub struct Notarization<S: Scheme, D: Digest> {
971 pub proposal: Proposal<D>,
973 pub certificate: S::Certificate,
975}
976
977impl<S: Scheme, D: Digest> Notarization<S, D> {
978 pub fn from_owned_notarizes<I>(
981 scheme: &S,
982 notarizes: I,
983 strategy: &impl Strategy,
984 ) -> Option<Self>
985 where
986 I: IntoIterator<Item = Notarize<S, D>>,
987 I::IntoIter: Send,
988 {
989 let mut notarizes = notarizes.into_iter();
990 let Notarize {
991 proposal,
992 attestation,
993 } = notarizes.next()?;
994 let attestations = once(attestation).chain(notarizes.map(|n| n.attestation));
995 let certificate = scheme.assemble::<_, N3f1>(attestations, strategy)?;
996
997 Some(Self {
998 proposal,
999 certificate,
1000 })
1001 }
1002
1003 pub fn from_notarizes<'a, I>(scheme: &S, notarizes: I, strategy: &impl Strategy) -> Option<Self>
1005 where
1006 I: IntoIterator<Item = &'a Notarize<S, D>>,
1007 I::IntoIter: Send,
1008 {
1009 Self::from_owned_notarizes(scheme, notarizes.into_iter().cloned(), strategy)
1010 }
1011
1012 pub fn verify<R: CryptoRng>(
1016 &self,
1017 rng: &mut R,
1018 scheme: &impl CertificateVerifier<D, Certificate = S::Certificate>,
1019 strategy: &impl Strategy,
1020 ) -> bool {
1021 scheme.verify_certificate::<_, D, N3f1>(
1022 rng,
1023 Subject::Notarize {
1024 proposal: &self.proposal,
1025 },
1026 &self.certificate,
1027 strategy,
1028 )
1029 }
1030
1031 pub const fn round(&self) -> Round {
1033 self.proposal.round
1034 }
1035}
1036
1037impl<S: Scheme, D: Digest> PartialEq for Notarization<S, D> {
1038 fn eq(&self, other: &Self) -> bool {
1039 self.proposal == other.proposal && self.certificate == other.certificate
1040 }
1041}
1042
1043impl<S: Scheme, D: Digest> Eq for Notarization<S, D> {}
1044
1045impl<S: Scheme, D: Digest> Hash for Notarization<S, D> {
1046 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1047 self.proposal.hash(state);
1048 self.certificate.hash(state);
1049 }
1050}
1051
1052impl<S: Scheme, D: Digest> Write for Notarization<S, D> {
1053 fn write(&self, writer: &mut impl BufMut) {
1054 self.proposal.write(writer);
1055 self.certificate.write(writer);
1056 }
1057}
1058
1059impl<S: Scheme, D: Digest> EncodeSize for Notarization<S, D> {
1060 fn encode_size(&self) -> usize {
1061 self.proposal.encode_size() + self.certificate.encode_size()
1062 }
1063}
1064
1065impl<S: Scheme, D: Digest> Read for Notarization<S, D> {
1066 type Cfg = <S::Certificate as Read>::Cfg;
1067
1068 fn read_cfg(reader: &mut impl Buf, cfg: &Self::Cfg) -> Result<Self, Error> {
1069 let proposal = Proposal::read(reader)?;
1070 let certificate = S::Certificate::read_cfg(reader, cfg)?;
1071
1072 Ok(Self {
1073 proposal,
1074 certificate,
1075 })
1076 }
1077}
1078
1079impl<S: Scheme, D: Digest> Epochable for Notarization<S, D> {
1080 fn epoch(&self) -> Epoch {
1081 self.proposal.epoch()
1082 }
1083}
1084
1085impl<S: Scheme, D: Digest> Viewable for Notarization<S, D> {
1086 fn view(&self) -> View {
1087 self.proposal.view()
1088 }
1089}
1090
1091#[cfg(feature = "arbitrary")]
1092impl<S: Scheme, D: Digest> arbitrary::Arbitrary<'_> for Notarization<S, D>
1093where
1094 S::Certificate: for<'a> arbitrary::Arbitrary<'a>,
1095 D: for<'a> arbitrary::Arbitrary<'a>,
1096{
1097 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
1098 let proposal = Proposal::arbitrary(u)?;
1099 let certificate = S::Certificate::arbitrary(u)?;
1100 Ok(Self {
1101 proposal,
1102 certificate,
1103 })
1104 }
1105}
1106
1107#[derive(Clone, Debug)]
1110pub struct Nullify<S: Scheme> {
1111 pub round: Round,
1113 pub attestation: Attestation<S>,
1115}
1116
1117impl<S: Scheme> PartialEq for Nullify<S> {
1118 fn eq(&self, other: &Self) -> bool {
1119 self.round == other.round && self.attestation == other.attestation
1120 }
1121}
1122
1123impl<S: Scheme> Eq for Nullify<S> {}
1124
1125impl<S: Scheme> Hash for Nullify<S> {
1126 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1127 self.round.hash(state);
1128 self.attestation.hash(state);
1129 }
1130}
1131
1132impl<S: Scheme> Nullify<S> {
1133 pub fn sign<D: Digest>(scheme: &S, round: Round) -> Option<Self>
1135 where
1136 S: scheme::Scheme<D>,
1137 {
1138 let attestation = scheme.sign::<D>(Subject::Nullify { round })?;
1139
1140 Some(Self { round, attestation })
1141 }
1142
1143 pub fn verify<R, D: Digest>(&self, rng: &mut R, scheme: &S, strategy: &impl Strategy) -> bool
1147 where
1148 R: CryptoRng,
1149 S: scheme::Scheme<D>,
1150 {
1151 scheme.verify_attestation::<_, D>(
1152 rng,
1153 Subject::Nullify { round: self.round },
1154 &self.attestation,
1155 strategy,
1156 )
1157 }
1158
1159 pub const fn round(&self) -> Round {
1161 self.round
1162 }
1163}
1164
1165impl<S: Scheme> Write for Nullify<S> {
1166 fn write(&self, writer: &mut impl BufMut) {
1167 self.round.write(writer);
1168 self.attestation.write(writer);
1169 }
1170}
1171
1172impl<S: Scheme> EncodeSize for Nullify<S> {
1173 fn encode_size(&self) -> usize {
1174 self.round.encode_size() + self.attestation.encode_size()
1175 }
1176}
1177
1178impl<S: Scheme> Read for Nullify<S> {
1179 type Cfg = ();
1180
1181 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
1182 let round = Round::read(reader)?;
1183 let attestation = Attestation::read(reader)?;
1184
1185 Ok(Self { round, attestation })
1186 }
1187}
1188
1189impl<S: Scheme> Attributable for Nullify<S> {
1190 fn signer(&self) -> Participant {
1191 self.attestation.signer
1192 }
1193}
1194
1195impl<S: Scheme> Epochable for Nullify<S> {
1196 fn epoch(&self) -> Epoch {
1197 self.round.epoch()
1198 }
1199}
1200
1201impl<S: Scheme> Viewable for Nullify<S> {
1202 fn view(&self) -> View {
1203 self.round.view()
1204 }
1205}
1206
1207#[cfg(feature = "arbitrary")]
1208impl<S: Scheme> arbitrary::Arbitrary<'_> for Nullify<S>
1209where
1210 S::Signature: for<'a> arbitrary::Arbitrary<'a>,
1211{
1212 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
1213 let round = Round::arbitrary(u)?;
1214 let attestation = Attestation::arbitrary(u)?;
1215 Ok(Self { round, attestation })
1216 }
1217}
1218
1219#[derive(Clone, Debug)]
1222pub struct Nullification<S: Scheme> {
1223 pub round: Round,
1225 pub certificate: S::Certificate,
1227}
1228
1229impl<S: Scheme> Nullification<S> {
1230 pub fn from_owned_nullifies<I>(
1233 scheme: &S,
1234 nullifies: I,
1235 strategy: &impl Strategy,
1236 ) -> Option<Self>
1237 where
1238 I: IntoIterator<Item = Nullify<S>>,
1239 I::IntoIter: Send,
1240 {
1241 let mut nullifies = nullifies.into_iter();
1242 let Nullify { round, attestation } = nullifies.next()?;
1243 let attestations = once(attestation).chain(nullifies.map(|n| n.attestation));
1244 let certificate = scheme.assemble::<_, N3f1>(attestations, strategy)?;
1245
1246 Some(Self { round, certificate })
1247 }
1248
1249 pub fn from_nullifies<'a, I>(scheme: &S, nullifies: I, strategy: &impl Strategy) -> Option<Self>
1251 where
1252 I: IntoIterator<Item = &'a Nullify<S>>,
1253 I::IntoIter: Send,
1254 {
1255 Self::from_owned_nullifies(scheme, nullifies.into_iter().cloned(), strategy)
1256 }
1257
1258 pub fn verify<R: CryptoRng, D: Digest>(
1262 &self,
1263 rng: &mut R,
1264 scheme: &impl CertificateVerifier<D, Certificate = S::Certificate>,
1265 strategy: &impl Strategy,
1266 ) -> bool {
1267 scheme.verify_certificate::<_, D, N3f1>(
1268 rng,
1269 Subject::Nullify { round: self.round },
1270 &self.certificate,
1271 strategy,
1272 )
1273 }
1274
1275 pub const fn round(&self) -> Round {
1277 self.round
1278 }
1279}
1280
1281impl<S: Scheme> PartialEq for Nullification<S> {
1282 fn eq(&self, other: &Self) -> bool {
1283 self.round == other.round && self.certificate == other.certificate
1284 }
1285}
1286
1287impl<S: Scheme> Eq for Nullification<S> {}
1288
1289impl<S: Scheme> Hash for Nullification<S> {
1290 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1291 self.round.hash(state);
1292 self.certificate.hash(state);
1293 }
1294}
1295
1296impl<S: Scheme> Write for Nullification<S> {
1297 fn write(&self, writer: &mut impl BufMut) {
1298 self.round.write(writer);
1299 self.certificate.write(writer);
1300 }
1301}
1302
1303impl<S: Scheme> EncodeSize for Nullification<S> {
1304 fn encode_size(&self) -> usize {
1305 self.round.encode_size() + self.certificate.encode_size()
1306 }
1307}
1308
1309impl<S: Scheme> Read for Nullification<S> {
1310 type Cfg = <S::Certificate as Read>::Cfg;
1311
1312 fn read_cfg(reader: &mut impl Buf, cfg: &Self::Cfg) -> Result<Self, Error> {
1313 let round = Round::read(reader)?;
1314 let certificate = S::Certificate::read_cfg(reader, cfg)?;
1315
1316 Ok(Self { round, certificate })
1317 }
1318}
1319
1320impl<S: Scheme> Epochable for Nullification<S> {
1321 fn epoch(&self) -> Epoch {
1322 self.round.epoch()
1323 }
1324}
1325
1326impl<S: Scheme> Viewable for Nullification<S> {
1327 fn view(&self) -> View {
1328 self.round.view()
1329 }
1330}
1331
1332#[cfg(feature = "arbitrary")]
1333impl<S: Scheme> arbitrary::Arbitrary<'_> for Nullification<S>
1334where
1335 S::Certificate: for<'a> arbitrary::Arbitrary<'a>,
1336{
1337 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
1338 let round = Round::arbitrary(u)?;
1339 let certificate = S::Certificate::arbitrary(u)?;
1340 Ok(Self { round, certificate })
1341 }
1342}
1343
1344#[derive(Clone, Debug)]
1348pub struct Finalize<S: Scheme, D: Digest> {
1349 pub proposal: Proposal<D>,
1351 pub attestation: Attestation<S>,
1353}
1354
1355impl<S: Scheme, D: Digest> Finalize<S, D> {
1356 pub fn sign(scheme: &S, proposal: Proposal<D>) -> Option<Self>
1358 where
1359 S: scheme::Scheme<D>,
1360 {
1361 let attestation = scheme.sign::<D>(Subject::Finalize {
1362 proposal: &proposal,
1363 })?;
1364
1365 Some(Self {
1366 proposal,
1367 attestation,
1368 })
1369 }
1370
1371 pub fn verify<R>(&self, rng: &mut R, scheme: &S, strategy: &impl Strategy) -> bool
1375 where
1376 R: CryptoRng,
1377 S: scheme::Scheme<D>,
1378 {
1379 scheme.verify_attestation::<_, D>(
1380 rng,
1381 Subject::Finalize {
1382 proposal: &self.proposal,
1383 },
1384 &self.attestation,
1385 strategy,
1386 )
1387 }
1388
1389 pub const fn round(&self) -> Round {
1391 self.proposal.round
1392 }
1393}
1394
1395impl<S: Scheme, D: Digest> PartialEq for Finalize<S, D> {
1396 fn eq(&self, other: &Self) -> bool {
1397 self.proposal == other.proposal && self.attestation == other.attestation
1398 }
1399}
1400
1401impl<S: Scheme, D: Digest> Eq for Finalize<S, D> {}
1402
1403impl<S: Scheme, D: Digest> Hash for Finalize<S, D> {
1404 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1405 self.proposal.hash(state);
1406 self.attestation.hash(state);
1407 }
1408}
1409
1410impl<S: Scheme, D: Digest> Write for Finalize<S, D> {
1411 fn write(&self, writer: &mut impl BufMut) {
1412 self.proposal.write(writer);
1413 self.attestation.write(writer);
1414 }
1415}
1416
1417impl<S: Scheme, D: Digest> EncodeSize for Finalize<S, D> {
1418 fn encode_size(&self) -> usize {
1419 self.proposal.encode_size() + self.attestation.encode_size()
1420 }
1421}
1422
1423impl<S: Scheme, D: Digest> Read for Finalize<S, D> {
1424 type Cfg = ();
1425
1426 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
1427 let proposal = Proposal::read(reader)?;
1428 let attestation = Attestation::read(reader)?;
1429
1430 Ok(Self {
1431 proposal,
1432 attestation,
1433 })
1434 }
1435}
1436
1437impl<S: Scheme, D: Digest> Attributable for Finalize<S, D> {
1438 fn signer(&self) -> Participant {
1439 self.attestation.signer
1440 }
1441}
1442
1443impl<S: Scheme, D: Digest> Epochable for Finalize<S, D> {
1444 fn epoch(&self) -> Epoch {
1445 self.proposal.epoch()
1446 }
1447}
1448
1449impl<S: Scheme, D: Digest> Viewable for Finalize<S, D> {
1450 fn view(&self) -> View {
1451 self.proposal.view()
1452 }
1453}
1454
1455#[cfg(feature = "arbitrary")]
1456impl<S: Scheme, D: Digest> arbitrary::Arbitrary<'_> for Finalize<S, D>
1457where
1458 S::Signature: for<'a> arbitrary::Arbitrary<'a>,
1459 D: for<'a> arbitrary::Arbitrary<'a>,
1460{
1461 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
1462 let proposal = Proposal::arbitrary(u)?;
1463 let attestation = Attestation::arbitrary(u)?;
1464 Ok(Self {
1465 proposal,
1466 attestation,
1467 })
1468 }
1469}
1470
1471#[derive(Clone, Debug)]
1478pub struct Finalization<S: Scheme, D: Digest> {
1479 pub proposal: Proposal<D>,
1481 pub certificate: S::Certificate,
1483}
1484
1485impl<S: Scheme, D: Digest> Finalization<S, D> {
1486 pub fn from_owned_finalizes<I>(
1489 scheme: &S,
1490 finalizes: I,
1491 strategy: &impl Strategy,
1492 ) -> Option<Self>
1493 where
1494 I: IntoIterator<Item = Finalize<S, D>>,
1495 I::IntoIter: Send,
1496 {
1497 let mut finalizes = finalizes.into_iter();
1498 let Finalize {
1499 proposal,
1500 attestation,
1501 } = finalizes.next()?;
1502 let attestations = once(attestation).chain(finalizes.map(|f| f.attestation));
1503 let certificate = scheme.assemble::<_, N3f1>(attestations, strategy)?;
1504
1505 Some(Self {
1506 proposal,
1507 certificate,
1508 })
1509 }
1510
1511 pub fn from_finalizes<'a, I>(scheme: &S, finalizes: I, strategy: &impl Strategy) -> Option<Self>
1513 where
1514 I: IntoIterator<Item = &'a Finalize<S, D>>,
1515 I::IntoIter: Send,
1516 {
1517 Self::from_owned_finalizes(scheme, finalizes.into_iter().cloned(), strategy)
1518 }
1519
1520 pub fn verify<R: CryptoRng>(
1524 &self,
1525 rng: &mut R,
1526 scheme: &impl CertificateVerifier<D, Certificate = S::Certificate>,
1527 strategy: &impl Strategy,
1528 ) -> bool {
1529 scheme.verify_certificate::<_, D, N3f1>(
1530 rng,
1531 Subject::Finalize {
1532 proposal: &self.proposal,
1533 },
1534 &self.certificate,
1535 strategy,
1536 )
1537 }
1538
1539 pub const fn round(&self) -> Round {
1541 self.proposal.round
1542 }
1543}
1544
1545impl<S: Scheme, D: Digest> PartialEq for Finalization<S, D> {
1546 fn eq(&self, other: &Self) -> bool {
1547 self.proposal == other.proposal && self.certificate == other.certificate
1548 }
1549}
1550
1551impl<S: Scheme, D: Digest> Eq for Finalization<S, D> {}
1552
1553impl<S: Scheme, D: Digest> Hash for Finalization<S, D> {
1554 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1555 self.proposal.hash(state);
1556 self.certificate.hash(state);
1557 }
1558}
1559
1560impl<S: Scheme, D: Digest> Write for Finalization<S, D> {
1561 fn write(&self, writer: &mut impl BufMut) {
1562 self.proposal.write(writer);
1563 self.certificate.write(writer);
1564 }
1565}
1566
1567impl<S: Scheme, D: Digest> EncodeSize for Finalization<S, D> {
1568 fn encode_size(&self) -> usize {
1569 self.proposal.encode_size() + self.certificate.encode_size()
1570 }
1571}
1572
1573impl<S: Scheme, D: Digest> Read for Finalization<S, D> {
1574 type Cfg = <S::Certificate as Read>::Cfg;
1575
1576 fn read_cfg(reader: &mut impl Buf, cfg: &Self::Cfg) -> Result<Self, Error> {
1577 let proposal = Proposal::read(reader)?;
1578 let certificate = S::Certificate::read_cfg(reader, cfg)?;
1579
1580 Ok(Self {
1581 proposal,
1582 certificate,
1583 })
1584 }
1585}
1586
1587impl<S: Scheme, D: Digest> Epochable for Finalization<S, D> {
1588 fn epoch(&self) -> Epoch {
1589 self.proposal.epoch()
1590 }
1591}
1592
1593impl<S: Scheme, D: Digest> Viewable for Finalization<S, D> {
1594 fn view(&self) -> View {
1595 self.proposal.view()
1596 }
1597}
1598
1599#[cfg(feature = "arbitrary")]
1600impl<S: Scheme, D: Digest> arbitrary::Arbitrary<'_> for Finalization<S, D>
1601where
1602 S::Certificate: for<'a> arbitrary::Arbitrary<'a>,
1603 D: for<'a> arbitrary::Arbitrary<'a>,
1604{
1605 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
1606 let proposal = Proposal::arbitrary(u)?;
1607 let certificate = S::Certificate::arbitrary(u)?;
1608 Ok(Self {
1609 proposal,
1610 certificate,
1611 })
1612 }
1613}
1614
1615#[derive(Clone, Debug, PartialEq)]
1618pub enum Backfiller<S: Scheme, D: Digest> {
1619 Request(Request),
1621 Response(Response<S, D>),
1623}
1624
1625impl<S: Scheme, D: Digest> Write for Backfiller<S, D> {
1626 fn write(&self, writer: &mut impl BufMut) {
1627 match self {
1628 Self::Request(request) => {
1629 0u8.write(writer);
1630 request.write(writer);
1631 }
1632 Self::Response(response) => {
1633 1u8.write(writer);
1634 response.write(writer);
1635 }
1636 }
1637 }
1638}
1639
1640impl<S: Scheme, D: Digest> EncodeSize for Backfiller<S, D> {
1641 fn encode_size(&self) -> usize {
1642 1 + match self {
1643 Self::Request(v) => v.encode_size(),
1644 Self::Response(v) => v.encode_size(),
1645 }
1646 }
1647}
1648
1649impl<S: Scheme, D: Digest> Read for Backfiller<S, D> {
1650 type Cfg = (usize, <S::Certificate as Read>::Cfg);
1651
1652 fn read_cfg(reader: &mut impl Buf, cfg: &Self::Cfg) -> Result<Self, Error> {
1653 let tag = <u8>::read(reader)?;
1654 match tag {
1655 0 => {
1656 let (max_len, _) = cfg;
1657 let v = Request::read_cfg(reader, max_len)?;
1658 Ok(Self::Request(v))
1659 }
1660 1 => {
1661 let v = Response::<S, D>::read_cfg(reader, cfg)?;
1662 Ok(Self::Response(v))
1663 }
1664 _ => Err(Error::Invalid(
1665 "consensus::simplex::Backfiller",
1666 "Invalid type",
1667 )),
1668 }
1669 }
1670}
1671
1672#[cfg(feature = "arbitrary")]
1673impl<S: Scheme, D: Digest> arbitrary::Arbitrary<'_> for Backfiller<S, D>
1674where
1675 S::Certificate: for<'a> arbitrary::Arbitrary<'a>,
1676 D: for<'a> arbitrary::Arbitrary<'a>,
1677{
1678 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
1679 let tag = u.int_in_range(0..=1)?;
1680 match tag {
1681 0 => {
1682 let v = Request::arbitrary(u)?;
1683 Ok(Self::Request(v))
1684 }
1685 1 => {
1686 let v = Response::<S, D>::arbitrary(u)?;
1687 Ok(Self::Response(v))
1688 }
1689 _ => unreachable!(),
1690 }
1691 }
1692}
1693
1694#[derive(Clone, Debug, PartialEq)]
1697#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1698pub struct Request {
1699 pub id: u64,
1701 pub notarizations: Vec<View>,
1703 pub nullifications: Vec<View>,
1705}
1706
1707impl Request {
1708 pub const fn new(id: u64, notarizations: Vec<View>, nullifications: Vec<View>) -> Self {
1710 Self {
1711 id,
1712 notarizations,
1713 nullifications,
1714 }
1715 }
1716}
1717
1718impl Write for Request {
1719 fn write(&self, writer: &mut impl BufMut) {
1720 UInt(self.id).write(writer);
1721 self.notarizations.write(writer);
1722 self.nullifications.write(writer);
1723 }
1724}
1725
1726impl EncodeSize for Request {
1727 fn encode_size(&self) -> usize {
1728 UInt(self.id).encode_size()
1729 + self.notarizations.encode_size()
1730 + self.nullifications.encode_size()
1731 }
1732}
1733
1734impl Read for Request {
1735 type Cfg = usize;
1736
1737 fn read_cfg(reader: &mut impl Buf, max_len: &usize) -> Result<Self, Error> {
1738 let id = UInt::read(reader)?.into();
1739 let mut views = HashSet::new();
1740 let notarizations = Vec::<View>::read_range(reader, ..=*max_len)?;
1741 for view in notarizations.iter() {
1742 if !views.insert(view) {
1743 return Err(Error::Invalid(
1744 "consensus::simplex::Request",
1745 "Duplicate notarization",
1746 ));
1747 }
1748 }
1749 let remaining = max_len - notarizations.len();
1750 views.clear();
1751 let nullifications = Vec::<View>::read_range(reader, ..=remaining)?;
1752 for view in nullifications.iter() {
1753 if !views.insert(view) {
1754 return Err(Error::Invalid(
1755 "consensus::simplex::Request",
1756 "Duplicate nullification",
1757 ));
1758 }
1759 }
1760 Ok(Self {
1761 id,
1762 notarizations,
1763 nullifications,
1764 })
1765 }
1766}
1767
1768#[derive(Clone, Debug, PartialEq)]
1771pub struct Response<S: Scheme, D: Digest> {
1772 pub id: u64,
1774 pub notarizations: Vec<Notarization<S, D>>,
1776 pub nullifications: Vec<Nullification<S>>,
1778}
1779
1780impl<S: Scheme, D: Digest> Response<S, D> {
1781 pub const fn new(
1783 id: u64,
1784 notarizations: Vec<Notarization<S, D>>,
1785 nullifications: Vec<Nullification<S>>,
1786 ) -> Self {
1787 Self {
1788 id,
1789 notarizations,
1790 nullifications,
1791 }
1792 }
1793
1794 pub fn verify<R: CryptoRng>(&self, rng: &mut R, scheme: &S, strategy: &impl Strategy) -> bool
1796 where
1797 S: scheme::Scheme<D>,
1798 {
1799 if self.notarizations.is_empty() && self.nullifications.is_empty() {
1801 return true;
1802 }
1803
1804 let notarizations = self.notarizations.iter().map(|notarization| {
1805 let context = Subject::Notarize {
1806 proposal: ¬arization.proposal,
1807 };
1808
1809 (context, ¬arization.certificate)
1810 });
1811
1812 let nullifications = self.nullifications.iter().map(|nullification| {
1813 let context = Subject::Nullify {
1814 round: nullification.round,
1815 };
1816
1817 (context, &nullification.certificate)
1818 });
1819
1820 scheme.verify_certificates::<_, D, _, N3f1>(
1821 rng,
1822 notarizations.chain(nullifications),
1823 strategy,
1824 )
1825 }
1826}
1827
1828impl<S: Scheme, D: Digest> Write for Response<S, D> {
1829 fn write(&self, writer: &mut impl BufMut) {
1830 UInt(self.id).write(writer);
1831 self.notarizations.write(writer);
1832 self.nullifications.write(writer);
1833 }
1834}
1835
1836impl<S: Scheme, D: Digest> EncodeSize for Response<S, D> {
1837 fn encode_size(&self) -> usize {
1838 UInt(self.id).encode_size()
1839 + self.notarizations.encode_size()
1840 + self.nullifications.encode_size()
1841 }
1842}
1843
1844impl<S: Scheme, D: Digest> Read for Response<S, D> {
1845 type Cfg = (usize, <S::Certificate as Read>::Cfg);
1846
1847 fn read_cfg(reader: &mut impl Buf, cfg: &Self::Cfg) -> Result<Self, Error> {
1848 let (max_len, certificate_cfg) = cfg;
1849 let id = UInt::read(reader)?.into();
1850 let mut views = HashSet::new();
1851 let notarizations = Vec::<Notarization<S, D>>::read_cfg(
1852 reader,
1853 &((..=*max_len).into(), certificate_cfg.clone()),
1854 )?;
1855 for notarization in notarizations.iter() {
1856 if !views.insert(notarization.view()) {
1857 return Err(Error::Invalid(
1858 "consensus::simplex::Response",
1859 "Duplicate notarization",
1860 ));
1861 }
1862 }
1863 let remaining = max_len - notarizations.len();
1864 views.clear();
1865 let nullifications = Vec::<Nullification<S>>::read_cfg(
1866 reader,
1867 &((..=remaining).into(), certificate_cfg.clone()),
1868 )?;
1869 for nullification in nullifications.iter() {
1870 if !views.insert(nullification.view()) {
1871 return Err(Error::Invalid(
1872 "consensus::simplex::Response",
1873 "Duplicate nullification",
1874 ));
1875 }
1876 }
1877 Ok(Self {
1878 id,
1879 notarizations,
1880 nullifications,
1881 })
1882 }
1883}
1884
1885#[cfg(feature = "arbitrary")]
1886impl<S: Scheme, D: Digest> arbitrary::Arbitrary<'_> for Response<S, D>
1887where
1888 S::Certificate: for<'a> arbitrary::Arbitrary<'a>,
1889 D: for<'a> arbitrary::Arbitrary<'a>,
1890{
1891 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
1892 let id = u.arbitrary()?;
1893 let notarizations = u.arbitrary()?;
1894 let nullifications = u.arbitrary()?;
1895 Ok(Self {
1896 id,
1897 notarizations,
1898 nullifications,
1899 })
1900 }
1901}
1902
1903#[derive(Clone, Debug)]
1921pub enum Activity<S: Scheme, D: Digest> {
1922 Notarize(Notarize<S, D>),
1924 Notarization(Notarization<S, D>),
1926 Certification(Notarization<S, D>),
1928 Nullify(Nullify<S>),
1930 Nullification(Nullification<S>),
1932 Finalize(Finalize<S, D>),
1934 Finalization(Finalization<S, D>),
1936 ConflictingNotarize(ConflictingNotarize<S, D>),
1938 ConflictingFinalize(ConflictingFinalize<S, D>),
1940 NullifyFinalize(NullifyFinalize<S, D>),
1942}
1943
1944impl<S: Scheme, D: Digest> PartialEq for Activity<S, D> {
1945 fn eq(&self, other: &Self) -> bool {
1946 match (self, other) {
1947 (Self::Notarize(a), Self::Notarize(b)) => a == b,
1948 (Self::Notarization(a), Self::Notarization(b)) => a == b,
1949 (Self::Certification(a), Self::Certification(b)) => a == b,
1950 (Self::Nullify(a), Self::Nullify(b)) => a == b,
1951 (Self::Nullification(a), Self::Nullification(b)) => a == b,
1952 (Self::Finalize(a), Self::Finalize(b)) => a == b,
1953 (Self::Finalization(a), Self::Finalization(b)) => a == b,
1954 (Self::ConflictingNotarize(a), Self::ConflictingNotarize(b)) => a == b,
1955 (Self::ConflictingFinalize(a), Self::ConflictingFinalize(b)) => a == b,
1956 (Self::NullifyFinalize(a), Self::NullifyFinalize(b)) => a == b,
1957 _ => false,
1958 }
1959 }
1960}
1961
1962impl<S: Scheme, D: Digest> Eq for Activity<S, D> {}
1963
1964impl<S: Scheme, D: Digest> Hash for Activity<S, D> {
1965 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1966 match self {
1967 Self::Notarize(v) => {
1968 0u8.hash(state);
1969 v.hash(state);
1970 }
1971 Self::Notarization(v) => {
1972 1u8.hash(state);
1973 v.hash(state);
1974 }
1975 Self::Certification(v) => {
1976 2u8.hash(state);
1977 v.hash(state);
1978 }
1979 Self::Nullify(v) => {
1980 3u8.hash(state);
1981 v.hash(state);
1982 }
1983 Self::Nullification(v) => {
1984 4u8.hash(state);
1985 v.hash(state);
1986 }
1987 Self::Finalize(v) => {
1988 5u8.hash(state);
1989 v.hash(state);
1990 }
1991 Self::Finalization(v) => {
1992 6u8.hash(state);
1993 v.hash(state);
1994 }
1995 Self::ConflictingNotarize(v) => {
1996 7u8.hash(state);
1997 v.hash(state);
1998 }
1999 Self::ConflictingFinalize(v) => {
2000 8u8.hash(state);
2001 v.hash(state);
2002 }
2003 Self::NullifyFinalize(v) => {
2004 9u8.hash(state);
2005 v.hash(state);
2006 }
2007 }
2008 }
2009}
2010
2011impl<S: Scheme, D: Digest> Activity<S, D> {
2012 pub const fn verified(&self) -> bool {
2014 match self {
2015 Self::Notarize(_) => false,
2016 Self::Notarization(_) => true,
2017 Self::Certification(_) => false,
2018 Self::Nullify(_) => false,
2019 Self::Nullification(_) => true,
2020 Self::Finalize(_) => false,
2021 Self::Finalization(_) => true,
2022 Self::ConflictingNotarize(_) => false,
2023 Self::ConflictingFinalize(_) => false,
2024 Self::NullifyFinalize(_) => false,
2025 }
2026 }
2027
2028 pub fn verify<R: CryptoRng>(&self, rng: &mut R, scheme: &S, strategy: &impl Strategy) -> bool
2034 where
2035 S: scheme::Scheme<D>,
2036 {
2037 match self {
2038 Self::Notarize(n) => n.verify(rng, scheme, strategy),
2039 Self::Notarization(n) => n.verify(rng, scheme, strategy),
2040 Self::Certification(n) => n.verify(rng, scheme, strategy),
2041 Self::Nullify(n) => n.verify(rng, scheme, strategy),
2042 Self::Nullification(n) => n.verify(rng, scheme, strategy),
2043 Self::Finalize(f) => f.verify(rng, scheme, strategy),
2044 Self::Finalization(f) => f.verify(rng, scheme, strategy),
2045 Self::ConflictingNotarize(c) => c.verify(rng, scheme, strategy),
2046 Self::ConflictingFinalize(c) => c.verify(rng, scheme, strategy),
2047 Self::NullifyFinalize(c) => c.verify(rng, scheme, strategy),
2048 }
2049 }
2050}
2051
2052impl<S: Scheme, D: Digest> Write for Activity<S, D> {
2053 fn write(&self, writer: &mut impl BufMut) {
2054 match self {
2055 Self::Notarize(v) => {
2056 0u8.write(writer);
2057 v.write(writer);
2058 }
2059 Self::Notarization(v) => {
2060 1u8.write(writer);
2061 v.write(writer);
2062 }
2063 Self::Certification(v) => {
2064 2u8.write(writer);
2065 v.write(writer);
2066 }
2067 Self::Nullify(v) => {
2068 3u8.write(writer);
2069 v.write(writer);
2070 }
2071 Self::Nullification(v) => {
2072 4u8.write(writer);
2073 v.write(writer);
2074 }
2075 Self::Finalize(v) => {
2076 5u8.write(writer);
2077 v.write(writer);
2078 }
2079 Self::Finalization(v) => {
2080 6u8.write(writer);
2081 v.write(writer);
2082 }
2083 Self::ConflictingNotarize(v) => {
2084 7u8.write(writer);
2085 v.write(writer);
2086 }
2087 Self::ConflictingFinalize(v) => {
2088 8u8.write(writer);
2089 v.write(writer);
2090 }
2091 Self::NullifyFinalize(v) => {
2092 9u8.write(writer);
2093 v.write(writer);
2094 }
2095 }
2096 }
2097}
2098
2099impl<S: Scheme, D: Digest> EncodeSize for Activity<S, D> {
2100 fn encode_size(&self) -> usize {
2101 1 + match self {
2102 Self::Notarize(v) => v.encode_size(),
2103 Self::Notarization(v) => v.encode_size(),
2104 Self::Certification(v) => v.encode_size(),
2105 Self::Nullify(v) => v.encode_size(),
2106 Self::Nullification(v) => v.encode_size(),
2107 Self::Finalize(v) => v.encode_size(),
2108 Self::Finalization(v) => v.encode_size(),
2109 Self::ConflictingNotarize(v) => v.encode_size(),
2110 Self::ConflictingFinalize(v) => v.encode_size(),
2111 Self::NullifyFinalize(v) => v.encode_size(),
2112 }
2113 }
2114}
2115
2116impl<S: Scheme, D: Digest> Read for Activity<S, D> {
2117 type Cfg = <S::Certificate as Read>::Cfg;
2118
2119 fn read_cfg(reader: &mut impl Buf, cfg: &Self::Cfg) -> Result<Self, Error> {
2120 let tag = <u8>::read(reader)?;
2121 match tag {
2122 0 => {
2123 let v = Notarize::<S, D>::read(reader)?;
2124 Ok(Self::Notarize(v))
2125 }
2126 1 => {
2127 let v = Notarization::<S, D>::read_cfg(reader, cfg)?;
2128 Ok(Self::Notarization(v))
2129 }
2130 2 => {
2131 let v = Notarization::<S, D>::read_cfg(reader, cfg)?;
2132 Ok(Self::Certification(v))
2133 }
2134 3 => {
2135 let v = Nullify::<S>::read(reader)?;
2136 Ok(Self::Nullify(v))
2137 }
2138 4 => {
2139 let v = Nullification::<S>::read_cfg(reader, cfg)?;
2140 Ok(Self::Nullification(v))
2141 }
2142 5 => {
2143 let v = Finalize::<S, D>::read(reader)?;
2144 Ok(Self::Finalize(v))
2145 }
2146 6 => {
2147 let v = Finalization::<S, D>::read_cfg(reader, cfg)?;
2148 Ok(Self::Finalization(v))
2149 }
2150 7 => {
2151 let v = ConflictingNotarize::<S, D>::read(reader)?;
2152 Ok(Self::ConflictingNotarize(v))
2153 }
2154 8 => {
2155 let v = ConflictingFinalize::<S, D>::read(reader)?;
2156 Ok(Self::ConflictingFinalize(v))
2157 }
2158 9 => {
2159 let v = NullifyFinalize::<S, D>::read(reader)?;
2160 Ok(Self::NullifyFinalize(v))
2161 }
2162 _ => Err(Error::Invalid(
2163 "consensus::simplex::Activity",
2164 "Invalid type",
2165 )),
2166 }
2167 }
2168}
2169
2170impl<S: Scheme, D: Digest> Epochable for Activity<S, D> {
2171 fn epoch(&self) -> Epoch {
2172 match self {
2173 Self::Notarize(v) => v.epoch(),
2174 Self::Notarization(v) => v.epoch(),
2175 Self::Certification(v) => v.epoch(),
2176 Self::Nullify(v) => v.epoch(),
2177 Self::Nullification(v) => v.epoch(),
2178 Self::Finalize(v) => v.epoch(),
2179 Self::Finalization(v) => v.epoch(),
2180 Self::ConflictingNotarize(v) => v.epoch(),
2181 Self::ConflictingFinalize(v) => v.epoch(),
2182 Self::NullifyFinalize(v) => v.epoch(),
2183 }
2184 }
2185}
2186
2187impl<S: Scheme, D: Digest> Viewable for Activity<S, D> {
2188 fn view(&self) -> View {
2189 match self {
2190 Self::Notarize(v) => v.view(),
2191 Self::Notarization(v) => v.view(),
2192 Self::Certification(v) => v.view(),
2193 Self::Nullify(v) => v.view(),
2194 Self::Nullification(v) => v.view(),
2195 Self::Finalize(v) => v.view(),
2196 Self::Finalization(v) => v.view(),
2197 Self::ConflictingNotarize(v) => v.view(),
2198 Self::ConflictingFinalize(v) => v.view(),
2199 Self::NullifyFinalize(v) => v.view(),
2200 }
2201 }
2202}
2203
2204#[cfg(feature = "arbitrary")]
2205impl<S: Scheme, D: Digest> arbitrary::Arbitrary<'_> for Activity<S, D>
2206where
2207 S::Signature: for<'a> arbitrary::Arbitrary<'a>,
2208 S::Certificate: for<'a> arbitrary::Arbitrary<'a>,
2209 D: for<'a> arbitrary::Arbitrary<'a>,
2210{
2211 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
2212 let tag = u.int_in_range(0..=9)?;
2213 match tag {
2214 0 => {
2215 let v = Notarize::<S, D>::arbitrary(u)?;
2216 Ok(Self::Notarize(v))
2217 }
2218 1 => {
2219 let v = Notarization::<S, D>::arbitrary(u)?;
2220 Ok(Self::Notarization(v))
2221 }
2222 2 => {
2223 let v = Notarization::<S, D>::arbitrary(u)?;
2224 Ok(Self::Certification(v))
2225 }
2226 3 => {
2227 let v = Nullify::<S>::arbitrary(u)?;
2228 Ok(Self::Nullify(v))
2229 }
2230 4 => {
2231 let v = Nullification::<S>::arbitrary(u)?;
2232 Ok(Self::Nullification(v))
2233 }
2234 5 => {
2235 let v = Finalize::<S, D>::arbitrary(u)?;
2236 Ok(Self::Finalize(v))
2237 }
2238 6 => {
2239 let v = Finalization::<S, D>::arbitrary(u)?;
2240 Ok(Self::Finalization(v))
2241 }
2242 7 => {
2243 let v = ConflictingNotarize::<S, D>::arbitrary(u)?;
2244 Ok(Self::ConflictingNotarize(v))
2245 }
2246 8 => {
2247 let v = ConflictingFinalize::<S, D>::arbitrary(u)?;
2248 Ok(Self::ConflictingFinalize(v))
2249 }
2250 9 => {
2251 let v = NullifyFinalize::<S, D>::arbitrary(u)?;
2252 Ok(Self::NullifyFinalize(v))
2253 }
2254 _ => unreachable!(),
2255 }
2256 }
2257}
2258
2259#[derive(Clone, Debug)]
2262pub struct ConflictingNotarize<S: Scheme, D: Digest> {
2263 notarize_1: Notarize<S, D>,
2265 notarize_2: Notarize<S, D>,
2267}
2268
2269impl<S: Scheme, D: Digest> PartialEq for ConflictingNotarize<S, D> {
2270 fn eq(&self, other: &Self) -> bool {
2271 self.notarize_1 == other.notarize_1 && self.notarize_2 == other.notarize_2
2272 }
2273}
2274
2275impl<S: Scheme, D: Digest> Eq for ConflictingNotarize<S, D> {}
2276
2277impl<S: Scheme, D: Digest> Hash for ConflictingNotarize<S, D> {
2278 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
2279 self.notarize_1.hash(state);
2280 self.notarize_2.hash(state);
2281 }
2282}
2283
2284impl<S: Scheme, D: Digest> ConflictingNotarize<S, D> {
2285 pub fn new(notarize_1: Notarize<S, D>, notarize_2: Notarize<S, D>) -> Self {
2292 assert_eq!(notarize_1.round(), notarize_2.round());
2293 assert_eq!(notarize_1.signer(), notarize_2.signer());
2294 assert_ne!(
2295 notarize_1.proposal, notarize_2.proposal,
2296 "proposals must differ to constitute conflicting evidence"
2297 );
2298
2299 Self {
2300 notarize_1,
2301 notarize_2,
2302 }
2303 }
2304
2305 pub fn verify<R>(&self, rng: &mut R, scheme: &S, strategy: &impl Strategy) -> bool
2307 where
2308 R: CryptoRng,
2309 S: scheme::Scheme<D>,
2310 {
2311 self.notarize_1.verify(rng, scheme, strategy)
2312 && self.notarize_2.verify(rng, scheme, strategy)
2313 }
2314}
2315
2316impl<S: Scheme, D: Digest> Attributable for ConflictingNotarize<S, D> {
2317 fn signer(&self) -> Participant {
2318 self.notarize_1.signer()
2319 }
2320}
2321
2322impl<S: Scheme, D: Digest> Epochable for ConflictingNotarize<S, D> {
2323 fn epoch(&self) -> Epoch {
2324 self.notarize_1.epoch()
2325 }
2326}
2327
2328impl<S: Scheme, D: Digest> Viewable for ConflictingNotarize<S, D> {
2329 fn view(&self) -> View {
2330 self.notarize_1.view()
2331 }
2332}
2333
2334impl<S: Scheme, D: Digest> Write for ConflictingNotarize<S, D> {
2335 fn write(&self, writer: &mut impl BufMut) {
2336 self.notarize_1.write(writer);
2337 self.notarize_2.write(writer);
2338 }
2339}
2340
2341impl<S: Scheme, D: Digest> Read for ConflictingNotarize<S, D> {
2342 type Cfg = ();
2343
2344 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
2345 let notarize_1 = Notarize::read(reader)?;
2346 let notarize_2 = Notarize::read(reader)?;
2347
2348 if notarize_1.signer() != notarize_2.signer()
2349 || notarize_1.round() != notarize_2.round()
2350 || notarize_1.proposal == notarize_2.proposal
2351 {
2352 return Err(Error::Invalid(
2353 "consensus::simplex::ConflictingNotarize",
2354 "invalid conflicting notarize",
2355 ));
2356 }
2357
2358 Ok(Self {
2359 notarize_1,
2360 notarize_2,
2361 })
2362 }
2363}
2364
2365impl<S: Scheme, D: Digest> EncodeSize for ConflictingNotarize<S, D> {
2366 fn encode_size(&self) -> usize {
2367 self.notarize_1.encode_size() + self.notarize_2.encode_size()
2368 }
2369}
2370
2371#[cfg(feature = "arbitrary")]
2372impl<S: Scheme, D: Digest> arbitrary::Arbitrary<'_> for ConflictingNotarize<S, D>
2373where
2374 S::Signature: for<'a> arbitrary::Arbitrary<'a>,
2375 D: for<'a> arbitrary::Arbitrary<'a>,
2376{
2377 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
2378 let notarize_1 = Notarize::arbitrary(u)?;
2379 let notarize_2 = Notarize::arbitrary(u)?;
2380 Ok(Self {
2381 notarize_1,
2382 notarize_2,
2383 })
2384 }
2385}
2386
2387#[derive(Clone, Debug)]
2390pub struct ConflictingFinalize<S: Scheme, D: Digest> {
2391 finalize_1: Finalize<S, D>,
2393 finalize_2: Finalize<S, D>,
2395}
2396
2397impl<S: Scheme, D: Digest> PartialEq for ConflictingFinalize<S, D> {
2398 fn eq(&self, other: &Self) -> bool {
2399 self.finalize_1 == other.finalize_1 && self.finalize_2 == other.finalize_2
2400 }
2401}
2402
2403impl<S: Scheme, D: Digest> Eq for ConflictingFinalize<S, D> {}
2404
2405impl<S: Scheme, D: Digest> Hash for ConflictingFinalize<S, D> {
2406 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
2407 self.finalize_1.hash(state);
2408 self.finalize_2.hash(state);
2409 }
2410}
2411
2412impl<S: Scheme, D: Digest> ConflictingFinalize<S, D> {
2413 pub fn new(finalize_1: Finalize<S, D>, finalize_2: Finalize<S, D>) -> Self {
2420 assert_eq!(finalize_1.round(), finalize_2.round());
2421 assert_eq!(finalize_1.signer(), finalize_2.signer());
2422 assert_ne!(
2423 finalize_1.proposal, finalize_2.proposal,
2424 "proposals must differ to constitute conflicting evidence"
2425 );
2426
2427 Self {
2428 finalize_1,
2429 finalize_2,
2430 }
2431 }
2432
2433 pub fn verify<R>(&self, rng: &mut R, scheme: &S, strategy: &impl Strategy) -> bool
2435 where
2436 R: CryptoRng,
2437 S: scheme::Scheme<D>,
2438 {
2439 self.finalize_1.verify(rng, scheme, strategy)
2440 && self.finalize_2.verify(rng, scheme, strategy)
2441 }
2442}
2443
2444impl<S: Scheme, D: Digest> Attributable for ConflictingFinalize<S, D> {
2445 fn signer(&self) -> Participant {
2446 self.finalize_1.signer()
2447 }
2448}
2449
2450impl<S: Scheme, D: Digest> Epochable for ConflictingFinalize<S, D> {
2451 fn epoch(&self) -> Epoch {
2452 self.finalize_1.epoch()
2453 }
2454}
2455
2456impl<S: Scheme, D: Digest> Viewable for ConflictingFinalize<S, D> {
2457 fn view(&self) -> View {
2458 self.finalize_1.view()
2459 }
2460}
2461
2462impl<S: Scheme, D: Digest> Write for ConflictingFinalize<S, D> {
2463 fn write(&self, writer: &mut impl BufMut) {
2464 self.finalize_1.write(writer);
2465 self.finalize_2.write(writer);
2466 }
2467}
2468
2469impl<S: Scheme, D: Digest> Read for ConflictingFinalize<S, D> {
2470 type Cfg = ();
2471
2472 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
2473 let finalize_1 = Finalize::read(reader)?;
2474 let finalize_2 = Finalize::read(reader)?;
2475
2476 if finalize_1.signer() != finalize_2.signer()
2477 || finalize_1.round() != finalize_2.round()
2478 || finalize_1.proposal == finalize_2.proposal
2479 {
2480 return Err(Error::Invalid(
2481 "consensus::simplex::ConflictingFinalize",
2482 "invalid conflicting finalize",
2483 ));
2484 }
2485
2486 Ok(Self {
2487 finalize_1,
2488 finalize_2,
2489 })
2490 }
2491}
2492
2493impl<S: Scheme, D: Digest> EncodeSize for ConflictingFinalize<S, D> {
2494 fn encode_size(&self) -> usize {
2495 self.finalize_1.encode_size() + self.finalize_2.encode_size()
2496 }
2497}
2498
2499#[cfg(feature = "arbitrary")]
2500impl<S: Scheme, D: Digest> arbitrary::Arbitrary<'_> for ConflictingFinalize<S, D>
2501where
2502 S::Signature: for<'a> arbitrary::Arbitrary<'a>,
2503 D: for<'a> arbitrary::Arbitrary<'a>,
2504{
2505 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
2506 let finalize_1 = Finalize::arbitrary(u)?;
2507 let finalize_2 = Finalize::arbitrary(u)?;
2508 Ok(Self {
2509 finalize_1,
2510 finalize_2,
2511 })
2512 }
2513}
2514
2515#[derive(Clone, Debug)]
2519pub struct NullifyFinalize<S: Scheme, D: Digest> {
2520 nullify: Nullify<S>,
2522 finalize: Finalize<S, D>,
2524}
2525
2526impl<S: Scheme, D: Digest> PartialEq for NullifyFinalize<S, D> {
2527 fn eq(&self, other: &Self) -> bool {
2528 self.nullify == other.nullify && self.finalize == other.finalize
2529 }
2530}
2531
2532impl<S: Scheme, D: Digest> Eq for NullifyFinalize<S, D> {}
2533
2534impl<S: Scheme, D: Digest> Hash for NullifyFinalize<S, D> {
2535 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
2536 self.nullify.hash(state);
2537 self.finalize.hash(state);
2538 }
2539}
2540
2541impl<S: Scheme, D: Digest> NullifyFinalize<S, D> {
2542 pub fn new(nullify: Nullify<S>, finalize: Finalize<S, D>) -> Self {
2544 assert_eq!(nullify.round, finalize.round());
2545 assert_eq!(nullify.signer(), finalize.signer());
2546
2547 Self { nullify, finalize }
2548 }
2549
2550 pub fn verify<R>(&self, rng: &mut R, scheme: &S, strategy: &impl Strategy) -> bool
2552 where
2553 R: CryptoRng,
2554 S: scheme::Scheme<D>,
2555 {
2556 self.nullify.verify(rng, scheme, strategy) && self.finalize.verify(rng, scheme, strategy)
2557 }
2558}
2559
2560impl<S: Scheme, D: Digest> Attributable for NullifyFinalize<S, D> {
2561 fn signer(&self) -> Participant {
2562 self.nullify.signer()
2563 }
2564}
2565
2566impl<S: Scheme, D: Digest> Epochable for NullifyFinalize<S, D> {
2567 fn epoch(&self) -> Epoch {
2568 self.nullify.epoch()
2569 }
2570}
2571
2572impl<S: Scheme, D: Digest> Viewable for NullifyFinalize<S, D> {
2573 fn view(&self) -> View {
2574 self.nullify.view()
2575 }
2576}
2577
2578impl<S: Scheme, D: Digest> Write for NullifyFinalize<S, D> {
2579 fn write(&self, writer: &mut impl BufMut) {
2580 self.nullify.write(writer);
2581 self.finalize.write(writer);
2582 }
2583}
2584
2585impl<S: Scheme, D: Digest> Read for NullifyFinalize<S, D> {
2586 type Cfg = ();
2587
2588 fn read_cfg(reader: &mut impl Buf, _: &()) -> Result<Self, Error> {
2589 let nullify = Nullify::read(reader)?;
2590 let finalize = Finalize::read(reader)?;
2591
2592 if nullify.signer() != finalize.signer() || nullify.round != finalize.round() {
2593 return Err(Error::Invalid(
2594 "consensus::simplex::NullifyFinalize",
2595 "mismatched signatures",
2596 ));
2597 }
2598
2599 Ok(Self { nullify, finalize })
2600 }
2601}
2602
2603impl<S: Scheme, D: Digest> EncodeSize for NullifyFinalize<S, D> {
2604 fn encode_size(&self) -> usize {
2605 self.nullify.encode_size() + self.finalize.encode_size()
2606 }
2607}
2608
2609#[cfg(feature = "arbitrary")]
2610impl<S: Scheme, D: Digest> arbitrary::Arbitrary<'_> for NullifyFinalize<S, D>
2611where
2612 S::Signature: for<'a> arbitrary::Arbitrary<'a>,
2613 D: for<'a> arbitrary::Arbitrary<'a>,
2614{
2615 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
2616 let nullify = Nullify::arbitrary(u)?;
2617 let finalize = Finalize::arbitrary(u)?;
2618 Ok(Self { nullify, finalize })
2619 }
2620}
2621
2622#[cfg(test)]
2623mod tests {
2624 use super::*;
2625 use crate::simplex::{
2626 quorum,
2627 scheme::{
2628 bls12381_multisig,
2629 bls12381_threshold::{
2630 standard as bls12381_threshold_std, vrf as bls12381_threshold_vrf,
2631 },
2632 ed25519, secp256r1, Scheme,
2633 },
2634 };
2635 use bytes::Bytes;
2636 use commonware_codec::{Decode, DecodeExt, Encode};
2637 use commonware_cryptography::{
2638 bls12381::primitives::variant::{MinPk, MinSig},
2639 certificate::mocks::Fixture,
2640 sha256::Digest as Sha256,
2641 };
2642 use commonware_parallel::Sequential;
2643 use commonware_utils::{test_rng, Faults, N3f1, TestRng};
2644
2645 const NAMESPACE: &[u8] = b"test";
2646
2647 fn sample_digest(v: u8) -> Sha256 {
2649 Sha256::from([v; 32]) }
2651
2652 fn setup_seeded<S, F>(n: u32, seed: u64, fixture: F) -> Fixture<S>
2654 where
2655 F: FnOnce(&mut TestRng, &[u8], u32) -> Fixture<S>,
2656 {
2657 setup_seeded_ns(n, seed, NAMESPACE, fixture)
2658 }
2659
2660 fn setup_seeded_ns<S, F>(n: u32, seed: u64, namespace: &[u8], fixture: F) -> Fixture<S>
2662 where
2663 F: FnOnce(&mut TestRng, &[u8], u32) -> Fixture<S>,
2664 {
2665 let mut rng = TestRng::new(seed);
2666 fixture(&mut rng, namespace, n)
2667 }
2668
2669 #[test]
2670 fn test_proposal_encode_decode() {
2671 let proposal = Proposal::new(
2672 Round::new(Epoch::new(0), View::new(10)),
2673 View::new(5),
2674 sample_digest(1),
2675 );
2676 let encoded = proposal.encode();
2677 let decoded = Proposal::<Sha256>::decode(encoded).unwrap();
2678 assert_eq!(proposal, decoded);
2679 }
2680
2681 fn notarize_encode_decode<S, F>(fixture: F)
2682 where
2683 S: Scheme<Sha256>,
2684 F: FnOnce(&mut TestRng, &[u8], u32) -> Fixture<S>,
2685 {
2686 let mut rng = test_rng();
2687 let fixture = fixture(&mut rng, NAMESPACE, 5);
2688 let round = Round::new(Epoch::new(0), View::new(10));
2689 let proposal = Proposal::new(round, View::new(5), sample_digest(1));
2690 let notarize = Notarize::sign(&fixture.schemes[0], proposal).unwrap();
2691
2692 let encoded = notarize.encode();
2693 let decoded = Notarize::decode(encoded).unwrap();
2694
2695 assert_eq!(notarize, decoded);
2696 assert!(decoded.verify(&mut rng, &fixture.schemes[0], &Sequential));
2697 }
2698
2699 #[test]
2700 fn test_notarize_encode_decode() {
2701 notarize_encode_decode(ed25519::fixture);
2702 notarize_encode_decode(secp256r1::fixture);
2703 notarize_encode_decode(bls12381_multisig::fixture::<MinPk, _>);
2704 notarize_encode_decode(bls12381_multisig::fixture::<MinSig, _>);
2705 notarize_encode_decode(bls12381_threshold_vrf::fixture::<MinPk, _>);
2706 notarize_encode_decode(bls12381_threshold_vrf::fixture::<MinSig, _>);
2707 notarize_encode_decode(bls12381_threshold_std::fixture::<MinPk, _>);
2708 notarize_encode_decode(bls12381_threshold_std::fixture::<MinSig, _>);
2709 }
2710
2711 fn notarization_encode_decode<S, F>(fixture: F)
2712 where
2713 S: Scheme<Sha256>,
2714 F: FnOnce(&mut TestRng, &[u8], u32) -> Fixture<S>,
2715 {
2716 let mut rng = test_rng();
2717 let fixture = fixture(&mut rng, NAMESPACE, 5);
2718 let proposal = Proposal::new(
2719 Round::new(Epoch::new(0), View::new(10)),
2720 View::new(5),
2721 sample_digest(1),
2722 );
2723 let notarizes: Vec<_> = fixture
2724 .schemes
2725 .iter()
2726 .map(|scheme| Notarize::sign(scheme, proposal.clone()).unwrap())
2727 .collect();
2728 let notarization =
2729 Notarization::from_notarizes(&fixture.schemes[0], ¬arizes, &Sequential).unwrap();
2730 let encoded = notarization.encode();
2731 let cfg = fixture.schemes[0].certificate_codec_config();
2732 let decoded = Notarization::decode_cfg(encoded, &cfg).unwrap();
2733 assert_eq!(notarization, decoded);
2734 assert!(decoded.verify(&mut rng, &fixture.schemes[0], &Sequential));
2735 }
2736
2737 #[test]
2738 fn test_notarization_encode_decode() {
2739 notarization_encode_decode(ed25519::fixture);
2740 notarization_encode_decode(secp256r1::fixture);
2741 notarization_encode_decode(bls12381_multisig::fixture::<MinPk, _>);
2742 notarization_encode_decode(bls12381_multisig::fixture::<MinSig, _>);
2743 notarization_encode_decode(bls12381_threshold_vrf::fixture::<MinPk, _>);
2744 notarization_encode_decode(bls12381_threshold_vrf::fixture::<MinSig, _>);
2745 notarization_encode_decode(bls12381_threshold_std::fixture::<MinPk, _>);
2746 notarization_encode_decode(bls12381_threshold_std::fixture::<MinSig, _>);
2747 }
2748
2749 fn nullify_encode_decode<S, F>(fixture: F)
2750 where
2751 S: Scheme<Sha256>,
2752 F: FnOnce(&mut TestRng, &[u8], u32) -> Fixture<S>,
2753 {
2754 let mut rng = test_rng();
2755 let fixture = fixture(&mut rng, NAMESPACE, 5);
2756 let round = Round::new(Epoch::new(0), View::new(10));
2757 let nullify = Nullify::sign::<Sha256>(&fixture.schemes[0], round).unwrap();
2758 let encoded = nullify.encode();
2759 let decoded = Nullify::decode(encoded).unwrap();
2760 assert_eq!(nullify, decoded);
2761 assert!(decoded.verify::<_, Sha256>(&mut rng, &fixture.schemes[0], &Sequential));
2762 }
2763
2764 #[test]
2765 fn test_nullify_encode_decode() {
2766 nullify_encode_decode(ed25519::fixture);
2767 nullify_encode_decode(secp256r1::fixture);
2768 nullify_encode_decode(bls12381_multisig::fixture::<MinPk, _>);
2769 nullify_encode_decode(bls12381_multisig::fixture::<MinSig, _>);
2770 nullify_encode_decode(bls12381_threshold_vrf::fixture::<MinPk, _>);
2771 nullify_encode_decode(bls12381_threshold_vrf::fixture::<MinSig, _>);
2772 nullify_encode_decode(bls12381_threshold_std::fixture::<MinPk, _>);
2773 nullify_encode_decode(bls12381_threshold_std::fixture::<MinSig, _>);
2774 }
2775
2776 fn nullification_encode_decode<S, F>(fixture: F)
2777 where
2778 S: Scheme<Sha256>,
2779 F: FnOnce(&mut TestRng, &[u8], u32) -> Fixture<S>,
2780 {
2781 let mut rng = test_rng();
2782 let fixture = fixture(&mut rng, NAMESPACE, 5);
2783 let round = Round::new(Epoch::new(333), View::new(10));
2784 let nullifies: Vec<_> = fixture
2785 .schemes
2786 .iter()
2787 .map(|scheme| Nullify::sign::<Sha256>(scheme, round).unwrap())
2788 .collect();
2789 let nullification =
2790 Nullification::from_nullifies(&fixture.schemes[0], &nullifies, &Sequential).unwrap();
2791 let encoded = nullification.encode();
2792 let cfg = fixture.schemes[0].certificate_codec_config();
2793 let decoded = Nullification::decode_cfg(encoded, &cfg).unwrap();
2794 assert_eq!(nullification, decoded);
2795 assert!(decoded.verify::<_, Sha256>(&mut rng, &fixture.schemes[0], &Sequential));
2796 }
2797
2798 #[test]
2799 fn test_nullification_encode_decode() {
2800 nullification_encode_decode(ed25519::fixture);
2801 nullification_encode_decode(secp256r1::fixture);
2802 nullification_encode_decode(bls12381_multisig::fixture::<MinPk, _>);
2803 nullification_encode_decode(bls12381_multisig::fixture::<MinSig, _>);
2804 nullification_encode_decode(bls12381_threshold_vrf::fixture::<MinPk, _>);
2805 nullification_encode_decode(bls12381_threshold_vrf::fixture::<MinSig, _>);
2806 nullification_encode_decode(bls12381_threshold_std::fixture::<MinPk, _>);
2807 nullification_encode_decode(bls12381_threshold_std::fixture::<MinSig, _>);
2808 }
2809
2810 fn finalize_encode_decode<S, F>(fixture: F)
2811 where
2812 S: Scheme<Sha256>,
2813 F: FnOnce(&mut TestRng, &[u8], u32) -> Fixture<S>,
2814 {
2815 let mut rng = test_rng();
2816 let fixture = fixture(&mut rng, NAMESPACE, 5);
2817 let round = Round::new(Epoch::new(0), View::new(10));
2818 let proposal = Proposal::new(round, View::new(5), sample_digest(1));
2819 let finalize = Finalize::sign(&fixture.schemes[0], proposal).unwrap();
2820 let encoded = finalize.encode();
2821 let decoded = Finalize::decode(encoded).unwrap();
2822 assert_eq!(finalize, decoded);
2823 assert!(decoded.verify(&mut rng, &fixture.schemes[0], &Sequential));
2824 }
2825
2826 #[test]
2827 fn test_finalize_encode_decode() {
2828 finalize_encode_decode(ed25519::fixture);
2829 finalize_encode_decode(secp256r1::fixture);
2830 finalize_encode_decode(bls12381_multisig::fixture::<MinPk, _>);
2831 finalize_encode_decode(bls12381_multisig::fixture::<MinSig, _>);
2832 finalize_encode_decode(bls12381_threshold_vrf::fixture::<MinPk, _>);
2833 finalize_encode_decode(bls12381_threshold_vrf::fixture::<MinSig, _>);
2834 finalize_encode_decode(bls12381_threshold_std::fixture::<MinPk, _>);
2835 finalize_encode_decode(bls12381_threshold_std::fixture::<MinSig, _>);
2836 }
2837
2838 fn finalization_encode_decode<S, F>(fixture: F)
2839 where
2840 S: Scheme<Sha256>,
2841 F: FnOnce(&mut TestRng, &[u8], u32) -> Fixture<S>,
2842 {
2843 let mut rng = test_rng();
2844 let fixture = fixture(&mut rng, NAMESPACE, 5);
2845 let round = Round::new(Epoch::new(0), View::new(10));
2846 let proposal = Proposal::new(round, View::new(5), sample_digest(1));
2847 let finalizes: Vec<_> = fixture
2848 .schemes
2849 .iter()
2850 .map(|scheme| Finalize::sign(scheme, proposal.clone()).unwrap())
2851 .collect();
2852 let finalization =
2853 Finalization::from_finalizes(&fixture.schemes[0], &finalizes, &Sequential).unwrap();
2854 let encoded = finalization.encode();
2855 let cfg = fixture.schemes[0].certificate_codec_config();
2856 let decoded = Finalization::decode_cfg(encoded, &cfg).unwrap();
2857 assert_eq!(finalization, decoded);
2858 assert!(decoded.verify(&mut rng, &fixture.schemes[0], &Sequential));
2859 }
2860
2861 #[test]
2862 fn test_finalization_encode_decode() {
2863 finalization_encode_decode(ed25519::fixture);
2864 finalization_encode_decode(secp256r1::fixture);
2865 finalization_encode_decode(bls12381_multisig::fixture::<MinPk, _>);
2866 finalization_encode_decode(bls12381_multisig::fixture::<MinSig, _>);
2867 finalization_encode_decode(bls12381_threshold_vrf::fixture::<MinPk, _>);
2868 finalization_encode_decode(bls12381_threshold_vrf::fixture::<MinSig, _>);
2869 finalization_encode_decode(bls12381_threshold_std::fixture::<MinPk, _>);
2870 finalization_encode_decode(bls12381_threshold_std::fixture::<MinSig, _>);
2871 }
2872
2873 fn backfiller_encode_decode<S, F>(fixture: F)
2874 where
2875 S: Scheme<Sha256>,
2876 F: FnOnce(&mut TestRng, &[u8], u32) -> Fixture<S>,
2877 {
2878 let mut rng = test_rng();
2879 let fixture = fixture(&mut rng, NAMESPACE, 5);
2880 let cfg = fixture.schemes[0].certificate_codec_config();
2881 let request = Request::new(
2882 1,
2883 vec![View::new(10), View::new(11)],
2884 vec![View::new(12), View::new(13)],
2885 );
2886 let encoded_request = Backfiller::<S, Sha256>::Request(request.clone()).encode();
2887 let decoded_request =
2888 Backfiller::<S, Sha256>::decode_cfg(encoded_request, &(usize::MAX, cfg.clone()))
2889 .unwrap();
2890 assert!(matches!(decoded_request, Backfiller::Request(r) if r == request));
2891
2892 let round = Round::new(Epoch::new(0), View::new(10));
2893 let proposal = Proposal::new(round, View::new(5), sample_digest(1));
2894 let notarizes: Vec<_> = fixture
2895 .schemes
2896 .iter()
2897 .map(|scheme| Notarize::sign(scheme, proposal.clone()).unwrap())
2898 .collect();
2899 let notarization =
2900 Notarization::from_notarizes(&fixture.schemes[0], ¬arizes, &Sequential).unwrap();
2901
2902 let nullifies: Vec<_> = fixture
2903 .schemes
2904 .iter()
2905 .map(|scheme| Nullify::sign::<Sha256>(scheme, round).unwrap())
2906 .collect();
2907 let nullification =
2908 Nullification::from_nullifies(&fixture.schemes[0], &nullifies, &Sequential).unwrap();
2909
2910 let response = Response::<S, Sha256>::new(1, vec![notarization], vec![nullification]);
2911 let encoded_response = Backfiller::<S, Sha256>::Response(response.clone()).encode();
2912 let decoded_response =
2913 Backfiller::<S, Sha256>::decode_cfg(encoded_response, &(usize::MAX, cfg)).unwrap();
2914 assert!(matches!(decoded_response, Backfiller::Response(r) if r.id == response.id));
2915 }
2916
2917 #[test]
2918 fn test_backfiller_encode_decode() {
2919 backfiller_encode_decode(ed25519::fixture);
2920 backfiller_encode_decode(secp256r1::fixture);
2921 backfiller_encode_decode(bls12381_multisig::fixture::<MinPk, _>);
2922 backfiller_encode_decode(bls12381_multisig::fixture::<MinSig, _>);
2923 backfiller_encode_decode(bls12381_threshold_vrf::fixture::<MinPk, _>);
2924 backfiller_encode_decode(bls12381_threshold_vrf::fixture::<MinSig, _>);
2925 backfiller_encode_decode(bls12381_threshold_std::fixture::<MinPk, _>);
2926 backfiller_encode_decode(bls12381_threshold_std::fixture::<MinSig, _>);
2927 }
2928
2929 #[test]
2930 fn test_request_encode_decode() {
2931 let request = Request::new(
2932 1,
2933 vec![View::new(10), View::new(11)],
2934 vec![View::new(12), View::new(13)],
2935 );
2936 let encoded = request.encode();
2937 let decoded = Request::decode_cfg(encoded, &usize::MAX).unwrap();
2938 assert_eq!(request, decoded);
2939 }
2940
2941 fn response_encode_decode<S, F>(fixture: F)
2942 where
2943 S: Scheme<Sha256>,
2944 F: FnOnce(&mut TestRng, &[u8], u32) -> Fixture<S>,
2945 {
2946 let mut rng = test_rng();
2947 let fixture = fixture(&mut rng, NAMESPACE, 5);
2948 let round = Round::new(Epoch::new(0), View::new(10));
2949 let proposal = Proposal::new(round, View::new(5), sample_digest(1));
2950
2951 let notarizes: Vec<_> = fixture
2952 .schemes
2953 .iter()
2954 .map(|scheme| Notarize::sign(scheme, proposal.clone()).unwrap())
2955 .collect();
2956 let notarization =
2957 Notarization::from_notarizes(&fixture.schemes[0], ¬arizes, &Sequential).unwrap();
2958
2959 let nullifies: Vec<_> = fixture
2960 .schemes
2961 .iter()
2962 .map(|scheme| Nullify::sign::<Sha256>(scheme, round).unwrap())
2963 .collect();
2964 let nullification =
2965 Nullification::from_nullifies(&fixture.schemes[0], &nullifies, &Sequential).unwrap();
2966
2967 let response = Response::<S, Sha256>::new(1, vec![notarization], vec![nullification]);
2968 let cfg = fixture.schemes[0].certificate_codec_config();
2969 let mut decoded =
2970 Response::<S, Sha256>::decode_cfg(response.encode(), &(usize::MAX, cfg)).unwrap();
2971 assert_eq!(response.id, decoded.id);
2972 assert_eq!(response.notarizations.len(), decoded.notarizations.len());
2973 assert_eq!(response.nullifications.len(), decoded.nullifications.len());
2974
2975 assert!(decoded.verify(&mut rng, &fixture.schemes[0], &Sequential));
2976
2977 decoded.nullifications[0].round = Round::new(
2978 decoded.nullifications[0].round.epoch(),
2979 decoded.nullifications[0].round.view().next(),
2980 );
2981 assert!(!decoded.verify(&mut rng, &fixture.schemes[0], &Sequential));
2982 }
2983
2984 #[test]
2985 fn test_response_encode_decode() {
2986 response_encode_decode(ed25519::fixture);
2987 response_encode_decode(secp256r1::fixture);
2988 response_encode_decode(bls12381_multisig::fixture::<MinPk, _>);
2989 response_encode_decode(bls12381_multisig::fixture::<MinSig, _>);
2990 response_encode_decode(bls12381_threshold_vrf::fixture::<MinPk, _>);
2991 response_encode_decode(bls12381_threshold_vrf::fixture::<MinSig, _>);
2992 response_encode_decode(bls12381_threshold_std::fixture::<MinPk, _>);
2993 response_encode_decode(bls12381_threshold_std::fixture::<MinSig, _>);
2994 }
2995
2996 fn conflicting_notarize_encode_decode<S, F>(fixture: F)
2997 where
2998 S: Scheme<Sha256>,
2999 F: FnOnce(&mut TestRng, &[u8], u32) -> Fixture<S>,
3000 {
3001 let mut rng = test_rng();
3002 let fixture = fixture(&mut rng, NAMESPACE, 5);
3003 let proposal1 = Proposal::new(
3004 Round::new(Epoch::new(0), View::new(10)),
3005 View::new(5),
3006 sample_digest(1),
3007 );
3008 let proposal2 = Proposal::new(
3009 Round::new(Epoch::new(0), View::new(10)),
3010 View::new(5),
3011 sample_digest(2),
3012 );
3013 let notarize1 = Notarize::sign(&fixture.schemes[0], proposal1).unwrap();
3014 let notarize2 = Notarize::sign(&fixture.schemes[0], proposal2).unwrap();
3015 let conflicting = ConflictingNotarize::new(notarize1, notarize2);
3016
3017 let encoded = conflicting.encode();
3018 let decoded = ConflictingNotarize::<S, Sha256>::decode(encoded).unwrap();
3019
3020 assert_eq!(conflicting, decoded);
3021 assert!(decoded.verify(&mut rng, &fixture.schemes[0], &Sequential));
3022 }
3023
3024 #[test]
3025 fn test_conflicting_notarize_encode_decode() {
3026 conflicting_notarize_encode_decode(ed25519::fixture);
3027 conflicting_notarize_encode_decode(secp256r1::fixture);
3028 conflicting_notarize_encode_decode(bls12381_multisig::fixture::<MinPk, _>);
3029 conflicting_notarize_encode_decode(bls12381_multisig::fixture::<MinSig, _>);
3030 conflicting_notarize_encode_decode(bls12381_threshold_vrf::fixture::<MinPk, _>);
3031 conflicting_notarize_encode_decode(bls12381_threshold_vrf::fixture::<MinSig, _>);
3032 conflicting_notarize_encode_decode(bls12381_threshold_std::fixture::<MinPk, _>);
3033 conflicting_notarize_encode_decode(bls12381_threshold_std::fixture::<MinSig, _>);
3034 }
3035
3036 fn conflicting_finalize_encode_decode<S, F>(fixture: F)
3037 where
3038 S: Scheme<Sha256>,
3039 F: FnOnce(&mut TestRng, &[u8], u32) -> Fixture<S>,
3040 {
3041 let mut rng = test_rng();
3042 let fixture = fixture(&mut rng, NAMESPACE, 5);
3043 let proposal1 = Proposal::new(
3044 Round::new(Epoch::new(0), View::new(10)),
3045 View::new(5),
3046 sample_digest(1),
3047 );
3048 let proposal2 = Proposal::new(
3049 Round::new(Epoch::new(0), View::new(10)),
3050 View::new(5),
3051 sample_digest(2),
3052 );
3053 let finalize1 = Finalize::sign(&fixture.schemes[0], proposal1).unwrap();
3054 let finalize2 = Finalize::sign(&fixture.schemes[0], proposal2).unwrap();
3055 let conflicting = ConflictingFinalize::new(finalize1, finalize2);
3056
3057 let encoded = conflicting.encode();
3058 let decoded = ConflictingFinalize::<S, Sha256>::decode(encoded).unwrap();
3059
3060 assert_eq!(conflicting, decoded);
3061 assert!(decoded.verify(&mut rng, &fixture.schemes[0], &Sequential));
3062 }
3063
3064 #[test]
3065 fn test_conflicting_finalize_encode_decode() {
3066 conflicting_finalize_encode_decode(ed25519::fixture);
3067 conflicting_finalize_encode_decode(secp256r1::fixture);
3068 conflicting_finalize_encode_decode(bls12381_multisig::fixture::<MinPk, _>);
3069 conflicting_finalize_encode_decode(bls12381_multisig::fixture::<MinSig, _>);
3070 conflicting_finalize_encode_decode(bls12381_threshold_vrf::fixture::<MinPk, _>);
3071 conflicting_finalize_encode_decode(bls12381_threshold_vrf::fixture::<MinSig, _>);
3072 conflicting_finalize_encode_decode(bls12381_threshold_std::fixture::<MinPk, _>);
3073 conflicting_finalize_encode_decode(bls12381_threshold_std::fixture::<MinSig, _>);
3074 }
3075
3076 fn nullify_finalize_encode_decode<S, F>(fixture: F)
3077 where
3078 S: Scheme<Sha256>,
3079 F: FnOnce(&mut TestRng, &[u8], u32) -> Fixture<S>,
3080 {
3081 let mut rng = test_rng();
3082 let fixture = fixture(&mut rng, NAMESPACE, 5);
3083 let round = Round::new(Epoch::new(0), View::new(10));
3084 let proposal = Proposal::new(round, View::new(5), sample_digest(1));
3085 let nullify = Nullify::sign::<Sha256>(&fixture.schemes[0], round).unwrap();
3086 let finalize = Finalize::sign(&fixture.schemes[0], proposal).unwrap();
3087 let conflict = NullifyFinalize::new(nullify, finalize);
3088
3089 let encoded = conflict.encode();
3090 let decoded = NullifyFinalize::<S, Sha256>::decode(encoded).unwrap();
3091
3092 assert_eq!(conflict, decoded);
3093 assert!(decoded.verify(&mut rng, &fixture.schemes[0], &Sequential));
3094 }
3095
3096 #[test]
3097 fn test_nullify_finalize_encode_decode() {
3098 nullify_finalize_encode_decode(ed25519::fixture);
3099 nullify_finalize_encode_decode(secp256r1::fixture);
3100 nullify_finalize_encode_decode(bls12381_multisig::fixture::<MinPk, _>);
3101 nullify_finalize_encode_decode(bls12381_multisig::fixture::<MinSig, _>);
3102 nullify_finalize_encode_decode(bls12381_threshold_vrf::fixture::<MinPk, _>);
3103 nullify_finalize_encode_decode(bls12381_threshold_vrf::fixture::<MinSig, _>);
3104 nullify_finalize_encode_decode(bls12381_threshold_std::fixture::<MinPk, _>);
3105 nullify_finalize_encode_decode(bls12381_threshold_std::fixture::<MinSig, _>);
3106 }
3107
3108 fn notarize_verify_wrong_namespace<S, F>(f: F)
3109 where
3110 S: Scheme<Sha256>,
3111 F: Fn(&mut TestRng, &[u8], u32) -> Fixture<S>,
3112 {
3113 let mut rng = test_rng();
3115 let fixture = setup_seeded_ns(5, 0, NAMESPACE, &f);
3116 let wrong_fixture = setup_seeded_ns(5, 0, b"wrong_namespace", &f);
3117 let round = Round::new(Epoch::new(0), View::new(10));
3118 let proposal = Proposal::new(round, View::new(5), sample_digest(1));
3119 let notarize = Notarize::sign(&fixture.schemes[0], proposal).unwrap();
3120
3121 assert!(notarize.verify(&mut rng, &fixture.schemes[0], &Sequential));
3122 assert!(!notarize.verify(&mut rng, &wrong_fixture.schemes[0], &Sequential));
3123 }
3124
3125 #[test]
3126 fn test_notarize_verify_wrong_namespace() {
3127 notarize_verify_wrong_namespace(ed25519::fixture);
3128 notarize_verify_wrong_namespace(secp256r1::fixture);
3129 notarize_verify_wrong_namespace(bls12381_multisig::fixture::<MinPk, _>);
3130 notarize_verify_wrong_namespace(bls12381_multisig::fixture::<MinSig, _>);
3131 notarize_verify_wrong_namespace(bls12381_threshold_vrf::fixture::<MinPk, _>);
3132 notarize_verify_wrong_namespace(bls12381_threshold_vrf::fixture::<MinSig, _>);
3133 notarize_verify_wrong_namespace(bls12381_threshold_std::fixture::<MinPk, _>);
3134 notarize_verify_wrong_namespace(bls12381_threshold_std::fixture::<MinSig, _>);
3135 }
3136
3137 fn notarize_verify_wrong_scheme<S, F>(f: F)
3138 where
3139 S: Scheme<Sha256>,
3140 F: Fn(&mut TestRng, &[u8], u32) -> Fixture<S>,
3141 {
3142 let mut rng = test_rng();
3143 let fixture = setup_seeded(5, 0, &f);
3144 let wrong_fixture = setup_seeded(5, 1, &f);
3145 let round = Round::new(Epoch::new(0), View::new(10));
3146 let proposal = Proposal::new(round, View::new(5), sample_digest(2));
3147 let notarize = Notarize::sign(&fixture.schemes[0], proposal).unwrap();
3148
3149 assert!(notarize.verify(&mut rng, &fixture.schemes[0], &Sequential));
3150 assert!(!notarize.verify(&mut rng, &wrong_fixture.verifier, &Sequential));
3151 }
3152
3153 #[test]
3154 fn test_notarize_verify_wrong_scheme() {
3155 notarize_verify_wrong_scheme(ed25519::fixture);
3156 notarize_verify_wrong_scheme(secp256r1::fixture);
3157 notarize_verify_wrong_scheme(bls12381_multisig::fixture::<MinPk, _>);
3158 notarize_verify_wrong_scheme(bls12381_multisig::fixture::<MinSig, _>);
3159 notarize_verify_wrong_scheme(bls12381_threshold_vrf::fixture::<MinPk, _>);
3160 notarize_verify_wrong_scheme(bls12381_threshold_vrf::fixture::<MinSig, _>);
3161 notarize_verify_wrong_scheme(bls12381_threshold_std::fixture::<MinPk, _>);
3162 notarize_verify_wrong_scheme(bls12381_threshold_std::fixture::<MinSig, _>);
3163 }
3164
3165 fn notarization_verify_wrong_scheme<S, F>(f: F)
3166 where
3167 S: Scheme<Sha256>,
3168 F: Fn(&mut TestRng, &[u8], u32) -> Fixture<S>,
3169 {
3170 let mut rng = test_rng();
3171 let fixture = setup_seeded(5, 0, &f);
3172 let wrong_fixture = setup_seeded(5, 1, &f);
3173 let round = Round::new(Epoch::new(0), View::new(10));
3174 let proposal = Proposal::new(round, View::new(5), sample_digest(3));
3175 let quorum = N3f1::quorum(fixture.schemes.len()) as usize;
3176 let notarizes: Vec<_> = fixture
3177 .schemes
3178 .iter()
3179 .take(quorum)
3180 .map(|scheme| Notarize::sign(scheme, proposal.clone()).unwrap())
3181 .collect();
3182
3183 let notarization =
3184 Notarization::from_notarizes(&fixture.schemes[0], ¬arizes, &Sequential)
3185 .expect("quorum notarization");
3186 assert!(notarization.verify(&mut rng, &fixture.schemes[0], &Sequential));
3187 assert!(!notarization.verify(&mut rng, &wrong_fixture.verifier, &Sequential));
3188 }
3189
3190 #[test]
3191 fn test_notarization_verify_wrong_scheme() {
3192 notarization_verify_wrong_scheme(ed25519::fixture);
3193 notarization_verify_wrong_scheme(secp256r1::fixture);
3194 notarization_verify_wrong_scheme(bls12381_multisig::fixture::<MinPk, _>);
3195 notarization_verify_wrong_scheme(bls12381_multisig::fixture::<MinSig, _>);
3196 notarization_verify_wrong_scheme(bls12381_threshold_vrf::fixture::<MinPk, _>);
3197 notarization_verify_wrong_scheme(bls12381_threshold_vrf::fixture::<MinSig, _>);
3198 notarization_verify_wrong_scheme(bls12381_threshold_std::fixture::<MinPk, _>);
3199 notarization_verify_wrong_scheme(bls12381_threshold_std::fixture::<MinSig, _>);
3200 }
3201
3202 fn notarization_verify_wrong_namespace<S, F>(f: F)
3203 where
3204 S: Scheme<Sha256>,
3205 F: Fn(&mut TestRng, &[u8], u32) -> Fixture<S>,
3206 {
3207 let fixture = setup_seeded_ns(5, 0, NAMESPACE, &f);
3209 let wrong_fixture = setup_seeded_ns(5, 0, b"wrong_namespace", &f);
3210 let mut rng = test_rng();
3211 let round = Round::new(Epoch::new(0), View::new(10));
3212 let proposal = Proposal::new(round, View::new(5), sample_digest(4));
3213 let quorum = N3f1::quorum(fixture.schemes.len()) as usize;
3214 let notarizes: Vec<_> = fixture
3215 .schemes
3216 .iter()
3217 .take(quorum)
3218 .map(|scheme| Notarize::sign(scheme, proposal.clone()).unwrap())
3219 .collect();
3220
3221 let notarization =
3222 Notarization::from_notarizes(&fixture.schemes[0], ¬arizes, &Sequential)
3223 .expect("quorum notarization");
3224 assert!(notarization.verify(&mut rng, &fixture.schemes[0], &Sequential));
3225
3226 assert!(!notarization.verify(&mut rng, &wrong_fixture.schemes[0], &Sequential));
3227 }
3228
3229 #[test]
3230 fn test_notarization_verify_wrong_namespace() {
3231 notarization_verify_wrong_namespace(ed25519::fixture);
3232 notarization_verify_wrong_namespace(secp256r1::fixture);
3233 notarization_verify_wrong_namespace(bls12381_multisig::fixture::<MinPk, _>);
3234 notarization_verify_wrong_namespace(bls12381_multisig::fixture::<MinSig, _>);
3235 notarization_verify_wrong_namespace(bls12381_threshold_vrf::fixture::<MinPk, _>);
3236 notarization_verify_wrong_namespace(bls12381_threshold_vrf::fixture::<MinSig, _>);
3237 notarization_verify_wrong_namespace(bls12381_threshold_std::fixture::<MinPk, _>);
3238 notarization_verify_wrong_namespace(bls12381_threshold_std::fixture::<MinSig, _>);
3239 }
3240
3241 fn notarization_recover_insufficient_signatures<S, F>(fixture: F)
3242 where
3243 S: Scheme<Sha256>,
3244 F: FnOnce(&mut TestRng, &[u8], u32) -> Fixture<S>,
3245 {
3246 let mut rng = test_rng();
3247 let fixture = fixture(&mut rng, NAMESPACE, 5);
3248 let quorum_size = quorum(fixture.schemes.len() as u32) as usize;
3249 assert!(quorum_size > 1, "test requires quorum larger than one");
3250 let round = Round::new(Epoch::new(0), View::new(10));
3251 let proposal = Proposal::new(round, View::new(5), sample_digest(5));
3252 let notarizes: Vec<_> = fixture
3253 .schemes
3254 .iter()
3255 .take(quorum_size - 1)
3256 .map(|scheme| Notarize::sign(scheme, proposal.clone()).unwrap())
3257 .collect();
3258
3259 assert!(
3260 Notarization::from_notarizes(&fixture.schemes[0], ¬arizes, &Sequential).is_none(),
3261 "insufficient votes should not form a notarization"
3262 );
3263 }
3264
3265 #[test]
3266 fn test_notarization_recover_insufficient_signatures() {
3267 notarization_recover_insufficient_signatures(ed25519::fixture);
3268 notarization_recover_insufficient_signatures(secp256r1::fixture);
3269 notarization_recover_insufficient_signatures(bls12381_multisig::fixture::<MinPk, _>);
3270 notarization_recover_insufficient_signatures(bls12381_multisig::fixture::<MinSig, _>);
3271 notarization_recover_insufficient_signatures(bls12381_threshold_vrf::fixture::<MinPk, _>);
3272 notarization_recover_insufficient_signatures(bls12381_threshold_vrf::fixture::<MinSig, _>);
3273 notarization_recover_insufficient_signatures(bls12381_threshold_std::fixture::<MinPk, _>);
3274 notarization_recover_insufficient_signatures(bls12381_threshold_std::fixture::<MinSig, _>);
3275 }
3276
3277 fn conflicting_notarize_detection<S, F>(f: F)
3278 where
3279 S: Scheme<Sha256>,
3280 F: Fn(&mut TestRng, &[u8], u32) -> Fixture<S>,
3281 {
3282 let mut rng = test_rng();
3283 let fixture = setup_seeded(5, 0, &f);
3284 let wrong_ns_fixture = setup_seeded_ns(5, 0, b"wrong_namespace", &f);
3285 let wrong_scheme_fixture = setup_seeded(5, 1, &f);
3286
3287 let round = Round::new(Epoch::new(0), View::new(10));
3288 let proposal1 = Proposal::new(round, View::new(5), sample_digest(6));
3289 let proposal2 = Proposal::new(round, View::new(5), sample_digest(7));
3290
3291 let notarize1 = Notarize::sign(&fixture.schemes[0], proposal1).unwrap();
3292 let notarize2 = Notarize::sign(&fixture.schemes[0], proposal2).unwrap();
3293 let conflict = ConflictingNotarize::new(notarize1, notarize2);
3294
3295 assert!(conflict.verify(&mut rng, &fixture.schemes[0], &Sequential));
3296 assert!(!conflict.verify(&mut rng, &wrong_ns_fixture.schemes[0], &Sequential));
3297 assert!(!conflict.verify(&mut rng, &wrong_scheme_fixture.verifier, &Sequential));
3298 }
3299
3300 #[test]
3301 fn test_conflicting_notarize_detection() {
3302 conflicting_notarize_detection(ed25519::fixture);
3303 conflicting_notarize_detection(secp256r1::fixture);
3304 conflicting_notarize_detection(bls12381_multisig::fixture::<MinPk, _>);
3305 conflicting_notarize_detection(bls12381_multisig::fixture::<MinSig, _>);
3306 conflicting_notarize_detection(bls12381_threshold_vrf::fixture::<MinPk, _>);
3307 conflicting_notarize_detection(bls12381_threshold_vrf::fixture::<MinSig, _>);
3308 conflicting_notarize_detection(bls12381_threshold_std::fixture::<MinPk, _>);
3309 conflicting_notarize_detection(bls12381_threshold_std::fixture::<MinSig, _>);
3310 }
3311
3312 fn nullify_finalize_detection<S, F>(f: F)
3313 where
3314 S: Scheme<Sha256>,
3315 F: Fn(&mut TestRng, &[u8], u32) -> Fixture<S>,
3316 {
3317 let mut rng = test_rng();
3318 let fixture = setup_seeded(5, 0, &f);
3319 let wrong_ns_fixture = setup_seeded_ns(5, 0, b"wrong_namespace", &f);
3320 let wrong_scheme_fixture = setup_seeded(5, 1, &f);
3321
3322 let round = Round::new(Epoch::new(0), View::new(10));
3323 let proposal = Proposal::new(round, View::new(5), sample_digest(8));
3324
3325 let nullify = Nullify::sign::<Sha256>(&fixture.schemes[0], round).unwrap();
3326 let finalize = Finalize::sign(&fixture.schemes[0], proposal).unwrap();
3327 let conflict = NullifyFinalize::new(nullify, finalize);
3328
3329 assert!(conflict.verify(&mut rng, &fixture.schemes[0], &Sequential));
3330 assert!(!conflict.verify(&mut rng, &wrong_ns_fixture.schemes[0], &Sequential));
3331 assert!(!conflict.verify(&mut rng, &wrong_scheme_fixture.verifier, &Sequential));
3332 }
3333
3334 #[test]
3335 fn test_nullify_finalize_detection() {
3336 nullify_finalize_detection(ed25519::fixture);
3337 nullify_finalize_detection(secp256r1::fixture);
3338 nullify_finalize_detection(bls12381_multisig::fixture::<MinPk, _>);
3339 nullify_finalize_detection(bls12381_multisig::fixture::<MinSig, _>);
3340 nullify_finalize_detection(bls12381_threshold_vrf::fixture::<MinPk, _>);
3341 nullify_finalize_detection(bls12381_threshold_vrf::fixture::<MinSig, _>);
3342 nullify_finalize_detection(bls12381_threshold_std::fixture::<MinPk, _>);
3343 nullify_finalize_detection(bls12381_threshold_std::fixture::<MinSig, _>);
3344 }
3345
3346 fn finalization_verify_wrong_scheme<S, F>(f: F)
3347 where
3348 S: Scheme<Sha256>,
3349 F: Fn(&mut TestRng, &[u8], u32) -> Fixture<S>,
3350 {
3351 let mut rng = test_rng();
3352 let fixture = setup_seeded(5, 0, &f);
3353 let wrong_fixture = setup_seeded(5, 1, &f);
3354 let round = Round::new(Epoch::new(0), View::new(10));
3355 let proposal = Proposal::new(round, View::new(5), sample_digest(9));
3356 let quorum = N3f1::quorum(fixture.schemes.len()) as usize;
3357 let finalizes: Vec<_> = fixture
3358 .schemes
3359 .iter()
3360 .take(quorum)
3361 .map(|scheme| Finalize::sign(scheme, proposal.clone()).unwrap())
3362 .collect();
3363
3364 let finalization =
3365 Finalization::from_finalizes(&fixture.schemes[0], &finalizes, &Sequential)
3366 .expect("quorum finalization");
3367 assert!(finalization.verify(&mut rng, &fixture.schemes[0], &Sequential));
3368 assert!(!finalization.verify(&mut rng, &wrong_fixture.verifier, &Sequential));
3369 }
3370
3371 #[test]
3372 fn test_finalization_wrong_scheme() {
3373 finalization_verify_wrong_scheme(ed25519::fixture);
3374 finalization_verify_wrong_scheme(secp256r1::fixture);
3375 finalization_verify_wrong_scheme(bls12381_multisig::fixture::<MinPk, _>);
3376 finalization_verify_wrong_scheme(bls12381_multisig::fixture::<MinSig, _>);
3377 finalization_verify_wrong_scheme(bls12381_threshold_vrf::fixture::<MinPk, _>);
3378 finalization_verify_wrong_scheme(bls12381_threshold_vrf::fixture::<MinSig, _>);
3379 finalization_verify_wrong_scheme(bls12381_threshold_std::fixture::<MinPk, _>);
3380 finalization_verify_wrong_scheme(bls12381_threshold_std::fixture::<MinSig, _>);
3381 }
3382
3383 struct MockAttributable(Participant);
3384
3385 impl Attributable for MockAttributable {
3386 fn signer(&self) -> Participant {
3387 self.0
3388 }
3389 }
3390
3391 #[test]
3392 fn test_attributable_map() {
3393 let mut map = AttributableMap::new(5);
3394 assert_eq!(map.len(), 0);
3395 assert!(map.is_empty());
3396
3397 for i in 0..5 {
3399 assert!(map.get(Participant::new(i)).is_none());
3400 }
3401
3402 assert!(map.insert(MockAttributable(Participant::new(3))));
3403 assert_eq!(map.len(), 1);
3404 assert!(!map.is_empty());
3405 let mut iter = map.iter();
3406 assert!(matches!(iter.next(), Some(a) if a.signer() == Participant::new(3)));
3407 assert!(iter.next().is_none());
3408 drop(iter);
3409
3410 assert!(
3412 matches!(map.get(Participant::new(3)), Some(a) if a.signer() == Participant::new(3))
3413 );
3414
3415 assert!(map.insert(MockAttributable(Participant::new(1))));
3416 assert_eq!(map.len(), 2);
3417 assert!(!map.is_empty());
3418 let mut iter = map.iter();
3419 assert!(matches!(iter.next(), Some(a) if a.signer() == Participant::new(1)));
3420 assert!(matches!(iter.next(), Some(a) if a.signer() == Participant::new(3)));
3421 assert!(iter.next().is_none());
3422 drop(iter);
3423
3424 assert!(
3426 matches!(map.get(Participant::new(1)), Some(a) if a.signer() == Participant::new(1))
3427 );
3428 assert!(
3429 matches!(map.get(Participant::new(3)), Some(a) if a.signer() == Participant::new(3))
3430 );
3431
3432 assert!(map.get(Participant::new(0)).is_none());
3434 assert!(map.get(Participant::new(2)).is_none());
3435 assert!(map.get(Participant::new(4)).is_none());
3436
3437 assert!(!map.insert(MockAttributable(Participant::new(3))));
3438 assert_eq!(map.len(), 2);
3439 assert!(!map.is_empty());
3440 let mut iter = map.iter();
3441 assert!(matches!(iter.next(), Some(a) if a.signer() == Participant::new(1)));
3442 assert!(matches!(iter.next(), Some(a) if a.signer() == Participant::new(3)));
3443 assert!(iter.next().is_none());
3444 drop(iter);
3445
3446 assert!(!map.insert(MockAttributable(Participant::new(5))));
3448 assert!(!map.insert(MockAttributable(Participant::new(100))));
3449 assert_eq!(map.len(), 2);
3450
3451 map.clear();
3453 assert_eq!(map.len(), 0);
3454 assert!(map.is_empty());
3455 assert!(map.iter().next().is_none());
3456
3457 assert!(map.insert(MockAttributable(Participant::new(2))));
3459 assert_eq!(map.len(), 1);
3460 let mut iter = map.iter();
3461 assert!(matches!(iter.next(), Some(a) if a.signer() == Participant::new(2)));
3462 assert!(iter.next().is_none());
3463 }
3464
3465 #[test]
3466 #[should_panic(expected = "proposals must differ")]
3467 fn issue_2944_regression_conflicting_notarize_new() {
3468 let mut rng = test_rng();
3469 let fixture = ed25519::fixture(&mut rng, NAMESPACE, 1);
3470 let proposal = Proposal::new(
3471 Round::new(Epoch::new(0), View::new(10)),
3472 View::new(5),
3473 sample_digest(1),
3474 );
3475 let notarize = Notarize::sign(&fixture.schemes[0], proposal).unwrap();
3476 let _ = ConflictingNotarize::new(notarize.clone(), notarize);
3477 }
3478
3479 #[test]
3480 fn issue_2944_regression_conflicting_notarize_decode() {
3481 let mut rng = test_rng();
3482 let fixture = ed25519::fixture(&mut rng, NAMESPACE, 1);
3483 let proposal = Proposal::new(
3484 Round::new(Epoch::new(0), View::new(10)),
3485 View::new(5),
3486 sample_digest(1),
3487 );
3488 let notarize = Notarize::sign(&fixture.schemes[0], proposal).unwrap();
3489
3490 let mut buf = Vec::new();
3492 notarize.write(&mut buf);
3493 notarize.write(&mut buf);
3494
3495 let result = ConflictingNotarize::<ed25519::Scheme, Sha256>::decode(Bytes::from(buf));
3497 assert!(result.is_err());
3498 }
3499
3500 #[test]
3501 #[should_panic(expected = "proposals must differ")]
3502 fn issue_2944_regression_conflicting_finalize_new() {
3503 let mut rng = test_rng();
3504 let fixture = ed25519::fixture(&mut rng, NAMESPACE, 1);
3505 let proposal = Proposal::new(
3506 Round::new(Epoch::new(0), View::new(10)),
3507 View::new(5),
3508 sample_digest(1),
3509 );
3510 let finalize = Finalize::sign(&fixture.schemes[0], proposal).unwrap();
3511 let _ = ConflictingFinalize::new(finalize.clone(), finalize);
3512 }
3513
3514 #[test]
3515 fn issue_2944_regression_conflicting_finalize_decode() {
3516 let mut rng = test_rng();
3517 let fixture = ed25519::fixture(&mut rng, NAMESPACE, 1);
3518 let proposal = Proposal::new(
3519 Round::new(Epoch::new(0), View::new(10)),
3520 View::new(5),
3521 sample_digest(1),
3522 );
3523 let finalize = Finalize::sign(&fixture.schemes[0], proposal).unwrap();
3524
3525 let mut buf = Vec::new();
3527 finalize.write(&mut buf);
3528 finalize.write(&mut buf);
3529
3530 let result = ConflictingFinalize::<ed25519::Scheme, Sha256>::decode(Bytes::from(buf));
3532 assert!(result.is_err());
3533 }
3534
3535 #[cfg(feature = "arbitrary")]
3536 mod conformance {
3537 use super::*;
3538 use crate::simplex::scheme::bls12381_threshold::vrf as bls12381_threshold_vrf;
3539 use commonware_codec::conformance::CodecConformance;
3540 use commonware_cryptography::{ed25519::PublicKey, sha256::Digest as Sha256Digest};
3541
3542 type Scheme = bls12381_threshold_vrf::Scheme<PublicKey, MinSig>;
3543
3544 commonware_conformance::conformance_tests! {
3545 CodecConformance<Vote<Scheme, Sha256Digest>>,
3546 CodecConformance<Certificate<Scheme, Sha256Digest>>,
3547 CodecConformance<Artifact<Scheme, Sha256Digest>>,
3548 CodecConformance<Proposal<Sha256Digest>>,
3549 CodecConformance<Notarize<Scheme, Sha256Digest>>,
3550 CodecConformance<Notarization<Scheme, Sha256Digest>>,
3551 CodecConformance<Nullify<Scheme>>,
3552 CodecConformance<Nullification<Scheme>>,
3553 CodecConformance<Finalize<Scheme, Sha256Digest>>,
3554 CodecConformance<Finalization<Scheme, Sha256Digest>>,
3555 CodecConformance<Backfiller<Scheme, Sha256Digest>>,
3556 CodecConformance<Request>,
3557 CodecConformance<Response<Scheme, Sha256Digest>>,
3558 CodecConformance<Activity<Scheme, Sha256Digest>>,
3559 CodecConformance<ConflictingNotarize<Scheme, Sha256Digest>>,
3560 CodecConformance<ConflictingFinalize<Scheme, Sha256Digest>>,
3561 CodecConformance<NullifyFinalize<Scheme, Sha256Digest>>,
3562 CodecConformance<Context<Sha256Digest, PublicKey>>
3563 }
3564 }
3565}