Messages
All message sent in the network are of type PeerMessage
. They are encoded using Borsh which allows a rich structure, small size and fast encoding/decoding. For details about data structures used as part of the message see the reference code.
Encoding
A PeerMessage
is converted into an array of bytes (Vec<u8>
) using borsh serialization. An encoded message is conformed by 4 bytes with the length of the serialized PeerMessage
concatenated with the serialized PeerMessage
.
Check Borsh specification details to see how it handles each data structure.
Data structures
PeerID
The id of a peer in the network is its PublicKey.
#![allow(unused)] fn main() { struct PeerId(PublicKey); }
PeerInfo
#![allow(unused)] fn main() { struct PeerInfo { id: PeerId, addr: Option<SocketAddr>, account_id: Option<AccountId>, } }
PeerInfo
contains relevant information to try to connect to other peer. SocketAddr
is a tuple of the form: IP:port
.
AccountID
#![allow(unused)] fn main() { type AccountId = String; }
PeerMessage
#![allow(unused)] fn main() { enum PeerMessage { Handshake(Handshake), HandshakeFailure(PeerInfo, HandshakeFailureReason), /// When a failed nonce is used by some peer, this message is sent back as evidence. LastEdge(Edge), /// Contains accounts and edge information. Sync(SyncData), RequestUpdateNonce(EdgeInfo), ResponseUpdateNonce(Edge), PeersRequest, PeersResponse(Vec<PeerInfo>), BlockHeadersRequest(Vec<CryptoHash>), BlockHeaders(Vec<BlockHeader>), BlockRequest(CryptoHash), Block(Block), Transaction(SignedTransaction), Routed(RoutedMessage), /// Gracefully disconnect from other peer. Disconnect, Challenge(Challenge), } }
AnnounceAccount
Each peer should announce its account
#![allow(unused)] fn main() { struct AnnounceAccount { /// AccountId to be announced. account_id: AccountId, /// PeerId from the owner of the account. peer_id: PeerId, /// This announcement is only valid for this `epoch`. epoch_id: EpochId, /// Signature using AccountId associated secret key. signature: Signature, } }
Handshake
#![allow(unused)] fn main() { struct Handshake { /// Protocol version. pub version: u32, /// Oldest supported protocol version. pub oldest_supported_version: u32, /// Sender's peer id. pub peer_id: PeerId, /// Receiver's peer id. pub target_peer_id: PeerId, /// Sender's listening addr. pub listen_port: Option<u16>, /// Peer's chain information. pub chain_info: PeerChainInfoV2, /// Info for new edge. pub edge_info: EdgeInfo, } }
Edge
#![allow(unused)] fn main() { struct Edge { /// Since edges are not directed `peer0 < peer1` should hold. peer0: PeerId, peer1: PeerId, /// Nonce to keep tracking of the last update on this edge. nonce: u64, /// Signature from parties validating the edge. These are signature of the added edge. signature0: Signature, signature1: Signature, /// Info necessary to declare an edge as removed. /// The bool says which party is removing the edge: false for Peer0, true for Peer1 /// The signature from the party removing the edge. removal_info: Option<(bool, Signature)>, } }
EdgeInfo
#![allow(unused)] fn main() { struct EdgeInfo { nonce: u64, signature: Signature, } }
RoutedMessage
#![allow(unused)] fn main() { struct RoutedMessage { /// Peer id which is directed this message. /// If `target` is hash, this a message should be routed back. target: PeerIdOrHash, /// Original sender of this message author: PeerId, /// Signature from the author of the message. If this signature is invalid we should ban /// last sender of this message. If the message is invalid we should ben author of the message. signature: Signature, /// Time to live for this message. After passing through some hop this number should be /// decreased by 1. If this number is 0, drop this message. ttl: u8, /// Message body: RoutedMessageBody, } }
RoutedMessageBody
#![allow(unused)] fn main() { enum RoutedMessageBody { BlockApproval(Approval), ForwardTx(SignedTransaction), TxStatusRequest(AccountId, CryptoHash), TxStatusResponse(FinalExecutionOutcomeView), QueryRequest { query_id: String, block_id_or_finality: BlockIdOrFinality, request: QueryRequest, }, QueryResponse { query_id: String, response: Result<QueryResponse, String>, }, ReceiptOutcomeRequest(CryptoHash), ReceiptOutComeResponse(ExecutionOutcomeWithIdAndProof), StateRequestHeader(ShardId, CryptoHash), StateRequestPart(ShardId, CryptoHash, u64), StateResponse(StateResponseInfo), PartialEncodedChunkRequest(PartialEncodedChunkRequestMsg), PartialEncodedChunkResponse(PartialEncodedChunkResponseMsg), PartialEncodedChunk(PartialEncodedChunk), Ping(Ping), Pong(Pong), } }
CryptoHash
CryptoHash
are objects with 256 bits of information.
#![allow(unused)] fn main() { pub struct Digest(pub [u8; 32]); pub struct CryptoHash(pub Digest); }