# Prepare and Connect to Other Nodes
With the genesis created and received, a node operator needs to join the eventual network. In practice this means two things:
- To open your node to connections from other nodes.
- To know where the other nodes are, or at least a subset of them, so that your node can attempt to connect to them.
In this section, you concern yourself with CometBFT and the peer-to-peer network. Other niceties like incorporating gRPC and REST into your Cosmos application are different concerns.
# Set up
As a node operator, from the time of genesis or at any time in the future, and on each machine, you first run an init
command to at least set up the folders and pick an ASCII-only moniker:
Overwrite the genesis created with the actual agreed one. While you are doing so, you can make it read-only:
The init
command has also created a number of configuration files:
This should return:
# Open your node
In the config.toml
file (opens new window) you can configure the open ports. The important piece is your listen address:
Here it listens on port 26656
of all IP addresses. Define or find out your publicly accessible IP address, for instance 172.217.22.14
. If you use a DNS-resolvable name, like lascaux.myproject.example.com
, you can use that as well instead of the IP address.
Keep in mind that a name is subject to the DNS being well configured and working well. Add this too so that, whenever your node contacts a new node, yours can tell the other node which address is preferred:
The other piece of information that uniquely identifies your node is your node ID. Its private key is stored in ~/.myprojectd/config/node_key.json
. The public ID is that by which your peers will know your node. You can compute the public ID with the CometBFT command:
This should return something like:
If you lose node_key.json
or have it stolen, it is not as serious as if you lost your token's private key. Your node can always recreate a new one and let your peers know about the new ID, with no problems. The file location is mentioned in config.toml
on the line node_key_file = "config/node_key.json"
.
The node key also exists so that your own node can identify itself, in the event that it tried to connect to itself via a circuitous peer-to-peer route and therefore ought to cut the useless connection.
In short, here is the information you need to share with other early participants in the network:
- Listen address, for instance:
"tcp://172.217.22.14:26656"
. - Node ID, for instance:
ce1c54ea7a2c50b4b9f2f869faf8fa4d1a1cf43a
.
The shorthand for this information is written and exchanged in the format node-id@listen-address, like this:
If you create a node for a network that is already running you need to follow these same steps, but you do not need to inform others of your parameters, because when you connect your node will do this anyway.
As a side note, your computer or local network may not allow other nodes to initiate a connection to your node on port 26656
. Therefore, it is a good idea to open this port in the firewall(s).
# Connection to others
You have collected your node's information, and have shared it with the early network participants. In return you received theirs. You can put this information in config.toml
, separated by commas:
If one of the operators informs you that their node behaves as a seed node, then you add it under:
You can also take this opportunity to document the list of peers on your production repository (the same that hosts the genesis file). Only list the addresses that are meant to be public, to mitigate the risks of DoS attacks.
You are not obliged to put all the known peers in your persistent_peers
. You may well choose to put there only those you trust.
# Further network configuration
Setting up your node and identifying other peers is important. However, this is not the only network configuration available. Look into ~/.myprojectd/config/config.toml
for tweaks.
If you change the parameters in this file, you are not going to affect the ability of the network to reach consensus on blocks. Parameters that are necessary for consensus are all in the genesis file.
Parameters in config.toml
(opens new window) can be divided into two broad categories:
- Network scoped: by changing these, you change the posture of your node at the risk of disrupting the ability of other nodes to communicate with yours. Examples include
max_num_inbound_peers
andhandshake_timeout
. - Single node scoped: these only matter to your node. Examples include
db_backend
andlog_level
.
Among the network-scoped parameters, some deal with the intricacies of BFT, such as timeout_prevote
and timeout_precommit_delta
. If you want to tweak them away from their defaults, you can search for more information. Here (opens new window) is as good a place to start as any other.
Tangential to these parameters, you can find others in ~/.myprojectd/config/app.toml
that also relate to the network. For instance minimum-gas-prices
, which you could set at 1nstone
for instance.
To avoid surprises when looking at the configuration, keep in mind your CometBFT version:
This returns something like:
# DDoS
Being part of a network with a known IP address can be a security or service risk. Distributed denial-of-service (DDoS) is a classic kind of network attack, but there are ways to mitigate the risks.
First, be aware that regular nodes and validator nodes face different risks:
- If your regular node is DoS'd, you are at risk of dropping out of the network, and preventing you or your customers from calling an RPC endpoint for network activity.
- If your validator node is DoS'd, you are at risk of consensus penalties.
It is common practice to expose your regular nodes and to hide your validator nodes. The latter hide behind a sentry node (opens new window), such that:
- Your sentry nodes (opens new window) are located in a cloud infrastructure, where the database (or filesystem) and the software part of the node are separated. With this, the same sentry node can release its old public IP address and receive a new one within a few seconds; or a new sentry node can spring up at a different IP address by using the same database (or filesystem), as in a game of whack-a-mole.
- Your validator nodes are located anywhere, with persistent addresses, but connect only to the sentry nodes, with the use of
persistent_peers
inconfig.toml
. The content of this field has to change when a sentry node has been whacked unless the validator node can connect to the sentry node over the same private IP address. - Your sentry nodes never gossip your validators' addresses over the peer-to-peer network, thanks to the use of
private_peer_ids
inconfig.toml
.
If you would like to see how to apply what you've learned, you can go straight to the exercise in Simulate production in Docker to start from scratch.
More specifically, you can jump to:
- Network preparation, to see how to prepare nodes to know about each other, and to keep some things private.
- Networks they run in, to see how the network topology is prepared.
To summarize, this section has explored:
- How to make your node accessible to connections from other nodes.
- How to locate some subset of other nodes in order to make a connection to them.
- The use of a publicly accessible IP address or DNS-resolvable name, along with the public half of your public-private node key, to uniquely identify your node to others.
- How the node key can also prevent inadvertent attempts by the node to connect to itself via an unforeseen peer-to-peer route.
- The option of further configuring your network via network scoped and single node scoped parameters.
- How to mitigate the risks of distributed denial-of-service (DDoS) attacks through the use of sentry nodes.