> ## Documentation Index
> Fetch the complete documentation index at: https://docs.monad.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# How Full Nodes Receive Blocks

<Note>
  See [here](/node-ops/full-node-installation) for instructions on how to set up a full node.
</Note>

The [RaptorCast](/monad-arch/consensus/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.

<Note>
  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.
</Note>

## 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](/node-ops/validator-installation#configure-nodetoml) 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

| Configuration                        | Requires validator to whitelist full node | RaptorCast mode         | Data Source          |
| ------------------------------------ | ----------------------------------------- | ----------------------- | -------------------- |
| **Normal**                           | No                                        | `enable_client = true`  | Secondary RaptorCast |
| **Prioritized secondary RaptorCast** | Yes                                       | `enable_client = true`  | Secondary RaptorCast |
| **Chunk forwarding**                 | Yes                                       | `enable_client = false` | Primary 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`.

<Tip title="RaptorCast">
  For more technical details about the RaptorCast, see the
  [RaptorCast documentation](/monad-arch/consensus/raptorcast).
</Tip>
