hotshot_types/
simple_vote.rs

1// Copyright (c) 2021-2024 Espresso Systems (espressosys.com)
2// This file is part of the HotShot repository.
3
4// You should have received a copy of the MIT License
5// along with the HotShot repository. If not, see <https://mit-license.org/>.
6
7//! Implementations of the simple vote types.
8
9use std::{
10    fmt::Debug,
11    hash::Hash,
12    marker::PhantomData,
13    ops::{Deref, DerefMut},
14};
15
16use committable::{Commitment, Committable};
17use hotshot_utils::anytrace::*;
18use serde::{de::DeserializeOwned, Deserialize, Serialize};
19use vbs::version::Version;
20
21use crate::{
22    data::{Leaf, Leaf2, VidCommitment},
23    light_client::{LightClientState, StakeTableState},
24    message::UpgradeLock,
25    traits::{
26        node_implementation::{ConsensusTime, NodeType, Versions},
27        signature_key::{SignatureKey, StateSignatureKey},
28    },
29    vote::{HasViewNumber, Vote},
30};
31
32/// Marker that data should use the quorum cert type
33pub(crate) trait QuorumMarker {}
34
35#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Hash, Eq)]
36/// Data used for a yes vote.
37#[serde(bound(deserialize = ""))]
38pub struct QuorumData<TYPES: NodeType> {
39    /// Commitment to the leaf
40    pub leaf_commit: Commitment<Leaf<TYPES>>,
41}
42#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Hash, Eq)]
43/// Data used for a yes vote.
44#[serde(bound(deserialize = ""))]
45pub struct QuorumData2<TYPES: NodeType> {
46    /// Commitment to the leaf
47    pub leaf_commit: Commitment<Leaf2<TYPES>>,
48    /// An epoch to which the data belongs to. Relevant for validating against the correct stake table
49    pub epoch: Option<TYPES::Epoch>,
50    /// Block number of the leaf. It's optional to be compatible with pre-epoch version.
51    pub block_number: Option<u64>,
52}
53/// Data used for a yes vote. Used to distinguish votes sent by the next epoch nodes.
54#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Hash, Eq)]
55#[serde(bound(deserialize = ""))]
56pub struct NextEpochQuorumData2<TYPES: NodeType>(QuorumData2<TYPES>);
57#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Hash, Eq)]
58/// Data used for a DA vote.
59pub struct DaData {
60    /// Commitment to a block payload
61    pub payload_commit: VidCommitment,
62}
63#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Hash, Eq)]
64/// Data used for a DA vote.
65pub struct DaData2<TYPES: NodeType> {
66    /// Commitment to a block payload
67    pub payload_commit: VidCommitment,
68    /// An optional commitment to a block payload calculated for the next epoch (epoch + 1)
69    pub next_epoch_payload_commit: Option<VidCommitment>,
70    /// Epoch number
71    pub epoch: Option<TYPES::Epoch>,
72}
73#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Hash, Eq)]
74/// Data used for a timeout vote.
75pub struct TimeoutData<TYPES: NodeType> {
76    /// View the timeout is for
77    pub view: TYPES::View,
78}
79#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Hash, Eq)]
80/// Data used for a timeout vote.
81pub struct TimeoutData2<TYPES: NodeType> {
82    /// View the timeout is for
83    pub view: TYPES::View,
84    /// Epoch number
85    pub epoch: Option<TYPES::Epoch>,
86}
87#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Hash, Eq)]
88/// Data used for a Pre Commit vote.
89pub struct ViewSyncPreCommitData<TYPES: NodeType> {
90    /// The relay this vote is intended for
91    pub relay: u64,
92    /// The view number we are trying to sync on
93    pub round: TYPES::View,
94}
95#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Hash, Eq)]
96/// Data used for a Pre Commit vote.
97pub struct ViewSyncPreCommitData2<TYPES: NodeType> {
98    /// The relay this vote is intended for
99    pub relay: u64,
100    /// The view number we are trying to sync on
101    pub round: TYPES::View,
102    /// Epoch number
103    pub epoch: Option<TYPES::Epoch>,
104}
105#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Hash, Eq)]
106/// Data used for a Commit vote.
107pub struct ViewSyncCommitData<TYPES: NodeType> {
108    /// The relay this vote is intended for
109    pub relay: u64,
110    /// The view number we are trying to sync on
111    pub round: TYPES::View,
112}
113#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Hash, Eq)]
114/// Data used for a Commit vote.
115pub struct ViewSyncCommitData2<TYPES: NodeType> {
116    /// The relay this vote is intended for
117    pub relay: u64,
118    /// The view number we are trying to sync on
119    pub round: TYPES::View,
120    /// Epoch number
121    pub epoch: Option<TYPES::Epoch>,
122}
123#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Hash, Eq)]
124/// Data used for a Finalize vote.
125pub struct ViewSyncFinalizeData<TYPES: NodeType> {
126    /// The relay this vote is intended for
127    pub relay: u64,
128    /// The view number we are trying to sync on
129    pub round: TYPES::View,
130}
131#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Hash, Eq)]
132/// Data used for a Finalize vote.
133pub struct ViewSyncFinalizeData2<TYPES: NodeType> {
134    /// The relay this vote is intended for
135    pub relay: u64,
136    /// The view number we are trying to sync on
137    pub round: TYPES::View,
138    /// Epoch number
139    pub epoch: Option<TYPES::Epoch>,
140}
141#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Hash, Eq)]
142/// Data used for a Upgrade vote.
143pub struct UpgradeProposalData<TYPES: NodeType + DeserializeOwned> {
144    /// The old version that we are upgrading from.
145    pub old_version: Version,
146    /// The new version that we are upgrading to.
147    pub new_version: Version,
148    /// The last view in which we are allowed to reach a decide on this upgrade.
149    /// If it is not decided by that view, we discard it.
150    pub decide_by: TYPES::View,
151    /// A unique identifier for the specific protocol being voted on.
152    pub new_version_hash: Vec<u8>,
153    /// The last block for which the old version will be in effect.
154    pub old_version_last_view: TYPES::View,
155    /// The first block for which the new version will be in effect.
156    pub new_version_first_view: TYPES::View,
157}
158
159/// Data used for an upgrade once epochs are implemented
160pub struct UpgradeData2<TYPES: NodeType> {
161    /// The old version that we are upgrading from
162    pub old_version: Version,
163    /// The new version that we are upgrading to
164    pub new_version: Version,
165    /// A unique identifier for the specific protocol being voted on
166    pub hash: Vec<u8>,
167    /// The first epoch in which the upgrade will be in effect
168    pub epoch: Option<TYPES::Epoch>,
169}
170
171/// Marker trait for data or commitments that can be voted on.
172/// Only structs in this file can implement voteable.  This is enforced with the `Sealed` trait
173/// Sealing this trait prevents creating new vote types outside this file.
174pub trait Voteable<TYPES: NodeType>:
175    sealed::Sealed + Committable + Clone + Serialize + Debug + PartialEq + Hash + Eq
176{
177}
178
179/// Marker trait for data or commitments that can be voted on.
180/// Only structs in this file can implement voteable.  This is enforced with the `Sealed` trait
181/// Sealing this trait prevents creating new vote types outside this file.
182pub trait Voteable2<TYPES: NodeType>:
183    sealed::Sealed + HasEpoch<TYPES> + Committable + Clone + Serialize + Debug + PartialEq + Hash + Eq
184{
185}
186
187/// Sealed is used to make sure no other files can implement the Voteable trait.
188/// All simple voteable types should be implemented here.  This prevents us from
189/// creating/using improper types when using the vote types.
190mod sealed {
191    use committable::Committable;
192
193    /// Only structs in this file can impl `Sealed`
194    pub trait Sealed {}
195
196    // TODO: Does the implement for things outside this file that are committable?
197    impl<C: Committable> Sealed for C {}
198}
199
200impl<T: NodeType> QuorumMarker for QuorumData<T> {}
201impl<T: NodeType> QuorumMarker for QuorumData2<T> {}
202impl<T: NodeType> QuorumMarker for NextEpochQuorumData2<T> {}
203impl<T: NodeType> QuorumMarker for TimeoutData<T> {}
204impl<T: NodeType> QuorumMarker for TimeoutData2<T> {}
205impl<T: NodeType> QuorumMarker for ViewSyncPreCommitData<T> {}
206impl<T: NodeType> QuorumMarker for ViewSyncCommitData<T> {}
207impl<T: NodeType> QuorumMarker for ViewSyncFinalizeData<T> {}
208impl<T: NodeType> QuorumMarker for ViewSyncPreCommitData2<T> {}
209impl<T: NodeType> QuorumMarker for ViewSyncCommitData2<T> {}
210impl<T: NodeType> QuorumMarker for ViewSyncFinalizeData2<T> {}
211impl<T: NodeType + DeserializeOwned> QuorumMarker for UpgradeProposalData<T> {}
212
213/// A simple yes vote over some votable type.
214#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Hash, Eq)]
215pub struct SimpleVote<TYPES: NodeType, DATA: Voteable<TYPES>> {
216    /// The signature share associated with this vote
217    pub signature: (
218        TYPES::SignatureKey,
219        <TYPES::SignatureKey as SignatureKey>::PureAssembledSignatureType,
220    ),
221    /// The leaf commitment being voted on.
222    pub data: DATA,
223    /// The view this vote was cast for
224    pub view_number: TYPES::View,
225}
226
227impl<TYPES: NodeType, DATA: Voteable<TYPES> + 'static> HasViewNumber<TYPES>
228    for SimpleVote<TYPES, DATA>
229{
230    fn view_number(&self) -> <TYPES as NodeType>::View {
231        self.view_number
232    }
233}
234
235impl<TYPES: NodeType, DATA: Voteable<TYPES> + 'static> Vote<TYPES> for SimpleVote<TYPES, DATA> {
236    type Commitment = DATA;
237
238    fn signing_key(&self) -> <TYPES as NodeType>::SignatureKey {
239        self.signature.0.clone()
240    }
241
242    fn signature(&self) -> <TYPES::SignatureKey as SignatureKey>::PureAssembledSignatureType {
243        self.signature.1.clone()
244    }
245
246    fn date(&self) -> &DATA {
247        &self.data
248    }
249
250    fn data_commitment(&self) -> Commitment<DATA> {
251        self.data.commit()
252    }
253}
254
255impl<TYPES: NodeType, DATA: Voteable<TYPES> + 'static> SimpleVote<TYPES, DATA> {
256    /// Creates and signs a simple vote
257    /// # Errors
258    /// If we are unable to sign the data
259    pub async fn create_signed_vote<V: Versions>(
260        data: DATA,
261        view: TYPES::View,
262        pub_key: &TYPES::SignatureKey,
263        private_key: &<TYPES::SignatureKey as SignatureKey>::PrivateKey,
264        upgrade_lock: &UpgradeLock<TYPES, V>,
265    ) -> Result<Self> {
266        let commit = VersionedVoteData::new(data.clone(), view, upgrade_lock)
267            .await?
268            .commit();
269
270        let signature = (
271            pub_key.clone(),
272            TYPES::SignatureKey::sign(private_key, commit.as_ref())
273                .wrap()
274                .context(error!("Failed to sign vote"))?,
275        );
276
277        Ok(Self {
278            signature,
279            data,
280            view_number: view,
281        })
282    }
283}
284
285#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Hash, Eq)]
286/// A wrapper for vote data that carries a view number and an `upgrade_lock`, allowing switching the commitment calculation dynamically depending on the version
287pub struct VersionedVoteData<TYPES: NodeType, DATA: Voteable<TYPES>, V: Versions> {
288    /// underlying vote data
289    data: DATA,
290
291    /// view number
292    view: TYPES::View,
293
294    /// version applied to the view number
295    version: Version,
296
297    /// phantom data
298    _pd: PhantomData<V>,
299}
300
301impl<TYPES: NodeType, DATA: Voteable<TYPES>, V: Versions> VersionedVoteData<TYPES, DATA, V> {
302    /// Create a new `VersionedVoteData` struct
303    ///
304    /// # Errors
305    ///
306    /// Returns an error if `upgrade_lock.version(view)` is unable to return a version we support
307    pub async fn new(
308        data: DATA,
309        view: TYPES::View,
310        upgrade_lock: &UpgradeLock<TYPES, V>,
311    ) -> Result<Self> {
312        let version = upgrade_lock.version(view).await?;
313
314        Ok(Self {
315            data,
316            view,
317            version,
318            _pd: PhantomData,
319        })
320    }
321
322    /// Create a new `VersionedVoteData` struct
323    ///
324    /// This function cannot error, but may use an invalid version.
325    pub async fn new_infallible(
326        data: DATA,
327        view: TYPES::View,
328        upgrade_lock: &UpgradeLock<TYPES, V>,
329    ) -> Self {
330        let version = upgrade_lock.version_infallible(view).await;
331
332        Self {
333            data,
334            view,
335            version,
336            _pd: PhantomData,
337        }
338    }
339}
340
341impl<TYPES: NodeType, DATA: Voteable<TYPES>, V: Versions> Committable
342    for VersionedVoteData<TYPES, DATA, V>
343{
344    fn commit(&self) -> Commitment<Self> {
345        committable::RawCommitmentBuilder::new("Vote")
346            .var_size_bytes(self.data.commit().as_ref())
347            .u64(*self.view)
348            .finalize()
349    }
350}
351
352impl<TYPES: NodeType> Committable for QuorumData<TYPES> {
353    fn commit(&self) -> Commitment<Self> {
354        committable::RawCommitmentBuilder::new("Quorum data")
355            .var_size_bytes(self.leaf_commit.as_ref())
356            .finalize()
357    }
358}
359
360impl<TYPES: NodeType> Committable for QuorumData2<TYPES> {
361    fn commit(&self) -> Commitment<Self> {
362        let QuorumData2 {
363            leaf_commit,
364            epoch,
365            block_number,
366        } = self;
367
368        let mut cb = committable::RawCommitmentBuilder::new("Quorum data")
369            .var_size_bytes(leaf_commit.as_ref());
370
371        if let Some(ref epoch) = *epoch {
372            cb = cb.u64_field("epoch number", **epoch);
373        }
374
375        if let Some(ref block_number) = *block_number {
376            cb = cb.u64_field("block number", *block_number);
377        }
378
379        cb.finalize()
380    }
381}
382
383impl<TYPES: NodeType> Committable for NextEpochQuorumData2<TYPES> {
384    fn commit(&self) -> Commitment<Self> {
385        let NextEpochQuorumData2(QuorumData2 {
386            leaf_commit,
387            epoch,
388            block_number,
389        }) = self;
390
391        let mut cb = committable::RawCommitmentBuilder::new("Quorum data")
392            .var_size_bytes(leaf_commit.as_ref());
393
394        if let Some(ref epoch) = *epoch {
395            cb = cb.u64_field("epoch number", **epoch);
396        }
397
398        if let Some(ref block_number) = *block_number {
399            cb = cb.u64_field("block number", *block_number);
400        }
401
402        cb.finalize()
403    }
404}
405
406impl<TYPES: NodeType> Committable for TimeoutData<TYPES> {
407    fn commit(&self) -> Commitment<Self> {
408        committable::RawCommitmentBuilder::new("Timeout data")
409            .u64(*self.view)
410            .finalize()
411    }
412}
413
414impl<TYPES: NodeType> Committable for TimeoutData2<TYPES> {
415    fn commit(&self) -> Commitment<Self> {
416        let TimeoutData2 { view, epoch: _ } = self;
417
418        committable::RawCommitmentBuilder::new("Timeout data")
419            .u64(**view)
420            .finalize()
421    }
422}
423
424impl Committable for DaData {
425    fn commit(&self) -> Commitment<Self> {
426        committable::RawCommitmentBuilder::new("DA data")
427            .var_size_bytes(self.payload_commit.as_ref())
428            .finalize()
429    }
430}
431
432impl<TYPES: NodeType> Committable for DaData2<TYPES> {
433    fn commit(&self) -> Commitment<Self> {
434        let DaData2 {
435            payload_commit,
436            next_epoch_payload_commit,
437            epoch,
438        } = self;
439
440        let mut cb = committable::RawCommitmentBuilder::new("DA data")
441            .var_size_bytes(payload_commit.as_ref());
442
443        if let Some(ref next_epoch_payload_commit) = *next_epoch_payload_commit {
444            cb = cb.var_size_bytes(next_epoch_payload_commit.as_ref());
445        }
446
447        if let Some(ref epoch) = *epoch {
448            cb = cb.u64_field("epoch number", **epoch);
449        }
450
451        cb.finalize()
452    }
453}
454
455impl<TYPES: NodeType> Committable for UpgradeProposalData<TYPES> {
456    fn commit(&self) -> Commitment<Self> {
457        let builder = committable::RawCommitmentBuilder::new("Upgrade data");
458        builder
459            .u64(*self.decide_by)
460            .u64(*self.new_version_first_view)
461            .u64(*self.old_version_last_view)
462            .var_size_bytes(self.new_version_hash.as_slice())
463            .u16(self.new_version.minor)
464            .u16(self.new_version.major)
465            .u16(self.old_version.minor)
466            .u16(self.old_version.major)
467            .finalize()
468    }
469}
470
471impl<TYPES: NodeType> Committable for UpgradeData2<TYPES> {
472    fn commit(&self) -> Commitment<Self> {
473        let UpgradeData2 {
474            old_version,
475            new_version,
476            hash,
477            epoch,
478        } = self;
479
480        let mut cb = committable::RawCommitmentBuilder::new("Upgrade data")
481            .u16(old_version.minor)
482            .u16(old_version.major)
483            .u16(new_version.minor)
484            .u16(new_version.major)
485            .var_size_bytes(hash.as_slice());
486
487        if let Some(ref epoch) = *epoch {
488            cb = cb.u64_field("epoch number", **epoch);
489        }
490
491        cb.finalize()
492    }
493}
494
495/// This implements commit for all the types which contain a view and relay public key.
496fn view_and_relay_commit<TYPES: NodeType, T: Committable>(
497    view: TYPES::View,
498    relay: u64,
499    epoch: Option<TYPES::Epoch>,
500    tag: &str,
501) -> Commitment<T> {
502    let builder = committable::RawCommitmentBuilder::new(tag);
503    let mut cb = builder.u64(*view).u64(relay);
504
505    if let Some(epoch) = epoch {
506        cb = cb.u64_field("epoch number", *epoch);
507    }
508
509    cb.finalize()
510}
511
512impl<TYPES: NodeType> Committable for ViewSyncPreCommitData<TYPES> {
513    fn commit(&self) -> Commitment<Self> {
514        view_and_relay_commit::<TYPES, Self>(self.round, self.relay, None, "View Sync Precommit")
515    }
516}
517
518impl<TYPES: NodeType> Committable for ViewSyncPreCommitData2<TYPES> {
519    fn commit(&self) -> Commitment<Self> {
520        let ViewSyncPreCommitData2 {
521            relay,
522            round,
523            epoch,
524        } = self;
525
526        view_and_relay_commit::<TYPES, Self>(*round, *relay, *epoch, "View Sync Precommit")
527    }
528}
529
530impl<TYPES: NodeType> Committable for ViewSyncFinalizeData<TYPES> {
531    fn commit(&self) -> Commitment<Self> {
532        view_and_relay_commit::<TYPES, Self>(self.round, self.relay, None, "View Sync Finalize")
533    }
534}
535
536impl<TYPES: NodeType> Committable for ViewSyncFinalizeData2<TYPES> {
537    fn commit(&self) -> Commitment<Self> {
538        let ViewSyncFinalizeData2 {
539            relay,
540            round,
541            epoch,
542        } = self;
543
544        view_and_relay_commit::<TYPES, Self>(*round, *relay, *epoch, "View Sync Finalize")
545    }
546}
547
548impl<TYPES: NodeType> Committable for ViewSyncCommitData<TYPES> {
549    fn commit(&self) -> Commitment<Self> {
550        view_and_relay_commit::<TYPES, Self>(self.round, self.relay, None, "View Sync Commit")
551    }
552}
553
554impl<TYPES: NodeType> Committable for ViewSyncCommitData2<TYPES> {
555    fn commit(&self) -> Commitment<Self> {
556        let ViewSyncCommitData2 {
557            relay,
558            round,
559            epoch,
560        } = self;
561
562        view_and_relay_commit::<TYPES, Self>(*round, *relay, *epoch, "View Sync Commit")
563    }
564}
565
566/// A trait for types belonging for specific epoch
567pub trait HasEpoch<TYPES: NodeType> {
568    /// Returns `Epoch`
569    fn epoch(&self) -> Option<TYPES::Epoch>;
570}
571
572/// Helper macro for trivial implementation of the `HasEpoch` trait
573#[macro_export]
574macro_rules! impl_has_epoch {
575    ($($t:ty),*) => {
576        $(
577            impl<TYPES: NodeType> HasEpoch<TYPES> for $t {
578                fn epoch(&self) -> Option<TYPES::Epoch> {
579                    self.epoch
580                }
581            }
582        )*
583    };
584}
585
586impl_has_epoch!(
587    QuorumData2<TYPES>,
588    NextEpochQuorumData2<TYPES>,
589    DaData2<TYPES>,
590    TimeoutData2<TYPES>,
591    ViewSyncPreCommitData2<TYPES>,
592    ViewSyncCommitData2<TYPES>,
593    ViewSyncFinalizeData2<TYPES>,
594    UpgradeData2<TYPES>
595);
596
597/// Helper macro for trivial implementation of the `HasEpoch` trait for types that have no epoch
598#[macro_export]
599macro_rules! impl_has_none_epoch {
600    ($($t:ty),*) => {
601        $(
602            impl<TYPES: NodeType> HasEpoch<TYPES> for $t {
603                fn epoch(&self) -> Option<TYPES::Epoch> {
604                    None
605                }
606            }
607        )*
608    };
609}
610
611impl_has_none_epoch!(
612    QuorumData<TYPES>,
613    DaData,
614    TimeoutData<TYPES>,
615    ViewSyncPreCommitData<TYPES>,
616    ViewSyncCommitData<TYPES>,
617    ViewSyncFinalizeData<TYPES>,
618    UpgradeProposalData<TYPES>
619);
620
621impl<TYPES: NodeType, DATA: Voteable<TYPES> + HasEpoch<TYPES>> HasEpoch<TYPES>
622    for SimpleVote<TYPES, DATA>
623{
624    fn epoch(&self) -> Option<TYPES::Epoch> {
625        self.data.epoch()
626    }
627}
628
629// impl votable for all the data types in this file sealed marker should ensure nothing is accidentally
630// implemented for structs that aren't "voteable"
631impl<
632        TYPES: NodeType,
633        V: sealed::Sealed + Committable + Clone + Serialize + Debug + PartialEq + Hash + Eq,
634    > Voteable<TYPES> for V
635{
636}
637
638// impl votable for all the data types in this file sealed marker should ensure nothing is accidentally
639// implemented for structs that aren't "voteable"
640impl<
641        TYPES: NodeType,
642        V: sealed::Sealed
643            + HasEpoch<TYPES>
644            + Committable
645            + Clone
646            + Serialize
647            + Debug
648            + PartialEq
649            + Hash
650            + Eq,
651    > Voteable2<TYPES> for V
652{
653}
654
655impl<TYPES: NodeType> QuorumVote<TYPES> {
656    /// Convert a `QuorumVote` to a `QuorumVote2`
657    pub fn to_vote2(self) -> QuorumVote2<TYPES> {
658        let bytes: [u8; 32] = self.data.leaf_commit.into();
659
660        let signature = self.signature;
661        let data = QuorumData2 {
662            leaf_commit: Commitment::from_raw(bytes),
663            epoch: None,
664            block_number: None,
665        };
666        let view_number = self.view_number;
667
668        SimpleVote {
669            signature,
670            data,
671            view_number,
672        }
673    }
674}
675
676impl<TYPES: NodeType> QuorumVote2<TYPES> {
677    /// Convert a `QuorumVote2` to a `QuorumVote`
678    pub fn to_vote(self) -> QuorumVote<TYPES> {
679        let bytes: [u8; 32] = self.data.leaf_commit.into();
680
681        let signature = self.signature.clone();
682        let data = QuorumData {
683            leaf_commit: Commitment::from_raw(bytes),
684        };
685        let view_number = self.view_number;
686
687        SimpleVote {
688            signature,
689            data,
690            view_number,
691        }
692    }
693}
694
695impl<TYPES: NodeType> DaVote<TYPES> {
696    /// Convert a `QuorumVote` to a `QuorumVote2`
697    pub fn to_vote2(self) -> DaVote2<TYPES> {
698        let signature = self.signature;
699        let data = DaData2 {
700            payload_commit: self.data.payload_commit,
701            next_epoch_payload_commit: None,
702            epoch: None,
703        };
704        let view_number = self.view_number;
705
706        SimpleVote {
707            signature,
708            data,
709            view_number,
710        }
711    }
712}
713
714impl<TYPES: NodeType> DaVote2<TYPES> {
715    /// Convert a `QuorumVote2` to a `QuorumVote`
716    pub fn to_vote(self) -> DaVote<TYPES> {
717        let signature = self.signature;
718        let data = DaData {
719            payload_commit: self.data.payload_commit,
720        };
721        let view_number = self.view_number;
722
723        SimpleVote {
724            signature,
725            data,
726            view_number,
727        }
728    }
729}
730
731impl<TYPES: NodeType> TimeoutVote<TYPES> {
732    /// Convert a `TimeoutVote` to a `TimeoutVote2`
733    pub fn to_vote2(self) -> TimeoutVote2<TYPES> {
734        let signature = self.signature;
735        let data = TimeoutData2 {
736            view: self.data.view,
737            epoch: None,
738        };
739        let view_number = self.view_number;
740
741        SimpleVote {
742            signature,
743            data,
744            view_number,
745        }
746    }
747}
748
749impl<TYPES: NodeType> TimeoutVote2<TYPES> {
750    /// Convert a `QuorumVote2` to a `QuorumVote`
751    pub fn to_vote(self) -> TimeoutVote<TYPES> {
752        let signature = self.signature;
753        let data = TimeoutData {
754            view: self.data.view,
755        };
756        let view_number = self.view_number;
757
758        SimpleVote {
759            signature,
760            data,
761            view_number,
762        }
763    }
764}
765
766impl<TYPES: NodeType> ViewSyncPreCommitVote<TYPES> {
767    /// Convert a `ViewSyncPreCommitVote` to a `ViewSyncPreCommitVote2`
768    pub fn to_vote2(self) -> ViewSyncPreCommitVote2<TYPES> {
769        let signature = self.signature;
770        let data = ViewSyncPreCommitData2 {
771            relay: self.data.relay,
772            round: self.data.round,
773            epoch: None,
774        };
775        let view_number = self.view_number;
776
777        SimpleVote {
778            signature,
779            data,
780            view_number,
781        }
782    }
783}
784
785impl<TYPES: NodeType> ViewSyncPreCommitVote2<TYPES> {
786    /// Convert a `ViewSyncPreCommitVote2` to a `ViewSyncPreCommitVote`
787    pub fn to_vote(self) -> ViewSyncPreCommitVote<TYPES> {
788        let signature = self.signature;
789        let data = ViewSyncPreCommitData {
790            relay: self.data.relay,
791            round: self.data.round,
792        };
793        let view_number = self.view_number;
794
795        SimpleVote {
796            signature,
797            data,
798            view_number,
799        }
800    }
801}
802
803impl<TYPES: NodeType> ViewSyncCommitVote<TYPES> {
804    /// Convert a `ViewSyncCommitVote` to a `ViewSyncCommitVote2`
805    pub fn to_vote2(self) -> ViewSyncCommitVote2<TYPES> {
806        let signature = self.signature;
807        let data = ViewSyncCommitData2 {
808            relay: self.data.relay,
809            round: self.data.round,
810            epoch: None,
811        };
812        let view_number = self.view_number;
813
814        SimpleVote {
815            signature,
816            data,
817            view_number,
818        }
819    }
820}
821
822impl<TYPES: NodeType> ViewSyncCommitVote2<TYPES> {
823    /// Convert a `ViewSyncCommitVote2` to a `ViewSyncCommitVote`
824    pub fn to_vote(self) -> ViewSyncCommitVote<TYPES> {
825        let signature = self.signature;
826        let data = ViewSyncCommitData {
827            relay: self.data.relay,
828            round: self.data.round,
829        };
830        let view_number = self.view_number;
831
832        SimpleVote {
833            signature,
834            data,
835            view_number,
836        }
837    }
838}
839
840impl<TYPES: NodeType> ViewSyncFinalizeVote<TYPES> {
841    /// Convert a `ViewSyncFinalizeVote` to a `ViewSyncFinalizeVote2`
842    pub fn to_vote2(self) -> ViewSyncFinalizeVote2<TYPES> {
843        let signature = self.signature;
844        let data = ViewSyncFinalizeData2 {
845            relay: self.data.relay,
846            round: self.data.round,
847            epoch: None,
848        };
849        let view_number = self.view_number;
850
851        SimpleVote {
852            signature,
853            data,
854            view_number,
855        }
856    }
857}
858
859impl<TYPES: NodeType> ViewSyncFinalizeVote2<TYPES> {
860    /// Convert a `ViewSyncFinalizeVote2` to a `ViewSyncFinalizeVote`
861    pub fn to_vote(self) -> ViewSyncFinalizeVote<TYPES> {
862        let signature = self.signature;
863        let data = ViewSyncFinalizeData {
864            relay: self.data.relay,
865            round: self.data.round,
866        };
867        let view_number = self.view_number;
868
869        SimpleVote {
870            signature,
871            data,
872            view_number,
873        }
874    }
875}
876
877// Type aliases for simple use of all the main votes.  We should never see `SimpleVote` outside this file
878
879/// Quorum vote Alias
880pub type QuorumVote<TYPES> = SimpleVote<TYPES, QuorumData<TYPES>>;
881// Type aliases for simple use of all the main votes.  We should never see `SimpleVote` outside this file
882/// Quorum vote Alias
883pub type QuorumVote2<TYPES> = SimpleVote<TYPES, QuorumData2<TYPES>>;
884/// Quorum vote Alias. This type is useful to distinguish the next epoch nodes' votes.
885pub type NextEpochQuorumVote2<TYPES> = SimpleVote<TYPES, NextEpochQuorumData2<TYPES>>;
886/// DA vote type alias
887pub type DaVote<TYPES> = SimpleVote<TYPES, DaData>;
888/// DA vote 2 type alias
889pub type DaVote2<TYPES> = SimpleVote<TYPES, DaData2<TYPES>>;
890
891/// Timeout Vote type alias
892pub type TimeoutVote<TYPES> = SimpleVote<TYPES, TimeoutData<TYPES>>;
893/// Timeout Vote 2 type alias
894pub type TimeoutVote2<TYPES> = SimpleVote<TYPES, TimeoutData2<TYPES>>;
895
896/// View Sync Pre Commit Vote type alias
897pub type ViewSyncPreCommitVote<TYPES> = SimpleVote<TYPES, ViewSyncPreCommitData<TYPES>>;
898/// View Sync Pre Commit Vote 2 type alias
899pub type ViewSyncPreCommitVote2<TYPES> = SimpleVote<TYPES, ViewSyncPreCommitData2<TYPES>>;
900/// View Sync Finalize Vote type alias
901pub type ViewSyncFinalizeVote<TYPES> = SimpleVote<TYPES, ViewSyncFinalizeData<TYPES>>;
902/// View Sync Finalize Vote 2 type alias
903pub type ViewSyncFinalizeVote2<TYPES> = SimpleVote<TYPES, ViewSyncFinalizeData2<TYPES>>;
904/// View Sync Commit Vote type alias
905pub type ViewSyncCommitVote<TYPES> = SimpleVote<TYPES, ViewSyncCommitData<TYPES>>;
906/// View Sync Commit Vote 2 type alias
907pub type ViewSyncCommitVote2<TYPES> = SimpleVote<TYPES, ViewSyncCommitData2<TYPES>>;
908/// Upgrade proposal vote
909pub type UpgradeVote<TYPES> = SimpleVote<TYPES, UpgradeProposalData<TYPES>>;
910/// Upgrade proposal 2 vote
911pub type UpgradeVote2<TYPES> = SimpleVote<TYPES, UpgradeData2<TYPES>>;
912
913impl<TYPES: NodeType> Deref for NextEpochQuorumData2<TYPES> {
914    type Target = QuorumData2<TYPES>;
915    fn deref(&self) -> &Self::Target {
916        &self.0
917    }
918}
919impl<TYPES: NodeType> DerefMut for NextEpochQuorumData2<TYPES> {
920    fn deref_mut(&mut self) -> &mut Self::Target {
921        &mut self.0
922    }
923}
924impl<TYPES: NodeType> From<QuorumData2<TYPES>> for NextEpochQuorumData2<TYPES> {
925    fn from(data: QuorumData2<TYPES>) -> Self {
926        Self(QuorumData2 {
927            epoch: data.epoch,
928            leaf_commit: data.leaf_commit,
929            block_number: data.block_number,
930        })
931    }
932}
933
934impl<TYPES: NodeType> From<QuorumVote2<TYPES>> for NextEpochQuorumVote2<TYPES> {
935    fn from(qvote: QuorumVote2<TYPES>) -> Self {
936        Self {
937            data: qvote.data.into(),
938            view_number: qvote.view_number,
939            signature: qvote.signature.clone(),
940        }
941    }
942}
943
944/// Type for light client state update vote
945#[derive(Serialize, Deserialize, Eq, Hash, PartialEq, Debug, Clone)]
946pub struct LightClientStateUpdateVote<TYPES: NodeType> {
947    /// The epoch number
948    pub epoch: TYPES::Epoch,
949    /// The light client state
950    pub light_client_state: LightClientState,
951    /// The next stake table state
952    pub next_stake_table_state: StakeTableState,
953    /// The signature to the light client state
954    pub signature: <TYPES::StateSignatureKey as StateSignatureKey>::StateSignature,
955}
956
957impl<TYPES: NodeType> HasViewNumber<TYPES> for LightClientStateUpdateVote<TYPES> {
958    fn view_number(&self) -> TYPES::View {
959        TYPES::View::new(self.light_client_state.view_number)
960    }
961}
962
963impl<TYPES: NodeType> HasEpoch<TYPES> for LightClientStateUpdateVote<TYPES> {
964    fn epoch(&self) -> Option<TYPES::Epoch> {
965        Some(self.epoch)
966    }
967}
968
969#[derive(Serialize, Deserialize, Eq, Hash, PartialEq, Debug, Clone)]
970#[serde(bound(deserialize = "QuorumVote2<TYPES>:for<'a> Deserialize<'a>"))]
971pub struct EpochRootQuorumVote<TYPES: NodeType> {
972    pub vote: QuorumVote2<TYPES>,
973    pub state_vote: LightClientStateUpdateVote<TYPES>,
974}
975
976impl<TYPES: NodeType> HasViewNumber<TYPES> for EpochRootQuorumVote<TYPES> {
977    fn view_number(&self) -> TYPES::View {
978        self.vote.view_number()
979    }
980}
981
982impl<TYPES: NodeType> HasEpoch<TYPES> for EpochRootQuorumVote<TYPES> {
983    fn epoch(&self) -> Option<TYPES::Epoch> {
984        self.vote.epoch()
985    }
986}