Tools and configuration for bootstrapping a Certen Protocol BFT validator network.
bootstrap-network.batchmod +x bootstrap-network.sh
./bootstrap-network.shcerten-network-set-up/
├── cmd/
│ └── generate-genesis/
│ └── main.go # Genesis generator source
├── genesis-output/ # Generated after running bootstrap
│ ├── genesis.json # Shared genesis file
│ ├── network-config.json # Full network configuration
│ ├── peers.txt # Persistent peers list
│ └── validators/
│ ├── validator-1/
│ │ ├── config/
│ │ │ ├── genesis.json
│ │ │ ├── node_key.json
│ │ │ └── priv_validator_key.json
│ │ ├── data/
│ │ │ └── priv_validator_state.json
│ │ └── .env
│ ├── validator-2/
│ ├── validator-3/
│ └── validator-4/
├── migrations/
│ └── 001_initial_schema.sql # Database schema
├── docker-compose-network.yml # Multi-validator compose
├── bootstrap-network.sh # Linux/macOS bootstrap
├── bootstrap-network.bat # Windows bootstrap
├── go.mod # Go module
├── .env # Network environment (generated)
└── README.md # This file
cd cmd/generate-genesis
go build -o ../../generate-genesis .
cd ../.../generate-genesis \
--validators=4 \
--chain-id=certen-mainnet \
--output=./genesis-output \
--genesis-time="2026-01-15T00:00:00Z" \
--voting-power=10Options:
| Flag | Default | Description |
|---|---|---|
--validators |
4 | Number of validators |
--chain-id |
certen-mainnet | Network chain ID |
--output |
./genesis-output | Output directory |
--genesis-time |
now + 5 min | Genesis time (RFC3339) |
--voting-power |
10 | Power per validator |
--base-port |
26656 | Base P2P port |
--base-host |
validator | Hostname pattern |
Edit .env with your credentials:
# Required: Ethereum RPC endpoint
ETHEREUM_URL=https://eth-sepolia.g.alchemy.com/v2/YOUR_API_KEY
# Required: Validator private keys (one per validator)
ETH_PRIVATE_KEY_1=0x_YOUR_PRIVATE_KEY_1
ETH_PRIVATE_KEY_2=0x_YOUR_PRIVATE_KEY_2
ETH_PRIVATE_KEY_3=0x_YOUR_PRIVATE_KEY_3
ETH_PRIVATE_KEY_4=0x_YOUR_PRIVATE_KEY_4
# Optional: Database password
POSTGRES_PASSWORD=your_secure_password# Start database first
docker-compose -f docker-compose-network.yml up -d postgres
# Wait for database
sleep 10
# Start all validators
docker-compose -f docker-compose-network.yml up -d# Check validator health endpoints
curl http://localhost:8081/health
curl http://localhost:8082/health
curl http://localhost:8083/health
curl http://localhost:8084/health
# Check CometBFT consensus status
curl http://localhost:26671/status | jq '.result.sync_info'┌─────────────────────────────────────────────────────────────────┐
│ CERTEN VALIDATOR NETWORK │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Validator-1 │◄──►│ Validator-2 │◄──►│ Validator-3 │ │
│ │ :8081 │ │ :8082 │ │ :8083 │ │
│ │ :26671 │ │ :26672 │ │ :26673 │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ └──────────────────┼──────────────────┘ │
│ │ │
│ ┌────────┴────────┐ │
│ │ Validator-4 │ │
│ │ :8084 │ │
│ │ :26674 │ │
│ └────────┬────────┘ │
│ │ │
│ ┌────────┴────────┐ │
│ │ PostgreSQL │ │
│ │ :5432 │ │
│ └─────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
| Service | API Port | Metrics | P2P Port | RPC Port |
|---|---|---|---|---|
| validator-1 | 8081 | 9091 | 26661 | 26671 |
| validator-2 | 8082 | 9092 | 26662 | 26672 |
| validator-3 | 8083 | 9093 | 26663 | 26673 |
| validator-4 | 8084 | 9094 | 26664 | 26674 |
| postgres | - | - | - | 5432 |
| Parameter | Value | Description |
|---|---|---|
| Validators | 4 | Total validator count |
| Byzantine Threshold | 1 | Max faulty nodes (f) |
| Consensus Quorum | 3 | Required votes (2f+1) |
| Voting Power | 10 each | Equal power distribution |
| Block Time | ~1-3s | CometBFT default |
# View all logs
docker-compose -f docker-compose-network.yml logs -f
# View specific validator logs
docker-compose -f docker-compose-network.yml logs -f validator-1
# Stop network
docker-compose -f docker-compose-network.yml down
# Stop and remove volumes (DESTROYS DATA)
docker-compose -f docker-compose-network.yml down -v
# Restart specific validator
docker-compose -f docker-compose-network.yml restart validator-1
# Scale validators (if using replicas)
docker-compose -f docker-compose-network.yml up -d --scale validator=4
# Check container status
docker-compose -f docker-compose-network.yml psFor deploying validators across multiple machines:
./generate-genesis --validators=4 --chain-id=certen-productionCopy to each validator node:
genesis-output/validators/validator-N/→ Node Ngenesis-output/genesis.json→ All nodesgenesis-output/peers.txt→ All nodes
On each validator machine, update the .env:
# Use actual hostnames/IPs
COMETBFT_P2P_PERSISTENT_PEERS=nodeID1@validator-1.example.com:26656,nodeID2@validator-2.example.com:26656,...
# Attestation peers with public URLs
ATTESTATION_PEERS=http://validator-1.example.com:8080,http://validator-2.example.com:8080,...Start all validators before genesis time:
# On each node
docker-compose -f docker-compose.yml up -d- Check persistent peers are correctly configured
- Verify firewall allows P2P ports (26656)
- Check all validators use same genesis.json
# Compare genesis hashes
sha256sum genesis-output/validators/*/config/genesis.json- Ensure 2f+1 validators are running (3 of 4)
- Check validators have synced clocks
- Verify genesis time has passed
# Check CometBFT status
curl http://localhost:26671/status | jq '.result.sync_info.catching_up'# Check PostgreSQL logs
docker-compose -f docker-compose-network.yml logs postgres
# Verify database is accessible
docker exec certen-postgres pg_isready -U certen -d certen- Private Keys: Never commit
.envfiles with real private keys - Database: Change default PostgreSQL password in production
- Network: Use TLS for inter-validator communication in production
- Firewall: Restrict P2P ports to known validator IPs
- Keys: Store validator keys in secure key management system
After network is running:
- Register Validators: Call
registerValidator()on CertenAnchorV3 contract - Fund Validators: Ensure each validator has ETH for gas
- Monitor: Set up Prometheus/Grafana dashboards
- Backup: Configure automated key and database backups