Guide
Networking and peers
Ports, peers, bootstrap and relay nodes, NAT traversal and connection limits for tenraid, and how nodes authenticate each other.
Nodes talk to each other over QUIC and TCP on port 28700. On a public network the node joins by itself: it listens on that port and, on mainnet, connects to the built-in peers. The development network starts its P2P only with --listen, --peer, --sync-peer or a public_p2p section in node.json.
Ports
| Port | Protocol | Open to |
|---|---|---|
| 28700 | UDP (QUIC) and TCP | The internet, for peers |
| 28701 | TCP | This machine: HTTP API and WebSocket events |
| 28702 | TCP | This machine: mining work |
These are the mainnet ports. A testnet node uses 28705 to 28707, a development node 28710 to 28712, see Default ports.
No port has to be opened. A node behind a router connects out and works over those connections, without any option. Forwarding port 28700 for TCP and UDP is optional: other nodes can then connect to yours, which helps the network. Validators work the same way, see How validators reach each other.
Peers
A peer is named by its IP address or host name. The port may be left out.
tenraid run --peer 198.51.100.7
tenraid run --peer node.example.org:28700| Form | Meaning |
|---|---|
198.51.100.7, node.example.org | The node at this address, on the P2P port of the network |
198.51.100.7:28700 | The same with a port |
<identity>@/ip4/198.51.100.7/udp/28700/quic-v1/p2p/<peer id> | Only the node with this identity. The node logs its own value in this form at start |
--peer repeats. A peer named by address is bound to the identity it shows at the first contact until the node restarts. With the long form the node refuses anyone else at that address; get such values through a channel you trust.
--sync-peer names one peer, in the same forms, that the node prefers to sync from; other peers take over when it fails. Learned peers go into the node's peer book; tenraid reset-peers --yes forgets them, configured peers stay.
Roles and limits
| Option | Default | Meaning |
|---|---|---|
--listen <IP[:PORT]> | 0.0.0.0:28700 | Listens on QUIC and TCP; without a port on the network's P2P port. Repeatable |
--max-inbound <N> | 24 | Inbound peers; can only be lowered |
--max-outbound <N> | 8 | Outbound peers; can only be lowered |
--connections-per-ip <N> | 8 | Connections from one network: an IPv4 /24 or an IPv6 /64 |
--relay-fanout <N> | 6 | Peers each new block and transaction is pushed to |
--p2p-role bootstrap | standard | Accepts up to 64 inbound and 16 outbound peers and needs no peer of its own |
--quic-congestion-control bbr | cubic | Congestion control on QUIC connections, the validator overlay's included |
QUIC connections use CUBIC unless told otherwise. CUBIC takes every lost packet as congestion and cuts its rate, so on a long link that loses a packet now and then it sends far below what the line carries. BBR measures the bandwidth and round trip instead and keeps its rate. Only the sending rate changes: TLS with X25519MLKEM768 and the ML-DSA authentication stay exactly the same. TCP connections use what the operating system chooses.
Behind NAT
| Option | Use |
|---|---|
--upnp | Asks the router to forward the P2P port, and on a validator the overlay port |
--relay-peer <IDENTITY@MULTIADDR> | A peer that relays for nodes without an inbound route. Repeatable |
--no-relay-service | Relays for no validator |
AutoNAT runs by itself and logs whether the node can be reached from outside. It does not change anything: the node works over its own outbound connections either way. Forwarding port 28700 on the router makes the node reachable.
A node that other nodes reach relays for validators behind NAT: only current committee members can reserve a slot or open a circuit, and the circuit carries their own TLS and ML-DSA handshake, so the relay sees nothing but ciphertext. --no-relay-service or "relay_service": false turns this off.
How peers are checked
Every connection uses TLS 1.3 with the post-quantum key exchange X25519MLKEM768 only. On top of that, nodes authenticate each other with ML-DSA-65 signatures bound to the TLS session, so a relay in between cannot pass a signed handshake from one session to another.
Each connection proves this on its own while it is set up. A connection that fails never reaches the node, and a reconnect or a second connection inherits nothing from an earlier one. One address may have at most 4 connections in setup at a time, so a single host cannot hold all handshake slots.
A peer that sends invalid data is disconnected and refused for 5 minutes, longer each time it happens again. Its IP address is refused as well only once three different identities from that address misbehaved within 10 minutes, so honest nodes behind the same router or carrier NAT are not shut out by one bad neighbour.
A peer serves chain data only after its transport identity, ML-DSA authentication, protocol and chain all agree. Bootstrap and relay peers only help with connectivity; they have no say over the chain.
Node identity
The node identity is created on first start and logged as node identity <hex>. tenraid reset-identity --yes creates a new one at the next start; peers and wallets that pinned the old one have to be given the new value.
Moving a node
An IP address is not part of the chain state. Stop the old process before starting a copied node. To keep the same P2P and API identity on another machine, copy these private files from the data directory with their ownership and permissions intact:
network/host.key
network/mldsa65.seedStarting without them creates a new identity. That is fine for an ordinary node, but peers, wallets and IDENTITY@MULTIADDR settings that pinned the old identity must be updated. Never run two copies of either identity at once.
After reconnecting, peers learn the node's new address; a public IP change needs no transaction. A validator has more to move, see Run a validator.
