This guide explains how to run a Bounty Challenge validator.
Validators perform two key functions:
- Auto-scan: Periodically scan GitHub for new valid issues
- Credit rewards: Link issues to registered miners and update weights
- Server: Linux with 1+ CPU, 2GB RAM
- Network: Outbound HTTPS access to GitHub API and Platform
- Database: PostgreSQL 14+ (or access to Platform's PostgreSQL)
- Bittensor: Validator hotkey registered on the subnet
# Clone repository
git clone https://github.com/PlatformNetwork/bounty-challenge.git
cd bounty-challenge
# Build release
cargo build --release
# Verify
./target/release/bounty --version# Required
export DATABASE_URL="postgres://user:pass@localhost:5432/bounty"
export GITHUB_TOKEN="ghp_xxxxxxxxxxxx"
# Optional
export CHALLENGE_HOST="0.0.0.0"
export CHALLENGE_PORT="8080"
export PLATFORM_URL="https://chain.platform.network"
export VALIDATOR_HOTKEY="5FHneW46..."The server automatically runs migrations on startup. Alternatively:
psql $DATABASE_URL < migrations/002_rewards_schema.sqlRun the full server with auto-scanning:
./target/release/bounty serverOr with explicit options:
./target/release/bounty server --host 0.0.0.0 --port 8080Run validator-only mode (no HTTP server):
./target/release/bounty validate \
--platform https://chain.platform.network \
--hotkey $VALIDATOR_HOTKEY[github]
client_id = "Ov23liAkfvnMhA6C68iy"
# Target repository for bounties
[[github.repos]]
owner = "PlatformNetwork"
repo = "bounty-challenge"
[server]
host = "0.0.0.0"
port = 8080
[database]
# PostgreSQL URL from environment variable DATABASE_URL
# Set DATABASE_URL environment variable for PostgreSQL connection
[rewards]
# 50 points = 100% weight (1 point per valid issue + 0.25 per starred repo)
max_points_for_full_weight = 50
weight_per_point = 0.02
valid_label = "valid"| Variable | Required | Description |
|---|---|---|
DATABASE_URL |
Yes | PostgreSQL connection string |
GITHUB_TOKEN |
Yes | GitHub API token (for rate limits) |
PLATFORM_URL |
No | Platform server URL |
VALIDATOR_HOTKEY |
No | Your validator hotkey |
CHALLENGE_HOST |
No | Server bind address |
CHALLENGE_PORT |
No | Server port |
By default, validators scan every 5 minutes:
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Fetch closed │────▶│ Filter with │────▶│ Credit to │
│ issues │ │ 'valid' label│ │ miners │
└──────────────┘ └──────────────┘ └──────────────┘
- Target repos: All repos in config.toml
- Issue state: Only closed issues
- Label filter: Only issues with
validlabel - Time filter: Since last scan timestamp
For each valid issue:
- Check if already credited (by issue ID)
- Look up GitHub username → hotkey mapping
- Calculate weight at time of resolution
- Record in
resolved_issuestable
curl http://localhost:8080/healthResponse:
{
"healthy": true,
"uptime_secs": 3600,
"version": "0.1.0"
}curl http://localhost:8080/statsResponse:
{
"total_bounties": 150,
"total_miners": 25
}Run with verbose logging:
RUST_LOG=info ./target/release/bounty serverLog levels:
error: Critical errors onlywarn: Warnings and errorsinfo: Normal operation (recommended)debug: Detailed debuggingtrace: Very verbose
sudo nano /etc/systemd/system/bounty-validator.service[Unit]
Description=Bounty Challenge Validator
After=network.target postgresql.service
[Service]
Type=simple
User=bounty
WorkingDirectory=/opt/bounty-challenge
ExecStart=/opt/bounty-challenge/target/release/bounty server
Restart=always
RestartSec=10
Environment=DATABASE_URL=postgres://user:pass@localhost:5432/bounty
Environment=GITHUB_TOKEN=ghp_xxxx
Environment=RUST_LOG=info
[Install]
WantedBy=multi-user.targetsudo systemctl daemon-reload
sudo systemctl enable bounty-validator
sudo systemctl start bounty-validator
sudo systemctl status bounty-validatorsudo journalctl -u bounty-validator -fFROM rust:1.75 as builder
WORKDIR /app
COPY . .
RUN cargo build --release
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*
COPY --from=builder /app/target/release/bounty /usr/local/bin/
EXPOSE 8080
CMD ["bounty", "server"]version: '3.8'
services:
bounty:
build: .
ports:
- "8080:8080"
environment:
- DATABASE_URL=postgres://bounty:secret@db:5432/bounty
- GITHUB_TOKEN=${GITHUB_TOKEN}
- RUST_LOG=info
depends_on:
- db
db:
image: postgres:14
environment:
- POSTGRES_USER=bounty
- POSTGRES_PASSWORD=secret
- POSTGRES_DB=bounty
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:GITHUB_TOKEN=ghp_xxx docker-compose up -d- Cause: Too many API requests without token
- Fix: Set
GITHUB_TOKENenvironment variable
- Cause: Invalid
DATABASE_URLor PostgreSQL not running - Fix: Verify connection string and database availability
- Cause: No closed issues with
validlabel - Fix: Verify target repos have valid issues
- Cause: Large number of issues being processed
- Fix: Increase server RAM or reduce scan batch size
- Use a token with minimal permissions (read-only)
- Store securely (environment variable, not in config)
- Rotate regularly
- Use strong passwords
- Enable SSL for remote connections
- Restrict network access
- Use HTTPS for all external communication
- Consider running behind a reverse proxy (nginx)