Skip to main content

4. Networking

info

This chapter, in its current form, is incomplete and considered work in progress. Authors appreciate receiving requests for clarification or any reports regarding deviation from the current Polkadot network protocol. This can be done by filing an issue in Polkadot Specification repository.

4.1. Introduction

The Polkadot network is decentralized and does not rely on any central authority or entity to achieve its fullest potential of provided functionality. The networking protocol is based on a family of open protocols, including protocol implemented libp2p, e.g., the distributed Kademlia hash table, which is used for peer discovery.

This chapter walks through the behavior of the networking implementation of the Polkadot Host and defines the network messages. The implementation details of the libp2p protocols used are specified in external sources as described in Section 4.2.

4.2. External Documentation

Complete specification of the Polkadot networking protocol relies on the following external protocols:

  • libp2p - libp2p is a modular peer-to-peer networking stack composed of many modules and different parts. includes the multiplexing protocols and

  • libp2p addressing - The Polkadot Host uses the libp2p addressing system to identify and connect to peers.

  • Kademlia - Kademlia is a distributed hash table for decentralized peer-to-peer networks. The Polkadot Host uses Kademlia for peer discovery.

  • Noise - The Noise protocol is a framework for building cryptographic protocols. The Polkadot Host uses Noise to establish the encryption layer to remote peers.

  • yamux - yamux is a multiplexing protocol developed by HashiCorp. It is the de-facto standard for the Polkadot Host. Section 4.7. describes the subprotocol in more detail.

  • Protocol Buffers - Protocol Buffers is a language-neutral, platform-neutral mechanism for serializing structured data and is developed by Google. The Polkadot Host uses Protocol Buffers to serialize specific messages, as clarified in Section 4.8..

4.3. Node Identities

Like any other distributed system, each Polkadot Host node has a unique global identifier. This identifier, called PeerId, serves as a singular reference to a particular node within the overall network. In Polkadot, each node is required to maintain its own pair of ED25519 cryptographic keys from which the PeerId is derived.

The Polkadot node’s PeerId is structured based on the libp2p specification but does not fully conform to the specification. In particular, it does not support CID and the only supported key type is ED25519. The PeerId is built by hashing the encoded public key with multihash and represented as follows:

Definition 34. PeerId

The byte representation of the PeerId is always of the following bytes in this exact order:

b0=0{b}_{{0}}={0}
b1=36{b}_{{1}}={36}
b2=8{b}_{{2}}={8}
b3=1{b}_{{3}}={1}
b4=18{b}_{{4}}={18}
b5=32{b}_{{5}}={32}
b6..37={b}_{{{6}.{.37}}}=\ldots

where

  • b0{b}_{{0}} is the multihash prefix of value 0{0} (implying no hashing is used).

  • b1{b}_{{1}} the length of the PeerId (remaining bytes).

  • b2{b}_{{2}} and b3{b}_{{3}} are a protobuf encoded field-value pair indicating the used key type (field 1{1} of value 1{1} implies ED25519).

  • b4{b}_{{4}}, b5{b}_{{5}} and b6..37{b}_{{{6}.{.37}}} are a protobuf encoded field-value pair where b5{b}_{{5}} indicates the length of the public key followed by the raw ED25519 public key itself, which varies for each Polkadot Host and is always 32 bytes (field 2{2} contains the public key, which has a field value length prefix).

4.4. Network bootstrap and discovery

The Polkadot Host uses various mechanisms to find peers within the network, to establish and maintain a list of peers, and to share that list with other peers from the network as follows:

  • Bootstrap nodes are hard-coded node identities and addresses provided by the genesis state (Section A.3.3.).

  • mDNS is a protocol that performs a broadcast to the local network. Nodes that might be listening can respond to the broadcast. The libp2p mDNS specification defines this process in more detail. This protocol is an optional implementation detail for Polkadot Host implementers and is not required to participate in the Polkadot network.

  • Kademlia requests invoking Kademlia requests, where nodes respond with their list of available peers. Kademlia requests are performed on a specific substream as described in Section 4.7..

4.5. Connection establishment

Polkadot nodes connect to peers by establishing a TCP connection. Once established, the node initiates a handshake with the remote peers on the encryption layer. An additional layer on top of the encryption layer, known as the multiplexing layer, allows a connection to be split into substreams, as described by the yamux specification, either by the local or remote node.

The Polkadot node supports two types of substream protocols. Section 4.7. describes the usage of each type in more detail:

  • Request-Response substreams: After the protocol is negotiated by the multiplexing layer, the initiator sends a single message containing a request. The responder then sends a response, after which the substream is then immediately closed. The requests and responses are prefixed with their LEB128 encoded length.

  • Notification substreams. After the protocol is negotiated, the initiator sends a single handshake message. The responder can then either accept the substream by sending its own handshake or reject it by closing the substream. After the substream has been accepted, the initiator can send an unbound number of individual messages. The responder keeps its sending side of the substream open, despite not sending anything anymore, and can later close it in order to signal to the initiator that it no longer wishes to communicate.

    Handshakes and messages are prefixed with their LEB128 encoded lengths. A handshake can be empty, in which case the length prefix would be 0.

