ChipForge introduces the first digital design subnet for decentralized hardware innovation. This subnet enables miners to compete in designing real silicon. Processor development is organized into on-chain challenges — spanning AI accelerators, cryptographic modules, mini-GPUs, and other critical components. Participants download specifications, leverage AI tools, and submit complete Verilog/SystemVerilog implementations. The highest-quality designs earn rewards while contributing to fully manufacturable chips.
In the short term, ChipForge focuses on advancing digital hardware design, with future applications across IoT, robotics, edge devices, and post-quantum security. Our roadmap includes progressing from design to full-scale fabrication within a year. Revenue from design IPs and fabricated chips will be reinvested into the ecosystem, ensuring sustainable value creation. Backed by the Tatsu validator team and open to strategic partnerships, ChipForge marks the beginning of a new era — decentralized, collaborative, and on-chain digital design.
ChipForge operates as a competitive platform where:
- Miners submit hardware design solutions (Verilog/SystemVerilog)
- Validators evaluate submissions using industry-standard EDA tools (Verilator, Yosys, Icarus, Openlane)
- Challenges are rotated periodically with different design requirements
- Rewards are distributed based on performance metrics and competitive scoring - This is a winner-takes-all reward mechanism
- Chipforge Challenge Server - Manages challenges, submissions, and evaluations
- Miners - Submit optimized hardware designs for active challenges
- Validators - Download, evaluate, and score miner submissions against provided test benches and test cases
- Chipforge EDA Server - Performs synthesis, place & route, and timing analysis
1. Challenge Activation → 2. Miner Submissions → 3. Batch Creation →
4. Validator Downloads → 5. EDA Evaluation → 6. Score Submission →
7. Weight Setting → 8. Challenge Completion
- Docker with the compose plugin (recommended), or Python 3.12
- Bittensor wallet with registered hotkey
- Access to Chipforge Challenge Server API
- Chipforge EDA Server (for validators)
Both miners and validators need a hotkey registered on subnet 108 (btcli docs):
btcli wallet create --wallet-name mywallet --hotkey default # coldkey + hotkey
btcli subnets register --netuid 108 --network finney --wallet-name mywallet --hotkey defaultThe folder name you chose (mywallet) is what goes in VALIDATOR_WALLET_NAME / MINER_WALLET_NAME.
Validators additionally need:
- a validator permit, which the chain gives to the top-staked hotkeys of the subnet: stake to your hotkey
with
btcli stake add --netuid 108 .... Your influence on who gets paid is proportional to your stake; - a
VALIDATOR_SECRET_KEYfrom the ChipForge team (ask on Discord); - the ChipForge EDA server running and reachable
at
EDA_SERVER_URL(defaulthttp://localhost:8080) before the validator starts.
For testnet, use --network test with your test subnet's netuid, and set NETUID / SUBTENSOR_NETWORK in .env to match.
All settings live in .env; .env.example documents every one of them.
git clone https://github.com/TatsuProject/ChipForge_SN108
cd ChipForge_SN108
cp .env.example .env # defaults are for mainnet (netuid 108); set the VALIDATOR_/MINER_ wallet
# settings (+ VALIDATOR_SECRET_KEY for a validator)
make env-check # after updating the repo: lists settings your .env is missing
make up # validator
make up ROLE=miner # miner
make logs # follow logs (add ROLE=miner for the miner)
make status # container + heartbeat
make restart / make down
make backup-state # tar.gz of ./data into ./backups- Wallets: the validator and the miner have separate settings (
VALIDATOR_WALLET_DIR/VALIDATOR_WALLET_NAME/VALIDATOR_HOTKEY, and the same withMINER_), so both can run from one folder with different wallets. Each role's directory is mounted read-only; the wallet name is the folder name inside it, not a path.make downstops only the selectedROLE. - State: everything that must survive restarts (validator state, emission state, bans, downloaded submissions, logs, miner challenge packages) is kept in
./data(DATA_DIR). Moving from a bare-metal validator? Runmake migrate-stateonce: it copies (never moves) the old state files from the repo root into./data. - Networking: the containers use host networking (Linux). The validator reaches the EDA server at
EDA_SERVER_URL(defaulthttp://localhost:8080); the miner's axon listens onAXON_PORT(default 8091), which must be reachable from the internet. - Health: each neuron rewrites a heartbeat file every 30 s from its event loop; the container is marked unhealthy if it goes stale for 3 minutes, and
restart: unless-stoppedbrings it back after crashes and reboots. Logs are rotated (5 × 50 MB). - Miner CLI in Docker:
make submit FILE=solution.zip, or any command withmake cli ARGS="status". make testruns the test-suite in a throwaway container.- Updating:
git pull, thenmake env-check(add any new settings from.env.example), thenmake up(it rebuilds the image). State in./datais kept.
To create wallets, visit this:
https://docs.learnbittensor.org/btcli
# Clone the repository
git clone https://github.com/TatsuProject/ChipForge_SN108
cd ChipForge_SN108
# Create an isolated environment (Python 3.12 recommended)
conda create -n chipforge-subnet python=3.12
conda activate chipforge-subnet
# Install dependencies (Bittensor 10.x classic SDK)
pip install -r requirements.txt
pip install -e .requirements.txt lists the direct dependencies and pins the Bittensor stack
(bittensor==10.5.0, bittensor-wallet==4.1.0, bittensor-cli==9.23.2,
async-substrate-interface==2.2.1). requirements-lock.txt is the exact
resolved set the test-suite was last run against, if you need a reproducible
install:
pip install -r requirements-lock.txtBittensor 11 removed the
axon/dendrite/Synapsenetworking layer that the miner and validator use, so this repo intentionally stays on the 10.x line.
pip install -r requirements-dev.txt
pytest # unit + loopback transport tests
CHIPFORGE_LIVE_TESTS=1 pytest -m live # optional: hits testnet (netuid 440 by default)Set parameters in .env (see .env.example; the miner's wallet is MINER_WALLET_DIR,
MINER_WALLET_NAME, MINER_HOTKEY) and run:
./start_miner.sh # or, with Docker: make up ROLE=minerThe miner polls the challenge server every MINER_POLL_SECONDS (default 300 s) and
immediately when a validator announces a new challenge, then downloads and extracts the
challenge package to downloaded_active_challenge/<challenge_id>/. A failed download is
retried on the next poll. The axon only answers hotkeys with a validator permit.
To run miner/validator through nohup (no hang up, an alternative of pm2):
nohup ./start_miner.sh > miner.log 2>&1 &To show logs in real-time:
tail -f miner.logTo terminate the process:
# Find the process ID:
ps aux | grep miner
# Kill by PID:
kill <PID>
# Or kill by process name:
pkill -f "miner.py"
# Force kill if needed:
kill -9 <PID>- Download challenge (use
miner_cli.py download) - Solve it
- Submit the solution (use
miner_cli.py submit)
The miner CLI tool (python_scripts/miner_cli.py) provides all the functionality needed for these tasks. See MINER_CLI_COMMANDS.md for complete documentation.
Using the Miner CLI Tool (Recommended):
The miner_cli.py tool provides a comprehensive command-line interface for miners:
# Check current challenge status and your submissions
python3 python_scripts/miner_cli.py status
# List all your submissions
python3 python_scripts/miner_cli.py submissions
# Download and extract the challenge package (spec, testbench) + challenge info
python3 python_scripts/miner_cli.py download
# Submit a solution (with validation)
python3 python_scripts/miner_cli.py submit solution.zip --check_status
# Dry run (validate without submitting)
python3 python_scripts/miner_cli.py submit solution.zip --dry_runUsing the Shell Script:
# Set wallet and path to zip file in .env file and run this
./submit_solution.shDirect Python Script:
You can also use the miner CLI directly with explicit arguments:
python3 python_scripts/miner_cli.py submit solution.zip \
--wallet.name YOUR_WALLET \
--wallet.hotkey YOUR_HOTKEY \
--api_url https://api.chipforge.io \
--check_status--wallet.name, --wallet.hotkey, --wallet.path and --api_url can be given before or
after the command.
For more details, see MINER_CLI_COMMANDS.md.
- Leaderboard: chipforge.io/leaderboard shows the score to beat, the current winner on chain, every submission (one row each, with the validators' consensus score and gates), a page per miner and per submission with a plain explanation of the result (e.g. "functional gate failed", "passed but below the score to beat").
- Scores are published when a batch closes. While your submission is in an open batch it shows "In batch"; no validator can see another's results before submitting its own.
- Full evaluation logs are not public (the website shows a summary: gates, metrics, error code and message).
The miner who made the submission gets them, once its batch has closed:
python3 python_scripts/miner_cli.py logs <submission_id> # saves one file per validator
- Winning designs can be revealed to every hotkey registered on the subnet (miners and validators), when
the subnet has reveals turned on. Each winner's design is revealed a set time after it won, earlier if a
newer winner overtakes it, and/or when the challenge ends; the Winners tab on the leaderboard shows the policy
and when each design becomes available.
The request is signed with your hotkey (an unregistered hotkey gets 403), downloads are limited per day and logged, and the file is checked against the winner's signed hash before it is saved.
python3 python_scripts/miner_cli.py reveals # policy + status of each winning design python3 python_scripts/miner_cli.py reveal-download <submission_id> # saves ./revealed_designs/<id>.zip
- Copies don't win: a file byte-identical to a winning design is refused at submission, and the subnet can
require a new winner to beat the score to beat by a minimum margin (
MIN_IMPROVEMENT_PERCENT).
Solutions must be packaged as ZIP files containing:
- Verilog/SystemVerilog source files (.v, .sv)
- Testbench files (optional)
- Constraint files (optional)
- README with design description (optional)
Important Constraints:
- Maximum file size: 50 MB
- File must be a valid ZIP archive
- The miner CLI tool automatically validates these requirements before submission
- Miner endpoints of the challenge server (submit, status, history) accept 2 requests per minute and 5 per hour per IP by default.
logsandreveal-downloadhave their own, separate budget (10 per minute, 60 per hour per IP by default), plus a daily cap per hotkey for revealed designs.- One hotkey is allowed to submit a maximum 5 solutions for a specific challenge (per-challenge setting).
- The public API used by the website and
miner_cli.py revealsis limited separately (120 per minute per IP).
Pull and run Chipforge EDA Server:
https://github.com/TatsuProject/chipforge_eda_server
The EDA server has no API key: keep its port (8080) closed to the internet, or bind it to
127.0.0.1 on the validator machine.
Set parameters in .env (see .env.example; defaults are for mainnet): the validator's wallet is VALIDATOR_WALLET_DIR,
VALIDATOR_WALLET_NAME, VALIDATOR_HOTKEY, and VALIDATOR_SECRET_KEY goes there too (never on the
command line). Then run:
make up # Docker (recommended), or: ./start_validator.shA miner can run from the same folder with its own wallet (MINER_WALLET_*, make up ROLE=miner).
What the validator does each cycle:
- polls the challenge server (
/validator/sync, one cached request for challenge, batch, bans and test-case version), - downloads the exposed batch (each file's sha256 is checked against the hash the miner signed) and evaluates it on the EDA server within the batch's deadline,
- submits scores, and if a submission beats the challenge's best qualified score, it becomes this validator's winner,
- puts weights on chain immediately when the winner changes (within the chain's rate limit) and refreshes them every
WEIGHTS_REFRESH_SECONDS: the winner getsMINER_EMISSION_PERCENTAGEpercent, the rest is burned to UID 0.
How many submissions a batch holds is set by the challenge server, and the validator evaluates all of
them. EDA_MAX_CONCURRENCY only limits how many it sends to its EDA server at once (the rest wait their
turn within the batch's deadline), so set it to what your EDA machine can run in parallel.
Each validator picks its winner from its own evaluations; there is no winner sync between
validators or with the challenge server. The winner's share of the weight
(MINER_EMISSION_PERCENTAGE) is the validator's own setting unless the challenge server sets one,
in which case the server's value is used (the validator logs when it overrides the local value). If the subnet sets a minimum improvement margin,
MIN_IMPROVEMENT_PERCENT in the validator's .env must equal the challenge server's value
(default 0), otherwise validators disagree about who won.
To run validator through nohup (no hang up, an alternative of pm2):
nohup ./start_validator.sh > validator.log 2>&1 &To show logs in real-time:
tail -f validator.logTo terminate the process:
# Find the process ID:
ps aux | grep validator
# Kill by PID:
kill <PID>
# Or kill by process name:
pkill -f "validator.py"
# Force kill if needed:
kill -9 <PID>- Download submissions from active batches
- Evaluate designs using EDA tools
- Submit the scores the EDA server returns: functionality, area, performance (delay), power and the overall score, plus the functional and overall gates. How the metrics are weighted is set per challenge by its evaluator bundle (see below)
Each submission is evaluated across four metrics. Their weights and targets are set per challenge (in the challenge's hidden evaluator bundle), so they can differ between challenges. A submission only counts when it passes both gates: the functional gate (enough of the testbench passes) and the overall gate.
- Functionality Score: share of the challenge's testbench that passes in simulation (Verilator)
- Area Score: synthesized cell area in µm² from the ASIC flow (OpenLane), compared with the challenge's target
- Delay (performance) Score: achieved speed (e.g. maximum frequency or throughput), compared with the target
- Power Score: estimated power in mW, compared with the target
- Submissions are ranked by overall score (the average of the validators that evaluated them)
- The challenge server decides the winner when a batch closes, from every validator's results: a
submission's score is the highest gate-passing score it received, and the best one in the batch wins
if it beats the score to beat (plus
MIN_IMPROVEMENT_PERCENTif the subnet sets one). Ties go to the earlier submission, and the score to beat then rises to the new winner's score - Weights reward the highest-scoring submission with
MINER_EMISSION_PERCENTAGEof the validator's weight; the rest is burned - Emission burning occurs when no submissions exceed quality thresholds
- The winner of a challenge will keep getting reward for specific time after challenge expiration
- The chain decides who is actually paid (highest incentive); the leaderboard shows it and which validators agree
- Winning designs may be revealed to registered neurons after a delay (see "Results, logs and revealed winning designs")
- RISC-V based Processors
- AI Accelerators
GET /api/v1/challenges/active # Get active challenge
POST /api/v1/challenges/{id}/generate-submission-id # Generate submission ID
POST /api/v1/challenges/{id}/submit # Submit design solution
GET /api/v1/challenges/{id}/submissions/hotkey/{hotkey} # Check submissions (signed)
GET /api/v1/challenges/{id}/download # Challenge package
GET /api/v1/submissions/{submission_id}/evaluation_logs # Full logs of your own submission (signed)
GET /api/v1/reveals/{submission_id}/download # Revealed winning design (signed, registered hotkeys)
GET /api/v1/public/snapshot # Active challenge, score to beat, winner (server + chain), batch
GET /api/v1/public/challenges # Active and past challenges
GET /api/v1/public/challenges/{id}/leaderboard # One row per submission
GET /api/v1/public/submissions/{id} # One submission: batches, per-validator results and summary
GET /api/v1/public/miners/{hotkey} # A miner across challenges
GET /api/v1/public/validators # Validators, their on-chain pick, agreement with the chain
GET /api/v1/public/reveals?challenge_id= # Reveal policy and status of each winning design
GET /api/v1/public/rules # Competition rules as data
GET /api/v1/validator/sync # Challenge, batch, bans, test-case version in one call (ETag)
GET /api/v1/challenges/{id}/batch/current # Get current evaluation batch
GET /api/v1/challenges/{id}/submissions/{submission_id}/download # Download submission
POST /api/v1/challenges/{id}/submissions/{submission_id}/submit_score # Submit evaluation
The subnet uses a dynamic batch system:
- Submissions are grouped into evaluation batches
- Each batch has a download window and an evaluation window; the lengths come from the challenge server
- Only one batch is exposed to validators at a time
- Batches transition: EXPOSED → EVALUATING → COMPLETED
- Signature-based auth: requests are signed with your Bittensor hotkey (sr25519)
- Validator secrets: Additional secret keys for validator endpoints
- Hotkey verification: Ensures submissions come from registered miners, and evaluated scores come from registered validators
- Timestamp validation: Prevents replay attacks
- File hashing: All submissions are verified with SHA256 hashes
- Signature verification: Using Bittensor's native signing methods
# Challenge server
curl https://api.chipforge.io/health
# EDA server (validators)
curl http://localhost:8080/health
# Validator / miner under Docker
make status-
Signature Verification Failed
- Ensure using Bittensor's native signing methods
- Check timestamp accuracy (must be within 10 minutes)
- Verify hotkey registration on subnet
-
Submission Upload Failed
- Use
miner_cli.py submit solution.zip --dry_runto validate before submitting - Check ZIP file format and contents
- Verify file size limits (50 MB maximum - checked by the miner CLI before uploading)
- Ensure proper authentication headers
- Check wallet configuration in
.envfile or command-line arguments
- Use
-
Validator Download Issues
- Confirm validator secret configuration
- Check batch timing and availability
- Verify network connectivity to challenge server
-
EDA Tool Integration
curl http://localhost:8080/healthon the validator machine must answer{"status": "ok"}EDA_SERVER_URLin.envmust point at it (with Docker host networking,localhostis the host)- The EDA server's own README covers its setup and logs (
make logsthere)
-
Settings missing after an update
- Run
make env-check: it lists keys that.env.examplehas and your.envlacks
- Run
- Follow PEP 8 coding standards
- Include comprehensive tests
- Update documentation for new features
- Ensure backward compatibility
This project is licensed under the MIT License - see the LICENSE file for details.
- Discord: ChipForge
- Additional challenge categories
- Enhanced evaluation metrics
- Improved toolchain integration
- v1.0.0 - Initial release with challenge download, solution design, solution verification, submitting scores, and giving reward to winner.