The list behind pool.drivechain.info, and the source of pool attribution for the block explorer.
Three forknets exist at once right now — alphanet is being retired, betanet opens on 19 September 2026, and mainnet opens on 31 October 2026. Each one has its own folder, so a forknet can be added or deleted without touching the others. See The network lifecycle for the schedule and the exact steps.
Files you edit:
networks.json— which forknets exist and where each is in its life. The page builds its tab strip from this, and derives each network's state from its dates.networks/<net>/pools.json— the pools on that forknet. One object per pool. This is the file you edit to list a pool.mempool/upstream-pools-v2.json— mempool's own pool list, verbatim. Re-synced wholesale; never hand-edited.mining-pool-logos/— one logo per pool, shared by every forknet. A pool without one renders a letter monogram instead.index.html— a static page that renders the JSON in the browser. No build step, no dependencies, no network calls beyond fetching those files from the same origin.
Files generated by tools/build.py, which you do not edit:
networks/<net>/pools-v2.json— upstream plus that forknet's pools, in mempool's attribution format, for feeding that forknet's mempool instance.pools.jsonandpools-v2.jsonat the root — copies of whichever networkroot_networknames innetworks.json. They exist so the URLs the block explorer and the mempool instance already fetch keep working while the forknets come and go underneath them. Moveroot_networkwhen the network of record moves and those consumers follow without being reconfigured.
python3 tools/build.py # write the generated files
python3 tools/build.py --check # exit 1 if any is stale, touching nothingIt is Python 3 standard library only, and it validates as it goes: missing
required fields, a chain that disagrees with the folder it sits in, an
uncommitted logo, two pools claiming the same coinbase_tag, a colliding
mempool id. Run it before you open a PR and commit what it writes.
Open a pull request that appends one object to the pools array in
networks/<net>/pools.json, for the forknet you are mining, then run
python3 tools/build.py and commit its output alongside. Nothing else needs to
change — the page is generated from those files at load time.
You can list on a forknet before it opens. Betanet and mainnet are accepting entries now; a pool added before launch day is on the page the moment the network goes live.
{
"name": "your-pool",
"operator": "you or your org",
"chain": "betanet",
"mode": "pps-classic",
"fee_bps": 100,
"coinbase_tag": "/yourpool/",
"stratum_url": "stratum+tcp://pool.example.com:3334",
"dashboard_url": "https://pool.example.com",
"status_url": "https://pool.example.com/api/status",
"operator_address": "bc1q...",
"pool_btc_address": "bc1q...",
"payout": "One sentence: what the stratum username must be, and how miners get paid.",
"software": "simplepool",
"logo": "mining-pool-logos/yourpool.svg",
"contact": "you@example.com"
}Running a pool on more than one forknet means one object in each network's file. They are separate entries with separate ids, and they can differ — different stratum host, different fee — because they are different chains.
| Field | What it is |
|---|---|
name |
Short display name. |
operator |
Who runs it — an org, handle or domain. |
chain |
Which forknet. Must match the folder the file is in, and build.py enforces that. Note bitcoind reports main on all of these: they are mainnet forks, so main is correct and not a misconfiguration. |
mode |
solo or pps-classic. Decides what the stratum username must be. |
fee_bps |
Basis points. 100 = 1%. |
coinbase_tag |
Exactly as it appears in your coinbase, slashes included. |
stratum_url |
Full stratum+tcp://host:port a miner can paste. null only if the pool takes no outside hashrate, such as a solo operator self-mining. |
operator_address |
The address taking the fee cut. |
dashboard_url, status_url, pool_btc_address (null for solo),
coinbase_addresses, payout, software, contact, logo, mempool_id.
logo is a path to a file committed under mining-pool-logos/, which is shared
across every forknet — the same pool on alphanet and mainnet points at the same
file. SVG is preferred and it should be roughly square: the page draws it into a
56px tile with object-fit: contain, so any aspect ratio fits without
distortion. The tile is deliberately light in both colour themes, because logo
files carry their own fixed colours and dark ink would disappear against the dark
panel. Leave the field out and the card falls back to a monogram of the pool's
first letter; the same fallback covers a logo path that fails to load.
coinbase_addresses and mempool_id are escape hatches for the generated
mempool file — see below. Most pools need neither.
It is the string your pool stamps into the coinbase of every block it finds, and
it is the only thing an explorer can use to attribute a block to you. If it is
wrong — or still on simplepool's /simplepool/ default — your blocks are
credited to someone else and nothing anywhere reports an error.
Read it out of the pool that is actually running, not from memory or from your install notes:
grep coinbase_tag /path/to/simplepool/proxy.confOn simplepool specifically, the installer restores its answers from
/etc/simplepool/install.env on every run, so a proxy.conf edited by hand is
silently reverted on the next upgrade. If those two files disagree, fix the
installer answer as well — otherwise the tag you list here will stop being true
the next time the pool is updated.
If you run the same pool on two forknets, give each a tag that says which one, or you cannot tell the two chains' blocks apart later.
mempool attributes blocks from its own list, pools-v2.json. Each forknet
gets its own generated copy at networks/<net>/pools-v2.json: the upstream file
verbatim, with that forknet's pools appended.
{
"id": 2001,
"name": "your-pool",
"addresses": ["bc1q..."],
"tags": ["/yourpool/"],
"link": "https://pool.example.com"
}build.py derives all of it from pools.json: name → name, coinbase_tag
→ the one entry in tags, dashboard_url → link.
addresses holds whatever address of the pool actually lands in the coinbase,
which the script works out in this order:
- an explicit
coinbase_addresses, if the entry has one; - otherwise
pool_btc_address, for a pooled payout; - otherwise
operator_address, for a pool that takes a fee cut in the coinbase; - otherwise
[], for a zero-fee non-custodial pool, which nothing but the tag can identify.
Case 4 is the one that needs a human. A zero-fee pool that is really an operator
mining for itself does have a coinbase address, and build.py stops and asks
for coinbase_addresses rather than guessing — FreeBank on alphanet is exactly
this. Case 3 also tracks the fee, so it is not settled once: a pool that starts
charging one begins paying itself in the coinbase and its addresses stops being
empty, so revisit the entry whenever fee_bps changes.
Each forknet gets its own block of ids, set by mempool_id_base in
networks.json: alphanet from 1001, betanet from 2001, mainnet from
3001. Upstream ids are sequential from 1 and upstream is still growing;
keeping our blocks well clear of it means re-syncing is "replace
mempool/upstream-pools-v2.json with the new upstream file" and never a
collision on an id two different pools claim.
Within a block, ids are assigned by position: the first pool in the array gets
the base, the second gets base + 1. That is why the house rule is to append
and never reorder — moving an entry silently re-points attribution for every
entry below it. If you have to reorder, pin the affected entries with an explicit
mempool_id first; build.py errors on a duplicate.
networks.json is the whole schedule. Each entry carries a launch date, a
sunset date, or neither, and the page derives what it shows from them against
today's date — so betanet turns live on its launch date and alphanet retires
on its sunset date with nobody editing anything that morning. status: "retired" is the one manual override, for pulling a forknet early.
| State | When | What the page does |
|---|---|---|
upcoming |
before launch, or no launch set yet |
Tab shows the opening date. Banner counts down. Listings still accepted. |
live |
between the dates | Tab shows LIVE. No banner. |
sunsetting |
a sunset date is set and has not passed |
Tab shows the last day. Banner counts down and links to the successor. |
retired |
past sunset |
Tab dims, pools dim, banner says it is gone. |
| Forknet | Opens | Retires |
|---|---|---|
| alphanet | already up | 24 September 2026, five days after betanet |
| betanet | 19 September 2026 | when mainnet is up |
| mainnet | 31 October 2026 | — |
Alphanet and betanet both go away once mainnet is up, which makes 31 October the day the repo drops back to a single forknet. Nothing needs doing on 19 or 24 September: those dates take care of themselves. The steps below are for the days you actually change something.
- Set its
launchdate innetworks.json. That alone flips it live on the day. - When it becomes the network of record for the explorer, move
root_networkto it, and movedefault_networkso it is the tab that opens first. python3 tools/build.pyand commit.
All three dates are already set, so there is nothing to do for betanet on 19 September or mainnet on 31 October beyond step 2 — and step 2 only when you want the explorer and the default tab to follow.
Wait until its sunset has passed and traffic has moved — the entry is
self-dimming in the meantime, so there is no rush to do this on the day.
git rm -r networks/<net>- Delete its object from
networksinnetworks.json. - Make sure
root_networkanddefault_networkdo not still point at it.build.pyrefuses to run if they do. python3 tools/build.pyand commit.
That is the whole removal. Nothing else in the repo mentions a forknet by name,
which is the reason for the folder-per-network layout: when alphanet and betanet
go after mainnet launches, it is two git rm -r and two objects out of one file.
- One pool per object; append rather than reordering, so diffs stay readable and mempool ids stay put.
- A PR that changes another operator's entry will not be merged without their sign-off.
- Keep
payoutto one sentence — it is the line a miner reads before connecting. - Run
python3 tools/build.pyand commit its output in the same PR. A PR where--checkfails has not finished.