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) sv: StepVotes,
729    }
730
731    impl ValidationResult {
732        pub fn new(sv: StepVotes, vote: Vote, quorum: QuorumType) -> Self {
733            Self { sv, vote, quorum }
734        }
735
736        pub fn quorum(&self) -> QuorumType {
737            self.quorum
738        }
739
740        pub fn sv(&self) -> &StepVotes {
741            &self.sv
742        }
743
744        pub fn vote(&self) -> &Vote {
745            &self.vote
746        }
747    }
748
749    #[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize)]
750    #[serde(untagged)]
751    #[cfg_attr(any(feature = "faker", test), derive(fake::Dummy))]
752    pub enum RatificationResult {
753        Fail(Vote),
754        Success(Vote),
755    }
756
757    impl Default for RatificationResult {
758        fn default() -> Self {
759            Self::Fail(Vote::NoQuorum)
760        }
761    }
762
763    impl From<Vote> for RatificationResult {
764        fn from(vote: Vote) -> Self {
765            match vote {
766                Vote::Valid(hash) => {
767                    RatificationResult::Success(Vote::Valid(hash))
768                }
769                fail => RatificationResult::Fail(fail),
770            }
771        }
772    }
773
774    impl RatificationResult {
775        pub fn vote(&self) -> &Vote {
776            match self {
777                Self::Success(v) => v,
778                Self::Fail(v) => v,
779            }
780        }
781
782        pub fn failed(&self) -> bool {
783            match self {
784                Self::Success(_) => false,
785                Self::Fail(_) => true,
786            }
787        }
788    }
789
790    #[derive(Debug, Clone, Eq, PartialEq)]
791    pub struct Quorum {
792        pub header: ConsensusHeader,
793        pub att: Attestation,
794    }
795
796    impl Serializable for Quorum {
797        fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
798            self.header.write(w)?;
799            self.att.write(w)?;
800
801            Ok(())
802        }
803
804        fn read<R: Read>(r: &mut R) -> io::Result<Self>
805        where
806            Self: Sized,
807        {
808            let header = ConsensusHeader::read(r)?;
809            let att = Attestation::read(r)?;
810
811            Ok(Quorum { header, att })
812        }
813    }
814
815    impl Quorum {
816        pub fn vote(&self) -> &Vote {
817            self.att.result.vote()
818        }
819    }
820
821    #[derive(Debug, Clone, Default)]
822    pub struct GetCandidate {
823        pub hash: [u8; 32],
824    }
825
826    impl Serializable for GetCandidate {
827        fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
828            w.write_all(&self.hash[..])?;
829
830            Ok(())
831        }
832
833        fn read<R: Read>(r: &mut R) -> io::Result<Self>
834        where
835            Self: Sized,
836        {
837            let hash = Self::read_bytes(r)?;
838
839            Ok(GetCandidate { hash })
840        }
841    }
842
843    #[derive(Debug, Clone, Default)]
844    pub struct GetCandidateResp {
845        pub candidate: Block,
846    }
847
848    impl Serializable for GetCandidateResp {
849        fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
850            self.candidate.write(w)
851        }
852
853        fn read<R: Read>(r: &mut R) -> io::Result<Self>
854        where
855            Self: Sized,
856        {
857            Ok(GetCandidateResp {
858                candidate: Block::read(r)?,
859            })
860        }
861    }
862    #[derive(Debug, Clone, Default)]
863    pub struct Nonce([u8; 8]);
864
865    impl Serializable for Nonce {
866        fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
867            w.write_all(&self.0)
868        }
869
870        fn read<R: Read>(r: &mut R) -> io::Result<Self>
871        where
872            Self: Sized,
873        {
874            let nonce = Self::read_bytes(r)?;
875            Ok(Self(nonce))
876        }
877    }
878
879    impl From<Nonce> for u64 {
880        fn from(value: Nonce) -> Self {
881            u64::from_le_bytes(value.0)
882        }
883    }
884
885    impl From<u64> for Nonce {
886        fn from(value: u64) -> Self {
887            Self(value.to_le_bytes())
888        }
889    }
890
891    impl From<IpAddr> for Nonce {
892        fn from(value: IpAddr) -> Self {
893            match value {
894                IpAddr::V4(v4) => v4.into(),
895                IpAddr::V6(v6) => v6.into(),
896            }
897        }
898    }
899
900    impl From<Ipv4Addr> for Nonce {
901        fn from(value: Ipv4Addr) -> Self {
902            let num = u32::from_le_bytes(value.octets());
903            (num as u64).into()
904        }
905    }
906
907    impl From<Ipv6Addr> for Nonce {
908        fn from(value: Ipv6Addr) -> Self {
909            let mut ret = [0u8; 8];
910            let value = value.octets();
911            let (a, b) = value.split_at(8);
912            a.iter()
913                .zip(b)
914                .map(|(a, b)| a.wrapping_add(*b))
915                .enumerate()
916                .for_each(|(idx, v)| ret[idx] = v);
917
918            Self(ret)
919        }
920    }
921
922    #[derive(Debug, Clone, Default)]
923    pub struct GetMempool {
924        pub(crate) nonce: Nonce,
925    }
926
927    impl GetMempool {
928        pub fn set_nonce<N: Into<Nonce>>(&mut self, nonce: N) {
929            self.nonce = nonce.into()
930        }
931    }
932
933    impl Serializable for GetMempool {
934        fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
935            self.nonce.write(w)?;
936            Ok(())
937        }
938
939        fn read<R: Read>(r: &mut R) -> io::Result<Self>
940        where
941            Self: Sized,
942        {
943            let nonce = Nonce::read(r)?;
944            Ok(GetMempool { nonce })
945        }
946    }
947
948    #[derive(Clone, Default, Debug, Copy)]
949    pub enum InvType {
950        /// A transaction fetched by tx_id
951        MempoolTx,
952        #[default]
953        /// A full block fetched by block hash
954        BlockFromHash,
955        /// A full block fetched by block height
956        BlockFromHeight,
957        /// A candidate block fetched by block hash, Att is None
958        CandidateFromHash,
959        /// A candidate block fetched by (prev_block_hash, iteration)
960        CandidateFromIteration,
961        /// A ValidationResult fetched by (prev_block_hash, round, iteration)
962        ValidationResult,
963    }
964
965    #[derive(Clone, Copy)]
966    pub enum InvParam {
967        Hash([u8; 32]),
968        Height(u64),
969        Iteration(ConsensusHeader),
970    }
971
972    impl Default for InvParam {
973        fn default() -> Self {
974            Self::Height(0)
975        }
976    }
977
978    impl fmt::Debug for InvParam {
979        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
980            match self {
981                InvParam::Hash(hash) => write!(f, "Hash: {}", to_str(hash)),
982                InvParam::Height(height) => write!(f, "Height: {}", height),
983                InvParam::Iteration(ch) => {
984                    write!(
985                        f,
986                        "PrevBlock: {}, Round: {}, Iteration: {}",
987                        to_str(&ch.prev_block_hash),
988                        ch.round,
989                        ch.iteration
990                    )
991                }
992            }
993        }
994    }
995
996    #[derive(Default, Debug, Clone, Copy)]
997    pub struct InvVect {
998        pub inv_type: InvType,
999        pub param: InvParam,
1000    }
1001
1002    #[derive(Default, Debug, Clone)]
1003    pub struct Inv {
1004        pub inv_list: Vec<InvVect>,
1005        pub max_entries: u16,
1006    }
1007
1008    impl Inv {
1009        pub fn new(max_entries: u16) -> Self {
1010            Self {
1011                inv_list: Default::default(),
1012                max_entries,
1013            }
1014        }
1015
1016        pub fn add_tx_id(&mut self, id: [u8; 32]) {
1017            self.inv_list.push(InvVect {
1018                inv_type: InvType::MempoolTx,
1019                param: InvParam::Hash(id),
1020            });
1021        }
1022
1023        pub fn add_block_from_hash(&mut self, hash: [u8; 32]) {
1024            self.inv_list.push(InvVect {
1025                inv_type: InvType::BlockFromHash,
1026                param: InvParam::Hash(hash),
1027            });
1028        }
1029
1030        pub fn add_block_from_height(&mut self, height: u64) {
1031            self.inv_list.push(InvVect {
1032                inv_type: InvType::BlockFromHeight,
1033                param: InvParam::Height(height),
1034            });
1035        }
1036
1037        pub fn add_candidate_from_hash(&mut self, hash: [u8; 32]) {
1038            self.inv_list.push(InvVect {
1039                inv_type: InvType::CandidateFromHash,
1040                param: InvParam::Hash(hash),
1041            });
1042        }
1043
1044        pub fn add_candidate_from_iteration(
1045            &mut self,
1046            consensus_header: ConsensusHeader,
1047        ) {
1048            self.inv_list.push(InvVect {
1049                inv_type: InvType::CandidateFromIteration,
1050                param: InvParam::Iteration(consensus_header),
1051            });
1052        }
1053
1054        pub fn add_validation_result(
1055            &mut self,
1056            consensus_header: ConsensusHeader,
1057        ) {
1058            self.inv_list.push(InvVect {
1059                inv_type: InvType::ValidationResult,
1060                param: InvParam::Iteration(consensus_header),
1061            });
1062        }
1063    }
1064
1065    impl Serializable for Inv {
1066        fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
1067            let items_len = self.inv_list.len() as u32;
1068            w.write_all(&items_len.to_le_bytes())?;
1069
1070            for item in &self.inv_list {
1071                w.write_all(&[item.inv_type as u8])?;
1072
1073                match &item.param {
1074                    InvParam::Hash(hash) => w.write_all(&hash[..])?,
1075                    InvParam::Height(height) => {
1076                        w.write_all(&height.to_le_bytes())?
1077                    }
1078                    InvParam::Iteration(ch) => {
1079                        ch.write(w)?;
1080                    }
1081                };
1082            }
1083
1084            w.write_all(&self.max_entries.to_le_bytes())?;
1085            Ok(())
1086        }
1087
1088        fn read<R: Read>(r: &mut R) -> io::Result<Self>
1089        where
1090            Self: Sized,
1091        {
1092            let items_len = Self::read_u32_le(r)?;
1093
1094            let mut inv = Inv::default();
1095            for _ in 0..items_len {
1096                let inv_type = Self::read_u8(r)?;
1097
1098                let inv_type = match inv_type {
1099                    0 => InvType::MempoolTx,
1100                    1 => InvType::BlockFromHash,
1101                    2 => InvType::BlockFromHeight,
1102                    3 => InvType::CandidateFromHash,
1103                    4 => InvType::CandidateFromIteration,
1104                    5 => InvType::ValidationResult,
1105                    _ => {
1106                        return Err(io::Error::from(io::ErrorKind::InvalidData))
1107                    }
1108                };
1109
1110                match inv_type {
1111                    InvType::MempoolTx => {
1112                        let hash = Self::read_bytes(r)?;
1113                        inv.add_tx_id(hash);
1114                    }
1115                    InvType::BlockFromHash => {
1116                        let hash = Self::read_bytes(r)?;
1117                        inv.add_block_from_hash(hash);
1118                    }
1119                    InvType::BlockFromHeight => {
1120                        inv.add_block_from_height(Self::read_u64_le(r)?);
1121                    }
1122                    InvType::CandidateFromHash => {
1123                        inv.add_candidate_from_hash(Self::read_bytes(r)?);
1124                    }
1125                    InvType::CandidateFromIteration => {
1126                        let ch = ConsensusHeader::read(r)?;
1127                        inv.add_candidate_from_iteration(ch);
1128                    }
1129                    InvType::ValidationResult => {
1130                        let ch = ConsensusHeader::read(r)?;
1131                        inv.add_validation_result(ch);
1132                    }
1133                }
1134            }
1135
1136            inv.max_entries = Self::read_u16_le(r)?;
1137            Ok(inv)
1138        }
1139    }
1140
1141    #[derive(Clone)]
1142    pub struct GetBlocks {
1143        pub locator: [u8; 32],
1144        pub(crate) nonce: Nonce,
1145    }
1146
1147    impl GetBlocks {
1148        pub fn new(locator: [u8; 32]) -> Self {
1149            Self {
1150                locator,
1151                nonce: Nonce::default(),
1152            }
1153        }
1154        pub fn set_nonce<N: Into<Nonce>>(&mut self, nonce: N) {
1155            self.nonce = nonce.into()
1156        }
1157    }
1158
1159    impl fmt::Debug for GetBlocks {
1160        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1161            write!(f, "GetBlocks, locator: {}", to_str(&self.locator))
1162        }
1163    }
1164
1165    impl Serializable for GetBlocks {
1166        fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
1167            w.write_all(&self.locator[..])?;
1168            self.nonce.write(w)?;
1169            Ok(())
1170        }
1171
1172        fn read<R: Read>(r: &mut R) -> io::Result<Self>
1173        where
1174            Self: Sized,
1175        {
1176            let locator = Self::read_bytes(r)?;
1177            let nonce = Nonce::read(r)?;
1178            Ok(Self { locator, nonce })
1179        }
1180    }
1181
1182    #[derive(Debug, Clone)]
1183    pub struct GetResource {
1184        /// Inventory/Resource to search for
1185        inventory: Inv,
1186
1187        /// (requester) Address to which the resource is sent back, if found
1188        requester_addr: Option<SocketAddr>,
1189
1190        /// Limits request lifespan by absolute (epoch) time
1191        ttl_as_sec: u64,
1192
1193        /// Limits request lifespan by number of hops
1194        hops_limit: u16,
1195    }
1196
1197    impl GetResource {
1198        pub fn new(
1199            inventory: Inv,
1200            requester_addr: Option<SocketAddr>,
1201            ttl_as_sec: u64,
1202            hops_limit: u16,
1203        ) -> Self {
1204            Self {
1205                inventory,
1206                requester_addr,
1207                ttl_as_sec,
1208                hops_limit,
1209            }
1210        }
1211
1212        pub fn clone_with_hop_decrement(&self) -> Option<Self> {
1213            if self.hops_limit <= 1 {
1214                return None;
1215            }
1216            let mut req = self.clone();
1217            req.hops_limit -= 1;
1218            Some(req)
1219        }
1220
1221        pub fn get_addr(&self) -> Option<SocketAddr> {
1222            self.requester_addr
1223        }
1224
1225        pub fn get_inv(&self) -> &Inv {
1226            &self.inventory
1227        }
1228
1229        pub fn is_expired(&self) -> bool {
1230            get_current_timestamp() > self.ttl_as_sec
1231        }
1232    }
1233
1234    impl Serializable for GetResource {
1235        fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
1236            self.inventory.write(w)?;
1237
1238            let requester_addr = self.requester_addr.ok_or(io::Error::new(
1239                io::ErrorKind::InvalidData,
1240                "Requester address is missing",
1241            ))?;
1242
1243            requester_addr.write(w)?;
1244            w.write_all(&self.ttl_as_sec.to_le_bytes()[..])?;
1245            w.write_all(&self.hops_limit.to_le_bytes()[..])
1246        }
1247
1248        fn read<R: Read>(r: &mut R) -> io::Result<Self>
1249        where
1250            Self: Sized,
1251        {
1252            let inner = Inv::read(r)?;
1253            let requester_addr = SocketAddr::read(r)?;
1254
1255            let mut buf = [0u8; 8];
1256            r.read_exact(&mut buf)?;
1257            let ttl_as_sec = u64::from_le_bytes(buf);
1258
1259            let mut buf = [0u8; 2];
1260            r.read_exact(&mut buf)?;
1261            let hops_limit = u16::from_le_bytes(buf);
1262
1263            Ok(GetResource {
1264                inventory: inner,
1265                requester_addr: Some(requester_addr),
1266                ttl_as_sec,
1267                hops_limit,
1268            })
1269        }
1270    }
1271
1272    impl Serializable for SocketAddr {
1273        fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
1274            match self {
1275                SocketAddr::V4(addr_v4) => {
1276                    w.write_all(&[4])?;
1277                    w.write_all(&addr_v4.ip().octets())?;
1278                    w.write_all(&addr_v4.port().to_le_bytes())?;
1279                }
1280                SocketAddr::V6(addr_v6) => {
1281                    w.write_all(&[6])?;
1282                    w.write_all(&addr_v6.ip().octets())?;
1283                    w.write_all(&addr_v6.port().to_le_bytes())?;
1284                }
1285            }
1286            Ok(())
1287        }
1288
1289        fn read<R: Read>(r: &mut R) -> io::Result<Self>
1290        where
1291            Self: Sized,
1292        {
1293            let mut ip_type = [0u8; 1];
1294            r.read_exact(&mut ip_type)?;
1295
1296            let ip = match ip_type[0] {
1297                4 => {
1298                    let mut octets = [0u8; 4];
1299                    r.read_exact(&mut octets)?;
1300
1301                    let mut port_bytes = [0u8; 2];
1302                    r.read_exact(&mut port_bytes)?;
1303
1304                    SocketAddr::V4(SocketAddrV4::new(
1305                        Ipv4Addr::from(octets),
1306                        u16::from_le_bytes(port_bytes),
1307                    ))
1308                }
1309                6 => {
1310                    let mut octets = [0u8; 16];
1311                    r.read_exact(&mut octets)?;
1312
1313                    let mut port_bytes = [0u8; 2];
1314                    r.read_exact(&mut port_bytes)?;
1315
1316                    SocketAddr::V6(SocketAddrV6::new(
1317                        Ipv6Addr::from(octets),
1318                        u16::from_le_bytes(port_bytes),
1319                        0,
1320                        0,
1321                    ))
1322                }
1323                _ => {
1324                    return Err(io::Error::new(
1325                        io::ErrorKind::InvalidData,
1326                        "Invalid IP type",
1327                    ))
1328                }
1329            };
1330            Ok(ip)
1331        }
1332    }
1333}
1334
1335macro_rules! map_topic {
1336    ($v:expr, $enum_v:expr) => {
1337        if $v == $enum_v as u8 {
1338            return $enum_v;
1339        }
1340    };
1341}
1342
1343#[derive(Debug, Clone, PartialEq, Eq, Copy, Default)]
1344#[cfg_attr(any(feature = "faker", test), derive(fake::Dummy))]
1345pub enum Topics {
1346    // Data exchange topics.
1347    GetResource = 8,
1348    GetBlocks = 9,
1349    GetMempool = 13, // NB: This is aliased as Mempool in the golang impl
1350    Inv = 14,
1351
1352    // Fire-and-forget messaging
1353    Tx = 10,
1354    Block = 11,
1355
1356    // Consensus main loop topics
1357    Candidate = 16,
1358    Validation = 17,
1359    Ratification = 18,
1360    Quorum = 19,
1361    ValidationQuorum = 20,
1362
1363    #[default]
1364    Unknown = 255,
1365}
1366
1367impl Topics {
1368    pub fn is_consensus_msg(&self) -> bool {
1369        matches!(
1370            &self,
1371            Topics::Candidate
1372                | Topics::Validation
1373                | Topics::Ratification
1374                | Topics::Quorum
1375                | Topics::ValidationQuorum
1376        )
1377    }
1378}
1379
1380impl From<u8> for Topics {
1381    fn from(v: u8) -> Self {
1382        map_topic!(v, Topics::GetResource);
1383        map_topic!(v, Topics::GetBlocks);
1384        map_topic!(v, Topics::Tx);
1385        map_topic!(v, Topics::Block);
1386        map_topic!(v, Topics::GetMempool);
1387        map_topic!(v, Topics::Inv);
1388        map_topic!(v, Topics::Candidate);
1389        map_topic!(v, Topics::Validation);
1390        map_topic!(v, Topics::Ratification);
1391        map_topic!(v, Topics::Quorum);
1392        map_topic!(v, Topics::ValidationQuorum);
1393
1394        Topics::Unknown
1395    }
1396}
1397
1398impl From<Topics> for u8 {
1399    fn from(t: Topics) -> Self {
1400        t as u8
1401    }
1402}
1403
1404/// AsyncQueue is a thin wrapper of async_channel.
1405#[derive(Clone)]
1406pub struct AsyncQueue<M: Clone> {
1407    receiver: async_channel::Receiver<M>,
1408    sender: async_channel::Sender<M>,
1409
1410    cap: usize,
1411    label: &'static str,
1412}
1413
1414impl<M: Clone> AsyncQueue<M> {
1415    /// Creates a bounded async queue with fixed capacity
1416    ///
1417    /// `Label` sets a queue label for logging
1418    ///
1419    /// Panics if `cap` is zero (Capacity must be a positive number).
1420    pub fn bounded(cap: usize, label: &'static str) -> Self {
1421        let (sender, receiver) = async_channel::bounded(cap);
1422        Self {
1423            receiver,
1424            sender,
1425            cap,
1426            label,
1427        }
1428    }
1429}
1430
1431impl<M: Clone> AsyncQueue<M> {
1432    pub fn try_send(&self, msg: M) {
1433        let label = self.label;
1434        let _ = self.sender.try_send(msg).map_err(|err| match err {
1435            TrySendError::Full(_) => {
1436                error!("queue ({label}) is full, cap: {}", self.cap);
1437            }
1438            TrySendError::Closed(_) => {
1439                error!("queue ({label}) is closed");
1440            }
1441        });
1442    }
1443
1444    pub fn recv(&self) -> async_channel::Recv<'_, M> {
1445        self.receiver.recv()
1446    }
1447}
1448
1449pub trait StepMessage {
1450    const STEP_NAME: StepName;
1451    fn header(&self) -> ConsensusHeader;
1452
1453    fn get_step(&self) -> u8 {
1454        Self::STEP_NAME.to_step(self.header().iteration)
1455    }
1456}
1457
1458pub trait SignedStepMessage: StepMessage {
1459    const SIGN_SEED: &'static [u8];
1460    fn signable(&self) -> Vec<u8>;
1461    fn sign_info(&self) -> SignInfo;
1462    fn sign_info_mut(&mut self) -> &mut SignInfo;
1463
1464    fn verify_signature(&self) -> Result<(), BlsSigError> {
1465        let signature = self.sign_info().signature;
1466        let sig = BlsMultisigSignature::from_bytes(signature.inner())?;
1467        let pk = BlsMultisigPublicKey::aggregate(&[*self
1468            .sign_info()
1469            .signer
1470            .inner()])?;
1471        let msg = self.signable();
1472        pk.verify(&sig, &msg)
1473    }
1474
1475    fn sign(&mut self, sk: &BlsSecretKey, pk: &BlsPublicKey) {
1476        let msg = self.signable();
1477        let sign_info = self.sign_info_mut();
1478        let signature = sk.sign_multisig(pk, &msg).to_bytes();
1479        sign_info.signature = signature.into();
1480        sign_info.signer = PublicKey::new(*pk)
1481    }
1482}
1483
1484impl StepMessage for Validation {
1485    const STEP_NAME: StepName = StepName::Validation;
1486
1487    fn header(&self) -> ConsensusHeader {
1488        self.header
1489    }
1490}
1491
1492impl SignedStepMessage for Validation {
1493    const SIGN_SEED: &'static [u8] = &[1u8];
1494
1495    fn sign_info(&self) -> SignInfo {
1496        self.sign_info.clone()
1497    }
1498    fn sign_info_mut(&mut self) -> &mut SignInfo {
1499        &mut self.sign_info
1500    }
1501    fn signable(&self) -> Vec<u8> {
1502        let mut signable = self.header.signable();
1503        signable.extend_from_slice(Self::SIGN_SEED);
1504        self.vote
1505            .write(&mut signable)
1506            .expect("Writing to vec should succeed");
1507        signable
1508    }
1509}
1510
1511impl StepMessage for Ratification {
1512    const STEP_NAME: StepName = StepName::Ratification;
1513
1514    fn header(&self) -> ConsensusHeader {
1515        self.header
1516    }
1517}
1518
1519impl SignedStepMessage for Ratification {
1520    const SIGN_SEED: &'static [u8] = &[2u8];
1521    fn sign_info(&self) -> SignInfo {
1522        self.sign_info.clone()
1523    }
1524    fn sign_info_mut(&mut self) -> &mut SignInfo {
1525        &mut self.sign_info
1526    }
1527    fn signable(&self) -> Vec<u8> {
1528        let mut signable = self.header.signable();
1529        signable.extend_from_slice(Self::SIGN_SEED);
1530        self.vote
1531            .write(&mut signable)
1532            .expect("Writing to vec should succeed");
1533        signable
1534    }
1535}
1536
1537impl StepMessage for Candidate {
1538    const STEP_NAME: StepName = StepName::Proposal;
1539
1540    fn header(&self) -> ConsensusHeader {
1541        ConsensusHeader {
1542            iteration: self.candidate.header().iteration,
1543            prev_block_hash: self.candidate.header().prev_block_hash,
1544            round: self.candidate.header().height,
1545        }
1546    }
1547}
1548
1549impl SignedStepMessage for Candidate {
1550    const SIGN_SEED: &'static [u8] = &[];
1551    fn sign_info(&self) -> SignInfo {
1552        let header = self.candidate.header();
1553        SignInfo {
1554            signer: PublicKey::try_from(header.generator_bls_pubkey.0)
1555                .unwrap_or_default(),
1556            signature: header.signature,
1557        }
1558    }
1559    fn sign_info_mut(&mut self) -> &mut SignInfo {
1560        panic!("sign_info_mut called on Candidate, this is a bug")
1561    }
1562    fn signable(&self) -> Vec<u8> {
1563        self.candidate.header().hash.to_vec()
1564    }
1565
1566    fn sign(&mut self, sk: &BlsSecretKey, pk: &BlsPublicKey) {
1567        let msg = self.signable();
1568        let signature = sk.sign_multisig(pk, &msg).to_bytes();
1569        self.candidate.set_signature(signature.into());
1570    }
1571}
1572
1573impl StepMessage for ValidationQuorum {
1574    const STEP_NAME: StepName = StepName::Validation;
1575
1576    fn header(&self) -> ConsensusHeader {
1577        self.header
1578    }
1579}
1580
1581#[derive(Clone, Default)]
1582#[cfg_attr(any(feature = "faker", test), derive(fake::Dummy, Eq, PartialEq))]
1583pub struct SignInfo {
1584    pub signer: bls::PublicKey,
1585    pub signature: Signature,
1586}
1587
1588impl Serializable for SignInfo {
1589    fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
1590        w.write_all(self.signer.bytes().inner())?;
1591        w.write_all(self.signature.inner())?;
1592
1593        Ok(())
1594    }
1595
1596    fn read<R: Read>(r: &mut R) -> io::Result<Self>
1597    where
1598        Self: Sized,
1599    {
1600        // Read bls pubkey
1601        let signer = Self::read_bytes(r)?;
1602        let signer = signer
1603            .try_into()
1604            .map_err(|_| io::Error::from(io::ErrorKind::InvalidData))?;
1605
1606        let signature = Self::read_bytes(r)?.into();
1607
1608        Ok(Self { signer, signature })
1609    }
1610}
1611
1612impl std::fmt::Debug for SignInfo {
1613    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1614        f.debug_struct("SignInfo")
1615            .field("signer", &to_str(self.signature.inner()))
1616            .field("signature", &self.signature)
1617            .finish()
1618    }
1619}
1620
1621#[cfg(test)]
1622#[allow(unused)]
1623mod tests {
1624    use self::payload::ValidationResult;
1625    use super::*;
1626    use crate::ledger::*;
1627    use crate::{ledger, Serializable};
1628
1629    #[test]
1630    fn test_serialize() {
1631        let consensus_header = ConsensusHeader {
1632            iteration: 1,
1633            prev_block_hash: [2; 32],
1634            round: 4,
1635        };
1636        assert_serialize(consensus_header.clone());
1637
1638        let header = ledger::Header {
1639            version: 3,
1640            height: 1888881,
1641            timestamp: 123456789,
1642            gas_limit: 111111111,
1643            prev_block_hash: [1; 32],
1644            seed: ledger::Seed::from([2; 48]),
1645            generator_bls_pubkey: bls::PublicKeyBytes([5; 96]),
1646            state_hash: [4; 32],
1647            event_bloom: [5; 256],
1648            hash: [6; 32],
1649            txroot: [7; 32],
1650            faultroot: [8; 32],
1651            att: Attestation {
1652                validation: ledger::StepVotes::new([6; 48], 22222222),
1653                ratification: ledger::StepVotes::new([7; 48], 3333333),
1654                ..Default::default()
1655            },
1656            iteration: 1,
1657            prev_block_cert: Attestation {
1658                validation: ledger::StepVotes::new([6; 48], 444444444),
1659                ratification: ledger::StepVotes::new([7; 48], 55555555),
1660                ..Default::default()
1661            },
1662            failed_iterations: Default::default(),
1663            signature: Signature::from([9; 48]),
1664        };
1665
1666        let sample_block = ledger::Block::new(header, vec![], vec![])
1667            .expect("should be valid block");
1668
1669        let sign_info = SignInfo {
1670            signer: bls::PublicKey::from_sk_seed_u64(3),
1671            signature: [5; 48].into(),
1672        };
1673
1674        assert_serialize(payload::Candidate {
1675            candidate: sample_block,
1676        });
1677
1678        assert_serialize(ledger::StepVotes::new([4; 48], 12345));
1679
1680        assert_serialize(payload::Validation {
1681            header: consensus_header.clone(),
1682            vote: payload::Vote::Valid([4; 32]),
1683            sign_info: sign_info.clone(),
1684        });
1685
1686        let validation_result = ValidationResult::new(
1687            ledger::StepVotes::new([1; 48], 12345),
1688            payload::Vote::Valid([5; 32]),
1689            payload::QuorumType::Valid,
1690        );
1691
1692        assert_serialize(payload::Ratification {
1693            header: consensus_header.clone(),
1694            vote: payload::Vote::Valid([4; 32]),
1695            sign_info: sign_info.clone(),
1696            validation_result,
1697            timestamp: 1_000_000,
1698        });
1699
1700        assert_serialize(payload::Quorum {
1701            header: consensus_header.clone(),
1702            att: Attestation {
1703                result: payload::Vote::Valid([4; 32]).into(),
1704                validation: ledger::StepVotes::new([1; 48], 12345),
1705                ratification: ledger::StepVotes::new([2; 48], 98765),
1706            },
1707        });
1708    }
1709
1710    fn assert_serialize<S: Serializable + PartialEq + core::fmt::Debug>(v: S) {
1711        let mut buf = vec![];
1712        assert!(v.write(&mut buf).is_ok());
1713        let dup = S::read(&mut &buf[..]).expect("deserialize is ok");
1714        assert_eq!(
1715            v,
1716            dup,
1717            "failed to (de)serialize {}",
1718            std::any::type_name::<S>()
1719        );
1720    }
1721}