use std::{any::Any, collections::BTreeMap, fmt::Debug, path::PathBuf};
use anyhow::Error;
use datasize::DataSize;
use serde::{Deserialize, Serialize};
use crate::{components::consensus::traits::Context, types::Timestamp, NodeRng};
#[derive(Clone, DataSize, Eq, PartialEq, Debug, Ord, PartialOrd, Hash)]
pub struct BlockContext {
timestamp: Timestamp,
height: u64,
}
impl BlockContext {
pub(crate) fn new(timestamp: Timestamp, height: u64) -> Self {
BlockContext { timestamp, height }
}
pub(crate) fn timestamp(&self) -> Timestamp {
self.timestamp
}
}
#[derive(Clone, DataSize, Debug, PartialOrd, Ord, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(bound(
serialize = "VID: Ord + Serialize",
deserialize = "VID: Ord + Deserialize<'de>",
))]
pub struct EraEnd<VID> {
pub(crate) equivocators: Vec<VID>,
pub(crate) rewards: BTreeMap<VID, u64>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub(crate) struct FinalizedBlock<C: Context> {
pub(crate) value: C::ConsensusValue,
pub(crate) timestamp: Timestamp,
pub(crate) height: u64,
pub(crate) rewards: Option<BTreeMap<C::ValidatorId, u64>>,
pub(crate) equivocators: Vec<C::ValidatorId>,
pub(crate) proposer: C::ValidatorId,
}
#[derive(Debug)]
pub(crate) enum ProtocolOutcome<I, C: Context> {
CreatedGossipMessage(Vec<u8>),
CreatedTargetedMessage(Vec<u8>, I),
InvalidIncomingMessage(Vec<u8>, I, Error),
ScheduleTimer(Timestamp),
CreateNewBlock {
block_context: BlockContext,
past_values: Vec<C::ConsensusValue>,
},
FinalizedBlock(FinalizedBlock<C>),
ValidateConsensusValue(I, C::ConsensusValue, Timestamp),
NewEvidence(C::ValidatorId),
SendEvidence(I, C::ValidatorId),
WeAreFaulty,
DoppelgangerDetected,
Disconnect(I),
}
pub(crate) trait ConsensusProtocol<I, C: Context> {
fn as_any(&self) -> &dyn Any;
fn handle_message(
&mut self,
sender: I,
msg: Vec<u8>,
evidence_only: bool,
rng: &mut NodeRng,
) -> Vec<ProtocolOutcome<I, C>>;
fn handle_new_peer(&mut self, peer_id: I) -> Vec<ProtocolOutcome<I, C>>;
fn handle_timer(
&mut self,
timestamp: Timestamp,
rng: &mut NodeRng,
) -> Vec<ProtocolOutcome<I, C>>;
fn propose(
&mut self,
value: C::ConsensusValue,
block_context: BlockContext,
rng: &mut NodeRng,
) -> Vec<ProtocolOutcome<I, C>>;
fn resolve_validity(
&mut self,
value: &C::ConsensusValue,
valid: bool,
rng: &mut NodeRng,
) -> Vec<ProtocolOutcome<I, C>>;
fn activate_validator(
&mut self,
our_id: C::ValidatorId,
secret: C::ValidatorSecret,
timestamp: Timestamp,
unit_hash_file: Option<PathBuf>,
) -> Vec<ProtocolOutcome<I, C>>;
fn deactivate_validator(&mut self);
fn has_evidence(&self, vid: &C::ValidatorId) -> bool;
fn mark_faulty(&mut self, vid: &C::ValidatorId);
fn request_evidence(&self, sender: I, vid: &C::ValidatorId) -> Vec<ProtocolOutcome<I, C>>;
fn validators_with_evidence(&self) -> Vec<&C::ValidatorId>;
fn has_received_messages(&self) -> bool;
fn is_active(&self) -> bool;
fn instance_id(&self) -> &C::InstanceId;
}