Skip to main content

hotmint_types/
vote.rs

1use serde::{Deserialize, Serialize};
2
3use crate::block::BlockHash;
4use crate::crypto::Signature;
5use crate::validator::ValidatorId;
6use crate::view::ViewNumber;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
9pub enum VoteType {
10    /// First-phase vote (step 3)
11    Vote,
12    /// Second-phase vote (step 5)
13    Vote2,
14}
15
16#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct Vote {
18    pub block_hash: BlockHash,
19    pub view: ViewNumber,
20    pub validator: ValidatorId,
21    pub signature: Signature,
22    pub vote_type: VoteType,
23}
24
25impl Vote {
26    /// Canonical bytes for signing: view || block_hash || vote_type
27    pub fn signing_bytes(view: ViewNumber, block_hash: &BlockHash, vote_type: VoteType) -> Vec<u8> {
28        let mut buf = Vec::with_capacity(32 + 8 + 1);
29        buf.extend_from_slice(&view.as_u64().to_le_bytes());
30        buf.extend_from_slice(&block_hash.0);
31        buf.push(vote_type as u8);
32        buf
33    }
34}
35
36#[cfg(test)]
37mod tests {
38    use super::*;
39
40    #[test]
41    fn test_signing_bytes_deterministic() {
42        let hash = BlockHash([42u8; 32]);
43        let a = Vote::signing_bytes(ViewNumber(5), &hash, VoteType::Vote);
44        let b = Vote::signing_bytes(ViewNumber(5), &hash, VoteType::Vote);
45        assert_eq!(a, b);
46    }
47
48    #[test]
49    fn test_signing_bytes_differ_by_type() {
50        let hash = BlockHash([1u8; 32]);
51        let a = Vote::signing_bytes(ViewNumber(1), &hash, VoteType::Vote);
52        let b = Vote::signing_bytes(ViewNumber(1), &hash, VoteType::Vote2);
53        assert_ne!(a, b);
54    }
55
56    #[test]
57    fn test_signing_bytes_differ_by_view() {
58        let hash = BlockHash([1u8; 32]);
59        let a = Vote::signing_bytes(ViewNumber(1), &hash, VoteType::Vote);
60        let b = Vote::signing_bytes(ViewNumber(2), &hash, VoteType::Vote);
61        assert_ne!(a, b);
62    }
63}