use serde::{Deserialize, Serialize};
use crate::types::{hash, Block, Hash, NodeId};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum MessageType {
PrePrepare,
Prepare,
Commit,
Reply,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Vote {
pub voter: NodeId,
pub approve: bool,
}
impl Vote {
pub fn approve(voter: NodeId) -> Self {
Self {
voter,
approve: true,
}
}
pub fn reject(voter: NodeId) -> Self {
Self {
voter,
approve: false,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Message {
pub source: NodeId,
pub round: u64,
pub msg_type: MessageType,
pub block_hash: Hash,
pub vote: Option<Vote>,
pub block: Option<Block>,
}
impl Message {
pub fn pre_prepare(source: NodeId, round: u64, block: Block) -> Self {
let block_hash = block.hash();
Self {
source,
round,
msg_type: MessageType::PrePrepare,
block_hash,
vote: None,
block: Some(block),
}
}
pub fn prepare(source: NodeId, round: u64, block_hash: Hash, approve: bool) -> Self {
let vote = if approve {
Vote::approve(source)
} else {
Vote::reject(source)
};
Self {
source,
round,
msg_type: MessageType::Prepare,
block_hash,
vote: Some(vote),
block: None,
}
}
pub fn commit(source: NodeId, round: u64, block_hash: Hash, approve: bool) -> Self {
let vote = if approve {
Vote::approve(source)
} else {
Vote::reject(source)
};
Self {
source,
round,
msg_type: MessageType::Commit,
block_hash,
vote: Some(vote),
block: None,
}
}
pub fn reply(source: NodeId, round: u64, block: Block) -> Self {
let block_hash = block.hash();
Self {
source,
round,
msg_type: MessageType::Reply,
block_hash,
vote: None,
block: Some(block),
}
}
pub fn hash(&self) -> Hash {
let bytes = bincode::serialize(self).expect("message serialization failed");
hash(&bytes)
}
}