Avalanche Network Protocol
The peer-to-peer messages that AvalancheGo nodes send to each other.
Overview
The Avalanche network protocol defines the messages that Avalanche nodes send to each other. Since v1.9.0 (Banff), nodes encode every message with Protocol Buffers (proto3). The schema is proto/p2p/p2p.proto in the AvalancheGo repository. The VM of each chain defines the bytes of the containers inside the messages. P-Chain and X-Chain containers use the primitive serialization format.
"Containers" are mentioned extensively in the description. A Container is simply a generic term for blocks.
This document describes the protocol for peer-to-peer communication using Protocol Buffers (proto3). The protocol defines a set of messages exchanged between peers in a peer-to-peer network. Each message is represented by the Message proto message, which can encapsulate various types of messages, including network messages, state-sync messages, bootstrapping messages, consensus messages, and application messages.
Message
The Message proto message is the main container for all peer-to-peer communication. It uses the oneof construct to represent different message types. The only supported compression algorithm is zstd. AvalancheGo v1.10.18 stopped gzip compression, and v1.11.3 removed the gzip field. Field 1 is now reserved.
message Message {
reserved 1; // Until E upgrade is activated.
reserved 37; // Next unused field number.
oneof message {
bytes compressed_zstd = 2;
// Fields lower than 10 are reserved for other compression algorithms.
// Network messages:
Ping ping = 11;
Pong pong = 12;
Handshake handshake = 13;
GetPeerList get_peer_list = 35;
PeerList peer_list = 14;
// State-sync messages:
GetStateSummaryFrontier get_state_summary_frontier = 15;
StateSummaryFrontier state_summary_frontier = 16;
GetAcceptedStateSummary get_accepted_state_summary = 17;
AcceptedStateSummary accepted_state_summary = 18;
// Bootstrapping messages:
GetAcceptedFrontier get_accepted_frontier = 19;
AcceptedFrontier accepted_frontier = 20;
GetAccepted get_accepted = 21;
Accepted accepted = 22;
GetAncestors get_ancestors = 23;
Ancestors ancestors = 24;
// Consensus messages:
Get get = 25;
Put put = 26;
PushQuery push_query = 27;
PullQuery pull_query = 28;
Chits chits = 29;
// App messages:
AppRequest app_request = 30;
AppResponse app_response = 31;
AppGossip app_gossip = 32;
AppError app_error = 34;
// Simplex messages:
Simplex simplex = 36;
}
}Compression
The compressed_zstd field holds the zstd-compressed bytes of a Message. The oneof field of that inner Message is one of the message types, not a compressed field. The sender sets this field only if the message type supports compression.
Network Messages
Ping
The Ping message reports a peer's perceived uptime percentage.
message Ping {
uint32 uptime = 1;
reserved 2; // Until Etna upgrade is activated.
}uptime: Uptime percentage on the primary network [0, 100].
AvalancheGo v1.11.12 removed the L1 uptimes (field 2) from Ping.
Pong
The Pong message is sent in response to a Ping. It has no fields. AvalancheGo v1.11.5 removed its uptime fields, because Ping carries the uptime.
message Pong {
reserved 1, 2; // Until E upgrade is activated.
}Handshake
The Handshake message is the first outbound message sent to a peer when a connection is established. The peer must respond with a PeerList message. Peers drop connections to peers with incompatible versions. AvalancheGo v1.10.18 renamed this message from Version to Handshake.
message Handshake {
uint32 network_id = 1;
uint64 my_time = 2;
bytes ip_addr = 3;
uint32 ip_port = 4;
uint64 upgrade_time = 5;
uint64 ip_signing_time = 6;
bytes ip_node_id_sig = 7;
repeated bytes tracked_subnets = 8;
Client client = 9;
repeated uint32 supported_acps = 10;
repeated uint32 objected_acps = 11;
BloomFilter known_peers = 12;
bytes ip_bls_sig = 13;
bool all_subnets = 14;
}network_id: Network identifier (for example local, testnet or Mainnet).my_time: Unix timestamp when theHandshakemessage was created.ip_addr: IP address of the peer.ip_port: IP port of the peer.upgrade_time: Unix timestamp (in seconds) of the most recently scheduled network upgrade. It can be a past upgrade or a future upgrade.ip_signing_time: Timestamp of the IP.ip_node_id_sig: Signature of the IP and port pair atip_signing_time, made with the TLS key.tracked_subnets: IDs of the L1s that the peer tracks.client: Client name (for exampleavalanchego) and its major, minor and patch version.supported_acps: ACPs that the peer supports.objected_acps: ACPs that the peer objects to.known_peers: Bloom filter, with a random salt, of the peers that the sender knows.ip_bls_sig: Signature of the IP and port pair atip_signing_time, made with the BLS key.all_subnets: Confirms that the peer tracks all L1s. The other peer sends the IPs of validators that the peer does not track only when this value is true.
PeerList
The PeerList message contains network-level metadata for a set of validators.
message PeerList {
repeated ClaimedIpPort claimed_ip_ports = 1;
}claimed_ip_ports: List of claimed IP and port pairs.
GetPeerList
The GetPeerList message contains a bloom filter of the validator IPs that the sender knows. A peer responds to it only after the handshake is complete. The response is a PeerList message with the validators that are not in the bloom filter. AvalancheGo v1.10.18 replaced PeerListAck with GetPeerList.
message GetPeerList {
BloomFilter known_peers = 1;
bool all_subnets = 2;
}known_peers: Bloom filter, with a random salt, of the validator IPs that the sender knows.all_subnets: Confirms that the sender tracks all L1s.
State-Sync Messages
GetStateSummaryFrontier
The GetStateSummaryFrontier message requests a peer's most recently accepted state summary.
message GetStateSummaryFrontier {
bytes chain_id = 1;
uint32 request_id = 2;
uint64 deadline = 3;
}chain_id: Chain being requested from.request_id: Unique identifier for this request.deadline: Timeout (ns) for this request.
StateSummaryFrontier
The StateSummaryFrontier message is sent in response to a GetStateSummaryFrontier request.
message StateSummaryFrontier {
bytes chain_id = 1;
uint32 request_id = 2;
bytes summary = 3;
}chain_id: Chain being responded from.request_id: Request ID of the originalGetStateSummaryFrontierrequest.summary: The requested state summary.
GetAcceptedStateSummary
The GetAcceptedStateSummary message requests a set of state summaries at specified block heights.
message GetAcceptedStateSummary {
bytes chain_id = 1;
uint32 request_id = 2;
uint64 deadline = 3;
repeated uint64 heights = 4;
}chain_id: Chain being requested from.request_id: Unique identifier for this request.deadline: Timeout (ns) for this request.heights: Heights being requested.
AcceptedStateSummary
The AcceptedStateSummary message is sent in response to GetAcceptedStateSummary.
message AcceptedStateSummary {
bytes chain_id = 1;
uint32 request_id = 2;
repeated bytes summary_ids = 3;
}chain_id: Chain being responded from.request_id: Request ID of the originalGetAcceptedStateSummaryrequest.summary_ids: State summary IDs.
Bootstrapping Messages
GetAcceptedFrontier
The GetAcceptedFrontier message requests the accepted frontier from a peer.
message GetAcceptedFrontier {
reserved 4;
bytes chain_id = 1;
uint32 request_id = 2;
uint64 deadline = 3;
}chain_id: Chain being requested from.request_id: Unique identifier for this request.deadline: Timeout (ns) for this request.
AcceptedFrontier
The AcceptedFrontier message contains the remote peer's last accepted frontier.
message AcceptedFrontier {
bytes chain_id = 1;
uint32 request_id = 2;
bytes container_id = 3;
}chain_id: Chain being responded from.request_id: Request ID of the originalGetAcceptedFrontierrequest.container_id: The ID of the last accepted frontier.
GetAccepted
The GetAccepted message sends a request with the sender's accepted frontier to a remote peer.
message GetAccepted {
reserved 5;
bytes chain_id = 1;
uint32 request_id = 2;
uint64 deadline = 3;
repeated bytes container_ids = 4;
}chain_id: Chain being requested from.request_id: Unique identifier for this message.deadline: Timeout (ns) for this request.container_ids: The sender's accepted frontier.
Accepted
The Accepted message is sent in response to GetAccepted.
message Accepted {
bytes chain_id = 1;
uint32 request_id = 2;
repeated bytes container_ids = 3;
}chain_id: Chain being responded from.request_id: Request ID of the originalGetAcceptedrequest.container_ids: Subset of container IDs from theGetAcceptedrequest that the sender has accepted.
GetAncestors
The GetAncestors message requests the ancestors for a given container.
message GetAncestors {
bytes chain_id = 1;
uint32 request_id = 2;
uint64 deadline = 3;
bytes container_id = 4;
EngineType engine_type = 5;
}chain_id: Chain being requested from.request_id: Unique identifier for this request.deadline: Timeout (ns) for this request.container_id: Container for which ancestors are being requested.engine_type: Consensus type to handle this message.
Ancestors
The Ancestors message is sent in response to GetAncestors.
message Ancestors {
bytes chain_id = 1;
uint32 request_id = 2;
repeated bytes containers = 3;
}chain_id: Chain being responded from.request_id: Request ID of the originalGetAncestorsrequest.containers: Ancestry for the requested container.
Consensus Messages
Get
The Get message requests a container from a remote peer.
message Get {
reserved 5;
bytes chain_id = 1;
uint32 request_id = 2;
uint64 deadline = 3;
bytes container_id = 4;
}chain_id: Chain being requested from.request_id: Unique identifier for this request.deadline: Timeout (ns) for this request.container_id: Container being requested.
Put
The Put message is sent in response to Get with the requested block.
message Put {
bytes chain_id = 1;
uint32 request_id = 2;
bytes container = 3;
}chain_id: Chain being responded from.request_id: Request ID of the originalGetrequest.container: Requested container.
PushQuery
The PushQuery message requests the preferences of a remote peer given a container.
message PushQuery {
reserved 5;
bytes chain_id = 1;
uint32 request_id = 2;
uint64 deadline = 3;
bytes container = 4;
uint64 requested_height = 6;
}chain_id: Chain being requested from.request_id: Unique identifier for this request.deadline: Timeout (ns) for this request.container: Container being gossiped.requested_height: Requesting peer's last accepted height.
PullQuery
The PullQuery message requests the preferences of a remote peer given a container id.
message PullQuery {
reserved 5;
bytes chain_id = 1;
uint32 request_id = 2;
uint64 deadline = 3;
bytes container_id = 4;
uint64 requested_height = 6;
}chain_id: Chain being requested from.request_id: Unique identifier for this request.deadline: Timeout (ns) for this request.container_id: Container id being gossiped.requested_height: Requesting peer's last accepted height.
Chits
The Chits message contains the preferences of a peer in response to a PushQuery or PullQuery message.
message Chits {
bytes chain_id = 1;
uint32 request_id = 2;
bytes preferred_id = 3;
bytes accepted_id = 4;
bytes preferred_id_at_height = 5;
uint64 accepted_height = 6;
}chain_id: Chain being responded from.request_id: Request ID of the originalPushQuery/PullQueryrequest.preferred_id: Currently preferred block.accepted_id: Last accepted block.preferred_id_at_height: Currently preferred block at the requested height.accepted_height: Height of the last accepted block.
Application Messages
AppRequest
The AppRequest message is a VM-defined request.
message AppRequest {
bytes chain_id = 1;
uint32 request_id = 2;
uint64 deadline = 3;
bytes app_bytes = 4;
}chain_id: Chain being requested from.request_id: Unique identifier for this request.deadline: Timeout (ns) for this request.app_bytes: Request body.
AppResponse
The AppResponse message is a VM-defined response sent in response to AppRequest.
message AppResponse {
bytes chain_id = 1;
uint32 request_id = 2;
bytes app_bytes = 3;
}chain_id: Chain being responded from.request_id: Request ID of the originalAppRequest.app_bytes: Response body.
AppError
The AppError message is a VM-defined error sent in response to AppRequest. A peer must respond to an AppRequest with an AppResponse or an AppError.
message AppError {
bytes chain_id = 1;
uint32 request_id = 2;
sint32 error_code = 3;
string error_message = 4;
}chain_id: Chain the message is for.request_id: Request ID of the originalAppRequest.error_code: VM-defined error code. VMs can define error codes greater than 0.error_message: VM-defined error message.
AppGossip
The AppGossip message is a VM-defined message.
message AppGossip {
bytes chain_id = 1;
bytes app_bytes = 2;
}chain_id: Chain the message is for.app_bytes: Message body.
Is this guide helpful?