Connections are established by using the following protocols:

  • /noise - a protocol that is announced when a connection to a peer is established.

  • /multistream/1.0.0 - a protocol that is announced when negotiating an encryption protocol or a substream.

  • /yamux/1.0.0 - a protocol used during yamux negotiation. See Section 4.7. for more information.

The Polkadot Host can establish a connection with any peer of which it knows the address. The Polkadot Host supports multiple networking protocols:

  • TCP/IP with addresses in the form of /ip4/1.2.3.4/tcp/30333 to establish a TCP connection and negotiate encryption and a multiplexing layer.

  • WebSocket with addresses in the form of /ip4/1.2.3.4/tcp/30333/ws to establish a TCP connection and negotiate the WebSocket protocol within the connection. Additionally, the encryption and multiplexing layer are negotiated within the WebSocket connection.

  • DNS addresses in form of /dns/example.com/tcp/30333 and /dns/example.com/tcp/30333/ws.

The addressing system is described in the libp2p addressing specification. After a base-layer protocol is established, the Polkadot Host will apply the Noise protocol to establish the encryption layer as described in Section 4.6..

4.6. Encryption Layer

Polkadot protocol uses the libp2p Noise framework to build an encryption protocol. The Noise protocol is a framework for building encryption protocols. libp2p utilizes that protocol for establishing encrypted communication channels. Refer to the libp2p Secure Channel Handshake specification for a detailed description.

Polkadot nodes use the XX handshake pattern to establish a connection between peers. The three following steps are required to complete the handshake process:

  1. The initiator generates a key pair and sends the public key to the responder. The Noise specification and the libp2p PeerId specification describe keypairs in more detail.

  2. The responder generates its own key pair and sends its public key back to the initiator. After that, the responder derives a shared secret and uses it to encrypt all further communication. The responder now sends its static Noise public key (which may change anytime and does not need to be persisted on disk), its libp2p public key, and a signature of the static Noise public key signed with the libp2p public key.

  3. The initiator derives a shared secret and uses it to encrypt all further communication. It also sends its static Noise public key, libp2p public key, and signature to the responder.

After these three steps, both the initiator and responder derive a new shared secret using the static and session-defined Noise keys, which are used to encrypt all further communication.

4.7. Protocols and Substreams

After the node establishes a connection with a peer, the use of multiplexing allows the Polkadot Host to open substreams. libp2p uses the yamux protocol to manage substreams and to allow the negotiation of application-specific protocols, where each protocol serves a specific utility.

The Polkadot Host uses multiple substreams whose usage depends on a specific purpose. Each substream is either a Request-Response substream or a Notification substream, as described in Section 4.5..

info

The prefixes on those substreams are known as protocol identifiers and are used to segregate communications to specific networks. This prevents any interference with other networks. dot is used exclusively for Polkadot. Kusama, for example, uses the protocol identifier ksmcc3.

  • /ipfs/ping/1.0.0 - Open a standardized substream libp2p to a peer and initialize a ping to verify if a connection is still alive. If the peer does not respond, the connection is dropped. This is a Request-Response substream.

    Further specification and reference implementations are available in the libp2p documentation.

  • /ipfs/id/1.0.0 - Open a standardized libp2p substream to a peer to ask for information about that peer. This is a Request-Response substream, but the initiator does not send any message to the responder and only waits for the response.

    Further specification and reference implementations are available in the libp2p documentation.

  • /dot/kad - Open a standardized substream for Kademlia FIND_NODE requests. This is a Request-Response substream, as defined by the libp2p standard.

    Further specification and reference implementation are available on Wikipedia respectively the golang Github repository.

  • /91b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb49219da7a70ce90c3/light/2 - a request and response protocol that allows a light client to request information about the state. This is a Request-Response substream.

    The messages are specified in Section 7.4..

info

For backward compatibility reasons, /dot/light/2 is also a valid substream for those messages.

  • /91b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb49219da7a70ce90c3/block-announces/1 - a substream/notification protocol which sends blocks to connected peers. This is a Notification substream.

    The messages are specified in Section 4.8.2..

info

For backward compatibility reasons, /dot/block-announces/1 is also a valid substream for those messages.

  • /91b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb49219da7a70ce90c3/sync/2 - a request and response protocol that allows the Polkadot Host to request information about blocks. This is a Request-Response substream.

    The messages are specified in Section 4.8.3..

info

