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