use std::fmt::{Debug, Display, Error as FmtError, Formatter};
use parity_scale_codec::{Decode, Encode};
use crate::{
phron_primitives::Header,
justification::PhronJustification,
sync::{
substrate::{
chain_status::{Error as ChainStatusError, SubstrateChainStatus},
BlockId,
},
BlockStatus, ChainStatus, Justification as JustificationT, UnverifiedJustification,
},
};
#[derive(Clone, Debug, Encode, Decode)]
pub enum InnerJustification {
PhronJustification(PhronJustification),
Genesis,
}
#[derive(Clone, Debug, Encode, Decode)]
pub struct Justification {
pub header: Header,
pub inner_justification: InnerJustification,
}
impl Justification {
pub fn phron_justification(header: Header, phron_justification: PhronJustification) -> Self {
Justification {
header,
inner_justification: InnerJustification::PhronJustification(phron_justification),
}
}
pub fn genesis_justification(header: Header) -> Self {
Justification {
header,
inner_justification: InnerJustification::Genesis,
}
}
pub fn into_inner(self) -> InnerJustification {
self.inner_justification
}
}
impl UnverifiedJustification for Justification {
type UnverifiedHeader = Header;
fn header(&self) -> &Self::UnverifiedHeader {
&self.header
}
}
impl JustificationT for Justification {
type Header = Header;
type Unverified = Self;
fn header(&self) -> &Self::Header {
&self.header
}
fn into_unverified(self) -> Self::Unverified {
self
}
}
#[derive(Debug)]
pub enum TranslateError {
ChainStatus(ChainStatusError),
NoBlock,
}
impl Display for TranslateError {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
use TranslateError::*;
match self {
ChainStatus(e) => {
write!(f, "error retrieving block status: {e}")
}
NoBlock => write!(f, "block not present"),
}
}
}
impl From<ChainStatusError> for TranslateError {
fn from(value: ChainStatusError) -> Self {
TranslateError::ChainStatus(value)
}
}
#[derive(Clone)]
pub struct JustificationTranslator {
chain_status: SubstrateChainStatus,
}
impl JustificationTranslator {
pub fn new(chain_status: SubstrateChainStatus) -> Self {
Self { chain_status }
}
pub fn translate(
&self,
phron_justification: PhronJustification,
block_id: BlockId,
) -> Result<Justification, TranslateError> {
use BlockStatus::*;
match self.chain_status.status_of(block_id)? {
Justified(Justification { header, .. }) | Present(header) => Ok(
Justification::phron_justification(header, phron_justification),
),
Unknown => Err(TranslateError::NoBlock),
}
}
}