use std::fmt::{self, Debug, Display};
use std::time;
use failure;
use threshold_crypto as crypto;
use hbbft::ConsensusProtocol;
use super::NetMessage;
pub enum CrankError<D>
where
D: ConsensusProtocol,
{
HandleInput(D::Error),
HandleInputAll(D::Error),
HandleMessage {
msg: NetMessage<D>,
err: D::Error,
},
NodeDisappearedInCrank(D::NodeId),
NodeDisappearedInDispatch(D::NodeId),
CrankLimitExceeded(usize),
MessageLimitExceeded(usize),
TimeLimitHit(time::Duration),
Fault {
reported_by: D::NodeId,
faulty_id: D::NodeId,
fault_kind: D::FaultKind,
},
InitialKeyGeneration(crypto::error::Error),
}
impl<D> Display for CrankError<D>
where
D: ConsensusProtocol,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
CrankError::HandleInput(err) => {
write!(f, "The algorithm could not process input: {:?}", err)
}
CrankError::HandleInputAll(err) => write!(
f,
"The algorithm could not process input to all nodes: {:?}",
err
),
CrankError::HandleMessage { msg, err } => write!(
f,
"The algorithm could not process network message {:?}. Error: {:?}",
msg, err
),
CrankError::NodeDisappearedInCrank(id) => write!(
f,
"Node {:?} disappeared or never existed, while it was cranked.",
id
),
CrankError::NodeDisappearedInDispatch(id) => write!(
f,
"Node {:?} disappeared or never existed, while it still had incoming messages.",
id
),
CrankError::CrankLimitExceeded(max) => {
write!(f, "Maximum number of cranks exceeded: {}", max)
}
CrankError::MessageLimitExceeded(max) => {
write!(f, "Maximum number of messages exceeded: {}", max)
}
CrankError::TimeLimitHit(lim) => {
write!(f, "Time limit of {} seconds exceeded.", lim.as_secs())
}
CrankError::Fault {
reported_by,
faulty_id,
fault_kind,
} => write!(
f,
"Correct node {:?} reported node {:?} as faulty: {:?}.",
reported_by, faulty_id, fault_kind
),
CrankError::InitialKeyGeneration(err) => write!(
f,
"An error occurred while generating initial keys for threshold cryptography: {:?}.",
err
),
}
}
}
impl<D> Debug for CrankError<D>
where
D: ConsensusProtocol,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
CrankError::HandleInput(err) => {
f.debug_struct("HandleInput").field("err", err).finish()
}
CrankError::HandleInputAll(err) => {
f.debug_struct("HandleInputAll").field("err", err).finish()
}
CrankError::HandleMessage { msg, err } => f
.debug_struct("HandleMessage")
.field("msg", msg)
.field("err", err)
.finish(),
CrankError::NodeDisappearedInCrank(id) => {
f.debug_tuple("NodeDisappearedInCrank").field(id).finish()
}
CrankError::NodeDisappearedInDispatch(id) => f
.debug_tuple("NodeDisappearedInDispatch")
.field(id)
.finish(),
CrankError::CrankLimitExceeded(max) => {
f.debug_tuple("CrankLimitExceeded").field(max).finish()
}
CrankError::MessageLimitExceeded(max) => {
f.debug_tuple("MessageLimitExceeded").field(max).finish()
}
CrankError::TimeLimitHit(lim) => f.debug_tuple("TimeLimitHit").field(lim).finish(),
CrankError::Fault {
reported_by,
faulty_id,
fault_kind,
} => f
.debug_struct("Fault")
.field("reported_by", reported_by)
.field("faulty_id", faulty_id)
.field("fault_kind", fault_kind)
.finish(),
CrankError::InitialKeyGeneration(err) => {
f.debug_tuple("InitialKeyGeneration").field(err).finish()
}
}
}
}
impl<D> failure::Fail for CrankError<D>
where
D: ConsensusProtocol + 'static,
{
fn cause(&self) -> Option<&dyn failure::Fail> {
match self {
CrankError::HandleInput(err) | CrankError::HandleInputAll(err) => Some(err),
CrankError::HandleMessage { err, .. } => Some(err),
CrankError::InitialKeyGeneration(err) => Some(err),
_ => None,
}
}
}