Skip to main content

Network Protocol

Metal Blockchain defines the core communication format between Metal Blockchain nodes. It uses the primitive serialization format for payload packing.

"Containers" are mentioned extensively in the description. A Container is simply a generic term for blocks or vertices, without needing to specify whether the consensus algorithm is DAG or Chain.

GetVersion

GetVersion requests for a Version message to be sent as a response.

The OpCode used by GetVersion messages is: 0x00.

What GetVersion contains

The payload of a GetVersion message is empty.

[]

How GetVersion is handled

A node receiving a GetVersion message must respond with a Version message containing the current time and node version.

When GetVersion is sent

GetVersion is sent when a node is connected to another node, but has not yet received a Version message. It may, however, be re-sent at any time.

Version

Version ensures that the nodes we are connected to are running compatible versions of Metal, and at least loosely agree on the current time.

The OpCode used by Version messages is: 0x01.

What Version contains

Version contains the node’s current time in Unix time format in number of milliseconds since the beginning of the epoch in 01/01/1970, as well as a version string describing the version of the code that the node is running.

Content:

[
Long <- Unix Timestamp (Seconds)
String <- Version String
]

How Version is handled

If the versions are incompatible or the current times differ too much, the connection will be terminated.

When Version is sent

Version is sent in response to a GetVersion message.

Version Example

Sending a Version message with the time November 16th, 2008 at 12:00am (UTC) and the version metal/0.0.1

[
Long <- 1226793600 = 0x00000000491f6280
String <- "metal/0.0.1"
]
=
[
0x00, 0x00, 0x00, 0x00, 0x49, 0x1f, 0x62, 0x80,
0x00, 0x0f, 0x61, 0x76, 0x61, 0x6c, 0x61, 0x6e,
0x63, 0x68, 0x65, 0x2f, 0x30, 0x2e, 0x30, 0x2e,
0x31,
]

GetPeers

Overview

GetPeers requests that a Peers message be sent as a response.

The OpCode used by GetPeers messages is: 0x02.

What GetPeers contains

The payload of a GetPeers message is empty.

[]

How GetPeers is handled

A node receiving GetPeers request must respond with a Peers message containing the IP addresses of its connected, staking nodes.

When GetPeers is sent

A node sends GetPeers messages upon startup to discover the participants in the network. It may also periodically send GetPeers messages in order to discover new nodes as they arrive in the network.

Peers

Overview

Peers message contains a list of peers, represented as IP Addresses. Note that an IP Address contains both the IP and the port number, and supports both IPv4 and IPv6 format.

The OpCode used by Peers messages is: 0x03.

What Peers contains

Peers contains the IP addresses of the staking nodes this node is currently connected to.

Content:

[
Variable Length IP Address Array
]

How Peers is handled

On receiving a Peers message, a node should compare the nodes appearing in the message to its own list of neighbors, and forge connections to any new nodes.

When Peers is sent

Peers messages do not need to be sent in response to a GetPeers message, and are sent periodically to announce newly arriving nodes. The default period for such push gossip is 60 seconds.

Peers Example

Sending a Peers message with the IP addresses "127.0.0.1:9650" and "[2001:0db8:ac10:fe01::]:12345"

[
Variable Length IP Address Array <- ["127.0.0.1:9650", "[2001:0db8:ac10:fe01::]:12345"]
]
=
[
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0x7f, 0x00, 0x00, 0x01, 0x25, 0xb2, 0x20, 0x01,
0x0d, 0xb8, 0xac, 0x10, 0xfe, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x39,
]

Get

Overview

A Get message requests a container, that is, block or vertex, from a node.

The OpCode used by Get messages is: 0x04.

What Get contains

A Get message contains a SubnetID, RequestID, and ContainerID.

SubnetID defines which Subnets this message is destined for.

RequestID is a counter that helps keep track of the messages sent by a node. Each time a node sends an un-prompted message, the node will create a new unique RequestID for the message.

