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 Vote,
12 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 pub fn signing_bytes(
31 chain_id_hash: &[u8; 32],
32 view: ViewNumber,
33 block_hash: &BlockHash,
34 vote_type: VoteType,
35 ) -> Vec<u8> {
36 let tag = b"HOTMINT_VOTE_V1\0";
37 let mut buf = Vec::with_capacity(tag.len() + 32 + 8 + 32 + 1);
38 buf.extend_from_slice(tag);
39 buf.extend_from_slice(chain_id_hash);
40 buf.extend_from_slice(&view.as_u64().to_le_bytes());
41 buf.extend_from_slice(&block_hash.0);
42 buf.push(vote_type as u8);
43 buf
44 }
45}
46
47#[cfg(test)]
48mod tests {
49 use super::*;
50
51 const TEST_CHAIN: [u8; 32] = [0u8; 32];
52
53 #[test]
54 fn test_signing_bytes_deterministic() {
55 let hash = BlockHash([42u8; 32]);
56 let a = Vote::signing_bytes(&TEST_CHAIN, ViewNumber(5), &hash, VoteType::Vote);
57 let b = Vote::signing_bytes(&TEST_CHAIN, ViewNumber(5), &hash, VoteType::Vote);
58 assert_eq!(a, b);
59 }
60
61 #[test]
62 fn test_signing_bytes_differ_by_type() {
63 let hash = BlockHash([1u8; 32]);
64 let a = Vote::signing_bytes(&TEST_CHAIN, ViewNumber(1), &hash, VoteType::Vote);
65 let b = Vote::signing_bytes(&TEST_CHAIN, ViewNumber(1), &hash, VoteType::Vote2);
66 assert_ne!(a, b);
67 }
68
69 #[test]
70 fn test_signing_bytes_differ_by_view() {
71 let hash = BlockHash([1u8; 32]);
72 let a = Vote::signing_bytes(&TEST_CHAIN, ViewNumber(1), &hash, VoteType::Vote);
73 let b = Vote::signing_bytes(&TEST_CHAIN, ViewNumber(2), &hash, VoteType::Vote);
74 assert_ne!(a, b);
75 }
76
77 #[test]
78 fn test_signing_bytes_differ_by_chain() {
79 let hash = BlockHash([1u8; 32]);
80 let chain_a = [1u8; 32];
81 let chain_b = [2u8; 32];
82 let a = Vote::signing_bytes(&chain_a, ViewNumber(1), &hash, VoteType::Vote);
83 let b = Vote::signing_bytes(&chain_b, ViewNumber(1), &hash, VoteType::Vote);
84 assert_ne!(a, b);
85 }
86}