Skip to main content
See here for instructions on how to set up a full node.
The RaptorCast protocol is a novel method of one-to-many block propagation that uses an erasure-coded two-level broadcast tree to propagate large blocks from a message originator to many listeners. There are two usages of RaptorCast in the Monad network: primary and secondary:
  • In its primary usage, RaptorCast is utilized by each leader to share its block proposal to all other validators in the active set. There is one primary RaptorCast group, consisting of all validators in the active set, with a leader that rotates.
  • In its secondary usage, one validator from the active set supports a number of downstream full nodes, propagating every block proposal (received by it via primary RaptorCast) to its downstream listeners. There are many secondary RaptorCast groups - one per validator in the active set - and for each one, the leader is static.
Secondary RaptorCast allows the network to support a huge set of full nodes. In the recommended configuration, each validator has a secondary RaptorCast group of size 150. Given a network of 200 active set validators, even after accounting for a redundancy factor of 2 (full nodes may register for multiple secondary RaptorCast groups), there is still capacity for 150 * 200 / 2 = 15,000 full nodes. The rest of this page documents the behavior of secondary RaptorCast, as well as how full node operators should configure it. Validators may find the configuration helpful as well, since validators usually start as full nodes.

Differences between primary and secondary RaptorCast

Secondary RaptorCast follows the same mechanism as primary RaptorCast. There are some differences, however. In Primary RaptorCast:
  • The participants are all validators
  • The originator changes given that the leader can change (due to leader election)
  • The “weights” on the other nodes are based on stake
In Secondary RaptorCast:
  • The originator of a group is fixed and always a validator
  • Other than the above, the other participants are full nodes
  • All nodes are equally weighted

How full nodes register for secondary RaptorCast

  1. Full nodes start by peering with some of the validators. They do this by peering with the bootstrap peers (aka other full nodes) specified in node.toml (see later in this document for more details), then asking them for their peers, and repeating until they have the name records of the full validator set.
  2. If a validator has enable_publisher = true in its node.toml, it will routinely send invites to the full nodes in its routing table (up to max_group_size). These invites will request the full node to join the validator’s secondary RaptorCast group.
  3. A full node has the option to accept or reject. If a full node is in too many groups, it will reject. This is controlled by the max_num_group parameter.
  4. The validator will collect these accept/reject responses and confirm a group.
  5. The group will last for round_span specified in the validator’s node.toml (default: 240 rounds). As the group’s age approaches round_span, the validator will start sending invites for its next secondary RaptorCast group.
  6. Full nodes can (and should) join multiple secondary RaptorCast groups for redundancy.
A full node can join a group even if it hasn’t finished syncing the state. Joining a group is how a full node becomes aware of the current round. That information can, in turn, be used to adjust the statesync target.

Configuring RaptorCast

General Recommendation

It is highly suggested that operators of validators have the node:
  • First be a full node with enable_client = true
  • AND also configure the validator specific settings in node.toml
  • Then convert to a validator via staking

Important Considerations

  • Several of the settings below only apply to nodes that are operating as a validator
  • Other apply only if the node is running as a full node
  • That being said, it’s recommended that BOTH sets of settings be in the node.toml
Why do we recommend the above? Because it’s possible for a node to “begin life” as a full node, become a validator (via staking) and then become a full node again (if staking is pulled back). Having settings for both modes (validator and full node) ensures that the node can keep up with the chain tip. For example, if a validator becomes a full node and is NOT part of a secondary RaptorCast group (aka enable_client = true) then it will miss block updates and fall behind the ledger tip.

node.toml

Below is a snippet of a node.toml that applies to RaptorCast. We’ve grouped the settings as “full node only”, “validator only” or “both” We’ve also added comments to explain what each setting does node.toml contains the following settings:
[fullnode_raptorcast]

# VALIDATOR ONLY
# "enable_publisher = true" means that if the full node becomes a validator, it will participate
# as a secondary RaptorCast originator.
enable_publisher = true

# maximum number of rounds that a validator will wait for invite response from the full node
max_invite_wait = 10

# number of rounds that a group lasts for
round_span = 240

# how far ahead (in rounds) validator sends invites to full nodes before the start of the round
# e.g. if the round_span is 240, the invites will go out at round 220
invite_lookahead = 20

# FULL NODE ONLY
# this needs to be "true" for full nodes to participate in secondary RaptorCast
enable_client = true

# upper limit on how many groups the full node will join
max_num_group = 3

# indicates the time range (in rounds) that the full node will accept group invites
invite_future_dist_min = 1
invite_future_dist_max = 600

# a heartbeat which is used to determine whether the full node is receiving proposals
invite_accept_heartbeat_ms = 10000

# BOTH MODES
# maximum number of nodes in a group
max_group_size = 150

raptor10_fullnode_redundancy_factor = 2.0
deadline_round_dist = 10
init_empty_round_span = 23

[fullnode_raptorcast.full_nodes_prioritized]
identities = []

Additional options

Prioritized secondary RaptorCast inclusion

A full node may coordinate with a validator to be explicitly and consistently invited to that validator’s secondary RaptorCast group. To do this, the full node provides some information for the validator to include in its [fullnode_raptorcast.full_nodes_prioritized.identities] section. See Validator Installation for details on what needs to be provided. Note that this means the full node doesn’t have to rely on peer discovery to peer with that validator.

Dedicated upstream

Validators also have the option of specifying full nodes to which they wish to directly forward all primary RaptorCast chunks. This utilizes a lot of validator bandwidth, since each registered downstream requires another copy of all chunks to be sent. It is potentially more reliable for the downstream node than subscribing via secondary RaptorCast, although in practice secondary RaptorCast is quite reliable. Note that if a full node is designated by one or more validators for dedicated chunk forwarding, then it could be configured with enable_client = false. This turns off attempting to participate in secondary RaptorCast.

Comparison

ConfigurationRequires validator to whitelist full nodeRaptorCast modeData Source
NormalNoenable_client = trueSecondary RaptorCast
Prioritized secondary RaptorCastYesenable_client = trueSecondary RaptorCast
Chunk forwardingYesenable_client = falsePrimary RaptorCast
Note that these configurations are properties of a relationship between a full node and a validator, rather than properties of the full node itself. A full node could coordinate with multiple validators to treat it specially, while also participating in normal secondary RaptorCast with other validators that it automatically peers with.

RaptorCast configurations for validators

Validators can toggle off their participation in secondary RaptorCast by setting enable_publisher = false. Although turning secondary RaptorCast off will reduce bandwidth usage, note that the bandwidth cost of secondary RaptorCast is relatively low; for example, even at 10,000 transactions per second, the expected usage will be about 6 MB per second (3 MB of block data with 2x redundancy). Therefore, it is recommended to keep enable_publisher = true.
For more technical details about the RaptorCast, see the RaptorCast documentation.