For backward compatibility reasons, /dot/sync/2 is also a valid substream for those messages.

  • /91b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb49219da7a70ce90c3/sync/warp - a request and response protocol that allows the Polkadot Host to perform a warp sync request. This is a Request-Response substream.

    The messages are specified in Section 4.8.5..

info

For backward compatibility reasons, /dot/sync/warp is also a valid substream for those messages.

  • /91b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb49219da7a70ce90c3/transactions/1 - a substream/notification protocol which sends transactions to connected peers. This is a Notification substream.

    The messages are specified in Section 4.8.6..

info

For backward compatibility reasons, /dot/transactions/1 is also a valid substream for those messages.

  • /91b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb49219da7a70ce90c3/grandpa/1 - a substream/notification protocol that sends GRANDPA votes to connected peers. This is a Notification substream.

    The messages are specified in Section 4.8.7..

info

For backward compatibility reasons, /paritytech/grandpa/1 is also a valid substream for those messages.

  • /91b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb49219da7a70ce90c3/beefy/1 - a substream/notification protocol which sends signed BEEFY payloads, as described in Section 6.7., to connected peers. This is a Notification substream.

    The messages are specified in Section 4.8.8..

info

For backward compatibility reasons, /paritytech/beefy/1 is also a valid substream for those messages.

4.8. Network Messages

The Polkadot Host must actively communicate with the network in order to participate in the validation process or act as a full node.

info

The Polkadot network originally only used SCALE encoding for all message formats. Meanwhile, Protobuf has been adopted for certain messages. The encoding of each listed message is always SCALE encoded unless Protobuf is explicitly mentioned. Encoding and message formats are subject to change.

4.8.1. Discovering authorities

The discovery mechanism enables Polkadot nodes to both publish their local addresses and learn about other nodes' identifiers and addresses. The Authority discovery mechanism differs from the bootstrap mechanism, described in Section 4.4., in that it restricts the discovery output to nodes currently holding the authority role (e.g., validators).

4.8.1.1. Requesting authority identifier and addresses

The following requests are exposed by the discovery authority to Polkadot nodes.

Definition 35. Authority addresses request

An authority addresses request is a request that Polkadot nodes can send to the authority discovery mechanism in order to request the addresses of an authority node. The request has the following format:

get_addresses_by_authority_id(authorityId)\texttt{get\_addresses\_by\_authority\_id}{\left(\texttt{authorityId}\right)}

where

  • authorityId\texttt{authorityId} is the authorityId 256-bit identifier representing the public key of the targeted authority node.

expected response

The response to the previous query includes an enum with one of the following values:

ValueDescription
NoneA type representing no value
HashSet[Multiaddr]An unordered collection of unique Multiaddr elements

with

Definition 36. Authority identifier request

An authority identifier request is a request that Polkadot nodes can send to the authority discovery mechanism in order to request the AuthorityId of an authority node. The request has the following format:

get_authority_ids_by_peer_id(PeerId)\texttt{get\_authority\_ids\_by\_peer\_id}{\left(\texttt{PeerId}\right)}

where

  • PeerId\texttt{PeerId} is the Polkadot node’s PeerId (Definition 34).

expected response The response to the previous query includes an enum with one of the following values:

ValueDescription
NoneA type representing no value
HashSet[authorityId]An unordered collection of unique authorityId elements

with

  • authorityId is the 256-bit identifier representing the public key of the requested PeerId.

4.8.1.2. Publishing and discovering addresses

The authority discovery mechanism triggers operations to publish a SignedAuthorityRecord of the addresses of authorities it knows from its current and next authority sets into the DHT. The SignedAuthorityRecord and the publish operation are created as follows:

Definition 37. Signed Authority Record

The SignedAuthorityRecord is a Protobuf serialized structure representing the authority records and signature to send over the wire. It is defined in the following format:

TypeIdDescription
AuthorityRecord1Serialized authority record
bytes2An Schnorrkel/Ristretto x25519 ("sr25519") signature
PeerSignature3Serialized peer signature

where

AuthorityRecord is a serialized Protobuf structure that lists the addresses of authority nodes that are currently part of the authority set.

TypeIdDescription
repeated bytes1Binary representation of zero or more multiaddresses through which a node is reachable

PeerSignature is a Protobuf serialized structure indicating the signature and public key used to sign and verify the AuthorityRecord. This is the protobuf structure used to exchange the signature with other nodes.

TypeIdDescription
bytes1An sr25519 signature
bytes2A sr25519 public key used to verify the signature
Definition 38. Publishing addresses

For each authority node ii in the current authority set, the local node invokes a put_value operation that triggers the publishing operation into the DHT with the following format:

put_value(KademliaKeyi,SigAR)\texttt{put\_value}{\left(\texttt{KademliaKey}_{i} , \texttt{Sig}_{AR}\right)}

