This guide provides a step-by-step process to add a validator to the TFChain network.
It covers generating keys using subkey
via Docker, starting the node, inserting keys, and submitting the necessary proposals for validation.
- Docker Installed: Ensure Docker is installed and running on your machine.
- Access to a Server or Machine: Where you can run the TFChain node and
subkey
via Docker. - Polkadot.js Browser Extension: For managing accounts and signing transactions.
- Basic Knowledge: Familiarity with command-line operations and blockchain concepts.
The most common way for a beginner to run a validator is on a cloud server running Linux. You may choose any VPS provider you prefer and any operating system you are comfortable with. For this guide, we will be using Ubuntu 22.04, but the instructions should be similar for other platforms.
The transaction weights in TFChain were benchmarked on standard hardware. It is recommended that validators run at least the standard hardware to ensure they can process all blocks in time. The following are not minimum requirements, but if you decide to run with less than this, be aware that you might have performance issues.
- CPU
- x86-64 compatible;
- Intel Ice Lake, or newer (Xeon or Core series); AMD Zen3, or newer (EPYC or Ryzen);
48 physical cores @ 3.4GHz;- Simultaneous multithreading disabled (Hyper-Threading on Intel, SMT on AMD);
- Prefer single-threaded performance over higher core count. A comparison of single-threaded performance can be found here.
- Storage
- An NVMe SSD. Should be reasonably sized to deal with blockchain growth. Minimum around 80GB but will need to be re-evaluated every six months.
- Memory
3264 GB DDR4 ECC.
- System
- Linux Kernel 5.16 or newer.
The specs posted above are not a hard requirement to run a validator but are considered best practice. Running a validator is a responsible task; using professional hardware is a must in any case.
We'll use subkey
via Docker to generate a new key pair for your validator account.
docker run --rm parity/subkey:latest generate --scheme sr25519
Take note of the following:
- Secret Phrase (Mnemonic): Securely store this mnemonic; it's crucial for account recovery.
- Secret Seed
- Public Key (hex)
- SS58 Address: This is your validator's account address.
This key will serve as your validator controller account and session key for AURA (validator node/author account). It will also be used to derive the GRANDPA key.
Generate the node key file, which identifies your node in the P2P network.
docker run --rm parity/subkey:latest generate-node-key > "<node_private_key_file>"
This command outputs a public key and writes the secret seed (private key) to the <node_private_key_file>
file. Keep the secret seed secure; you'll use it when starting the node.
Using the same mnemonic from step 1.1, derive the GRANDPA key (Ed25519).
docker run --rm parity/subkey:latest inspect --scheme ed25519 "mnemonic phrase"
Replace "mnemonic phrase"
with your actual mnemonic enclosed in quotes.
Note down the Public Key (hex) for GRANDPA. This key will serve as your session key for GRANDPA.
You can start the TFChain node using either Docker, a Kubernetes deployment or the TFChain binary.
Create a directory on your host machine to store node data (e.g., /path/to/storage
).
mkdir -p /path/to/storage
Since the TFChain Docker container doesn't persist keys between runs by default, we'll run temporary containers to insert the keys into the shared volume.
AURA Key:
docker run --rm \
-v /path/to/storage:/storage \
ghcr.io/threefoldtech/tfchain:latest \
key insert \
--base-path /storage \
--chain /etc/chainspecs/main/chainSpecRaw.json \
--key-type aura \
--suri "<mnemonic phrase>" \
--scheme sr25519
GRANDPA Key:
docker run --rm \
-v /path/to/storage:/storage \
ghcr.io/threefoldtech/tfchain:latest \
key insert \
--base-path /storage \
--chain /etc/chainspecs/main/chainSpecRaw.json \
--key-type gran \
--suri "<mnemonic phrase>" \
--scheme ed25519
- Ensure the
/path/to/storage
directory is consistent across commands. - Replace
<mnemonic phrase>
with your mnemonic from step 1.1.
docker run -d --name tfchain-validator \
-v /path/to/storage:/storage \
ghcr.io/threefoldtech/tfchain:latest \
--base-path /storage \
--chain /etc/chainspecs/<NETWORK>/chainSpecRaw.json \
--validator \
--node-key "<node_private_key>" \
--name "YourValidatorName" \
--telemetry-url 'wss://shard1.telemetry.tfchain.grid.tf/submit 1' \
--blocks-pruning archive \
--state-pruning 1000 \
--offchain-worker Always \
--sync warp
- Replace
<NETWORK>
with the name of the network you want to join (e.g.,test
ormain
). - Replace
<node_private_key>
with the node's secret seed from step 1.2. - Replace
"YourValidatorName"
with your chosen validator name. - The
--sync warp
flag enables faster synchronization by skipping state transitions from older blocks.
Create a values.yaml
file with your configurations for deploying the validator node using Kubernetes.
keys:
- name: aura
secret: "<mnemonic created by `subkey generate` in step 1>"
- name: grandpa
secret: "<mnemonic created by `subkey generate` in step 1>"
- name: node
secret: "<node private key generated in step 1>"
volume:
existingPersistentVolumeClaim: 'your-pvc-name'
persistentVolume:
create: false
is_validator: true
disable_offchain_worker: false
chainspec: '/etc/chainspecs/main/chainSpecRaw.json'
sync: warp
ingress:
enabled: false
- Replace
<mnemonic phrase>
with your mnemonic from step 1.1. - Replace
<node_private_key>
with the node's secret seed from step 1.2. - Ensure you have a Persistent Volume Claim (PVC) named
'your-pvc-name'
with sufficient storage (e.g., 100Gi). - Enable warp sync by setting
sync: warp
.
Install the Helm chart located at substrate-node/charts/substrate-node
using your custom values.yaml
file.
helm install tfchain-validator substrate-node/charts/substrate-node -f values.yaml
This will set up the TFChain validator node on your Kubernetes cluster using the specified configurations.
If you have never installed Rust, you should do this first.
If you have already installed Rust, run the following command to make sure you are using the latest version:
rustup update
If not, this command will fetch the latest version of Rust and install it:
curl https://sh.rustup.rs -sSf | sh -s -- -y
If you do not have "curl" installed, run sudo apt install curl
To configure your shell, run the following command.
source $HOME/.cargo/env
Verify your installation.
rustc --version
Finally, run this command to install the necessary dependencies for compiling and running the Polkadot node software:
sudo apt install make clang pkg-config libssl-dev build-essential
Note: If you are using macOS and you have Homebrew installed, you can use the following equivalent command INSTEAD of the previous one:
brew install cmake pkg-config openssl git llvm
NTP is a networking protocol designed to synchronize the clocks of computers over a network. NTP allows you to synchronize the clocks of all the systems within the network. Currently, it is required that validators' local clocks stay reasonably in sync, so you should be running NTP or a similar service. You can check whether you have the NTP client by running:
If you are using Ubuntu 18.04 / 19.04, NTP Client should be installed by default.
timedatectl
If NTP is installed and running, you should see "System clock synchronized: yes" (or a similar message). If you do not see it, you can install it by executing:
sudo apt-get install ntp
ntpd will be started automatically after installation. You can query ntpd for status information to verify that everything is working:
sudo ntpq -p
- WARNING: Skipping this can result in the validator node missing block authorship opportunities. If the clock is out of sync (even by a small amount), the blocks the validator produces may not be accepted by the network.
Clone the tfchain repository:
git clone https://github.com/threefoldtech/tfchain.git
cd substrate-node
Now build the binary:
cargo build --release
This step will take a while (generally 10 - 40 minutes, depending on your hardware).
You can find the compiled binary in ./target/release/
cd target/release/
./tfchain \
--base-path /storage \
--chain chainspecs/main/chainSpecRaw.json \
--validator \
--node-key-file "<node_private_key_file>" \
--name "YourValidatorName" \
--telemetry-url 'wss://shard1.telemetry.tfchain.grid.tf/submit 1' \
--blocks-pruning archive \
--state-pruning 1000 \
--sync warp
- Replace
<node_private_key_file>
with the path to the node's secret seed file from step 1.2. - Replace
"YourValidatorName"
with a name for your node. - Ensure the
--blocks-pruning archive
and--state-pruning 1000
flags are used for optimal database size. - The
--sync warp
flag enables faster synchronization by skipping intermediate state processing.
Insert the AURA and GRANDPA keys into your node's keystore.
AURA Key (Sr25519):
./tfchain key insert \
--base-path /storage \
--chain chainspecs/main/chainSpecRaw.json \
--key-type aura \
--suri "<mnemonic phrase>" \
--scheme sr25519
GRANDPA Key (Ed25519):
./tfchain key insert \
--base-path /storage \
--chain chainspecs/main/chainSpecRaw.json \
--key-type gran \
--suri "<mnemonic phrase>" \
--scheme ed25519
- Replace
<mnemonic phrase>
with your mnemonic from step 1.1.
You can restart your node at this point.
Example systemd file:
[Unit]
Description=TFchain service
After=network.target
StartLimitIntervalSec=0
[Service]
Type=simple
Restart=always
RestartSec=1
User=user
ExecStart=/home/user/tfchain/substrate-node/target/release/tfchain <...>
[Install]
WantedBy=multi-user.target
- Replace
user
by your username. - Replace
<...>
with the rest of the tfchain start command arguments.
sudo vim /etc/systemd/system/tfchain.service
Then paste the file content, save, and exit vim.
Starting the service:
sudo systemctl start tfchain
Stopping the service:
sudo systemctl stop tfchain
Reloading the configuration:
sudo systemctl stop tfchain
Editing the service file:
sudo systemctl start tfchain
After editing, remember to reload the configuration and restart the service.
With warp sync enabled, your node will synchronize much faster by downloading key block headers and skipping state transitions. To monitor the synchronization progress, you can view the logs:
# For Docker:
docker logs -f "<container-name>"
# For binary:
tail -f /storage/logs.txt
- Look for log entries indicating the node's best and finalized block numbers.
- Warp sync should significantly reduce the time required to catch up with the current state of the chain.
To have your node recognized as a validator, you need to set your session keys on-chain.
- Open the Polkadot.js browser extension.
- Import your validator controller account using the mnemonic from step 1.1.
- Ensure you have some TFT tokens in this account (0.1 TFT should suffice for transaction fees).
-
Navigate to PolkadotJS Apps.
-
Connect to the TFChain network (e.g., wss://tfchain.dev.grid.tf).
-
Go to Developer → Extrinsics.
-
Select your validator controller account as the signer.
-
Choose
session
→setKeys(keys, proof)
. -
Input your session keys:
-
keys: Use previously generated aura and gran hex public keys
- aura: Manually enter the hex public key of the sr25519 key
- gran: Manually enter the hex public key of the ed25519 key
-
proof: Set to
0x00
-
-
Submit the transaction. Once the session keys are set on-chain, your validator will be recognized by the network.
The TFChain network requires a governance proposal to add a validator node.
- Navigate to Governance → Council.
- Click on Propose Motion.
- Select
validatorSet
→addValidator(validatorId)
. - Input your validator controller account's SS58 address (generated in step 1.1).
- Submit the proposal.
After submission, inform other council members and request them to vote on the proposal.
Once your session keys are set and the council approves your validator, your node will start participating in block production after 2 sessions.
- Keep your node online and synchronized.
- Monitor logs for any errors or warnings.
- Subkey Utility via Docker: Parity Subkey Docker Image
- TFChain Docker Images: TFChain Docker Packages
- PolkadotJS Apps: PolkadotJS Interface
- PolkadotJS Extension: Browser Extension
- Validator Set Pallet: Substrate Validator Set Module
- Council Integration Guide: Council Integration
- Polkadot Validator Guide: How to Validate on Polkadot