use crate::role::Roles;
use bitflags::bitflags;
use codec::{Decode, Encode, Error, Input, Output};
pub use generic::{BlockAnnounce, FromBlock};
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor};
pub type BlockRequest<B> =
generic::BlockRequest<<B as BlockT>::Hash, <<B as BlockT>::Header as HeaderT>::Number>;
pub type BlockData<B> =
generic::BlockData<<B as BlockT>::Header, <B as BlockT>::Hash, <B as BlockT>::Extrinsic>;
pub type BlockResponse<B> =
generic::BlockResponse<<B as BlockT>::Header, <B as BlockT>::Hash, <B as BlockT>::Extrinsic>;
bitflags! {
pub struct BlockAttributes: u8 {
const HEADER = 0b00000001;
const BODY = 0b00000010;
const RECEIPT = 0b00000100;
const MESSAGE_QUEUE = 0b00001000;
const JUSTIFICATION = 0b00010000;
const INDEXED_BODY = 0b00100000;
}
}
impl BlockAttributes {
pub fn to_be_u32(&self) -> u32 {
u32::from_be_bytes([self.bits(), 0, 0, 0])
}
pub fn from_be_u32(encoded: u32) -> Result<Self, Error> {
Self::from_bits(encoded.to_be_bytes()[0])
.ok_or_else(|| Error::from("Invalid BlockAttributes"))
}
}
impl Encode for BlockAttributes {
fn encode_to<T: Output + ?Sized>(&self, dest: &mut T) {
dest.push_byte(self.bits())
}
}
impl codec::EncodeLike for BlockAttributes {}
impl Decode for BlockAttributes {
fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
Self::from_bits(input.read_byte()?).ok_or_else(|| Error::from("Invalid bytes"))
}
}
#[derive(Debug, PartialEq, Eq, Clone, Copy, Encode, Decode)]
pub enum Direction {
Ascending = 0,
Descending = 1,
}
#[derive(Debug, PartialEq, Eq, Clone, Copy, Encode, Decode)]
pub enum BlockState {
Normal,
Best,
}
#[derive(Debug)]
pub struct AnnouncementSummary<H: HeaderT> {
pub block_hash: H::Hash,
pub number: H::Number,
pub parent_hash: H::Hash,
pub state: Option<BlockState>,
}
impl<H: HeaderT> BlockAnnounce<H> {
pub fn summary(&self) -> AnnouncementSummary<H> {
AnnouncementSummary {
block_hash: self.header.hash(),
number: *self.header.number(),
parent_hash: *self.header.parent_hash(),
state: self.state,
}
}
}
pub mod generic {
use super::{BlockAttributes, BlockState, Direction};
use crate::message::RequestId;
use codec::{Decode, Encode, Input, Output};
use sp_runtime::{EncodedJustification, Justifications};
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub struct BlockData<Header, Hash, Extrinsic> {
pub hash: Hash,
pub header: Option<Header>,
pub body: Option<Vec<Extrinsic>>,
pub indexed_body: Option<Vec<Vec<u8>>>,
pub receipt: Option<Vec<u8>>,
pub message_queue: Option<Vec<u8>>,
pub justification: Option<EncodedJustification>,
pub justifications: Option<Justifications>,
}
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub struct BlockRequest<Hash, Number> {
pub id: RequestId,
pub fields: BlockAttributes,
pub from: FromBlock<Hash, Number>,
pub direction: Direction,
pub max: Option<u32>,
}
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub enum FromBlock<Hash, Number> {
Hash(Hash),
Number(Number),
}
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub struct BlockResponse<Header, Hash, Extrinsic> {
pub id: RequestId,
pub blocks: Vec<BlockData<Header, Hash, Extrinsic>>,
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct BlockAnnounce<H> {
pub header: H,
pub state: Option<BlockState>,
pub data: Option<Vec<u8>>,
}
impl<H: Encode> Encode for BlockAnnounce<H> {
fn encode_to<T: Output + ?Sized>(&self, dest: &mut T) {
self.header.encode_to(dest);
if let Some(state) = &self.state {
state.encode_to(dest);
}
if let Some(data) = &self.data {
data.encode_to(dest)
}
}
}
impl<H: Decode> Decode for BlockAnnounce<H> {
fn decode<I: Input>(input: &mut I) -> Result<Self, codec::Error> {
let header = H::decode(input)?;
let state = BlockState::decode(input).ok();
let data = Vec::decode(input).ok();
Ok(Self { header, state, data })
}
}
}
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub struct BlockAnnouncesHandshake<B: BlockT> {
pub roles: Roles,
pub best_number: NumberFor<B>,
pub best_hash: B::Hash,
pub genesis_hash: B::Hash,
}
impl<B: BlockT> BlockAnnouncesHandshake<B> {
pub fn build(
roles: Roles,
best_number: NumberFor<B>,
best_hash: B::Hash,
genesis_hash: B::Hash,
) -> Self {
Self { genesis_hash, roles, best_number, best_hash }
}
}