How to Signal for Any BIP While Mining on DMND
This guide explains how version-bits signaling actually works, how it flows through a DMND Job Declaration setup, and what to consider before signaling for any deployment — current or future. It applies to any BIP that uses version-bits activation; only the bit number changes.
How signaling works
Soft-fork signaling (BIP9 and its descendants, e.g. BIP8) uses the 4-byte version field of the block header. Each proposed deployment is assigned a signaling bit; a miner signals readiness by setting it: nVersion | (1 << bit). The top three bits must be 001 (0x20000000) for the version to count as BIP9-style signaling — Bitcoin Core sets this automatically.
Bits are reused across deployments over time, and each deployment defines its own activation parameters (threshold, start/timeout). Always take the bit number and activation window from the BIP text or the implementing software — never assume from a previous fork.
Why JD miners control their own signal
The version field is part of the block template. On DMND with Job Declaration, your Bitcoin Core node builds the template: sv2-tp relays it to the dmnd-client, the client declares it to the pool, and the pool validates and accepts your template as-is. DMND does not add, strip, or modify version bits — whatever your node puts in the template is what gets hashed and, if you find a block, what lands on chain.
Two consequences:
- Signaling happens at the node, never at the ASIC. Although BIP9 originally permits deployment bits 0–28, BIP320 reserves bits 13–28 for version rolling (overt ASICBoost). Modern deployments therefore avoid assigning signaling bits in that range, leaving them available for miners to roll without affecting consensus signaling. In practice, only bits 0–12 should be used for BIP adoption signaling — and the signaling bit itself is fixed by the template your node builds.
- You don't need the pool's permission. Under Stratum V1 the pool builds the template and decides signaling for all its hashrate. Under JD, each miner decides independently.
How to set the bit — three cases
Case 1: The BIP is merged into Bitcoin Core with deployment parameters.
The historical norm for uncontested soft forks (SegWit, Taproot). Nothing to patch: upgrade to the Core release that includes the deployment, and your node sets the bit automatically during the signaling window — and enforces the rules on activation. Check the release notes for whether signaling is on by default or behind a flag.
Case 2: The BIP is not in Core (contested or early-stage proposals).
Stock Core will never set the bit. A node can be patched to set it — in src/node/miner.cpp, in BlockAssembler::CreateNewBlock(), after the line computing the version:
pblock->nVersion = g_versionbitscache.ComputeBlockVersion(pindexPrev, chainparams.GetConsensus());
add:
pblock->nVersion |= (1 << N); // N = the deployment's signaling bit
OR multiple bits to signal several deployments. Rebuild with your usual flags — multiprocess/IPC support must remain enabled for sv2-tp — then restart the node, sv2-tp, and the dmnd-client. Extra version bits are fully consensus-valid; this cannot produce an invalid block today.
Caveat: a version bit conventionally means "this node will enforce the new rules." A patched-but-non-enforcing node that signals is making a claim it can't back: if the deployment activates, it may build templates containing newly-invalid transactions or extend an invalid tip. We recommend the Case 3 path instead — signal with software that actually enforces what it signals.
Case 3: Run an enforcing implementation — built on current Core.
The clean way to signal for a deployment Core hasn't merged is software that implements and enforces the new rules. One requirement matters above all: demand an implementation based on the current Bitcoin Core (v31), not an old-base fork. sv2-tp needs Core's multiprocess IPC interface; a minimal patch-set on top of current Core — just the deployment's rules and signaling, nothing else — keeps full JD compatibility. Old-base builds (e.g. forks of 29.x-era code) lack the IPC interface and cannot drive a JD setup at all. With a current-base enforcing node, signaling through DMND works exactly as in Case 1: your node sets the bit, your template carries it, your blocks signal.
Verify what your node signals
bitcoin-cli getblocktemplate '{"rules": ["segwit"]}' | grep version
Check version & (1 << N) for the deployment's bit N. The same version appears in sv2-tp logs at -loglevel=sv2:trace, and on any explorer once you mine a block.
What happens if your node and the pool disagree
An enforcing node rejects blocks that violate its rules — including, under mandatory-signaling designs, blocks that merely fail to signal. If the network produces such a block and our node accepts it while yours doesn't, you're on a different tip: your declared templates now build on a chain our node considers invalid, and we will reject them.
DMND only ever rejects declarations that are invalid bitcoin block templates — we don't filter templates for any other reason. And the dmnd-client does not silently fall back to solo mining on a rejected template: redirecting your hashrate onto a template the pool just rejected would burn power on blocks that may never be accepted. Instead, rejections fail loudly in the client logs so you notice immediately and decide deliberately. Your options at that point: move to a pool whose nodes enforce the same rules as yours, solo mine intentionally with your own infrastructure if you accept the variance, or reconsider your node software. What JD guarantees is the other direction — your hashrate is never redirected onto a chain your node rejects, and no pool can override your node's rules.
And because the dmnd-client is open source, none of this requires trusting our judgment: a miner who prefers automatic solo fallback over a loud failure can implement it in the client with a trivial change — the behavior at your edge of the connection is yours to define.
Talk to us before a contested activation window so you know where you'd stand.
Our position
We mine standard Bitcoin and pass your declared template through unchanged — we only reject what our node considers invalid. For deployments in Bitcoin Core, your signaling choice is fully yours and fully compatible with the pool. For contested deployments, JD guarantees your blocks always follow your node's rules; if our nodes ever disagree about the valid chain, you'll know immediately and the choice of what to do next stays yours. That transparency is the point of Job Declaration.