This guide is primarily for mining pool operators and pool software developers adding DigiDollar support to Stratum, getblocktemplate, or DigiHash-style pool software. It also includes a CPU-mining section because the same GBT rules apply to solo miners.
It is written for both human operators and AI coding agents. Terms like MUST, MUST NOT, and SHOULD are intentional implementation requirements. Do not treat them as optional wording when changing mining code.
The short version:
- Old miners can keep mining normal DigiByte blocks safely.
- DigiDollar-aware pools and miners MUST explicitly request the
digidollar-oraclegetblocktemplate rule. - When Core returns
default_oracle_commitment, the pool or miner MUST copy it into the coinbase as an exact zero-value output. - Pools MUST NOT invent an oracle commitment when Core does not provide one.
- Pools do not need oracle private keys. They only need an upgraded DigiByte node that can provide a fresh oracle-aware block template.
- Downstream ASIC/GPU miners do not need to understand DigiDollar if the pool builds the coinbase correctly.
Validated locally against:
- DigiByte Core GBT opt-in path:
src/rpc/mining.cpp,src/node/miner.cpp - DigiByte functional tests:
digidollar_gbt_optin.py,digidollar_oracle_gbt_stale_cache.py - cpuminer-multi DigiDollar mode:
cpu-miner.c,tests/test_gbt_regressions.py - node-stratum-pool DigiDollar mode:
lib/pool.js,lib/transactions.js,lib/test.js - DigiHashV2 coin config opt-in:
coins/digibyte.{sha256,scrypt,skein,qubit,odo}.json
Use these repos as the working examples for DigiDollar-aware mining support. They are listed here so pool operators and AI coding agents can compare their own code against known-good implementations instead of guessing from the GBT description alone.
| Component | Purpose | Reference |
|---|---|---|
cpuminer-multi |
Solo CPU mining against Core GBT. Shows --digidollar, the digidollar-oracle rules request, and coinbase preservation of default_oracle_commitment. |
https://github.com/JaredTate/cpuminer-multi/tree/8cfa8609e467c7d37f588246332065e1460612a6 |
node-stratum-pool |
Pool-server reference for Stratum mining. Shows strict coin.digidollar === true opt-in, DigiDollar-aware GBT requests, and oracle commitment output construction. |
https://github.com/JaredTate/node-stratum-pool/tree/433d38ad5a20a6cdae95457eb8a76820e4a28c95 |
digihashv2 |
DigiHash-style pool configuration example. Shows five DigiByte mainnet algo coin configs with digidollar: true. |
https://github.com/JaredTate/digihashv2/tree/90be40bcc6a906c5519938c1f961ac3d4c860ba5 |
Important files to review:
- cpuminer:
cpu-miner.c,README.md,tests/test_gbt_regressions.py - node-stratum-pool:
lib/pool.js,lib/transactions.js,lib/test.js - DigiHashV2:
coins/digibyte.sha256.json,coins/digibyte.scrypt.json,coins/digibyte.skein.json,coins/digibyte.qubit.json,coins/digibyte.odo.json,test/digidollar-coin-config-smoke.test.js
For a release, do not only copy the config flag. Verify the installed pool
dependency actually resolves to a patched node-stratum-pool that supports
default_oracle_commitment. A DigiHashV2 config with digidollar: true is not
enough if node-stratum-pool is still pinned to an older commit.
Any pool implementation that wants to mine DigiDollar mints/redeems correctly must satisfy this contract.
-
Request DigiDollar-aware GBT from the upstream DigiByte node.
{"rules":["segwit","digidollar-oracle"]} -
Pass the correct DigiByte algo for the template.
Direct Core RPC form:
getblocktemplate(template_request, "scrypt") getblocktemplate(template_request, "sha256d") getblocktemplate(template_request, "skein") getblocktemplate(template_request, "qubit") getblocktemplate(template_request, "odo")One-daemon-per-algo deployments are also valid when each daemon has the correct
algo=<algo>configured. -
If the template contains
default_oracle_commitment, add that exact script to the generated coinbase as a zero-value output. -
If the template does not contain
default_oracle_commitment, do not create one. Mine the normal template or wait for the next template. -
Use template
txidvalues for merkle leaves when they are present. Use raw transactiondatain the final serialized block. -
Submit the full block with the preserved oracle commitment.
For AI agents implementing this in a new pool: add tests for every MUST above before changing production mining code. The minimum test list is in TDD Requirements.
DigiDollar mint and redeem transactions require a fresh oracle price. The
oracle price is committed into the block coinbase through an OP_ORACLE
commitment output.
That means a block producer, and especially a pool server, must do two things:
- Ask DigiByte Core for a DigiDollar-aware block template.
- Preserve the oracle commitment in the coinbase when Core provides it.
Core now separates mining into two safe paths.
Request:
{"rules":["segwit"]}Result:
- Mines normal DigiByte blocks.
- Does not receive
default_oracle_commitment. - Does not receive oracle-priced DigiDollar mint/redeem work.
- Remains valid and safe for non-upgraded miners.
Request:
{"rules":["segwit","digidollar-oracle"]}Result:
- Mines normal DigiByte blocks when no oracle bundle is ready.
- When a fresh MuSig2 oracle bundle is ready, receives
default_oracle_commitment. - Can include DigiDollar mint/redeem transactions that depend on that oracle price.
Core advertises this in the returned rules array as:
"!digidollar-oracle"The ! means the miner or pool must understand and preserve that rule.
For a direct DigiByte Core check, pass digidollar-oracle in rules.
Example for scrypt:
digibyte-cli getblocktemplate \
'{"rules":["segwit","digidollar-oracle"],"capabilities":["coinbasetxn","coinbasevalue","coinbase/append","workid"]}' \
scryptExamples for the five DigiByte algos:
digibyte-cli getblocktemplate '{"rules":["segwit","digidollar-oracle"]}' scrypt
digibyte-cli getblocktemplate '{"rules":["segwit","digidollar-oracle"]}' sha256d
digibyte-cli getblocktemplate '{"rules":["segwit","digidollar-oracle"]}' skein
digibyte-cli getblocktemplate '{"rules":["segwit","digidollar-oracle"]}' qubit
digibyte-cli getblocktemplate '{"rules":["segwit","digidollar-oracle"]}' odoWhen oracle data is ready, the response should include:
"default_oracle_commitment": "<hex script>"That hex is the exact scriptPubKey for a zero-value coinbase output. Pool code SHOULD copy it exactly as script bytes. Do not decode and rebuild it unless your code already has a safe script parser.
If default_oracle_commitment is absent:
- Do not invent an oracle output.
- Do not force mint/redeem transactions into the block.
- Mine the returned template as a normal block, or wait for the next template.
Core is responsible for excluding oracle-priced DigiDollar transactions from GBT when a fresh bundle is not ready. Pool software MUST NOT override that decision by forcing mint/redeem transactions into a no-oracle template.
A DigiDollar-aware pool or miner that builds its own coinbase must preserve these template commitments:
default_witness_commitment, when presentdefault_oracle_commitment, when present
Each commitment MUST be included as a zero-value coinbase output.
Pseudo-code:
outputs = []
outputs.append(pool_reward_output)
if template.default_witness_commitment exists:
outputs.append(value=0, scriptPubKey=hex_to_bytes(template.default_witness_commitment))
if template.default_oracle_commitment exists:
outputs.append(value=0, scriptPubKey=hex_to_bytes(template.default_oracle_commitment))
Do not drop either commitment. If the template ever provides a complete
coinbasetxn, preserve it according to normal BIP22 rules instead of rebuilding
it casually. DigiDollar-aware DigiByte Core templates are designed for
miner-built coinbases using coinbasevalue plus explicit commitment fields.
The pool MUST also build the merkle root correctly:
- Use each template transaction's
txidfor the merkle leaf whentxidis provided. - Use raw transaction
datain the final serialized block. - Do not hash witness-inclusive raw transaction data as the merkle leaf when a
txidis available.
This matters for modern templates because raw data may include witness bytes,
but the block merkle root commits to txids.
The patched cpuminer uses an explicit opt-in flag:
--digidollarWith that flag, cpuminer requests:
["segwit","digidollar-oracle"]It also preserves default_oracle_commitment in its miner-built coinbase.
Example:
./cpuminer \
-a scrypt \
-o http://127.0.0.1:14046/ \
-O rpcuser:rpcpassword \
--coinbase-addr=<SCRYPT_PAYOUT_ADDRESS> \
--no-stratum \
--no-getwork \
--no-longpoll \
--digidollar \
--threads=6Run one process per supported algo:
./cpuminer -a scrypt -o http://127.0.0.1:14046/ -O rpcuser:rpcpassword --coinbase-addr=<SCRYPT_ADDRESS> --no-stratum --no-getwork --no-longpoll --digidollar --threads=6
./cpuminer -a sha256d -o http://127.0.0.1:14047/ -O rpcuser:rpcpassword --coinbase-addr=<SHA256_ADDRESS> --no-stratum --no-getwork --no-longpoll --digidollar --threads=6
./cpuminer -a skein -o http://127.0.0.1:14048/ -O rpcuser:rpcpassword --coinbase-addr=<SKEIN_ADDRESS> --no-stratum --no-getwork --no-longpoll --digidollar --threads=6
./cpuminer -a qubit -o http://127.0.0.1:14049/ -O rpcuser:rpcpassword --coinbase-addr=<QUBIT_ADDRESS> --no-stratum --no-getwork --no-longpoll --digidollar --threads=6Current cpuminer support:
- Supported here:
scrypt,sha256d,skein,qubit - Not supported here: DigiByte
odo/ Odocrypt
For Odo CPU/GPU/pool mining, use an Odo-capable miner or pool stack that follows the same GBT and coinbase rules in this guide.
A Stratum pool has two sides:
- Upstream side: pool asks DigiByte Core for work through GBT.
- Downstream side: miners connect to the pool using Stratum.
Most ASIC/GPU miners do not need to know about DigiDollar. The pool server MUST know about DigiDollar because the pool server builds the coinbase and the block template.
Required upstream GBT behavior from the pool to DigiByte Core:
{
"capabilities": ["coinbasetxn", "workid", "coinbase/append"],
"rules": ["segwit", "digidollar-oracle"]
}For DigiByte Core, the algo is passed as the second RPC argument:
getblocktemplate(template_request, "scrypt")
getblocktemplate(template_request, "sha256d")
getblocktemplate(template_request, "skein")
getblocktemplate(template_request, "qubit")
getblocktemplate(template_request, "odo")
Another valid deployment pattern is one daemon per algo with algo=<algo> in
each daemon's digibyte.conf. In that setup the pool can call GBT without the
second algo argument because each daemon already defaults to the correct algo.
Required pool coinbase behavior:
- Add pool payout output.
- Preserve witness commitment if present.
- Preserve oracle commitment if present.
- Add normal pool recipients/fees as before.
- Submit the final serialized block with
submitblock.
Do not require every downstream miner to upgrade. The pool controls the upstream GBT request and the coinbase. Downstream ASIC/GPU miners only need valid Stratum jobs for their algo.
The patched node-stratum-pool implementation is the reference pool pattern in this repository set. It uses a strict boolean coin config:
"digidollar": trueWhen that is present, lib/pool.js requests:
["segwit","digidollar-oracle"]When it is absent or not a boolean true, the pool keeps legacy behavior:
["segwit"]That strict opt-in prevents unrelated coins from accidentally requesting DigiDollar rules.
The patched lib/transactions.js copies the oracle commitment into the
coinbase:
if (rpcData.default_oracle_commitment !== undefined) {
var oracleCommitment = Buffer.from(rpcData.default_oracle_commitment, 'hex');
txOutputBuffers.unshift(Buffer.concat([
util.packInt64LE(0),
util.varIntBuffer(oracleCommitment.length),
oracleCommitment
]));
}The test coverage verifies:
digidollar: truerequests["segwit","digidollar-oracle"]digidollar: false, missing, or string"true"stays legacydefault_oracle_commitmentis included exactly once- the oracle commitment output has zero DGB value
- no oracle commitment is invented when GBT did not provide one
DigiHashV2 uses one coin JSON per DigiByte mainnet algo.
Each mainnet DigiByte coin config must contain:
{
"symbol": "DGB",
"digidollar": true,
"algorithm": "scrypt"
}The local DigiHashV2 example enables this for all five mainnet algo configs:
coins/digibyte.sha256.jsoncoins/digibyte.scrypt.jsoncoins/digibyte.skein.jsoncoins/digibyte.qubit.jsoncoins/digibyte.odo.json
Example coins/digibyte.scrypt.json pattern:
{
"name": "DigiByte-Scrypt",
"symbol": "DGB",
"digidollar": true,
"algorithm": "scrypt",
"peerMagic": "fac3b6da",
"coinbase": "DigiHashV2"
}The pool config then points to that coin file:
{
"enabled": true,
"coin": "digibyte.scrypt.json",
"address": "<POOL_PAYOUT_ADDRESS>",
"daemons": [
{
"host": "127.0.0.1",
"port": 14022,
"user": "user",
"password": "password"
}
]
}Important release requirement:
DigiHashV2 must run with a patched node-stratum-pool that contains the
DigiDollar GBT and coinbase support. In the local validation, that is
node-stratum-pool commit:
433d38a Add DigiDollar oracle mining template support
Do not ship a DigiHashV2 release whose package-lock.json pins an older
node-stratum-pool commit. A correct install must resolve to a stratum-pool
version that:
- requests
digidollar-oraclewhencoin.digidollar === true - preserves
default_oracle_commitment - keeps legacy behavior for coins without
digidollar: true
Use this checklist for any pool implementation.
- Include
segwitinrules. - Include
digidollar-oracleinrulesonly for DigiDollar-aware DigiByte mining. - Continue using legacy
["segwit"]for coins or miners that are not DigiDollar-aware. - Pass the correct DigiByte algo, either through one daemon per algo or through Core's second GBT argument.
- Read
transactionsfrom the template. - Use template
txidvalues for merkle leaves when present. - Serialize raw transaction
datainto the block. - Keep longpoll GBT requests using the same
rulesas normal GBT requests. - Do not mix cached legacy templates with DigiDollar-aware templates.
- Build a normal pool coinbase.
- Preserve
default_witness_commitmentif present. - Preserve
default_oracle_commitmentif present. - Put the oracle commitment in a zero-value output.
- Do not invent an oracle commitment.
- Do not drop the oracle commitment from a template that contains mint/redeem work.
- Submit full blocks with
submitblock. - If a proposal mode is used, propose the full block that includes the oracle commitment.
- Treat missing oracle commitment as a normal no-oracle template, not as a reason to fabricate data.
Before enabling production pool work, verify:
digibyte-cli getblocktemplate '{"rules":["segwit"]}' scryptExpected:
- no
default_oracle_commitment - no oracle-priced mint/redeem work
Then verify:
digibyte-cli getblocktemplate '{"rules":["segwit","digidollar-oracle"]}' scryptExpected when an oracle bundle is ready:
default_oracle_commitmentexistsrulesincludes!digidollar-oracle- mint/redeem transactions may appear when pending
If no oracle bundle is ready:
default_oracle_commitmentmay be absent- mint/redeem transactions that need a fresh price should not appear
- normal DigiByte mining can continue
The integration contract above is backed by focused tests in the current code. Use these when auditing or porting the logic to another pool.
Command:
test/functional/digidollar_gbt_optin.py
test/functional/digidollar_oracle_gbt_stale_cache.pyWhat these prove:
- Legacy GBT requests with
["segwit"]do not receivedefault_oracle_commitment. - Legacy GBT requests do not receive oracle-priced mint/redeem transactions.
- DigiDollar-aware GBT requests with
["segwit","digidollar-oracle"]receivedefault_oracle_commitmentwhen a fresh oracle bundle is ready. - DigiDollar-aware GBT includes pending mint/redeem transactions only when the oracle commitment is valid.
- Stale oracle commitments are not reused.
- Legacy and DigiDollar-aware GBT templates are cached separately.
Command:
python3 tests/test_gbt_regressions.pyWhat this proves:
--digidollarrequests["segwit","digidollar-oracle"].- Normal cpuminer mode keeps legacy
["segwit"]behavior. - Miner-built coinbases preserve
default_oracle_commitment. - BIP34 coinbase height encoding is minimal and valid.
- Merkle leaves use template
txidwhen provided.
Command:
node lib/test.jsWhat this proves:
coin.digidollar === truerequests["segwit","digidollar-oracle"].- Missing, false, or string
"true"does not opt in. default_oracle_commitmentis copied into coinbase exactly once.- The oracle output is zero value.
- The pool does not invent an oracle output when GBT does not provide one.
Command:
node test/digidollar-coin-config-smoke.test.jsWhat this proves:
- All five DigiByte mainnet coin configs opt in with
digidollar: true. - Unrelated example coin configs do not opt in accidentally.
- DigiHashV2's config layer is ready to drive the patched stratum-pool logic.
Minimum tests for a correct integration:
-
Legacy GBT test
- Request
["segwit"]. - Assert no
default_oracle_commitment. - Assert oracle-priced mint/redeem txs are not included.
- Request
-
DigiDollar-aware GBT test
- Request
["segwit","digidollar-oracle"]. - With a fresh oracle bundle, assert
default_oracle_commitmentexists. - With a pending mint/redeem, assert the tx appears.
- Request
-
Stale oracle test
- Let the oracle bundle age out.
- Assert stale templates do not keep old oracle commitments.
- Assert price-dependent mint/redeem txs are removed until a fresh bundle is ready.
-
Coinbase preservation test
- Build a coinbase from a template containing
default_oracle_commitment. - Assert exactly one zero-value output contains the exact script.
- Build a coinbase from a template containing
-
No-invention test
- Build a coinbase from a template without
default_oracle_commitment. - Assert no oracle output is created.
- Build a coinbase from a template without
-
Multi-algo block acceptance test
- Mine and submit blocks for
scrypt,sha256d,skein,qubit, andodowith the pool/miner implementation that supports each algo. - Verify blocks with pending mint/redeem txs are accepted when the oracle bundle is ready.
- Mine and submit blocks for
-
Non-DigiDollar coin safety test
- Verify unrelated coin configs do not request
digidollar-oracle.
- Verify unrelated coin configs do not request
Symptom:
- Normal blocks mine.
- Mints/redeems sit unconfirmed.
- GBT response has no
default_oracle_commitment.
Fix:
- Add
digidollar-oracleto GBTrules. - For cpuminer, use
--digidollar. - For pools, enable strict DigiDollar coin config opt-in.
Symptom:
- Pool asks for DigiDollar-aware templates.
- Template has
default_oracle_commitment. - Submitted block has no
OP_ORACLEcoinbase output. - Mint/redeem work cannot confirm correctly.
Fix:
- Copy
default_oracle_commitmentinto the coinbase as a zero-value output.
Symptom:
- Block submission fails even though the template looked valid.
Fix:
- Use template
txidfor merkle leaves when provided. - Serialize raw
datainto the final block only.
Symptom:
- DigiHashV2 coin configs say
digidollar: true. - Pool still requests only
["segwit"]. - No oracle commitment appears in the pool's submitted blocks.
Fix:
- Update/pin the patched stratum-pool dependency.
- Reinstall dependencies.
- Re-run the pool's DigiDollar GBT and coinbase tests.
DigiDollar mining does not require every miner on the network to be an oracle. It also does not require every old miner to upgrade immediately.
The rule is simple:
- Old miners mine normal DigiByte blocks.
- DigiDollar-aware miners and pools ask Core for DigiDollar-aware templates.
- Core provides an oracle commitment only when it has fresh oracle data.
- The miner or pool copies that commitment into the coinbase.
- Then mints and redeems can confirm in that block.
That is the safe split: no fork risk for old miners, and correct DigiDollar support for upgraded miners and pools.