Guide
Run a validator
Set up a Tenrai validator step by step. Prepare the node, register with a self-bond, give the node its keys and keep it live.
On this page
Validators sign the cuts that make Tenrai final. Each epoch (34,560 cuts, about a day) the 64 eligible validators with the most stake form the committee.
What you need
| Stake | At least 100,000 TRAI for the self-bond, plus a little for fees, in a tenrai-wallet file |
|---|---|
| A node | tenraid, synced, with the full TenQ dataset. A validator cannot run with --tenq-light |
| Storage | full or archive, synced from genesis; never pruned or started from a snapshot |
| Network | Nothing to open. A port that other validators reach directly is recommended, see How validators reach each other |
| One machine per key | The consensus key must never run on two nodes at once, see Never run one key twice |
A validator node is a normal node with two additions: the validator overlay, a network between the validators of the committee, and the consensus key, which signs votes.
1. Run a synced node
Set up the node as described in Run a node, with tenq.full_dataset in node.json or --tenq-threads. Wait until GET /v1/node/sync answers "synced": true.
All later steps use the node's data directory. If you do not use the default one, pass the same --data-dir to every tenraid command.
2. Create the endpoint
The endpoint names your node in the committee and, if you want, where other validators reach it. Run on the validator machine, with the node's network and data directory.
If port 28704 (testnet 28709) is open for TCP and UDP, give the public IP or host name:
tenraid validator-endpoint --route 198.51.100.7Without an open port, leave the route out. The node then connects out by itself:
tenraid validator-endpoint| Part | |
|---|---|
--route | Optional. The public IP or host name of the validator, with :PORT for another port. It stands for TCP and QUIC; a multiaddr names one route. At most four routes |
| Output | One line of hex, needed for the registration |
The command creates the overlay keys in network/validator-overlay/ in the data directory, and the endpoint is bound to them. Keep that folder; new keys mean a new endpoint.
3. Register the validator
Register from the wallet that holds the self-bond. The transaction bonds the stake and records the endpoint and the wallet's consensus key on the chain:
tenrai-wallet validator-register --amount 100000 --overlay-endpoint-hex <hex from step 2> --waitThe wallet commands on this page use the wallet of the machine they run on and ask for its password. --file and --password-file name another wallet file and a file with its password.
| Option | |
|---|---|
--amount | Self-bond in TRAI, at least 100,000 |
--commission-bps | Delegator commission: 0 to 1,000 basis points in steps of 10. The wallet default is 500 (5.0%) |
--reward-address | Address that receives the self-bond's rewards. Default: the wallet's first address |
--consensus-key-index | Wallet key used as consensus key. Default 2147483647; change it only to run several validators from one wallet |
--wait | Waits until the registration is final |
--dry-run | Shows the transaction and its fee without sending it |
Then look up the validator ID. It is the validator value of the new self_bond position:
tenrai-wallet positions4. Export the consensus key
Create validator.pass with a long random password first. Then:
tenrai-wallet validator-key-export \
--validator-key-file validator.key --validator-key-password-file validator.passThe command writes validator.key, encrypted with that password. If you changed --consensus-key-index in step 3, pass the same value here.
5. Export the heartbeat fee key
A validator has to publish a heartbeat transaction once per epoch to stay live. The node does this by itself and pays the fee from a separate key, so it never holds the key to your stake. Create heartbeat.pass with another password, then:
tenrai-wallet validator-heartbeat-fee-key-export \
--heartbeat-fee-key-file heartbeat.key --heartbeat-fee-key-password-file heartbeat.passThe output shows heartbeat_fee_address. Send a small amount to that address, for example 1 TRAI. Each heartbeat pays the minimum fee of one transaction.
6. Configure the node
Copy validator.key, validator.pass, heartbeat.key and heartbeat.pass to the validator machine. The node refuses key and password files that other users can read:
Linux
chmod 600 validator.key validator.pass heartbeat.key heartbeat.passmacOS
chmod 600 validator.key validator.pass heartbeat.key heartbeat.passWindows
foreach ($f in "validator.key","validator.pass","heartbeat.key","heartbeat.pass") {
icacls $f /inheritance:r /grant:r "${env:USERNAME}:F"
}Add the validator section to node.json. The overlay then listens on port 28704 on every interface; a validator_overlay section with listen_addrs changes that:
{
"validator": {
"consensus_key_file": "/srv/tenrai/validator.key",
"password_file": "/srv/tenrai/validator.pass",
"heartbeat": {
"validator_id": "<validator ID from step 3>",
"fee_key_file": "/srv/tenrai/heartbeat.key",
"fee_key_password_file": "/srv/tenrai/heartbeat.pass",
"max_fee_atoms": 1000000
}
}
}| Field | |
|---|---|
validator_overlay.listen_addrs | Optional. Where the overlay listens: an IP, IP:PORT or up to eight multiaddrs. The port must match the routes of step 2 |
consensus_key_file, password_file | The consensus key from step 4 |
heartbeat.validator_id | The validator ID, 96 hex characters |
heartbeat.fee_key_file, fee_key_password_file | The fee key from step 5 |
heartbeat.max_fee_atoms | Highest fee one heartbeat may pay, in atoms; 100,000,000 atoms are 1 TRAI |
heartbeat.fee_rate_per_mass | Optional fee rate. Default: the network minimum |
Relative paths count from the directory tenraid is started in, so use absolute ones. Heartbeats go out over the node's normal P2P connections, so no port has to be open; a development node needs a public_p2p section or P2P options for that. Restart the node.
7. Check it
| Check | Where |
|---|---|
validator heartbeat submitted once per epoch | Node log |
The validator is listed as eligible | tenrai-wallet validators |
| Health, signed cuts, stake | The validator's page in the explorer |
A new validator joins the committee and earns from the second epoch after the one it registered in, one to two days later.
Staying live
| Heartbeat | The node sends one at the start of every epoch, as long as the fee address has coins |
|---|---|
| Grace | A validator stays live for two epochs after its last final heartbeat |
| Lapsed | No seat in the next committee |
| Back | The next final heartbeat makes it live again |
Being live only keeps a validator eligible for the committee. To earn, a committee member must sign: each epoch is split into twelve windows of about two hours, and a member earns for the epoch only if its signature is in finalized cut certificates in at least nine of them. A member that misses this earns nothing for that epoch, nor do its delegators, and it is jailed for the next two epochs. Jailing costs no stake.
A heartbeat can also be sent by hand from the owner wallet, for example while the node is being moved:
tenrai-wallet validator-heartbeat --validator <validator ID>| Node log | Fix |
|---|---|
cannot fund validator heartbeat | The fee address is empty; send coins to it |
validator heartbeat exceeds configured fee cap | Raise max_fee_atoms |
Day to day
List all validators and their state:
tenrai-wallet validatorsSend the self-bond's rewards to another address:
tenrai-wallet reward-address --position <position ID> --to <address>Rotate the consensus key:
tenrai-wallet validator-rotate \
--validator <ID> --consensus-key-index 2147483646 --overlay-endpoint-hex <hex>Schedule a new registered endpoint without rotating the consensus key:
tenrai-wallet validator-endpoint \
--validator <ID> --consensus-key-index 2147483647 --overlay-endpoint-hex <hex>Schedule a new delegator commission, for example 2.6%:
tenrai-wallet validator-commission --validator <ID> --commission-bps 260 --waitThe commission is 0 to 1,000 basis points in steps of 10. Only one change can be pending; it takes effect 14 epochs later, so delegators see it coming.
Leave the validator set:
tenrai-wallet validator-exit --validator <ID>Rotation. A new consensus key needs an index that was never used, from 2147418112 to 2147483647. It signs from the second finalized epoch after the rotation; export it then with validator-key-export --consensus-key-index <new index> and point consensus_key_file at it. Do not edit the genesis manifest to change a running validator.
Endpoint. tenrai-wallet validator-endpoint replaces the registered endpoint and is signed by both the owner wallet and the active consensus key. Create the new endpoint bytes with tenraid validator-endpoint on the validator node first. The new endpoint takes effect two epochs later; the consensus key stays the same. A changed public IP does not need this transaction.
Opening the port later. The node keeps working without any change. To publish a route, create new endpoint bytes with tenraid validator-endpoint --route <address> and register them with validator-endpoint.
Moving to another machine. Hand the validator over; never clone it. Stop the old node and make sure its process has ended before the new one starts; no exit is needed. Move the complete data directory while the node is stopped, never a copy of a running database and never the consensus key alone: the directory holds the signer journal, which records what the key already signed, and the overlay identity. Move the encrypted consensus and heartbeat fee keys with their passwords as well. Never run two machines with the same consensus key, fee key or overlay identity.
Exit. A final validator exit starts unbonding for every position, delegations included, and each delegator withdraws their own after the 10 days. Shutting the node down does not exit the validator.
How validators reach each other
Validators with a route accept connections from the committee. Of two such validators the one with the lower validator ID dials; the other one dials back when nothing arrived after a few seconds, so a port that turns out to be closed is covered. A validator without a route dials every validator that has one.
Two validators without a direct connection, for example two without open ports, still hear each other: each asks two of its neighbours to pass on what the other signs, and those do the same further on if needed. Votes, proposals and certificates carry the signer's ML-DSA signature, which every validator checks on arrival and every forwarder before passing a message on. A forwarder can drop or delay a message but not change it, and with two independent paths one forwarder that drops everything cuts nobody off.
Direct connections come first; forwarding only covers what is missing, and each extra hop adds that link's delay.
Without any open port. A validator keeps a slot at two relays, nodes of the network that others can reach. It announces how to reach it, through those relays or through a port opened with --upnp, in a record signed with its overlay key, and every node passes that record on. Other validators check the signature against the registered key and connect through the relay. TLS with X25519MLKEM768 and the ML-DSA handshake run end to end inside the relayed connection, so the relay sees only ciphertext. A direct connection replaces a relayed one as soon as one works.
A changing public IP. No on-chain transaction has to follow it. The node notices that its connections broke, reconnects from the new address, and the other validators replace the old connection. A route that no longer answers counts as no route: the node dials out, and the committee hears it through the validators it reaches. Keep another committee member or relay reachable during a move; do not move an entire committee at once. Use validator-endpoint only when the registered static endpoint itself must change.
The log tells which case applies:
| Log line | Meaning |
|---|---|
validator overlay is connected to every committee member | Direct connections to the whole committee |
validator overlay reaches some committee members through other validators | direct counts direct connections, forwarded the members reached through others, unreachable those reached neither way |
Never run one key twice
Rewards
Half of all new TRAI and half of all fees go to stakers. Once a day, after the epoch's last cut, that pool is paid out to the positions of the committee members that signed enough, in proportion to their stake. The validator keeps the full share of its own bond and the commission from its delegators' shares. Payouts are normal coins to each position's reward address; nothing has to be claimed. Staking and delegation explains it from the delegator's side.
