use std::cmp::{Ord, Ordering, PartialOrd};
use bytes::Bytes;
use derive_more::Display;
use serde::{Deserialize, Serialize};
use crate::smr::smr_types::{Step, TriggerType};
use crate::Codec;
pub type Address = Bytes;
pub type Hash = Bytes;
pub type Signature = Bytes;
#[derive(Clone, Debug, Display, PartialEq, Eq)]
pub enum Role {
#[display(fmt = "Leader")]
Leader,
#[display(fmt = "Replica")]
Replica,
}
impl Into<u8> for Role {
fn into(self) -> u8 {
match self {
Role::Leader => 0,
Role::Replica => 1,
}
}
}
impl From<u8> for Role {
fn from(s: u8) -> Self {
match s {
0 => Role::Leader,
1 => Role::Replica,
_ => panic!("Invalid role!"),
}
}
}
#[derive(Clone, Debug, Display, PartialEq, Eq, Hash)]
pub enum VoteType {
#[display(fmt = "Prevote")]
Prevote,
#[display(fmt = "Precommit")]
Precommit,
}
impl Into<u8> for VoteType {
fn into(self) -> u8 {
match self {
VoteType::Prevote => 1,
VoteType::Precommit => 2,
}
}
}
impl Into<TriggerType> for VoteType {
fn into(self) -> TriggerType {
match self {
VoteType::Prevote => TriggerType::PrevoteQC,
VoteType::Precommit => TriggerType::PrecommitQC,
}
}
}
impl Into<Step> for VoteType {
fn into(self) -> Step {
match self {
VoteType::Prevote => Step::Prevote,
VoteType::Precommit => Step::Precommit,
}
}
}
impl From<u8> for VoteType {
fn from(s: u8) -> Self {
match s {
1 => VoteType::Prevote,
2 => VoteType::Precommit,
_ => panic!("Invalid vote type!"),
}
}
}
#[derive(Clone, Debug, Display, PartialEq, Eq)]
pub enum OverlordMsg<T: Codec> {
#[display(fmt = "Signed Proposal")]
SignedProposal(SignedProposal<T>),
#[display(fmt = "Signed Vote")]
SignedVote(SignedVote),
#[display(fmt = "Aggregated Vote")]
AggregatedVote(AggregatedVote),
#[display(fmt = "Rich Status")]
RichStatus(Status),
#[cfg(test)]
Commit(Commit<T>),
}
#[derive(Clone, Debug, Display, PartialEq, Eq)]
#[display(fmt = "Signed Proposal {:?}", proposal)]
pub struct SignedProposal<T: Codec> {
pub signature: Bytes,
pub proposal: Proposal<T>,
}
#[derive(Clone, Debug, Display, PartialEq, Eq)]
#[display(fmt = "Proposal height {}, round {}", height, round)]
pub struct Proposal<T: Codec> {
pub height: u64,
pub round: u64,
pub content: T,
pub block_hash: Hash,
pub lock: Option<PoLC>,
pub proposer: Address,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PoLC {
pub lock_round: u64,
pub lock_votes: AggregatedVote,
}
#[derive(Clone, Debug, Display, PartialEq, Eq, Hash)]
#[display(fmt = "Signed vote {:?}", vote)]
pub struct SignedVote {
pub signature: Bytes,
pub vote: Vote,
pub voter: Address,
}
impl PartialOrd for SignedVote {
fn partial_cmp(&self, other: &SignedVote) -> Option<Ordering> {
Some(self.voter.cmp(&other.voter))
}
}
impl Ord for SignedVote {
fn cmp(&self, other: &SignedVote) -> Ordering {
self.voter.cmp(&other.voter)
}
}
impl SignedVote {
pub fn get_height(&self) -> u64 {
self.vote.height
}
pub fn get_round(&self) -> u64 {
self.vote.round
}
pub fn get_hash(&self) -> Hash {
self.vote.block_hash.clone()
}
pub fn is_prevote(&self) -> bool {
self.vote.vote_type == VoteType::Prevote
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct AggregatedSignature {
pub signature: Signature,
pub address_bitmap: Bytes,
}
#[derive(Clone, Debug, Display, PartialEq, Eq)]
#[rustfmt::skip]
#[display(fmt = "{:?} aggregated vote height {}, round {}", vote_type, height, round)]
pub struct AggregatedVote {
pub signature: AggregatedSignature,
pub vote_type: VoteType,
pub height: u64,
pub round: u64,
pub block_hash: Hash,
pub leader: Address,
}
impl AggregatedVote {
pub fn get_height(&self) -> u64 {
self.height
}
pub fn get_round(&self) -> u64 {
self.round
}
pub fn is_prevote_qc(&self) -> bool {
self.vote_type == VoteType::Prevote
}
pub fn to_vote(&self) -> Vote {
Vote {
height: self.height,
round: self.round,
vote_type: self.vote_type.clone(),
block_hash: self.block_hash.clone(),
}
}
}
#[derive(Clone, Debug, Display, PartialEq, Eq, Hash)]
#[display(fmt = "{:?} vote height {}, round {}", vote_type, height, round)]
pub struct Vote {
pub height: u64,
pub round: u64,
pub vote_type: VoteType,
pub block_hash: Hash,
}
#[derive(Clone, Debug, Display, PartialEq, Eq)]
#[display(fmt = "Commit height {}", height)]
pub struct Commit<T: Codec> {
pub height: u64,
pub content: T,
pub proof: Proof,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Proof {
pub height: u64,
pub round: u64,
pub block_hash: Hash,
pub signature: AggregatedSignature,
}
#[derive(Clone, Debug, Display, PartialEq, Eq)]
#[display(fmt = "Rich status height {}", height)]
pub struct Status {
pub height: u64,
pub interval: Option<u64>,
pub authority_list: Vec<Node>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Node {
pub address: Address,
pub propose_weight: u8,
pub vote_weight: u8,
}
impl PartialOrd for Node {
fn partial_cmp(&self, other: &Node) -> Option<Ordering> {
Some(self.address.cmp(&other.address))
}
}
impl Ord for Node {
fn cmp(&self, other: &Node) -> Ordering {
self.address.cmp(&other.address)
}
}
impl Node {
pub fn new(addr: Address) -> Self {
Node {
address: addr,
propose_weight: 1u8,
vote_weight: 1u8,
}
}
pub fn set_propose_weight(&mut self, propose_weight: u8) {
self.propose_weight = propose_weight;
}
pub fn set_vote_weight(&mut self, vote_weight: u8) {
self.vote_weight = vote_weight;
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct Feed<T: Codec> {
pub(crate) height: u64,
pub(crate) content: T,
pub(crate) block_hash: Hash,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct VerifyResp {
pub height: u64,
pub block_hash: Hash,
pub is_pass: bool,
}