node and validator

Run a node or a validator

A full node follows the Dendra chain and checks every block for itself. A validator is a full node that also signs blocks and locks a stake. This page is for anyone with a Linux server that stays on: neither role needs a GPU.

How it works

A full node

Syncs the chain from the public seeds and serves RPC and REST on your machine. It signs nothing, has nothing at stake and earns nothing.

A validator

Also signs blocks, and its VRF key adds to the random seed that draws juries and work. Its stake answers for downtime and double-signing.

What validators are paid

Every paid job carries a protocol cut (protocol_fee_bps), and validator_reward_bps of that cut goes to validators, at the job’s finality.

No kit version

Neither role declares a kit version, so the kit deadline for miners does not apply to either of them.

What you need

A validator is the demanding case: it should run on a server that stays on.

ItemRequirement
MachineNo GPU. For a validator, a server that stays on, such as a VPS: long downtime gets a validator jailed and slashed.
SystemLinux, or Windows with WSL 2. Docker with Compose v2.
Disk and RAMFree disk above MIN_DISK_GB and RAM above MIN_RAM_MB, the floors deploy/install.sh applies. Without a prebuilt image the node compiles the chain binary from your clone, which is what the RAM floor is for.
NetworkPort 26656 (P2P) reachable from outside for a validator; for a full node it helps the network. The RPC port, 26657, stays on 127.0.0.1 by default.

Read the floors from a clone of the repository:

clone, then read the floors
$ git clone https://github.com/DendraNetwork/dendra-network.git && cd dendra-network
$ grep -E '^MIN_(DISK_GB|RAM_MB)=' deploy/install.sh

Join as a full node

Three steps. The node has no bond, so nothing here puts funds at risk.

  1. Clone

    clone the kit
    $ git clone https://github.com/DendraNetwork/dendra-network.git
    $ cd dendra-network/deploy/testnet-node
  2. Fill the configuration from the network’s own file

    The first command prints the network’s values. Copy its CHAIN_ID, GENESIS_URL, GENESIS_SHA256, SEEDS and PERSISTENT_PEERS lines into .env, and set MONIKER to the name your node shows to its peers.

    read the values, then edit .env
    $ curl -s https://testnet-api.dendranetwork.com/network-info.txt
    $ cp .env.example .env
    $ nano .env
  3. Start it

    The node checks the genesis it downloads against GENESIS_SHA256 and refuses to start on a mismatch.

    build, start, follow the log
    $ docker compose up -d --build
    $ docker compose logs -f node

Join as a validator

A validator starts from a node that join.sh sets up and syncs. join.sh never bonds: the bond is a separate command, and nothing is bonded without --yes-bond.

  1. Clone, read the launcher, join as a validator

    Run less on its own: a pager swallows anything pasted after it. Quit with q.

    clone the kit
    $ git clone https://github.com/DendraNetwork/dendra-network.git && cd dendra-network
    read the launcher
    $ less deploy/join.sh
    join as a validator
    $ CONFIG_URL=https://testnet-api.dendranetwork.com/network-info.txt bash deploy/join.sh --validator

    On a bare machine, the installer prepares Docker and runs the same join: bash install.sh --yes --validator (-Validator with install.ps1 on Windows). How to download it: install.

  2. Read what bonding commits you to

    The slashing terms (signed_blocks_window, min_signed_per_window, downtime_jail_duration, slash_fraction_downtime, slash_fraction_double_sign) and the staking terms (unbonding_time, max_validators) are read on chain:

    slashing and staking terms
    $ curl -s https://testnet-api.dendranetwork.com/rest/cosmos/slashing/v1beta1/params
    $ curl -s https://testnet-api.dendranetwork.com/rest/cosmos/staking/v1beta1/params

    Not ready for that uptime? A full node has no bond and nothing at stake.

  3. Create your key and see the plan

    Run it once the node is synced. It creates the operator key, prints your validator address, then refuses for lack of funds: that refusal is expected, and it is how you get the address.

    create the operator key
    $ bash deploy/bond_validator.sh
  4. Fund the address

    The public faucet asks for a short proof of work, computed in a terminal: the faucet claim, with the address from step 3. Then run bash deploy/bond_validator.sh again: it prints the largest bond your balance covers, in udndr.

  5. Bond

    There is no confirmation prompt: the flag is what bonds. It also anchors your VRF key and restarts the node with it.

    bond
    $ bash deploy/bond_validator.sh --amount <udndr printed in step 4> --yes-bond

    The script refuses a bond that would leave any validator with two thirds of the voting power or more. If it refuses yours, ask in #operator-support before going further.

Check

A node is synced

When this prints "catching_up":false:

local node status
$ curl -s http://localhost:26657/status | grep -o '"catching_up":[a-z]*'

A validator

Whether it is jailed or slashed, and the margin left before the next jail, from the clone’s root:

validator health
$ bash deploy/validator_health.sh

The validator set and the seed

The validator set and each one’s voting power:

validator set
$ curl -s https://testnet-api.dendranetwork.com/rpc/validators

The seed’s contributors. After you bond, latest_contributors goes up:

seed contributors
$ curl -s https://testnet-api.dendranetwork.com/rest/dendra/jobs/v1/committee_seed_health

Open the port

Allow 26656/tcp in the host firewall and, on a VPS, in your provider’s firewall, which is a separate setting in their console. At home, forward 26656 to the machine on your router. Then give the node its public address, in deploy/testnet-node:

set the public address, restart
$ sed -i 's|^DENDRA_EXTERNAL_ADDRESS=.*|DENDRA_EXTERNAL_ADDRESS=YOUR.PUBLIC.IP:26656|' .env
$ docker compose up -d

The node refuses to start on a private or loopback address. To see whether peers reach you, from the clone’s root:

peer reachability
$ bash deploy/node_reachability.sh

Keep the RPC local. 26657 is published on 127.0.0.1 by default (DENDRA_RPC_BIND in .env), and a miner on the same machine still reaches the node over Docker. Set 0.0.0.0 only for a public RPC on purpose: on a VPS, that is an unauthenticated RPC open to the internet.

Update

Do not use git pull: each release republishes the repository, so it refuses with “refusing to merge unrelated histories” and the old kit stays. First move the clone; the tree you leave stays on the branch kit-before-update, and this line alone changes nothing that runs:

move the clone to the new release
$ git fetch origin && git branch -f kit-before-update && git checkout -B main origin/main

A full node started with docker compose

Run docker compose up -d --build again, in deploy/testnet-node.

A validator set up by join.sh

Run the same join.sh command again, CONFIG_URL and --validator included. A re-run bonds nothing.

Installed with install.sh --ref

Download the installer of the newer release tag and run it with --yes, --ref set to that tag, and your first options.

A miner on the same machine

Update an installed kit.