mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 12:17:58 +00:00
47e665be2e
* deprecate chain_status field of network handshake * Update client/network/src/protocol/message.rs remove unneeded whitespace. Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> Co-authored-by: Pierre Krieger <pierre.krieger1708@gmail.com>
514 lines
16 KiB
Rust
514 lines
16 KiB
Rust
// Copyright 2017-2020 Parity Technologies (UK) Ltd.
|
|
// This file is part of Substrate.
|
|
|
|
// Substrate is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
|
|
// Substrate is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
//! Network packet message types. These get serialized and put into the lower level protocol payload.
|
|
|
|
use bitflags::bitflags;
|
|
use sp_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,
|
|
FinalityProofRequest, FinalityProofResponse,
|
|
FromBlock, RemoteReadChildRequest,
|
|
};
|
|
use sc_client_api::StorageProof;
|
|
|
|
/// A unique ID of a request.
|
|
pub type RequestId = u64;
|
|
|
|
/// Type alias for using the message type using block type parameters.
|
|
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,
|
|
>;
|
|
|
|
/// Type alias for using the status type using block type parameters.
|
|
pub type Status<B> = generic::Status<
|
|
<B as BlockT>::Hash,
|
|
<<B as BlockT>::Header as HeaderT>::Number,
|
|
>;
|
|
|
|
/// Type alias for using the block request type using block type parameters.
|
|
pub type BlockRequest<B> = generic::BlockRequest<
|
|
<B as BlockT>::Hash,
|
|
<<B as BlockT>::Header as HeaderT>::Number,
|
|
>;
|
|
|
|
/// Type alias for using the BlockData type using block type parameters.
|
|
pub type BlockData<B> = generic::BlockData<
|
|
<B as BlockT>::Header,
|
|
<B as BlockT>::Hash,
|
|
<B as BlockT>::Extrinsic,
|
|
>;
|
|
|
|
/// Type alias for using the BlockResponse type using block type parameters.
|
|
pub type BlockResponse<B> = generic::BlockResponse<
|
|
<B as BlockT>::Header,
|
|
<B as BlockT>::Hash,
|
|
<B as BlockT>::Extrinsic,
|
|
>;
|
|
|
|
/// A set of transactions.
|
|
pub type Transactions<E> = Vec<E>;
|
|
|
|
// Bits of block data and associated artifacts to request.
|
|
bitflags! {
|
|
/// Node roles bitmask.
|
|
pub struct BlockAttributes: u8 {
|
|
/// Include block header.
|
|
const HEADER = 0b00000001;
|
|
/// Include block body.
|
|
const BODY = 0b00000010;
|
|
/// Include block receipt.
|
|
const RECEIPT = 0b00000100;
|
|
/// Include block message queue.
|
|
const MESSAGE_QUEUE = 0b00001000;
|
|
/// Include a justification for the block.
|
|
const JUSTIFICATION = 0b00010000;
|
|
}
|
|
}
|
|
|
|
impl Encode for BlockAttributes {
|
|
fn encode_to<T: Output>(&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)]
|
|
/// Block enumeration direction.
|
|
pub enum Direction {
|
|
/// Enumerate in ascending order (from child to parent).
|
|
Ascending = 0,
|
|
/// Enumerate in descending order (from parent to canonical child).
|
|
Descending = 1,
|
|
}
|
|
|
|
/// Block state in the chain.
|
|
#[derive(Debug, PartialEq, Eq, Clone, Copy, Encode, Decode)]
|
|
pub enum BlockState {
|
|
/// Block is not part of the best chain.
|
|
Normal,
|
|
/// Latest best block.
|
|
Best,
|
|
}
|
|
|
|
/// Remote call response.
|
|
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
|
|
pub struct RemoteCallResponse {
|
|
/// Id of a request this response was made for.
|
|
pub id: RequestId,
|
|
/// Execution proof.
|
|
pub proof: StorageProof,
|
|
}
|
|
|
|
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
|
|
/// Remote read response.
|
|
pub struct RemoteReadResponse {
|
|
/// Id of a request this response was made for.
|
|
pub id: RequestId,
|
|
/// Read proof.
|
|
pub proof: StorageProof,
|
|
}
|
|
|
|
/// Generic types.
|
|
pub mod generic {
|
|
use codec::{Encode, Decode, Input, Output};
|
|
use sp_runtime::Justification;
|
|
use crate::config::Roles;
|
|
use super::{
|
|
RemoteReadResponse, Transactions, Direction,
|
|
RequestId, BlockAttributes, RemoteCallResponse, ConsensusEngineId,
|
|
BlockState, StorageProof,
|
|
};
|
|
/// Consensus is mostly opaque to us
|
|
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
|
|
pub struct ConsensusMessage {
|
|
/// Identifies consensus engine.
|
|
pub engine_id: ConsensusEngineId,
|
|
/// Message payload.
|
|
pub data: Vec<u8>,
|
|
}
|
|
|
|
/// Block data sent in the response.
|
|
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
|
|
pub struct BlockData<Header, Hash, Extrinsic> {
|
|
/// Block header hash.
|
|
pub hash: Hash,
|
|
/// Block header if requested.
|
|
pub header: Option<Header>,
|
|
/// Block body if requested.
|
|
pub body: Option<Vec<Extrinsic>>,
|
|
/// Block receipt if requested.
|
|
pub receipt: Option<Vec<u8>>,
|
|
/// Block message queue if requested.
|
|
pub message_queue: Option<Vec<u8>>,
|
|
/// Justification if requested.
|
|
pub justification: Option<Justification>,
|
|
}
|
|
|
|
/// Identifies starting point of a block sequence.
|
|
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
|
|
pub enum FromBlock<Hash, Number> {
|
|
/// Start with given hash.
|
|
Hash(Hash),
|
|
/// Start with given block number.
|
|
Number(Number),
|
|
}
|
|
|
|
/// A network message.
|
|
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
|
|
pub enum Message<Header, Hash, Number, Extrinsic> {
|
|
/// Status packet.
|
|
Status(Status<Hash, Number>),
|
|
/// Block request.
|
|
BlockRequest(BlockRequest<Hash, Number>),
|
|
/// Block response.
|
|
BlockResponse(BlockResponse<Header, Hash, Extrinsic>),
|
|
/// Block announce.
|
|
BlockAnnounce(BlockAnnounce<Header>),
|
|
/// Transactions.
|
|
Transactions(Transactions<Extrinsic>),
|
|
/// Consensus protocol message.
|
|
Consensus(ConsensusMessage),
|
|
/// Remote method call request.
|
|
RemoteCallRequest(RemoteCallRequest<Hash>),
|
|
/// Remote method call response.
|
|
RemoteCallResponse(RemoteCallResponse),
|
|
/// Remote storage read request.
|
|
RemoteReadRequest(RemoteReadRequest<Hash>),
|
|
/// Remote storage read response.
|
|
RemoteReadResponse(RemoteReadResponse),
|
|
/// Remote header request.
|
|
RemoteHeaderRequest(RemoteHeaderRequest<Number>),
|
|
/// Remote header response.
|
|
RemoteHeaderResponse(RemoteHeaderResponse<Header>),
|
|
/// Remote changes request.
|
|
RemoteChangesRequest(RemoteChangesRequest<Hash>),
|
|
/// Remote changes reponse.
|
|
RemoteChangesResponse(RemoteChangesResponse<Number, Hash>),
|
|
/// Remote child storage read request.
|
|
RemoteReadChildRequest(RemoteReadChildRequest<Hash>),
|
|
/// Finality proof request.
|
|
FinalityProofRequest(FinalityProofRequest<Hash>),
|
|
/// Finality proof reponse.
|
|
FinalityProofResponse(FinalityProofResponse<Hash>),
|
|
/// Batch of consensus protocol messages.
|
|
ConsensusBatch(Vec<ConsensusMessage>),
|
|
/// Chain-specific message.
|
|
#[codec(index = "255")]
|
|
ChainSpecific(Vec<u8>),
|
|
}
|
|
|
|
impl<Header, Hash, Number, Extrinsic> Message<Header, Hash, Number, Extrinsic> {
|
|
/// Message id useful for logging.
|
|
pub fn id(&self) -> &'static str {
|
|
match self {
|
|
Message::Status(_) => "Status",
|
|
Message::BlockRequest(_) => "BlockRequest",
|
|
Message::BlockResponse(_) => "BlockResponse",
|
|
Message::BlockAnnounce(_) => "BlockAnnounce",
|
|
Message::Transactions(_) => "Transactions",
|
|
Message::Consensus(_) => "Consensus",
|
|
Message::RemoteCallRequest(_) => "RemoteCallRequest",
|
|
Message::RemoteCallResponse(_) => "RemoteCallResponse",
|
|
Message::RemoteReadRequest(_) => "RemoteReadRequest",
|
|
Message::RemoteReadResponse(_) => "RemoteReadResponse",
|
|
Message::RemoteHeaderRequest(_) => "RemoteHeaderRequest",
|
|
Message::RemoteHeaderResponse(_) => "RemoteHeaderResponse",
|
|
Message::RemoteChangesRequest(_) => "RemoteChangesRequest",
|
|
Message::RemoteChangesResponse(_) => "RemoteChangesResponse",
|
|
Message::RemoteReadChildRequest(_) => "RemoteReadChildRequest",
|
|
Message::FinalityProofRequest(_) => "FinalityProofRequest",
|
|
Message::FinalityProofResponse(_) => "FinalityProofResponse",
|
|
Message::ConsensusBatch(_) => "ConsensusBatch",
|
|
Message::ChainSpecific(_) => "ChainSpecific",
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Status sent on connection.
|
|
// TODO https://github.com/paritytech/substrate/issues/4674: replace the `Status`
|
|
// struct with this one, after waiting a few releases beyond `NetworkSpecialization`'s
|
|
// removal (https://github.com/paritytech/substrate/pull/4665)
|
|
//
|
|
// and set MIN_VERSION to 6.
|
|
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
|
|
pub struct CompactStatus<Hash, Number> {
|
|
/// Protocol version.
|
|
pub version: u32,
|
|
/// Minimum supported version.
|
|
pub min_supported_version: u32,
|
|
/// Supported roles.
|
|
pub roles: Roles,
|
|
/// Best block number.
|
|
pub best_number: Number,
|
|
/// Best block hash.
|
|
pub best_hash: Hash,
|
|
/// Genesis block hash.
|
|
pub genesis_hash: Hash,
|
|
}
|
|
|
|
/// Status sent on connection.
|
|
#[derive(Debug, PartialEq, Eq, Clone, Encode)]
|
|
pub struct Status<Hash, Number> {
|
|
/// Protocol version.
|
|
pub version: u32,
|
|
/// Minimum supported version.
|
|
pub min_supported_version: u32,
|
|
/// Supported roles.
|
|
pub roles: Roles,
|
|
/// Best block number.
|
|
pub best_number: Number,
|
|
/// Best block hash.
|
|
pub best_hash: Hash,
|
|
/// Genesis block hash.
|
|
pub genesis_hash: Hash,
|
|
/// DEPRECATED. Chain-specific status.
|
|
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,
|
|
})
|
|
}
|
|
}
|
|
|
|
/// Request block data from a peer.
|
|
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
|
|
pub struct BlockRequest<Hash, Number> {
|
|
/// Unique request id.
|
|
pub id: RequestId,
|
|
/// Bits of block data to request.
|
|
pub fields: BlockAttributes,
|
|
/// Start from this block.
|
|
pub from: FromBlock<Hash, Number>,
|
|
/// End at this block. An implementation defined maximum is used when unspecified.
|
|
pub to: Option<Hash>,
|
|
/// Sequence direction.
|
|
pub direction: Direction,
|
|
/// Maximum number of blocks to return. An implementation defined maximum is used when unspecified.
|
|
pub max: Option<u32>,
|
|
}
|
|
|
|
/// Response to `BlockRequest`
|
|
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
|
|
pub struct BlockResponse<Header, Hash, Extrinsic> {
|
|
/// Id of a request this response was made for.
|
|
pub id: RequestId,
|
|
/// Block data for the requested sequence.
|
|
pub blocks: Vec<BlockData<Header, Hash, Extrinsic>>,
|
|
}
|
|
|
|
/// Announce a new complete relay chain block on the network.
|
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
|
pub struct BlockAnnounce<H> {
|
|
/// New block header.
|
|
pub header: H,
|
|
/// Block state. TODO: Remove `Option` and custom encoding when v4 becomes common.
|
|
pub state: Option<BlockState>,
|
|
/// Data associated with this block announcement, e.g. a candidate message.
|
|
pub data: Option<Vec<u8>>,
|
|
}
|
|
|
|
// Custom Encode/Decode impl to maintain backwards compatibility with v3.
|
|
// This assumes that the packet contains nothing but the announcement message.
|
|
// TODO: Get rid of it once protocol v4 is common.
|
|
impl<H: Encode> Encode for BlockAnnounce<H> {
|
|
fn encode_to<T: Output>(&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)]
|
|
/// Remote call request.
|
|
pub struct RemoteCallRequest<H> {
|
|
/// Unique request id.
|
|
pub id: RequestId,
|
|
/// Block at which to perform call.
|
|
pub block: H,
|
|
/// Method name.
|
|
pub method: String,
|
|
/// Call data.
|
|
pub data: Vec<u8>,
|
|
}
|
|
|
|
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
|
|
/// Remote storage read request.
|
|
pub struct RemoteReadRequest<H> {
|
|
/// Unique request id.
|
|
pub id: RequestId,
|
|
/// Block at which to perform call.
|
|
pub block: H,
|
|
/// Storage key.
|
|
pub keys: Vec<Vec<u8>>,
|
|
}
|
|
|
|
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
|
|
/// Remote storage read child request.
|
|
pub struct RemoteReadChildRequest<H> {
|
|
/// Unique request id.
|
|
pub id: RequestId,
|
|
/// Block at which to perform call.
|
|
pub block: H,
|
|
/// Child Storage key.
|
|
pub storage_key: Vec<u8>,
|
|
/// Child trie source information.
|
|
pub child_info: Vec<u8>,
|
|
/// Child type, its required to resolve `child_info`
|
|
/// content and choose child implementation.
|
|
pub child_type: u32,
|
|
/// Storage key.
|
|
pub keys: Vec<Vec<u8>>,
|
|
}
|
|
|
|
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
|
|
/// Remote header request.
|
|
pub struct RemoteHeaderRequest<N> {
|
|
/// Unique request id.
|
|
pub id: RequestId,
|
|
/// Block number to request header for.
|
|
pub block: N,
|
|
}
|
|
|
|
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
|
|
/// Remote header response.
|
|
pub struct RemoteHeaderResponse<Header> {
|
|
/// Id of a request this response was made for.
|
|
pub id: RequestId,
|
|
/// Header. None if proof generation has failed (e.g. header is unknown).
|
|
pub header: Option<Header>,
|
|
/// Header proof.
|
|
pub proof: StorageProof,
|
|
}
|
|
|
|
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
|
|
/// Remote changes request.
|
|
pub struct RemoteChangesRequest<H> {
|
|
/// Unique request id.
|
|
pub id: RequestId,
|
|
/// Hash of the first block of the range (including first) where changes are requested.
|
|
pub first: H,
|
|
/// Hash of the last block of the range (including last) where changes are requested.
|
|
pub last: H,
|
|
/// Hash of the first block for which the requester has the changes trie root. All other
|
|
/// affected roots must be proved.
|
|
pub min: H,
|
|
/// Hash of the last block that we can use when querying changes.
|
|
pub max: H,
|
|
/// Storage child node key which changes are requested.
|
|
pub storage_key: Option<Vec<u8>>,
|
|
/// Storage key which changes are requested.
|
|
pub key: Vec<u8>,
|
|
}
|
|
|
|
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
|
|
/// Remote changes response.
|
|
pub struct RemoteChangesResponse<N, H> {
|
|
/// Id of a request this response was made for.
|
|
pub id: RequestId,
|
|
/// Proof has been generated using block with this number as a max block. Should be
|
|
/// less than or equal to the RemoteChangesRequest::max block number.
|
|
pub max: N,
|
|
/// Changes proof.
|
|
pub proof: Vec<Vec<u8>>,
|
|
/// Changes tries roots missing on the requester' node.
|
|
pub roots: Vec<(N, H)>,
|
|
/// Missing changes tries roots proof.
|
|
pub roots_proof: StorageProof,
|
|
}
|
|
|
|
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
|
|
/// Finality proof request.
|
|
pub struct FinalityProofRequest<H> {
|
|
/// Unique request id.
|
|
pub id: RequestId,
|
|
/// Hash of the block to request proof for.
|
|
pub block: H,
|
|
/// Additional data blob (that both requester and provider understood) required for proving finality.
|
|
pub request: Vec<u8>,
|
|
}
|
|
|
|
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
|
|
/// Finality proof response.
|
|
pub struct FinalityProofResponse<H> {
|
|
/// Id of a request this response was made for.
|
|
pub id: RequestId,
|
|
/// Hash of the block (the same as in the FinalityProofRequest).
|
|
pub block: H,
|
|
/// Finality proof (if available).
|
|
pub proof: Option<Vec<u8>>,
|
|
}
|
|
}
|