use bitflags::bitflags;
use tp_runtime::{ConsensusEngineId, traits::{Block as BlockT, Header as HeaderT}};
use codec::{Encode, Decode, Input, Output, Error};
pub use self::generic::{
BlockAnnounce, RemoteCallRequest, RemoteReadRequest,
RemoteHeaderRequest, RemoteHeaderResponse,
RemoteChangesRequest, RemoteChangesResponse,
FromBlock, RemoteReadChildRequest, Roles,
};
use tc_client_api::StorageProof;
pub type RequestId = u64;
pub type Message<B> = generic::Message<
<B as BlockT>::Header,
<B as BlockT>::Hash,
<<B as BlockT>::Header as HeaderT>::Number,
<B as BlockT>::Extrinsic,
>;
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,
>;
pub type Transactions<E> = Vec<E>;
bitflags! {
pub struct BlockAttributes: u8 {
const HEADER = 0b00000001;
const BODY = 0b00000010;
const RECEIPT = 0b00000100;
const MESSAGE_QUEUE = 0b00001000;
const JUSTIFICATION = 0b00010000;
}
}
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> {
BlockAttributes::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, PartialEq, Eq, Clone, Encode, Decode)]
pub struct RemoteCallResponse {
pub id: RequestId,
pub proof: StorageProof,
}
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub struct RemoteReadResponse {
pub id: RequestId,
pub proof: StorageProof,
}
pub mod generic {
use bitflags::bitflags;
use codec::{Encode, Decode, Input, Output};
use tp_runtime::Justification;
use super::{
RemoteReadResponse, Transactions, Direction,
RequestId, BlockAttributes, RemoteCallResponse, ConsensusEngineId,
BlockState, StorageProof,
};
bitflags! {
pub struct Roles: u8 {
const NONE = 0b00000000;
const FULL = 0b00000001;
const LIGHT = 0b00000010;
const AUTHORITY = 0b00000100;
}
}
impl Roles {
pub fn is_full(&self) -> bool {
self.intersects(Roles::FULL | Roles::AUTHORITY)
}
pub fn is_authority(&self) -> bool {
*self == Roles::AUTHORITY
}
pub fn is_light(&self) -> bool {
!self.is_full()
}
}
impl<'a> From<&'a crate::config::Role> for Roles {
fn from(roles: &'a crate::config::Role) -> Self {
match roles {
crate::config::Role::Full => Roles::FULL,
crate::config::Role::Light => Roles::LIGHT,
crate::config::Role::Sentry { .. } => Roles::AUTHORITY,
crate::config::Role::Authority { .. } => Roles::AUTHORITY,
}
}
}
impl codec::Encode for Roles {
fn encode_to<T: codec::Output + ?Sized>(&self, dest: &mut T) {
dest.push_byte(self.bits())
}
}
impl codec::EncodeLike for Roles {}
impl codec::Decode for Roles {
fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
Self::from_bits(input.read_byte()?).ok_or_else(|| codec::Error::from("Invalid bytes"))
}
}
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub struct ConsensusMessage {
pub protocol: ConsensusEngineId,
pub data: Vec<u8>,
}
#[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 receipt: Option<Vec<u8>>,
pub message_queue: Option<Vec<u8>>,
pub justification: Option<Justification>,
}
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub enum FromBlock<Hash, Number> {
Hash(Hash),
Number(Number),
}
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub enum Message<Header, Hash, Number, Extrinsic> {
Status(Status<Hash, Number>),
BlockRequest(BlockRequest<Hash, Number>),
BlockResponse(BlockResponse<Header, Hash, Extrinsic>),
BlockAnnounce(BlockAnnounce<Header>),
Transactions(Transactions<Extrinsic>),
Consensus(ConsensusMessage),
RemoteCallRequest(RemoteCallRequest<Hash>),
RemoteCallResponse(RemoteCallResponse),
RemoteReadRequest(RemoteReadRequest<Hash>),
RemoteReadResponse(RemoteReadResponse),
RemoteHeaderRequest(RemoteHeaderRequest<Number>),
RemoteHeaderResponse(RemoteHeaderResponse<Header>),
RemoteChangesRequest(RemoteChangesRequest<Hash>),
RemoteChangesResponse(RemoteChangesResponse<Number, Hash>),
RemoteReadChildRequest(RemoteReadChildRequest<Hash>),
#[codec(index = 17)]
ConsensusBatch(Vec<ConsensusMessage>),
}
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub struct CompactStatus<Hash, Number> {
pub version: u32,
pub min_supported_version: u32,
pub roles: Roles,
pub best_number: Number,
pub best_hash: Hash,
pub genesis_hash: Hash,
}
#[derive(Debug, PartialEq, Eq, Clone, Encode)]
pub struct Status<Hash, Number> {
pub version: u32,
pub min_supported_version: u32,
pub roles: Roles,
pub best_number: Number,
pub best_hash: Hash,
pub genesis_hash: Hash,
pub chain_status: Vec<u8>,
}
impl<Hash: Decode, Number: Decode> Decode for Status<Hash, Number> {
fn decode<I: Input>(value: &mut I) -> Result<Self, codec::Error> {
const LAST_CHAIN_STATUS_VERSION: u32 = 5;
let compact = CompactStatus::decode(value)?;
let chain_status = match <Vec<u8>>::decode(value) {
Ok(v) => v,
Err(e) => if compact.version <= LAST_CHAIN_STATUS_VERSION {
return Err(e)
} else {
Vec::new()
}
};
let CompactStatus {
version,
min_supported_version,
roles,
best_number,
best_hash,
genesis_hash,
} = compact;
Ok(Status {
version,
min_supported_version,
roles,
best_number,
best_hash,
genesis_hash,
chain_status,
})
}
}
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub struct BlockRequest<Hash, Number> {
pub id: RequestId,
pub fields: BlockAttributes,
pub from: FromBlock<Hash, Number>,
pub to: Option<Hash>,
pub direction: Direction,
pub max: Option<u32>,
}
#[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(BlockAnnounce {
header,
state,
data,
})
}
}
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub struct RemoteCallRequest<H> {
pub id: RequestId,
pub block: H,
pub method: String,
pub data: Vec<u8>,
}
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub struct RemoteReadRequest<H> {
pub id: RequestId,
pub block: H,
pub keys: Vec<Vec<u8>>,
}
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub struct RemoteReadChildRequest<H> {
pub id: RequestId,
pub block: H,
pub storage_key: Vec<u8>,
pub keys: Vec<Vec<u8>>,
}
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub struct RemoteHeaderRequest<N> {
pub id: RequestId,
pub block: N,
}
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub struct RemoteHeaderResponse<Header> {
pub id: RequestId,
pub header: Option<Header>,
pub proof: StorageProof,
}
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub struct RemoteChangesRequest<H> {
pub id: RequestId,
pub first: H,
pub last: H,
pub min: H,
pub max: H,
pub storage_key: Option<Vec<u8>>,
pub key: Vec<u8>,
}
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub struct RemoteChangesResponse<N, H> {
pub id: RequestId,
pub max: N,
pub proof: Vec<Vec<u8>>,
pub roots: Vec<(N, H)>,
pub roots_proof: StorageProof,
}
}