ContainerID is the identifier of the requested container.

[
Length 32 Byte Array <- SubnetID
UInt <- RequestID
Length 32 Byte Array <- ContainerID
]

How Get is handled

The node should reply with a Put message with the same SubnetID, RequestID, and ContainerID along with the Container with the specified identifier. Under correct situations, a node should only be asked for a container that it has. Therefore, if the node does not have the specified container, the Get message can safely be dropped.

When Get is sent

A node will send a Get message to a node that tells us about the existence of a container. For example, suppose we have two nodes: Rick and Morty. If Rick sends a PullQuery message that contains a ContainerID, that Morty doesn’t have the container for, then Morty will send a Get message containing the missing ContainerID.

Get Example

[
SubnetID <- 0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20
RequestID <- 43110 = 0x0000A866
ContainerID <- 0x2122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40
]
=
[
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
0x00, 0x00, 0xa8, 0x66, 0x21, 0x22, 0x23, 0x24,
0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34,
0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c,
0x3d, 0x3e, 0x3f, 0x40,
]

Put

Overview

A Put message provides a requested container to a node.

The OpCode used by Put messages is: 0x05.

What Put contains

A Put message contains a SubnetID, RequestID, ContainerID, and Container.

SubnetID defines which Subnets this message is destined for.

RequestID is a counter that helps keep track of the messages sent by a node.

ContainerID is the identifier of the container this message is sending.

Container is the bytes of the container this message is sending.

[
Length 32 Byte Array <- SubnetID
UInt <- RequestID
Length 32 Byte Array <- ContainerID
Variable Length Byte Array <- Container
]

How Put is handled

The node should attempt to add the container to consensus.

When Put is sent

A node will send a Put message in response to receiving a Get message for a container the node has access to.

Put Example

[
SubnetID <- 0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20
RequestID <- 43110 = 0x0000A866
ContainerID <- 0x5ba080dcf6861c94c24ec62bc09a3c8b0fdd4691ebf02491e0e921dd0c77206f
Container <- 0x2122232425
]
=
[
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
0x00, 0x00, 0xa8, 0x66, 0x5b, 0xa0, 0x80, 0xdc,
0xf6, 0x86, 0x1c, 0x94, 0xc2, 0x4e, 0xc6, 0x2b,
0xc0, 0x9a, 0x3c, 0x8b, 0x0f, 0xdd, 0x46, 0x91,
0xeb, 0xf0, 0x24, 0x91, 0xe0, 0xe9, 0x21, 0xdd,
0x0c, 0x77, 0x20, 0x6f, 0x00, 0x00, 0x00, 0x05,
0x21, 0x22, 0x23, 0x24, 0x25,
]

PushQuery

Overview

A PushQuery message requests the preferred containerIDs from the node after the specified ContainerID has been added to consensus. If the ContainerID is not known, the Container is optimistically provided.

The OpCode used by PushQuery messages is: 0x06.

What PushQuery contains

A PushQuery message contains a SubnetID, RequestID, ContainerID, and Container.

SubnetID defines which Subnets this message is destined for.

RequestID is a counter that helps keep track of the messages sent by a node.

ContainerID is the identifier of the container this message expects to have been added to consensus before the response is sent.

Container is the bytes of the container with identifier ContainerID.

[
Length 32 Byte Array <- SubnetID
UInt <- RequestID
Length 32 Byte Array <- ContainerID
Variable Length Byte Array <- Container
]

How PushQuery is handled

The node should attempt to add the container to consensus. After the container is added to consensus, a Chits message should be sent with the current preference(s) of the node.

When PushQuery is sent

A node should send a PushQuery message if it wants to learn of this node’s current preferences and it feels that it is possible the node hasn’t learned of Container yet. The node will want to learn of nodes preferences when it learns of a new container or it has had pending containers for "awhile".

PushQuery Example