where

  • KademliaKeyi\texttt{KademliaKey}_{i} is the Sha256Sha256 hash of the authorityId of node ii.
  • SigAR\texttt{Sig}_{AR} is the SignedAuthorityRecord described above(Definition 37).

The authority discovery mechanism also invokes operations on the DHT to discover the addresses of authority nodes, as follows:

Definition 39. Discovering addresses

Periodically, the authority discovery performs a number of get_value operations in the following format:

get_value(KademliaKeyi)\texttt{get\_value}{\left(\texttt{KademliaKey}_{i}\right)}

where

  • KademliaKeyi\texttt{KademliaKey}_{i} is the Sha256Sha256 hash of the authorityId of node ii selected from the current authority set.

4.8.2. Announcing blocks

When the node creates or receives a new block, it must be announced to the network. Other nodes within the network will track this announcement and can request information about this block. The mechanism for tracking announcements and requesting the required data is implementation-specific.

Block announcements, requests, and responses are sent over the substream as described in Definition 40.

Definition 40. Block Announce Handshake

The BlockAnnounceHandshake initializes a substream to a remote peer. Once established, all BlockAnounce messages (Definition 41) created by the node are sent to the /dot/block-announces/1 substream.

The BlockAnnounceHandshake is a structure of the following format:

BAh=EncSC(R,NB,hB,hG){B}{A}_{{h}}=\text{Enc}_{{\text{SC}}}{\left({R},{N}_{{B}},{h}_{{B}},{h}_{{G}}\right)}

where

