mod commit;
pub mod commit_sig;
pub mod header;
mod height;
mod id;
mod meta;
pub mod parts;
mod round;
pub mod signed_header;
mod size;
pub use self::{
commit::*,
commit_sig::*,
header::Header,
height::*,
id::{Id, ParseId},
meta::Meta,
round::*,
size::Size,
};
use crate::{abci::transaction, error::Error, evidence};
use serde::{Deserialize, Serialize};
use std::convert::{TryFrom, TryInto};
use tendermint_proto::types::Block as RawBlock;
use tendermint_proto::Protobuf;
#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
#[non_exhaustive]
pub struct Block {
pub header: Header,
pub data: transaction::Data,
pub evidence: evidence::Data,
#[serde(with = "crate::serializers::optional")]
pub last_commit: Option<Commit>,
}
impl Protobuf<RawBlock> for Block {}
impl TryFrom<RawBlock> for Block {
type Error = Error;
fn try_from(value: RawBlock) -> Result<Self, Self::Error> {
let header: Header = value.header.ok_or_else(Error::missing_header)?.try_into()?;
let last_commit = value
.last_commit
.map(TryInto::try_into)
.transpose()?
.filter(|c| c != &Commit::default());
if last_commit.is_none() && header.height.value() != 1 {
return Err(Error::invalid_block(
"last_commit is empty on non-first block".to_string(),
));
}
Ok(Block {
header,
data: value.data.ok_or_else(Error::missing_data)?.into(),
evidence: value
.evidence
.ok_or_else(Error::missing_evidence)?
.try_into()?,
last_commit,
})
}
}
impl From<Block> for RawBlock {
fn from(value: Block) -> Self {
RawBlock {
header: Some(value.header.into()),
data: Some(value.data.into()),
evidence: Some(value.evidence.into()),
last_commit: value.last_commit.map(Into::into),
}
}
}
impl Block {
pub fn new(
header: Header,
data: transaction::Data,
evidence: evidence::Data,
last_commit: Option<Commit>,
) -> Result<Self, Error> {
if last_commit.is_none() && header.height.value() != 1 {
return Err(Error::invalid_block(
"last_commit is empty on non-first block".to_string(),
));
}
if last_commit.is_some() && header.height.value() == 1 {
return Err(Error::invalid_block(
"last_commit is filled on first block".to_string(),
));
}
Ok(Block {
header,
data,
evidence,
last_commit,
})
}
pub fn header(&self) -> &Header {
&self.header
}
pub fn data(&self) -> &transaction::Data {
&self.data
}
pub fn evidence(&self) -> &evidence::Data {
&self.evidence
}
pub fn last_commit(&self) -> &Option<Commit> {
&self.last_commit
}
}