[
SubnetID <- 0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20
RequestID <- 43110 = 0x0000A866
ContainerID <- 0x5ba080dcf6861c94c24ec62bc09a3c8b0fdd4691ebf02491e0e921dd0c77206f
Container <- 0x2122232425
]
=
[
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
0x00, 0x00, 0xa8, 0x66, 0x5b, 0xa0, 0x80, 0xdc,
0xf6, 0x86, 0x1c, 0x94, 0xc2, 0x4e, 0xc6, 0x2b,
0xc0, 0x9a, 0x3c, 0x8b, 0x0f, 0xdd, 0x46, 0x91,
0xeb, 0xf0, 0x24, 0x91, 0xe0, 0xe9, 0x21, 0xdd,
0x0c, 0x77, 0x20, 0x6f, 0x00, 0x00, 0x00, 0x05,
0x21, 0x22, 0x23, 0x24, 0x25,
]

PullQuery

Overview

A PullQuery message requests the preferred containerIDs from the node after the specified ContainerID has been added to consensus.

The OpCode used by PullQuery messages is: 0x07.

What PullQuery contains

A PullQuery message contains a SubnetID, RequestID, and ContainerID.

SubnetID defines which Subnets this message is destined for.

RequestID is a counter that helps keep track of the messages sent by a node.

ContainerID is the identifier of the container this message expects to have been added to consensus before the response is sent.

[
Length 32 Byte Array <- SubnetID
UInt <- RequestID
Length 32 Byte Array <- ContainerID
]

How PullQuery is handled

If the node hasn’t added ContainerID, it should attempt to add the container to consensus. After the container is added to consensus, a Chits message should be sent with the current preference(s) of the node.

When PullQuery is sent

A node should send a PullQuery message if it wants to learn of this node’s current preferences and it feels that it quite likely the node has already learned of Container. The node will want to learn of nodes preferences when it learns of a new container or it has had pending containers for "awhile".

PullQuery Example

[
SubnetID <- 0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20
RequestID <- 43110 = 0x0000A866
ContainerID <- 0x5ba080dcf6861c94c24ec62bc09a3c8b0fdd4691ebf02491e0e921dd0c77206f
]
=
[
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
0x00, 0x00, 0xa8, 0x66, 0x5b, 0xa0, 0x80, 0xdc,
0xf6, 0x86, 0x1c, 0x94, 0xc2, 0x4e, 0xc6, 0x2b,
0xc0, 0x9a, 0x3c, 0x8b, 0x0f, 0xdd, 0x46, 0x91,
0xeb, 0xf0, 0x24, 0x91, 0xe0, 0xe9, 0x21, 0xdd,
0x0c, 0x77, 0x20, 0x6f,
]

Chits

Overview

A Chits message provides a requested set of preferred container(s) to a node.

The OpCode used by Chits messages is: 0x08.

What Chits contains

A Chits message contains a SubnetID, RequestID, and Preferences.

SubnetID defines which Subnets this message is destined for.

RequestID is a counter that helps keep track of the messages sent by a node.

Preferences is the list of containerIDs that fully describe the node’s preferences.

[
Length 32 Byte Array <- SubnetID
UInt <- RequestID
Variable Length (Length 32 Byte Array) Array <- Preferences
]

How Chits is handled

The node should attempt to add any referenced containers to consensus. If the referenced containers can’t be added, the node can ignore the missing containers and apply the remaining chits to the poll. Once a poll is completed, container confidences should be updated appropriately.

When Chits is sent

A node will send a Chits message in response to receiving a PullQuery or PushQuery message for a container the node has added to consensus.

Chits Example

[
SubnetID <- 0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20
RequestID <- 43110 = 0x0000A866
Preferences <- [
0x2122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40,
0x4142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f60,
]
]
=
[
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
0x00, 0x00, 0xa8, 0x66, 0x00, 0x00, 0x00, 0x02,
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40,
0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60,
]