R={1The node is a full node2The node is a light client4The node is a validator{R}={\left\lbrace\begin{matrix}{1}&\text{The node is a full node}\\{2}&\text{The node is a light client}\\{4}&\text{The node is a validator}\end{matrix}\right.}
NB=Best block number according to the node{N}_{{B}}=\text{Best block number according to the node}
hB=Best block hash according to the node{h}_{{B}}=\text{Best block hash according to the node}
hG=Genesis block hash according to the node{h}_{{G}}=\text{Genesis block hash according to the node}
Definition 41. Block Announce

The BlockAnnounce message is sent to the specified substream and indicates to remote peers that the node has either created or received a new block.

The message is structured in the following format:

BA=EncSC(Head(B),b){B}{A}=\text{Enc}_{{\text{SC}}}{\left(\text{Head}{\left({B}\right)},{b}\right)}

where

Head(B)=Header of the announced block\text{Head}{\left({B}\right)}=\text{Header of the announced block}
b={0Is not part of the best chain1Is the best block according to the node{b}={\left\lbrace\begin{matrix}{0}&\text{Is not part of the best chain}\\{1}&\text{Is the best block according to the node}\end{matrix}\right.}

4.8.3. Requesting Blocks

Block requests can be used to retrieve a range of blocks from peers. Those messages are sent over the /dot/sync/2 substream.

Definition 42. Block Request

The BlockRequest message is a Protobuf serialized structure of the following format:

TypeIdDescriptionValue
uint321Bits of block data to requestBf{B}_{{f}}
oneofStart from this blockBs{B}_{{s}}
Direction5Sequence direction, interpreted as Id 0 (ascending) if missing.
uint326Maximum amount (optional)Bm{B}_{{m}}

where

  • Bf{B}_{{f}} indicates all the fields that should be included in the request. its big-endian encoded bitmask that applies to all desired fields with bitwise OR operations. For example, the Bf{B}_{{f}} value to request Header and Justification is 0001 0001 (17).

    FieldValue
    Header0000 0001
    Body0000 0010
    Justification0001 0000
  • Bs{B}_{{s}} is a Protobuf structure indicating a varying data type (enum) of the following values:

    TypeIdDescription
    bytes2The block hash
    bytes3The block number
  • Direction is a Protobuf structure indicating the sequence direction of the requested blocks. The structure is a varying data type (enum) of the following format:

    IdDescription
    0Enumerate in ascending order (from child to parent)
    1Enumerate in descending order (from parent to canonical child)
  • Bm{B}_{{m}} is the number of blocks to be returned. An implementation-defined maximum is used when unspecified.

Definition 43. Block Response

The BlockResponse message is received after sending a BlockRequest message to a peer. The message is a Protobuf serialized structure of the following format:

TypeIdDescription
Repeated BlockData1Block data for the requested sequence

where BlockData is a Protobuf structure containing the requested blocks. Do note that the optional values are either present or absent depending on the requested fields (bitmask value). The structure has the following format:

TypeIdDescriptionValue
bytes1Block header hashDefinition 12
bytes2Block header (optional)Definition 10
repeated bytes3Block body (optional)Definition 13
bytes4Block receipt (optional)
bytes5Block message queue (optional)
bytes6Justification (optional)Definition 83
bool7Indicates whether the justification is empty (i.e., should be ignored)

4.8.4. Requesting States

The Polkadot Host can request the state in the form of a key/value list at a specified block.

When receiving state entries from the state response messages (Definition 45), the node can verify the entries with the entry proof (id 1 in KeyValueStorage) against the Merkle root in the block header (of the block specified in Definition 44). Once the state response message claims that all entries have been sent (id 3 in KeyValueStorage), the node can use all collected entry proofs and validate them against the Merkle root to confirm that claim.

See the synchronization chapter for more information (Chapter 3).

Definition 44. State Request

A state request is sent to a peer to request the state at a specified block. The message is a single 32-byte Blake2 hash which indicates the block from which the sync should start.

Depending on what substream is used, the remote peer either sends back a state response (Definition 45) on the /dot/sync/2 substream or a warp sync proof (Definition 46) on the /dot/sync/warp.

Definition 45. State Response

The state response is sent to the peer that initialized the state request (Definition 44) and contains a list of key/value entries with an associated proof. This response is sent continuously until all key/value pairs have been submitted.

TypeIdDescription
repeated KeyValueStateEntry1State entries
bytes2State proof

where KeyValueStateEntry is of the following format:

TypeIdDescription
bytes1Root of the entry, empty if top-level
repeated StateEntry2Collection of key/values
bool3Equal 'true' if there are no more keys to return.

and StateEntry:

TypeIdDescription
bytes1The key of the entry
bytes2The value of the entry

4.8.5. Warp Sync

The warp sync protocols allow nodes to retrieve blocks from remote peers where authority set changes occurred. This can be used to speed up synchronization to the latest state.

See the synchronization chapter for more information (Chapter 3).

Definition 46. Warp Sync Proof

The warp sync proof message, P{P}, is sent to the peer that initialized the state request (Definition 44) on the /dot/sync/warp substream and contains accumulated proof of multiple authority set changes (Section 3.3.2.). It’s a data structure of the following format:

P=(fxfy,c){P}={\left({{f}_{{x}}\ldots}{{f}_{{y}},}{c}\right)}

fxfy{{f}_{{x}}\ldots}{{f}_{{y}}} is an array consisting of warp sync fragments of the following format:

fx=(Bh,Jr,stage(B)){{f}_{{x}}=}{\left({B}_{{h}},{J}^{{{r},\text{stage}}}{\left({B}\right)}\right)}

where Bh{B}_{{h}} is the last block header containing a digest item (Definition 11) signaling an authority set change from which the next authority set change can be fetched from. Jr,stage(B){J}^{{{r},\text{stage}}}{\left({B}\right)} is the GRANDPA justification (Definition 83) and c{c} is a boolean that indicates whether the warp sync has been completed.

4.8.6. Transactions

Transactions (Section 2.3.) are sent directly to peers with which the Polkadot Host has an open transaction substream (Definition 47). Polkadot Host implementers should implement a mechanism that only sends a transaction once to each peer and avoids sending duplicates. Sending duplicate transactions might result in undefined consequences such as being blocked for bad behavior by peers.

The mechanism for managing transactions is further described in Section Section 2.3..

Definition 47. Transaction Message

The transactions message is the structure of how the transactions are sent over the network. It is represented by MT{M}_{{T}} and is defined as follows:

MT=EncSC(C1,,Cn){M}_{{T}}\:=\text{Enc}_{{\text{SC}}}{\left({C}_{{1}},\ldots,{C}_{{n}}\right)}

in which

Ci=EncSC(Ei){C}_{{i}}\:=\text{Enc}_{{\text{SC}}}{\left({E}_{{i}}\right)}

Where each Ei{E}_{{i}} is a byte array and represents a separate extrinsic. The Polkadot Host is agnostic about the content of an extrinsic and treats it as a blob of data.

Transactions are sent over the /dot/transactions/1 substream.

4.8.7. GRANDPA Messages

The exchange of GRANDPA messages is conducted on the substream. The process for the creation and distribution of these messages is described in Chapter 6. The underlying messages are specified in this section.

Definition 48. Grandpa Gossip Message

A GRANDPA gossip message, M{M}, is a varying datatype (Definition 198) which identifies the message type that is cast by a voter followed by the message itself.

M={0Vote messageVm1Commit messageCm2Neighbor messageNm3Catch-up request messageRm4Catch-up messageUm{M}={\left\lbrace\begin{matrix}{0}&\text{Vote message}&{V}_{{m}}\\{1}&\text{Commit message}&{C}_{{m}}\\{2}&\text{Neighbor message}&{N}_{{m}}\\{3}&\text{Catch-up request message}&{R}_{{m}}\\{4}&\text{Catch-up message}&{U}_{{m}}\end{matrix}\right.}

where

Definition 49. GRANDPA Vote Messages

A GRANDPA vote message by voter v{v}, Mvr,stage{{M}_{{v}}^{{{r},\text{stage}}}}, is gossip to the network by voter v{v} with the following structure:

Mvr,stage(B)=EncSC(r,idV,SigMsg){{M}_{{v}}^{{{r},\text{stage}}}}{\left({B}\right)}\:=\text{Enc}_{{\text{SC}}}{\left({r},\text{id}_{{{\mathbb{{V}}}}},\text{SigMsg}\right)}
SigMsg=(msg,Sigvir,stage,vid)\text{SigMsg}\:={\left(\text{msg},{\text{Sig}_{{{v}_{{i}}}}^{{{r},\text{stage}}}},{v}_{{\text{id}}}\right)}
msg=EncSC(stage,Vvr,stage(B))\text{msg}\:=\text{Enc}_{{\text{SC}}}{\left(\text{stage},{{V}_{{v}}^{{{r},\text{stage}}}}{\left({B}\right)}\right)}

where

  • r{r} is an unsigned 64-bit integer indicating the Grandpa round number (Definition 81).

  • idV\text{id}_{{{\mathbb{{V}}}}} is an unsigned 64-bit integer indicating the authority Set Id (Definition 78).

  • Sigvir,stage{\text{Sig}_{{{v}_{{i}}}}^{{{r},\text{stage}}}} is a 512-bit byte array containing the signature of the authority (Definition 82).

  • vid{v}_{{{i}{d}}} is a 256-bit byte array containing the ed25519 public key of the authority.

  • stage\text{stage} is a 8-bit integer of value 0 if it’s a pre-vote sub-round, 1 if it’s a pre-commit sub-round or 2 if it’s a primary proposal message.

  • Vvr,stage(B){{V}_{{v}}^{{{r},\text{stage}}}}{\left({B}\right)} is the GRANDPA vote for block B{B} (Definition 81).

This message is the sub-component of the GRANDPA gossip message (Definition 48) of type Id 0.

Definition 50. GRANDPA Compact Justification Format

The GRANDPA compact justification format is an optimized data structure to store a collection of pre-commits and their signatures to be submitted as part of a commit message. Instead of storing an array of justifications, it uses the following format:

Jv0,nr,comp=({Vv0r,pc,Vvnr,pc},{(Sigv0r,pc,vid0),(Sigvnr,pc,vidn)}){{J}_{{{v}_{{{0},\ldots{n}}}}}^{{{r},\text{comp}}}}\:={\left({\left\lbrace{{V}_{{{v}_{{0}}}}^{{{r},{p}{c}}}},\ldots{{V}_{{{v}_{{n}}}}^{{{r},{p}{c}}}}\right\rbrace},{\left\lbrace{\left({\text{Sig}_{{{v}_{{0}}}}^{{{r},{p}{c}}}},{v}_{{\text{id}_{{0}}}}\right)},\ldots{\left({\text{Sig}_{{{v}_{{n}}}}^{{{r},{p}{c}}}},{v}_{{\text{id}_{{n}}}}\right)}\right\rbrace}\right)}

where

  • Vvir,pc{{V}_{{{v}_{{i}}}}^{{{r},{p}{c}}}} is a 256-bit byte array containing the pre-commit vote of authority vi{v}_{{i}} (Definition 81).

  • Sigvir,pc{\text{Sig}_{{{v}_{{i}}}}^{{{r},{p}{c}}}} is a 512-bit byte array containing the pre-commit signature of authority vi{v}_{{i}} (Definition 82).

  • vidn{v}_{{\text{id}_{{n}}}} is a 256-bit byte array containing the public key of authority vi{v}_{{i}}.

Definition 51. GRANDPA Commit Message

A GRANDPA commit message for block B{B} in round r{r}, Mvr,Fin(B){{M}_{{v}}^{{{r},\text{Fin}}}}{\left({B}\right)}, is a message broadcasted by voter v{v} to the network indicating that voter v{v} has finalized block B{B} in round r{r}. It has the following structure:

Mvr,Fin(B)=EncSC(r,idV,Vvr(B),Jv0,nr,comp){{M}_{{v}}^{{{r},\text{Fin}}}}{\left({B}\right)}\:=\text{Enc}_{{\text{SC}}}{\left({r},\text{id}_{{{\mathbb{{V}}}}},{{V}_{{v}}^{{r}}}{\left({B}\right)},{{J}_{{{v}_{{{0},\ldots{n}}}}}^{{{r},\text{comp}}}}\right)}

where

  • r{r} is an unsigned 64-bit integer indicating the round number (Definition 81).

  • idV{id}_{{{\mathbb{{V}}}}} is the authority set Id (Definition 78).

  • Vvr(B){{V}_{{v}}^{{r}}}{\left({B}\right)} is a 256-bit array containing the GRANDPA vote for block B{B} (Definition 80).

  • Jv0,nr,comp{{J}_{{{v}_{{{0},\ldots{n}}}}}^{{{r},\text{comp}}}} is the compacted GRANDPA justification containing observed pre-commit of authorities v0{v}_{{0}} to vn{v}_{{n}} (Definition 50).

This message is the sub-component of the GRANDPA gossip message (Definition 48) of type Id 1.

4.8.7.1. GRANDPA Neighbor Messages

Neighbor messages are sent to all connected peers but they are not repropagated on reception. A message should be sent whenever the values of the message change and at least every 5 minutes. The sender should take the recipient's state into account and avoid sending messages to peers that are using different voter sets or are in a different round. Messages received from a future voter set or round can be dropped and ignored.

Definition 52. GRANDPA Neighbor Message

A GRANDPA Neighbor Message is defined as:

Mneigh=EncSC(v,r,idV,Hi(Blast)){M}^{{\text{neigh}}}\:=\text{Enc}_{{\text{SC}}}{\left({v},{r},\text{id}_{{{\mathbb{{V}}}}},{H}_{{i}}{\left({B}_{{\text{last}}}\right)}\right)}

where

  • v{v} is an unsigned 8-bit integer indicating the version of the neighbor message, currently 1.

  • r{r} is an unsigned 64-bit integer indicating the round number (Definition 81).

  • idV\text{id}_{{{\mathbb{{V}}}}} is an unsigned 64-bit integer indicating the authority Id (Definition 78).

  • Hi(Blast){H}_{{i}}{\left({B}_{{\text{last}}}\right)} is an unsigned 32-bit integer indicating the block number of the last finalized block Blast{B}_{{\text{last}}}.

This message is the sub-component of the GRANDPA gossip message (Definition 48) of type Id 2.

4.8.7.2. GRANDPA Catch-up Messages

Whenever a Polkadot node detects that it is lagging behind the finality procedure, it needs to initiate a catch-up procedure. GRANDPA Neighbor messages (Definition 52) reveal the round number for the last finalized GRANDPA round which the node’s peers have observed. This provides the means to identify a discrepancy in the latest finalized round number observed among the peers. If such a discrepancy is observed, the node needs to initiate the catch-up procedure explained in Section 6.6.1.).

In particular, this procedure involves sending a catch-up request and processing catch-up response messages.

Definition 53. Catch-Up Request Message

A GRANDPA catch-up request message for round r{r}, Mi,vCatq(idV,r){{M}_{{{i},{v}}}^{{\text{Cat}-{q}}}}{\left(\text{id}_{{{\mathbb{{V}}}}},{r}\right)}, is a message sent from node i{i} to its voting peer node v{v} requesting the latest status of a GRANDPA round r>r{r}'>{r} of the authority set Vid{\mathbb{{V}}}_{{\text{id}}} along with the justification of the status and has the following structure:

Mi,vr,Catq=EncSC(r,idV){{M}_{{{i},{v}}}^{{{r},\text{Cat}-{q}}}}\:=\text{Enc}_{{\text{SC}}}{\left({r},\text{id}_{{{\mathbb{{V}}}}}\right)}

This message is the sub-component of the GRANDPA Gossip message (Definition 48) of type Id 3.

Definition 54. Catch-Up Response Message

A GRANDPA catch-up response message for round r{r}, Mv,iCats(idV,r){{M}_{{{v},{i}}}^{{\text{Cat}-{s}}}}{\left(\text{id}_{{{\mathbb{{V}}}}},{r}\right)}, is a message sent by a node v{v} to node i{i} in response of a catch-up request Mv,iCatq(idV,r){{M}_{{{v},{i}}}^{{\text{Cat}-{q}}}}{\left(\text{id}_{{{\mathbb{{V}}}}},{r}'\right)} in which rr{r}\ge{r}' is the latest GRANDPA round which v has prove of its finalization and has the following structure:

Mv,iCats=EncSC(idV,r,J0,nr,pv(B),J0,mr,pc(B),Hh(B),Hi(B)){{M}_{{{v},{i}}}^{{\text{Cat}-{s}}}}\:=\text{Enc}_{{\text{SC}}}{\left(\text{id}_{{{\mathbb{{V}}}}},{r},{{J}_{{{0},\ldots{n}}}^{{{r},\text{pv}}}}{\left({B}\right)},{{J}_{{{0},\ldots{m}}}^{{{r},\text{pc}}}}{\left({B}\right)},{H}_{{h}}{\left({B}'\right)},{H}_{{i}}{\left({B}'\right)}\right)}

Where B{B} is the highest block which v{v} believes to be finalized in round r{r} (Definition 81). B{B}' is the highest ancestor of all blocks voted on in the arrays of justifications J0,nr,pv(B){{J}_{{{0},\ldots{n}}}^{{{r},\text{pv}}}}{\left({B}\right)} and J0,mr,pc(B){{J}_{{{0},\ldots{m}}}^{{{r},\text{pc}}}}{\left({B}\right)} (Definition 83) with the exception of the equivocatory votes.

This message is the sub-component of the GRANDPA Gossip message (Definition 48) of type Id 4.

4.8.8. GRANDPA BEEFY

This section defines the messages required for the BEEFY protocol (Section 6.7.). Those messages are sent over the /91b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb49219da7a70ce90c3/beefy/1 substream.

Definition 55. Commitment

A commitment, C{C}, contains the information extracted from the finalized block at height Hi(Blast){H}_{{i}}{\left({B}_{{\text{last}}}\right)} as specified in the message body and a datastructure of the following format:

C=(Rh,Hi(Blast),idV){C}={\left({R}_{{h}},{H}_{{i}}{\left({B}_{{\text{last}}}\right)},\text{id}_{{{\mathbb{{V}}}}}\right)}

where

  • Rh{R}_{{h}} is the MMR root of all the block header hashes leading up to the latest, finalized block.
  • Hi(Blast){H}_{{i}}{\left({B}_{{\text{last}}}\right)} is the block number this commitment is for. Namely the latest, finalized block.
  • idV\text{id}_{{{\mathbb{{V}}}}} is the current authority set Id (Definition 78).
Definition 56. Vote Message

A vote message, Mv{M}_{{v}}, is direct vote created by the Polkadot Host on every BEEFY round and is gossiped to its peers. The message is a datastructure of the following format:

Mv=EncSC(C,Aidbfy,Asig){M}_{{v}}=\text{Enc}_{{\text{SC}}}{\left({C},{{A}_{{\text{id}}}^{{\text{bfy}}}},{A}_{{\text{sig}}}\right)}

where

  • C{C} is the BEEFY commitment (Definition 55).
  • Aidbfy{{A}_{{\text{id}}}^{{\text{bfy}}}} is the ECDSA public key of the Polkadot Host.
  • Asig{A}_{{\text{sig}}} is the signature created with Aidbfy{{A}_{{\text{id}}}^{{\text{bfy}}}} by signing the payload Rh{R}_{{h}} in C{C}.
Definition 57. Signed Commitment

A signed commitment, Msc{M}_{{\text{sc}}}, is a datastructure of the following format:

MSC=EncSC(C,Sn){M}_{{\text{SC}}}=\text{Enc}_{{\text{SC}}}{\left({C},{S}_{{n}}\right)}
Sn=(A0sig,Ansig){S}_{{n}}={\left({{A}_{{0}}^{{\text{sig}}}},\ldots{{A}_{{n}}^{{\text{sig}}}}\right)}

where

  • C{C} is the BEEFY commitment (Definition 55).
  • Sn{S}_{{n}} is an array where its exact size matches the number of validators in the current authority set as specified by idV\text{id}_{{{\mathbb{{V}}}}} (Definition 78) in C{C}. Individual items are of the type Option (Definition 200), which can contain a signature of a validator which signed the same payload (Rh{R}_{{h}} in C{C}) and is active in the current authority set. It’s critical that the signatures are sorted based on their corresponding public key entry in the authority set. For example, the signature of the validator at index 3 in the authority set must be placed at index 3 in Sn{S}_{{n}}. If not signature is available for that validator, then the Option variant is None inserted (Definition 200). This sorting allows clients to map public keys to their corresponding signatures.
Definition 58. Signed Commitment Witness

A signed commitment witness, MSCw{{M}_{{\text{SC}}}^{{w}}}, is a light version of the signed BEEFY commitment (Definition 57). Instead of containing the entire list of signatures, it only claims which validator signed the payload. The message is a datastructure of the following format:

MSCw=EncSC(C,V0,n,Rsig){{M}_{{\text{SC}}}^{{w}}}=\text{Enc}_{{\text{SC}}}{\left({C},{V}_{{{0},\ldots{n}}},{R}_{{\text{sig}}}\right)}

where

  • C{C} is the BEEFY commitment (Definition 55).
  • V0,n{V}_{{{0},\ldots{n}}} is an array where its exact size matches the number of validators in the current authority set as specified by idV\text{id}_{{{\mathbb{{V}}}}} in C{C}. Individual items are booleans which indicate whether the validator has signed the payload (true) or not (false). It’s critical that the boolean indicators are sorted based on their corresponding public key entry in the authority set. For example, the boolean indicator of the validator at index 3 in the authority set must be placed at index 3 in Vn{V}_{{n}}. This sorting allows clients to map public keys to their corresponding boolean indicators.
  • Rsig{R}_{{\text{sig}}} is the MMR root of the signatures in the original signed BEEFY commitment (Definition 57).