dusk_node_data/
message.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4//
5// Copyright (c) DUSK NETWORK. All rights reserved.
6
7use core::fmt;
8use std::cmp::Ordering;
9use std::io::{self, Read, Write};
10use std::net::SocketAddr;
11
12use async_channel::TrySendError;
13use dusk_bytes::Serializable as DuskSerializable;
14use dusk_core::signatures::bls::{
15    Error as BlsSigError, MultisigPublicKey as BlsMultisigPublicKey,
16    MultisigSignature as BlsMultisigSignature, PublicKey as BlsPublicKey,
17    SecretKey as BlsSecretKey,
18};
19use payload::{Nonce, ValidationQuorum};
20use tracing::{error, warn};
21
22use self::payload::{Candidate, Ratification, Validation};
23use crate::bls::PublicKey;
24use crate::ledger::{to_str, Hash, Signature};
25use crate::{bls, ledger, Serializable, StepName};
26
27/// Topic field position in the message binary representation
28pub const TOPIC_FIELD_POS: usize = 1 + 2 + 2;
29pub const PROTOCOL_VERSION: Version = Version(1, 0, 0);
30
31/// Block version
32pub const BLOCK_HEADER_VERSION: u8 = 1;
33
34/// Max value for failed iterations.
35pub const MESSAGE_MAX_FAILED_ITERATIONS: u8 = 8;
36
37#[derive(Debug, Clone)]
38/// Represent version (major, minor, patch)
39pub struct Version(pub u8, pub u16, pub u16);
40
41impl Default for Version {
42    fn default() -> Self {
43        PROTOCOL_VERSION
44    }
45}
46
47impl fmt::Display for Version {
48    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49        let Version(maj, min, patch) = self;
50        write!(f, "{maj}.{min}.{patch}")
51    }
52}
53
54impl crate::Serializable for Version {
55    fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
56        let Version(maj, min, patch) = self;
57        w.write_all(&[*maj])?;
58        w.write_all(&min.to_le_bytes())?;
59        w.write_all(&patch.to_le_bytes())?;
60
61        Ok(())
62    }
63
64    fn read<R: Read>(r: &mut R) -> io::Result<Self>
65    where
66        Self: Sized,
67    {
68        let maj = Self::read_u8(r)?;
69        let min = Self::read_u16_le(r)?;
70        let patch = Self::read_u16_le(r)?;
71        Ok(Self(maj, min, patch))
72    }
73}
74
75#[derive(Debug, Clone)]
76pub enum Status {
77    Past,
78    Present,
79    Future,
80}
81
82impl From<Ordering> for Status {
83    fn from(value: Ordering) -> Self {
84        match value {
85            Ordering::Less => Self::Past,
86            Ordering::Equal => Self::Present,
87            Ordering::Greater => Self::Future,
88        }
89    }
90}
91
92/// Message definition
93#[derive(Debug, Default, Clone)]
94pub struct Message {
95    pub version: Version,
96    topic: Topics,
97    pub header: ConsensusHeader,
98    pub payload: Payload,
99
100    pub metadata: Option<Metadata>,
101}
102
103pub trait WireMessage: Into<Payload> {
104    const TOPIC: Topics;
105    fn consensus_header(&self) -> ConsensusHeader {
106        ConsensusHeader::default()
107    }
108    fn payload(self) -> Payload {
109        self.into()
110    }
111}
112
113impl Message {
114    pub fn compare(&self, round: u64, iteration: u8, step: StepName) -> Status {
115        self.header
116            .round
117            .cmp(&round)
118            .then_with(|| self.get_step().cmp(&step.to_step(iteration)))
119            .into()
120    }
121    pub fn get_signer(&self) -> Option<bls::PublicKey> {
122        let signer = match &self.payload {
123            Payload::Candidate(c) => c.sign_info().signer,
124            Payload::Validation(v) => v.sign_info().signer,
125            Payload::Ratification(r) => r.sign_info().signer,
126            msg => {
127                warn!("Calling get_signer for {msg:?}");
128                return None;
129            }
130        };
131        Some(signer)
132    }
133    pub fn get_step(&self) -> u8 {
134        match &self.payload {
135            Payload::Candidate(c) => c.get_step(),
136            Payload::Validation(v) => v.get_step(),
137            Payload::Ratification(r) => r.get_step(),
138            Payload::Quorum(_) => {
139                // TODO: This should be removed in future
140                StepName::Ratification.to_step(self.header.iteration)
141            }
142            _ => StepName::Proposal.to_step(self.header.iteration),
143        }
144    }
145
146    pub fn get_iteration(&self) -> u8 {
147        match &self.payload {
148            Payload::Block(b) => b.header().iteration,
149            _ => self.header.iteration,
150        }
151    }
152
153    pub fn get_height(&self) -> u64 {
154        match &self.payload {
155            Payload::Block(b) => b.header().height,
156            _ => self.header.round,
157        }
158    }
159
160    pub fn version(&self) -> &Version {
161        &self.version
162    }
163
164    pub fn ray_id(&self) -> &str {
165        self.metadata
166            .as_ref()
167            .map(|m| m.ray_id.as_str())
168            .unwrap_or_default()
169    }
170
171    pub fn with_version(mut self, v: Version) -> Self {
172        self.version = v;
173        self
174    }
175
176    pub fn is_local(&self) -> bool {
177        self.metadata.is_none()
178    }
179}
180
181/// Defines a transport-related properties that determines how the message
182/// will be broadcast.
183#[derive(Debug, Clone, PartialEq, Eq)]
184pub struct Metadata {
185    pub height: u8,
186    pub src_addr: SocketAddr,
187    pub ray_id: String,
188}
189
190impl Serializable for Message {
191    fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
192        self.version.write(w)?;
193        w.write_all(&[self.topic as u8])?;
194
195        match &self.payload {
196            Payload::Candidate(p) => p.write(w),
197            Payload::Validation(p) => p.write(w),
198            Payload::Ratification(p) => p.write(w),
199            Payload::Quorum(p) => p.write(w),
200            Payload::ValidationQuorum(p) => p.write(w),
201
202            Payload::Block(p) => p.write(w),
203            Payload::Transaction(p) => p.write(w),
204            Payload::GetMempool(p) => p.write(w),
205            Payload::Inv(p) => p.write(w),
206            Payload::GetBlocks(p) => p.write(w),
207            Payload::GetResource(p) => p.write(w),
208
209            Payload::Empty | Payload::ValidationResult(_) => Ok(()), /* internal message, not sent on the wire */
210        }
211    }
212
213    fn read<R: Read>(r: &mut R) -> io::Result<Self>
214    where
215        Self: Sized,
216    {
217        let version = Version::read(r)?;
218
219        // Read topic
220        let topic = Topics::from(Self::read_u8(r)?);
221        let message: Message = match topic {
222            Topics::Candidate => payload::Candidate::read(r)?.into(),
223            Topics::Validation => payload::Validation::read(r)?.into(),
224            Topics::Ratification => payload::Ratification::read(r)?.into(),
225            Topics::Quorum => payload::Quorum::read(r)?.into(),
226            Topics::ValidationQuorum => {
227                payload::ValidationQuorum::read(r)?.into()
228            }
229
230            Topics::Block => ledger::Block::read(r)?.into(),
231            Topics::Tx => ledger::Transaction::read(r)?.into(),
232            Topics::GetResource => payload::GetResource::read(r)?.into(),
233            Topics::GetBlocks => payload::GetBlocks::read(r)?.into(),
234            Topics::GetMempool => payload::GetMempool::read(r)?.into(),
235            Topics::Inv => payload::Inv::read(r)?.into(),
236
237            Topics::Unknown => {
238                return Err(io::Error::new(
239                    io::ErrorKind::InvalidData,
240                    "Unknown topic",
241                ));
242            }
243        };
244
245        Ok(message.with_version(version))
246    }
247}
248
249impl<W: WireMessage> From<W> for Message {
250    fn from(wire_msg: W) -> Self {
251        Self {
252            header: wire_msg.consensus_header(),
253            topic: W::TOPIC,
254            payload: wire_msg.payload(),
255            ..Default::default()
256        }
257    }
258}
259
260impl WireMessage for Candidate {
261    const TOPIC: Topics = Topics::Candidate;
262    fn consensus_header(&self) -> ConsensusHeader {
263        self.header()
264    }
265}
266
267impl WireMessage for Validation {
268    const TOPIC: Topics = Topics::Validation;
269    fn consensus_header(&self) -> ConsensusHeader {
270        self.header
271    }
272}
273
274impl WireMessage for Ratification {
275    const TOPIC: Topics = Topics::Ratification;
276    fn consensus_header(&self) -> ConsensusHeader {
277        self.header
278    }
279}
280
281impl WireMessage for payload::Quorum {
282    const TOPIC: Topics = Topics::Quorum;
283    fn consensus_header(&self) -> ConsensusHeader {
284        self.header
285    }
286}
287
288impl WireMessage for payload::ValidationQuorum {
289    const TOPIC: Topics = Topics::ValidationQuorum;
290    fn consensus_header(&self) -> ConsensusHeader {
291        self.header
292    }
293}
294
295impl WireMessage for payload::GetMempool {
296    const TOPIC: Topics = Topics::GetMempool;
297}
298
299impl WireMessage for payload::Inv {
300    const TOPIC: Topics = Topics::Inv;
301}
302
303impl WireMessage for payload::GetBlocks {
304    const TOPIC: Topics = Topics::GetBlocks;
305}
306
307impl WireMessage for payload::GetResource {
308    const TOPIC: Topics = Topics::GetResource;
309}
310
311impl WireMessage for ledger::Block {
312    const TOPIC: Topics = Topics::Block;
313}
314
315impl WireMessage for ledger::Transaction {
316    const TOPIC: Topics = Topics::Tx;
317}
318
319impl WireMessage for payload::ValidationResult {
320    const TOPIC: Topics = Topics::Unknown;
321}
322
323impl Message {
324    /// Creates a unknown message with empty payload
325    pub fn empty() -> Message {
326        Self {
327            topic: Topics::default(),
328            payload: Payload::Empty,
329            ..Default::default()
330        }
331    }
332
333    pub fn topic(&self) -> Topics {
334        self.topic
335    }
336}
337
338#[derive(Default, Clone, PartialEq, Eq, Copy)]
339#[cfg_attr(any(feature = "faker", test), derive(fake::Dummy))]
340pub struct ConsensusHeader {
341    pub prev_block_hash: Hash,
342    pub round: u64,
343    #[cfg_attr(any(feature = "faker", test), dummy(faker = "0..50"))]
344    pub iteration: u8,
345}
346
347impl std::fmt::Debug for ConsensusHeader {
348    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
349        f.debug_struct("ConsensusHeader")
350            .field("prev_block_hash", &to_str(&self.prev_block_hash))
351            .field("round", &self.round)
352            .field("iteration", &self.iteration)
353            .finish()
354    }
355}
356
357impl Serializable for ConsensusHeader {
358    fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
359        w.write_all(&self.prev_block_hash)?;
360        w.write_all(&self.round.to_le_bytes())?;
361        w.write_all(&[self.iteration])?;
362
363        Ok(())
364    }
365
366    fn read<R: Read>(r: &mut R) -> io::Result<Self>
367    where
368        Self: Sized,
369    {
370        let prev_block_hash = Self::read_bytes(r)?;
371        let round = Self::read_u64_le(r)?;
372        let iteration = Self::read_u8(r)?;
373
374        Ok(ConsensusHeader {
375            prev_block_hash,
376            round,
377            iteration,
378        })
379    }
380}
381
382impl ConsensusHeader {
383    pub fn compare_round(&self, round: u64) -> Status {
384        if self.round == round {
385            return Status::Present;
386        }
387
388        if self.round > round {
389            return Status::Future;
390        }
391
392        Status::Past
393    }
394
395    pub fn signable(&self) -> Vec<u8> {
396        let mut buf = vec![];
397        self.write(&mut buf).expect("Writing to vec should succeed");
398        buf
399    }
400}
401
402#[derive(Default, Debug, Clone)]
403pub enum Payload {
404    Ratification(payload::Ratification),
405    Validation(payload::Validation),
406    Candidate(Box<payload::Candidate>),
407    Quorum(payload::Quorum),
408    ValidationQuorum(Box<payload::ValidationQuorum>),
409
410    Block(Box<ledger::Block>),
411    Transaction(Box<ledger::Transaction>),
412    GetMempool(payload::GetMempool),
413    Inv(payload::Inv),
414    GetBlocks(payload::GetBlocks),
415    GetResource(payload::GetResource),
416
417    // Internal messages payload
418    // Result message passed from Validation step to Ratification step
419    ValidationResult(Box<payload::ValidationResult>),
420
421    #[default]
422    Empty,
423}
424
425impl Payload {
426    pub fn set_nonce<N: Into<Nonce>>(&mut self, nonce: N) {
427        match self {
428            Payload::GetMempool(p) => p.set_nonce(nonce),
429            Payload::GetBlocks(p) => p.set_nonce(nonce),
430            _ => {}
431        }
432    }
433}
434
435// Consensus messages
436impl From<payload::Candidate> for Payload {
437    fn from(value: payload::Candidate) -> Self {
438        Self::Candidate(Box::new(value))
439    }
440}
441impl From<payload::Validation> for Payload {
442    fn from(value: payload::Validation) -> Self {
443        Self::Validation(value)
444    }
445}
446impl From<payload::Ratification> for Payload {
447    fn from(value: payload::Ratification) -> Self {
448        Self::Ratification(value)
449    }
450}
451impl From<payload::Quorum> for Payload {
452    fn from(value: payload::Quorum) -> Self {
453        Self::Quorum(value)
454    }
455}
456impl From<payload::ValidationQuorum> for Payload {
457    fn from(value: payload::ValidationQuorum) -> Self {
458        Self::ValidationQuorum(Box::new(value))
459    }
460}
461
462// Data exchange messages
463impl From<ledger::Block> for Payload {
464    fn from(value: ledger::Block) -> Self {
465        Self::Block(Box::new(value))
466    }
467}
468impl From<ledger::Transaction> for Payload {
469    fn from(value: ledger::Transaction) -> Self {
470        Self::Transaction(Box::new(value))
471    }
472}
473impl From<payload::GetMempool> for Payload {
474    fn from(value: payload::GetMempool) -> Self {
475        Self::GetMempool(value)
476    }
477}
478impl From<payload::Inv> for Payload {
479    fn from(value: payload::Inv) -> Self {
480        Self::Inv(value)
481    }
482}
483impl From<payload::GetBlocks> for Payload {
484    fn from(value: payload::GetBlocks) -> Self {
485        Self::GetBlocks(value)
486    }
487}
488impl From<payload::GetResource> for Payload {
489    fn from(value: payload::GetResource) -> Self {
490        Self::GetResource(value)
491    }
492}
493
494// Internal messages
495impl From<payload::ValidationResult> for Payload {
496    fn from(value: payload::ValidationResult) -> Self {
497        Self::ValidationResult(Box::new(value))
498    }
499}
500
501pub mod payload {
502    use std::fmt;
503    use std::io::{self, Read, Write};
504    use std::net::{
505        IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6,
506    };
507
508    use serde::Serialize;
509
510    use super::{ConsensusHeader, SignInfo};
511    use crate::ledger::{self, to_str, Attestation, Block, Hash, StepVotes};
512    use crate::{get_current_timestamp, Serializable};
513
514    #[derive(Debug, Clone)]
515    #[cfg_attr(
516        any(feature = "faker", test),
517        derive(fake::Dummy, Eq, PartialEq)
518    )]
519    pub struct Ratification {
520        pub header: ConsensusHeader,
521        pub vote: Vote,
522        pub timestamp: u64,
523        pub validation_result: ValidationResult,
524        pub sign_info: SignInfo,
525    }
526
527    #[derive(Debug, Clone)]
528    #[cfg_attr(
529        any(feature = "faker", test),
530        derive(fake::Dummy, Eq, PartialEq)
531    )]
532    pub struct Validation {
533        pub header: ConsensusHeader,
534        pub vote: Vote,
535        pub sign_info: SignInfo,
536    }
537
538    #[derive(
539        Clone, Copy, Hash, Eq, PartialEq, Default, PartialOrd, Ord, Serialize,
540    )]
541    #[cfg_attr(any(feature = "faker", test), derive(fake::Dummy))]
542    #[repr(u8)]
543    pub enum Vote {
544        NoCandidate = 0,
545        Valid(#[serde(serialize_with = "crate::serialize_hex")] Hash) = 1,
546        Invalid(#[serde(serialize_with = "crate::serialize_hex")] Hash) = 2,
547
548        #[default]
549        NoQuorum = 3,
550    }
551
552    impl Vote {
553        pub fn is_valid(&self) -> bool {
554            matches!(self, Vote::Valid(_))
555        }
556        pub fn size(&self) -> usize {
557            const ENUM_BYTE: usize = 1;
558
559            let data_size: usize = match &self {
560                Vote::NoCandidate => 0,
561                Vote::Valid(_) => 32,
562                Vote::Invalid(_) => 32,
563                Vote::NoQuorum => 0,
564            };
565            ENUM_BYTE + data_size
566        }
567    }
568
569    impl fmt::Debug for Vote {
570        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
571            let (desc, hash) = match &self {
572                Self::NoCandidate => ("NoCandidate", "".into()),
573                Self::Valid(hash) => ("Valid", to_str(hash)),
574                Self::Invalid(hash) => ("Invalid", to_str(hash)),
575                Self::NoQuorum => ("NoQuorum", "".into()),
576            };
577            write!(f, "Vote: {desc}({hash})")
578        }
579    }
580
581    impl Serializable for Vote {
582        fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
583            match &self {
584                Self::NoCandidate => w.write_all(&[0])?,
585
586                Self::Valid(hash) => {
587                    w.write_all(&[1])?;
588                    w.write_all(hash)?;
589                }
590                Self::Invalid(hash) => {
591                    w.write_all(&[2])?;
592                    w.write_all(hash)?;
593                }
594                Self::NoQuorum => w.write_all(&[3])?,
595            };
596            Ok(())
597        }
598
599        fn read<R: Read>(r: &mut R) -> io::Result<Self>
600        where
601            Self: Sized,
602        {
603            Ok(match Self::read_u8(r)? {
604                0 => Self::NoCandidate,
605                1 => Self::Valid(Self::read_bytes(r)?),
606                2 => Self::Invalid(Self::read_bytes(r)?),
607                3 => Self::NoQuorum,
608                _ => Err(io::Error::new(
609                    io::ErrorKind::InvalidData,
610                    "Invalid vote",
611                ))?,
612            })
613        }
614    }
615
616    impl Serializable for Validation {
617        fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
618            self.header.write(w)?;
619            self.vote.write(w)?;
620            // sign_info at the end
621            self.sign_info.write(w)?;
622            Ok(())
623        }
624
625        fn read<R: Read>(r: &mut R) -> io::Result<Self>
626        where
627            Self: Sized,
628        {
629            let header = ConsensusHeader::read(r)?;
630            let vote = Vote::read(r)?;
631            let sign_info = SignInfo::read(r)?;
632
633            Ok(Validation {
634                header,
635                vote,
636                sign_info,
637            })
638        }
639    }
640
641    #[derive(Clone)]
642    #[cfg_attr(any(feature = "faker", test), derive(fake::Dummy))]
643    pub struct Candidate {
644        pub candidate: Block,
645    }
646
647    impl std::fmt::Debug for Candidate {
648        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
649            f.debug_struct("Candidate")
650                .field(
651                    "signature",
652                    &ledger::to_str(self.candidate.header().signature.inner()),
653                )
654                .field("block", &self.candidate)
655                .finish()
656        }
657    }
658
659    impl PartialEq<Self> for Candidate {
660        fn eq(&self, other: &Self) -> bool {
661            self.candidate
662                .header()
663                .hash
664                .eq(&other.candidate.header().hash)
665        }
666    }
667
668    impl Eq for Candidate {}
669
670    impl Serializable for Candidate {
671        fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
672            self.candidate.write(w)?;
673            Ok(())
674        }
675
676        fn read<R: Read>(r: &mut R) -> io::Result<Self>
677        where
678            Self: Sized,
679        {
680            let candidate = Block::read(r)?;
681
682            Ok(Candidate { candidate })
683        }
684    }
685    #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
686    #[cfg_attr(any(feature = "faker", test), derive(fake::Dummy))]
687    pub enum QuorumType {
688        /// Supermajority of Valid votes
689        Valid = 0,
690        /// Majority of Invalid votes
691        Invalid = 1,
692        /// Majority of NoCandidate votes
693        NoCandidate = 2,
694        /// No quorum reached (timeout expired)
695        #[default]
696        NoQuorum = 255,
697    }
698
699    impl From<u8> for QuorumType {
700        fn from(v: u8) -> QuorumType {
701            match v {
702                0 => QuorumType::Valid,
703                1 => QuorumType::Invalid,
704                2 => QuorumType::NoCandidate,
705                _ => QuorumType::NoQuorum,
706            }
707        }
708    }
709
710    #[derive(Debug, Clone, Default)]
711    #[cfg_attr(
712        any(feature = "faker", test),
713        derive(fake::Dummy, Eq, PartialEq)
714    )]
715    pub struct ValidationQuorum {
716        pub header: ConsensusHeader,
717        pub result: ValidationResult,
718    }
719
720    #[derive(Debug, Clone, Default)]
721    #[cfg_attr(
722        any(feature = "faker", test),
723        derive(fake::Dummy, Eq, PartialEq)
724    )]
725    pub struct ValidationResult {
726        pub(crate) quorum: QuorumType,
727        pub(crate) vote: Vote,
728        pub(crate) step_votes: StepVotes,
729    }
730
731    impl ValidationResult {
732        pub fn new(
733            step_votes: StepVotes,
734            vote: Vote,
735            quorum: QuorumType,
736        ) -> Self {
737            Self {
738                step_votes,
739                vote,
740                quorum,
741            }
742        }
743
744        pub fn quorum(&self) -> QuorumType {
745            self.quorum
746        }
747
748        pub fn step_votes(&self) -> &StepVotes {
749            &self.step_votes
750        }
751
752        pub fn vote(&self) -> &Vote {
753            &self.vote
754        }
755    }
756
757    #[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize)]
758    #[serde(untagged)]
759    #[cfg_attr(any(feature = "faker", test), derive(fake::Dummy))]
760    pub enum RatificationResult {
761        Fail(Vote),
762        Success(Vote),
763    }
764
765    impl Default for RatificationResult {
766        fn default() -> Self {
767            Self::Fail(Vote::NoQuorum)
768        }
769    }
770
771    impl From<Vote> for RatificationResult {
772        fn from(vote: Vote) -> Self {
773            match vote {
774                Vote::Valid(hash) => {
775                    RatificationResult::Success(Vote::Valid(hash))
776                }
777                fail => RatificationResult::Fail(fail),
778            }
779        }
780    }
781
782    impl RatificationResult {
783        pub fn vote(&self) -> &Vote {
784            match self {
785                Self::Success(v) => v,
786                Self::Fail(v) => v,
787            }
788        }
789
790        pub fn failed(&self) -> bool {
791            match self {
792                Self::Success(_) => false,
793                Self::Fail(_) => true,
794            }
795        }
796    }
797
798    #[derive(Debug, Clone, Eq, PartialEq)]
799    pub struct Quorum {
800        pub header: ConsensusHeader,
801        pub att: Attestation,
802    }
803
804    impl Serializable for Quorum {
805        fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
806            self.header.write(w)?;
807            self.att.write(w)?;
808
809            Ok(())
810        }
811
812        fn read<R: Read>(r: &mut R) -> io::Result<Self>
813        where
814            Self: Sized,
815        {
816            let header = ConsensusHeader::read(r)?;
817            let att = Attestation::read(r)?;
818
819            Ok(Quorum { header, att })
820        }
821    }
822
823    impl Quorum {
824        pub fn vote(&self) -> &Vote {
825            self.att.result.vote()
826        }
827    }
828
829    #[derive(Debug, Clone, Default)]
830    pub struct GetCandidate {
831        pub hash: [u8; 32],
832    }
833
834    impl Serializable for GetCandidate {
835        fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
836            w.write_all(&self.hash[..])?;
837
838            Ok(())
839        }
840
841        fn read<R: Read>(r: &mut R) -> io::Result<Self>
842        where
843            Self: Sized,
844        {
845            let hash = Self::read_bytes(r)?;
846
847            Ok(GetCandidate { hash })
848        }
849    }
850
851    #[derive(Debug, Clone, Default)]
852    pub struct GetCandidateResp {
853        pub candidate: Block,
854    }
855
856    impl Serializable for GetCandidateResp {
857        fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
858            self.candidate.write(w)
859        }
860
861        fn read<R: Read>(r: &mut R) -> io::Result<Self>
862        where
863            Self: Sized,
864        {
865            Ok(GetCandidateResp {
866                candidate: Block::read(r)?,
867            })
868        }
869    }
870    #[derive(Debug, Clone, Default)]
871    pub struct Nonce([u8; 8]);
872
873    impl Serializable for Nonce {
874        fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
875            w.write_all(&self.0)
876        }
877
878        fn read<R: Read>(r: &mut R) -> io::Result<Self>
879        where
880            Self: Sized,
881        {
882            let nonce = Self::read_bytes(r)?;
883            Ok(Self(nonce))
884        }
885    }
886
887    impl From<Nonce> for u64 {
888        fn from(value: Nonce) -> Self {
889            u64::from_le_bytes(value.0)
890        }
891    }
892
893    impl From<u64> for Nonce {
894        fn from(value: u64) -> Self {
895            Self(value.to_le_bytes())
896        }
897    }
898
899    impl From<IpAddr> for Nonce {
900        fn from(value: IpAddr) -> Self {
901            match value {
902                IpAddr::V4(v4) => v4.into(),
903                IpAddr::V6(v6) => v6.into(),
904            }
905        }
906    }
907
908    impl From<Ipv4Addr> for Nonce {
909        fn from(value: Ipv4Addr) -> Self {
910            let num = u32::from_le_bytes(value.octets());
911            (num as u64).into()
912        }
913    }
914
915    impl From<Ipv6Addr> for Nonce {
916        fn from(value: Ipv6Addr) -> Self {
917            let mut ret = [0u8; 8];
918            let value = value.octets();
919            let (a, b) = value.split_at(8);
920            a.iter()
921                .zip(b)
922                .map(|(a, b)| a.wrapping_add(*b))
923                .enumerate()
924                .for_each(|(idx, v)| ret[idx] = v);
925
926            Self(ret)
927        }
928    }
929
930    #[derive(Debug, Clone, Default)]
931    pub struct GetMempool {
932        pub(crate) nonce: Nonce,
933    }
934
935    impl GetMempool {
936        pub fn set_nonce<N: Into<Nonce>>(&mut self, nonce: N) {
937            self.nonce = nonce.into()
938        }
939    }
940
941    impl Serializable for GetMempool {
942        fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
943            self.nonce.write(w)?;
944            Ok(())
945        }
946
947        fn read<R: Read>(r: &mut R) -> io::Result<Self>
948        where
949            Self: Sized,
950        {
951            let nonce = Nonce::read(r)?;
952            Ok(GetMempool { nonce })
953        }
954    }
955
956    #[derive(Clone, Default, Debug, Copy)]
957    pub enum InvType {
958        /// A transaction fetched by tx_id
959        MempoolTx,
960        #[default]
961        /// A full block fetched by block hash
962        BlockFromHash,
963        /// A full block fetched by block height
964        BlockFromHeight,
965        /// A candidate block fetched by block hash, Att is None
966        CandidateFromHash,
967        /// A candidate block fetched by (prev_block_hash, iteration)
968        CandidateFromIteration,
969        /// A ValidationResult fetched by (prev_block_hash, round, iteration)
970        ValidationResult,
971    }
972
973    #[derive(Clone, Copy)]
974    pub enum InvParam {
975        Hash([u8; 32]),
976        Height(u64),
977        Iteration(ConsensusHeader),
978    }
979
980    impl Default for InvParam {
981        fn default() -> Self {
982            Self::Height(0)
983        }
984    }
985
986    impl fmt::Debug for InvParam {
987        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
988            match self {
989                InvParam::Hash(hash) => write!(f, "Hash: {}", to_str(hash)),
990                InvParam::Height(height) => write!(f, "Height: {}", height),
991                InvParam::Iteration(ch) => {
992                    write!(
993                        f,
994                        "PrevBlock: {}, Round: {}, Iteration: {}",
995                        to_str(&ch.prev_block_hash),
996                        ch.round,
997                        ch.iteration
998                    )
999                }
1000            }
1001        }
1002    }
1003
1004    #[derive(Default, Debug, Clone, Copy)]
1005    pub struct InvVect {
1006        pub inv_type: InvType,
1007        pub param: InvParam,
1008    }
1009
1010    #[derive(Default, Debug, Clone)]
1011    pub struct Inv {
1012        pub inv_list: Vec<InvVect>,
1013        pub max_entries: u16,
1014    }
1015
1016    impl Inv {
1017        pub fn new(max_entries: u16) -> Self {
1018            Self {
1019                inv_list: Default::default(),
1020                max_entries,
1021            }
1022        }
1023
1024        pub fn add_tx_id(&mut self, id: [u8; 32]) {
1025            self.inv_list.push(InvVect {
1026                inv_type: InvType::MempoolTx,
1027                param: InvParam::Hash(id),
1028            });
1029        }
1030
1031        pub fn add_block_from_hash(&mut self, hash: [u8; 32]) {
1032            self.inv_list.push(InvVect {
1033                inv_type: InvType::BlockFromHash,
1034                param: InvParam::Hash(hash),
1035            });
1036        }
1037
1038        pub fn add_block_from_height(&mut self, height: u64) {
1039            self.inv_list.push(InvVect {
1040                inv_type: InvType::BlockFromHeight,
1041                param: InvParam::Height(height),
1042            });
1043        }
1044
1045        pub fn add_candidate_from_hash(&mut self, hash: [u8; 32]) {
1046            self.inv_list.push(InvVect {
1047                inv_type: InvType::CandidateFromHash,
1048                param: InvParam::Hash(hash),
1049            });
1050        }
1051
1052        pub fn add_candidate_from_iteration(
1053            &mut self,
1054            consensus_header: ConsensusHeader,
1055        ) {
1056            self.inv_list.push(InvVect {
1057                inv_type: InvType::CandidateFromIteration,
1058                param: InvParam::Iteration(consensus_header),
1059            });
1060        }
1061
1062        pub fn add_validation_result(
1063            &mut self,
1064            consensus_header: ConsensusHeader,
1065        ) {
1066            self.inv_list.push(InvVect {
1067                inv_type: InvType::ValidationResult,
1068                param: InvParam::Iteration(consensus_header),
1069            });
1070        }
1071    }
1072
1073    impl Serializable for Inv {
1074        fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
1075            let items_len = self.inv_list.len() as u32;
1076            w.write_all(&items_len.to_le_bytes())?;
1077
1078            for item in &self.inv_list {
1079                w.write_all(&[item.inv_type as u8])?;
1080
1081                match &item.param {
1082                    InvParam::Hash(hash) => w.write_all(&hash[..])?,
1083                    InvParam::Height(height) => {
1084                        w.write_all(&height.to_le_bytes())?
1085                    }
1086                    InvParam::Iteration(ch) => {
1087                        ch.write(w)?;
1088                    }
1089                };
1090            }
1091
1092            w.write_all(&self.max_entries.to_le_bytes())?;
1093            Ok(())
1094        }
1095
1096        fn read<R: Read>(r: &mut R) -> io::Result<Self>
1097        where
1098            Self: Sized,
1099        {
1100            let items_len = Self::read_u32_le(r)?;
1101
1102            let mut inv = Inv::default();
1103            for _ in 0..items_len {
1104                let inv_type = Self::read_u8(r)?;
1105
1106                let inv_type = match inv_type {
1107                    0 => InvType::MempoolTx,
1108                    1 => InvType::BlockFromHash,
1109                    2 => InvType::BlockFromHeight,
1110                    3 => InvType::CandidateFromHash,
1111                    4 => InvType::CandidateFromIteration,
1112                    5 => InvType::ValidationResult,
1113                    _ => {
1114                        return Err(io::Error::from(io::ErrorKind::InvalidData))
1115                    }
1116                };
1117
1118                match inv_type {
1119                    InvType::MempoolTx => {
1120                        let hash = Self::read_bytes(r)?;
1121                        inv.add_tx_id(hash);
1122                    }
1123                    InvType::BlockFromHash => {
1124                        let hash = Self::read_bytes(r)?;
1125                        inv.add_block_from_hash(hash);
1126                    }
1127                    InvType::BlockFromHeight => {
1128                        inv.add_block_from_height(Self::read_u64_le(r)?);
1129                    }
1130                    InvType::CandidateFromHash => {
1131                        inv.add_candidate_from_hash(Self::read_bytes(r)?);
1132                    }
1133                    InvType::CandidateFromIteration => {
1134                        let ch = ConsensusHeader::read(r)?;
1135                        inv.add_candidate_from_iteration(ch);
1136                    }
1137                    InvType::ValidationResult => {
1138                        let ch = ConsensusHeader::read(r)?;
1139                        inv.add_validation_result(ch);
1140                    }
1141                }
1142            }
1143
1144            inv.max_entries = Self::read_u16_le(r)?;
1145            Ok(inv)
1146        }
1147    }
1148
1149    #[derive(Clone)]
1150    pub struct GetBlocks {
1151        pub locator: [u8; 32],
1152        pub(crate) nonce: Nonce,
1153    }
1154
1155    impl GetBlocks {
1156        pub fn new(locator: [u8; 32]) -> Self {
1157            Self {
1158                locator,
1159                nonce: Nonce::default(),
1160            }
1161        }
1162        pub fn set_nonce<N: Into<Nonce>>(&mut self, nonce: N) {
1163            self.nonce = nonce.into()
1164        }
1165    }
1166
1167    impl fmt::Debug for GetBlocks {
1168        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1169            write!(f, "GetBlocks, locator: {}", to_str(&self.locator))
1170        }
1171    }
1172
1173    impl Serializable for GetBlocks {
1174        fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
1175            w.write_all(&self.locator[..])?;
1176            self.nonce.write(w)?;
1177            Ok(())
1178        }
1179
1180        fn read<R: Read>(r: &mut R) -> io::Result<Self>
1181        where
1182            Self: Sized,
1183        {
1184            let locator = Self::read_bytes(r)?;
1185            let nonce = Nonce::read(r)?;
1186            Ok(Self { locator, nonce })
1187        }
1188    }
1189
1190    #[derive(Debug, Clone)]
1191    pub struct GetResource {
1192        /// Inventory/Resource to search for
1193        inventory: Inv,
1194
1195        /// (requester) Address to which the resource is sent back, if found
1196        requester_addr: Option<SocketAddr>,
1197
1198        /// Limits request lifespan by absolute (epoch) time
1199        ttl_as_sec: u64,
1200
1201        /// Limits request lifespan by number of hops
1202        hops_limit: u16,
1203    }
1204
1205    impl GetResource {
1206        pub fn new(
1207            inventory: Inv,
1208            requester_addr: Option<SocketAddr>,
1209            ttl_as_sec: u64,
1210            hops_limit: u16,
1211        ) -> Self {
1212            Self {
1213                inventory,
1214                requester_addr,
1215                ttl_as_sec,
1216                hops_limit,
1217            }
1218        }
1219
1220        pub fn clone_with_hop_decrement(&self) -> Option<Self> {
1221            if self.hops_limit <= 1 {
1222                return None;
1223            }
1224            let mut req = self.clone();
1225            req.hops_limit -= 1;
1226            Some(req)
1227        }
1228
1229        pub fn get_addr(&self) -> Option<SocketAddr> {
1230            self.requester_addr
1231        }
1232
1233        pub fn get_inv(&self) -> &Inv {
1234            &self.inventory
1235        }
1236
1237        pub fn is_expired(&self) -> bool {
1238            get_current_timestamp() > self.ttl_as_sec
1239        }
1240    }
1241
1242    impl Serializable for GetResource {
1243        fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
1244            self.inventory.write(w)?;
1245
1246            let requester_addr = self.requester_addr.ok_or(io::Error::new(
1247                io::ErrorKind::InvalidData,
1248                "Requester address is missing",
1249            ))?;
1250
1251            requester_addr.write(w)?;
1252            w.write_all(&self.ttl_as_sec.to_le_bytes()[..])?;
1253            w.write_all(&self.hops_limit.to_le_bytes()[..])
1254        }
1255
1256        fn read<R: Read>(r: &mut R) -> io::Result<Self>
1257        where
1258            Self: Sized,
1259        {
1260            let inner = Inv::read(r)?;
1261            let requester_addr = SocketAddr::read(r)?;
1262
1263            let mut buf = [0u8; 8];
1264            r.read_exact(&mut buf)?;
1265            let ttl_as_sec = u64::from_le_bytes(buf);
1266
1267            let mut buf = [0u8; 2];
1268            r.read_exact(&mut buf)?;
1269            let hops_limit = u16::from_le_bytes(buf);
1270
1271            Ok(GetResource {
1272                inventory: inner,
1273                requester_addr: Some(requester_addr),
1274                ttl_as_sec,
1275                hops_limit,
1276            })
1277        }
1278    }
1279
1280    impl Serializable for SocketAddr {
1281        fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
1282            match self {
1283                SocketAddr::V4(addr_v4) => {
1284                    w.write_all(&[4])?;
1285                    w.write_all(&addr_v4.ip().octets())?;
1286                    w.write_all(&addr_v4.port().to_le_bytes())?;
1287                }
1288                SocketAddr::V6(addr_v6) => {
1289                    w.write_all(&[6])?;
1290                    w.write_all(&addr_v6.ip().octets())?;
1291                    w.write_all(&addr_v6.port().to_le_bytes())?;
1292                }
1293            }
1294            Ok(())
1295        }
1296
1297        fn read<R: Read>(r: &mut R) -> io::Result<Self>
1298        where
1299            Self: Sized,
1300        {
1301            let mut ip_type = [0u8; 1];
1302            r.read_exact(&mut ip_type)?;
1303
1304            let ip = match ip_type[0] {
1305                4 => {
1306                    let mut octets = [0u8; 4];
1307                    r.read_exact(&mut octets)?;
1308
1309                    let mut port_bytes = [0u8; 2];
1310                    r.read_exact(&mut port_bytes)?;
1311
1312                    SocketAddr::V4(SocketAddrV4::new(
1313                        Ipv4Addr::from(octets),
1314                        u16::from_le_bytes(port_bytes),
1315                    ))
1316                }
1317                6 => {
1318                    let mut octets = [0u8; 16];
1319                    r.read_exact(&mut octets)?;
1320
1321                    let mut port_bytes = [0u8; 2];
1322                    r.read_exact(&mut port_bytes)?;
1323
1324                    SocketAddr::V6(SocketAddrV6::new(
1325                        Ipv6Addr::from(octets),
1326                        u16::from_le_bytes(port_bytes),
1327                        0,
1328                        0,
1329                    ))
1330                }
1331                _ => {
1332                    return Err(io::Error::new(
1333                        io::ErrorKind::InvalidData,
1334                        "Invalid IP type",
1335                    ))
1336                }
1337            };
1338            Ok(ip)
1339        }
1340    }
1341}
1342
1343macro_rules! map_topic {
1344    ($v:expr, $enum_v:expr) => {
1345        if $v == $enum_v as u8 {
1346            return $enum_v;
1347        }
1348    };
1349}
1350
1351#[derive(Debug, Clone, PartialEq, Eq, Copy, Default)]
1352#[cfg_attr(any(feature = "faker", test), derive(fake::Dummy))]
1353pub enum Topics {
1354    // Data exchange topics.
1355    GetResource = 8,
1356    GetBlocks = 9,
1357    GetMempool = 13, // NB: This is aliased as Mempool in the golang impl
1358    Inv = 14,
1359
1360    // Fire-and-forget messaging
1361    Tx = 10,
1362    Block = 11,
1363
1364    // Consensus main loop topics
1365    Candidate = 16,
1366    Validation = 17,
1367    Ratification = 18,
1368    Quorum = 19,
1369    ValidationQuorum = 20,
1370
1371    #[default]
1372    Unknown = 255,
1373}
1374
1375impl Topics {
1376    pub fn is_consensus_msg(&self) -> bool {
1377        matches!(
1378            &self,
1379            Topics::Candidate
1380                | Topics::Validation
1381                | Topics::Ratification
1382                | Topics::Quorum
1383                | Topics::ValidationQuorum
1384        )
1385    }
1386}
1387
1388impl From<u8> for Topics {
1389    fn from(v: u8) -> Self {
1390        map_topic!(v, Topics::GetResource);
1391        map_topic!(v, Topics::GetBlocks);
1392        map_topic!(v, Topics::Tx);
1393        map_topic!(v, Topics::Block);
1394        map_topic!(v, Topics::GetMempool);
1395        map_topic!(v, Topics::Inv);
1396        map_topic!(v, Topics::Candidate);
1397        map_topic!(v, Topics::Validation);
1398        map_topic!(v, Topics::Ratification);
1399        map_topic!(v, Topics::Quorum);
1400        map_topic!(v, Topics::ValidationQuorum);
1401
1402        Topics::Unknown
1403    }
1404}
1405
1406impl From<Topics> for u8 {
1407    fn from(t: Topics) -> Self {
1408        t as u8
1409    }
1410}
1411
1412/// AsyncQueue is a thin wrapper of async_channel.
1413#[derive(Clone)]
1414pub struct AsyncQueue<M: Clone> {
1415    receiver: async_channel::Receiver<M>,
1416    sender: async_channel::Sender<M>,
1417
1418    cap: usize,
1419    label: &'static str,
1420}
1421
1422impl<M: Clone> AsyncQueue<M> {
1423    /// Creates a bounded async queue with fixed capacity
1424    ///
1425    /// `Label` sets a queue label for logging
1426    ///
1427    /// Panics if `cap` is zero (Capacity must be a positive number).
1428    pub fn bounded(cap: usize, label: &'static str) -> Self {
1429        let (sender, receiver) = async_channel::bounded(cap);
1430        Self {
1431            receiver,
1432            sender,
1433            cap,
1434            label,
1435        }
1436    }
1437}
1438
1439impl<M: Clone> AsyncQueue<M> {
1440    pub fn try_send(&self, msg: M) {
1441        let label = self.label;
1442        let _ = self.sender.try_send(msg).map_err(|err| match err {
1443            TrySendError::Full(_) => {
1444                error!("queue ({label}) is full, cap: {}", self.cap);
1445            }
1446            TrySendError::Closed(_) => {
1447                error!("queue ({label}) is closed");
1448            }
1449        });
1450    }
1451
1452    pub fn recv(&self) -> async_channel::Recv<'_, M> {
1453        self.receiver.recv()
1454    }
1455}
1456
1457pub trait StepMessage {
1458    const STEP_NAME: StepName;
1459    fn header(&self) -> ConsensusHeader;
1460
1461    fn get_step(&self) -> u8 {
1462        Self::STEP_NAME.to_step(self.header().iteration)
1463    }
1464}
1465
1466pub trait SignedStepMessage: StepMessage {
1467    const SIGN_SEED: &'static [u8];
1468    fn signable(&self) -> Vec<u8>;
1469    fn sign_info(&self) -> SignInfo;
1470    fn sign_info_mut(&mut self) -> &mut SignInfo;
1471
1472    fn verify_signature(&self) -> Result<(), BlsSigError> {
1473        let signature = self.sign_info().signature;
1474        let sig = BlsMultisigSignature::from_bytes(signature.inner())?;
1475        let pk = BlsMultisigPublicKey::aggregate(&[*self
1476            .sign_info()
1477            .signer
1478            .inner()])?;
1479        let msg = self.signable();
1480        pk.verify(&sig, &msg)
1481    }
1482
1483    fn sign(&mut self, sk: &BlsSecretKey, pk: &BlsPublicKey) {
1484        let msg = self.signable();
1485        let sign_info = self.sign_info_mut();
1486        let signature = sk.sign_multisig(pk, &msg).to_bytes();
1487        sign_info.signature = signature.into();
1488        sign_info.signer = PublicKey::new(*pk)
1489    }
1490}
1491
1492impl StepMessage for Validation {
1493    const STEP_NAME: StepName = StepName::Validation;
1494
1495    fn header(&self) -> ConsensusHeader {
1496        self.header
1497    }
1498}
1499
1500impl SignedStepMessage for Validation {
1501    const SIGN_SEED: &'static [u8] = &[1u8];
1502
1503    fn sign_info(&self) -> SignInfo {
1504        self.sign_info.clone()
1505    }
1506    fn sign_info_mut(&mut self) -> &mut SignInfo {
1507        &mut self.sign_info
1508    }
1509    fn signable(&self) -> Vec<u8> {
1510        let mut signable = self.header.signable();
1511        signable.extend_from_slice(Self::SIGN_SEED);
1512        self.vote
1513            .write(&mut signable)
1514            .expect("Writing to vec should succeed");
1515        signable
1516    }
1517}
1518
1519impl StepMessage for Ratification {
1520    const STEP_NAME: StepName = StepName::Ratification;
1521
1522    fn header(&self) -> ConsensusHeader {
1523        self.header
1524    }
1525}
1526
1527impl SignedStepMessage for Ratification {
1528    const SIGN_SEED: &'static [u8] = &[2u8];
1529    fn sign_info(&self) -> SignInfo {
1530        self.sign_info.clone()
1531    }
1532    fn sign_info_mut(&mut self) -> &mut SignInfo {
1533        &mut self.sign_info
1534    }
1535    fn signable(&self) -> Vec<u8> {
1536        let mut signable = self.header.signable();
1537        signable.extend_from_slice(Self::SIGN_SEED);
1538        self.vote
1539            .write(&mut signable)
1540            .expect("Writing to vec should succeed");
1541        signable
1542    }
1543}
1544
1545impl StepMessage for Candidate {
1546    const STEP_NAME: StepName = StepName::Proposal;
1547
1548    fn header(&self) -> ConsensusHeader {
1549        ConsensusHeader {
1550            iteration: self.candidate.header().iteration,
1551            prev_block_hash: self.candidate.header().prev_block_hash,
1552            round: self.candidate.header().height,
1553        }
1554    }
1555}
1556
1557impl SignedStepMessage for Candidate {
1558    const SIGN_SEED: &'static [u8] = &[];
1559    fn sign_info(&self) -> SignInfo {
1560        let header = self.candidate.header();
1561        SignInfo {
1562            signer: PublicKey::try_from(header.generator_bls_pubkey.0)
1563                .unwrap_or_default(),
1564            signature: header.signature,
1565        }
1566    }
1567    fn sign_info_mut(&mut self) -> &mut SignInfo {
1568        panic!("sign_info_mut called on Candidate, this is a bug")
1569    }
1570    fn signable(&self) -> Vec<u8> {
1571        self.candidate.header().hash.to_vec()
1572    }
1573
1574    fn sign(&mut self, sk: &BlsSecretKey, pk: &BlsPublicKey) {
1575        let msg = self.signable();
1576        let signature = sk.sign_multisig(pk, &msg).to_bytes();
1577        self.candidate.set_signature(signature.into());
1578    }
1579}
1580
1581impl StepMessage for ValidationQuorum {
1582    const STEP_NAME: StepName = StepName::Validation;
1583
1584    fn header(&self) -> ConsensusHeader {
1585        self.header
1586    }
1587}
1588
1589#[derive(Clone, Default)]
1590#[cfg_attr(any(feature = "faker", test), derive(fake::Dummy, Eq, PartialEq))]
1591pub struct SignInfo {
1592    pub signer: bls::PublicKey,
1593    pub signature: Signature,
1594}
1595
1596impl Serializable for SignInfo {
1597    fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
1598        w.write_all(self.signer.bytes().inner())?;
1599        w.write_all(self.signature.inner())?;
1600
1601        Ok(())
1602    }
1603
1604    fn read<R: Read>(r: &mut R) -> io::Result<Self>
1605    where
1606        Self: Sized,
1607    {
1608        // Read bls pubkey
1609        let signer = Self::read_bytes(r)?;
1610        let signer = signer
1611            .try_into()
1612            .map_err(|_| io::Error::from(io::ErrorKind::InvalidData))?;
1613
1614        let signature = Self::read_bytes(r)?.into();
1615
1616        Ok(Self { signer, signature })
1617    }
1618}
1619
1620impl std::fmt::Debug for SignInfo {
1621    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1622        f.debug_struct("SignInfo")
1623            .field("signer", &to_str(self.signature.inner()))
1624            .field("signature", &self.signature)
1625            .finish()
1626    }
1627}
1628
1629#[cfg(test)]
1630#[allow(unused)]
1631mod tests {
1632    use self::payload::ValidationResult;
1633    use super::*;
1634    use crate::ledger::*;
1635    use crate::{ledger, Serializable};
1636
1637    #[test]
1638    fn test_serialize() {
1639        let consensus_header = ConsensusHeader {
1640            iteration: 1,
1641            prev_block_hash: [2; 32],
1642            round: 4,
1643        };
1644        assert_serialize(consensus_header.clone());
1645
1646        let header = ledger::Header {
1647            version: 3,
1648            height: 1888881,
1649            timestamp: 123456789,
1650            gas_limit: 111111111,
1651            prev_block_hash: [1; 32],
1652            seed: ledger::Seed::from([2; 48]),
1653            generator_bls_pubkey: bls::PublicKeyBytes([5; 96]),
1654            state_hash: [4; 32],
1655            event_bloom: [5; 256],
1656            hash: [6; 32],
1657            txroot: [7; 32],
1658            faultroot: [8; 32],
1659            att: Attestation {
1660                validation: ledger::StepVotes::new([6; 48], 22222222),
1661                ratification: ledger::StepVotes::new([7; 48], 3333333),
1662                ..Default::default()
1663            },
1664            iteration: 1,
1665            prev_block_cert: Attestation {
1666                validation: ledger::StepVotes::new([6; 48], 444444444),
1667                ratification: ledger::StepVotes::new([7; 48], 55555555),
1668                ..Default::default()
1669            },
1670            failed_iterations: Default::default(),
1671            signature: Signature::from([9; 48]),
1672        };
1673
1674        let sample_block = ledger::Block::new(header, vec![], vec![])
1675            .expect("should be valid block");
1676
1677        let sign_info = SignInfo {
1678            signer: bls::PublicKey::from_sk_seed_u64(3),
1679            signature: [5; 48].into(),
1680        };
1681
1682        assert_serialize(payload::Candidate {
1683            candidate: sample_block,
1684        });
1685
1686        assert_serialize(ledger::StepVotes::new([4; 48], 12345));
1687
1688        assert_serialize(payload::Validation {
1689            header: consensus_header.clone(),
1690            vote: payload::Vote::Valid([4; 32]),
1691            sign_info: sign_info.clone(),
1692        });
1693
1694        let validation_result = ValidationResult::new(
1695            ledger::StepVotes::new([1; 48], 12345),
1696            payload::Vote::Valid([5; 32]),
1697            payload::QuorumType::Valid,
1698        );
1699
1700        assert_serialize(payload::Ratification {
1701            header: consensus_header.clone(),
1702            vote: payload::Vote::Valid([4; 32]),
1703            sign_info: sign_info.clone(),
1704            validation_result,
1705            timestamp: 1_000_000,
1706        });
1707
1708        assert_serialize(payload::Quorum {
1709            header: consensus_header.clone(),
1710            att: Attestation {
1711                result: payload::Vote::Valid([4; 32]).into(),
1712                validation: ledger::StepVotes::new([1; 48], 12345),
1713                ratification: ledger::StepVotes::new([2; 48], 98765),
1714            },
1715        });
1716    }
1717
1718    fn assert_serialize<S: Serializable + PartialEq + core::fmt::Debug>(v: S) {
1719        let mut buf = vec![];
1720        assert!(v.write(&mut buf).is_ok());
1721        let dup = S::read(&mut &buf[..]).expect("deserialize is ok");
1722        assert_eq!(
1723            v,
1724            dup,
1725            "failed to (de)serialize {}",
1726            std::any::type_name::<S>()
1727        );
1728    }
1729}