dMint Follow-up: PoW Distributed Mint (Future Work)¶
⚠️ This document is out of date — see code instead.
Written when pyrxd shipped only the premine-at-deploy path. Since then pyrxd has gained full V2 deploy support, V1 mint support against live mainnet contracts (M1), and V1 deploy support with byte-equal golden vectors against the live Radiant Glyph Protocol deploy (M2). The “what is NOT implemented” sections below are wrong: the V2 contract builder, ASERT/LWMA difficulty bytecode, V1+V2 parsers, V1+V2 mint tx builders, an external-miner shim, a reference Python miner, AND a V1 deploy builder all ship today.
Authoritative sources for current dMint capability:
docs/concepts/dmint-v1-deploy.md— the V1 deploy story end-to-end (multi-contract structure, CBOR shape, Photonic divergences, footguns)
docs/dmint-research-photonic-deploy.md— M2 byte-by-byte decode of the GLYPH mainnet deploy
src/pyrxd/glyph/dmint.py— builders, parsers, miner, verifier, chain helpers
src/pyrxd/glyph/builder.py—prepare_dmint_deploy(V1 default; V2 behindallow_v2_deploy=Truefootgun guard);DmintV1DeployParams/DmintV2DeployParams
examples/dmint_v1_deploy_demo.py— manual real-mainnet V1 deploy runner (DRY_RUN by default)
examples/dmint_claim_demo.py— manual real-mainnet V1 mint runner
docs/plans/2026-05-08-feat-dmint-v1-deploy-plan.md— M2 plan (V1 deploy; merged)What’s still genuinely future work:
Auth NFT in the V1 deploy reveal (M2 demo omits this; GLYPH has it)
Premine FT output on V1 deploy (deferred per Photonic divergence #2)
Walking forward through mined-from contracts in
find_dmint_contract_utxos(current impl returns fresh contracts only)Live-mainnet V2 deploy proof (M3, deferred indefinitely — no ecosystem demand)
EPOCH DAA int64-overflow — fixed upstream and re-enabled (DONE). All five DAA modes (FIXED/ASERT/LWMA/EPOCH/SCHEDULE) are ported and byte-matched to canonical Photonic. EPOCH deploy was briefly refused while the canonical EPOCH bytecode had an int64-overflow that bricked the contract on-chain (
target × clampedDeltaoverflows int64; the retarget also drifted past the 2^48 safe target —radiant-coreinterpreter.cppOP_MUL → safeMulabort). The fix is now merged upstream (Radiant-Core/Photonic-Wallet#2— EPOCH clamps target to 2^48 before the multiply, divides first(target/targetTime) × clampedDelta, caps the output at 2^48; LWMA floorstimeDeltaat 0 viaOP_0 OP_MAX; the previously-unusedEPOCH_MAX_SAFE_TARGETdeploy check is wired up). pyrxd byte-matches the merged canonical: the EPOCH/LWMA bytecode builders + the off-chain miner replicas (compute_next_target_epoch/_linear) were updated, the golden vectors regenerated, theDaaMode.EPOCHdeploy refusal dropped, and the full suite is green. EPOCH deploy needsdifficulty ≥ 32768(the 2^48 cap).Native fast miner — pyrxd ships a slow Python reference; users wanting GPU/multi-core go through the external-miner shim to
glyph-minerFull rewrite of this doc lands as a separate PR after M2 merges.
(Original document — historically accurate at writing time, no longer reflects the current code. Retained for context.)
pyrxd 0.2.x implements the premine-at-deploy FT path. This document captures what a future PoW-capable SDK would need to implement Photonic’s full dMint protocol, and why most consumers do not require it.
What pyrxd 0.2.x implements¶
GlyphMetadata.for_dmint_ft(...)— metadata withp:[1,4](FT + DMINT markers)GlyphBuilder.prepare_ft_deploy_reveal(...)— reveal scripts for a premine-at-deploy FT: entire supply to treasury PKH at vout[0]FtUtxoSet.build_transfer_tx(...)— conservation-enforcing FT transferCBOR cross-decoder tests (pyrxd encode ↔ RXinDexer reference decoder)
Deploy structural integration tests + VPS
testmempoolacceptproof
The p:[1,4] marker tells indexers this token follows the dMint protocol.
For premine-only consumers the only relevant part of that protocol is the
deploy shape — a single reveal output carrying the full supply. The PoW
ongoing-mint machinery is not used.
What is NOT implemented: PoW distributed mint¶
Photonic’s dMint protocol supports a second mode beyond premine: holders can mine new tokens by solving a PoW challenge embedded in a covenant UTXO that remains on-chain after deploy. pyrxd does not implement this.
Specifically missing:
1. Difficulty covenant UTXO¶
The deploy reveal would produce a second output — the “dMint covenant UTXO” — containing the mining difficulty parameters. This UTXO is spent and re-created by each minting transaction, updating the difficulty.
Radiant implementation would need:
A covenant script enforcing ASERT or LWMA difficulty adjustment
The minting tx must satisfy a hash-less-than-target check (
OP_SHA256of the minting tx’s nonce field < current target)The covenant re-creates itself at the next output with updated params
2. Per-mint commit/reveal¶
Each minting event uses a two-tx commit/reveal (same shape as NFT minting in pyrxd today, but carrying FT outputs). The commit locks a small UTXO; the reveal spends it, proves PoW, and produces new FT outputs.
GlyphBuilder.prepare_commit and prepare_reveal handle the basic shape
but don’t carry the PoW nonce or covenant interaction.
3. ASERT / LWMA difficulty adjustment¶
The difficulty target adjusts per-block (ASERT) or per-window (LWMA).
Implementing this in a Radiant script covenant requires bignum comparison
(OP_BIN2NUM, OP_DIV) — the same operations the Gravity Protocol uses
for BTC header work. Feasible but non-trivial.
When premine-only is enough¶
A premine-only token mints the entire supply to a treasury wallet at
deploy. Distribution happens via plain FT transfers
(FtUtxoSet.build_transfer_tx) as the issuer hands out tokens. No
post-deploy minting occurs.
The p:[1,4] marker is appropriate for premine-only deploys because:
Photonic Wallet and most RXD indexers recognize it as the correct FT token class for fungible tokens with explicit supply
It is forward-compatible — if a downstream consumer later needs a secondary PoW mint phase, the token ref is already correctly typed
Using p:[1] alone (plain FT, no dMint marker) also works for the
premine shape. The choice between [1] and [1,4] is a downstream
decision — [1,4] reads as “this token participates in the dMint
protocol family even if it never uses the PoW phase,” which some
indexers prefer.
Implementing PoW dMint (future contributor guide)¶
If a future contributor wants to add full PoW dMint support:
Difficulty covenant script — model after
pyrxd/gravity/covenant.py. Encode difficulty params as constructor arguments baked into bytecode. The covenant must re-create itself at output index N with updated target.Mint tx builder — new function
build_mint_tx(covenant_utxo, nonce, miner_pkh, fee_sats). The nonce is a 4-byte field in the tx that the miner varies to find a valid PoW solution.Difficulty verification —
OP_SHA256of the serialized mint tx (minus nonce field) must be<=the current target. This is a script constraint enforced by the covenant, not by pyrxd.Tests — unit tests can use a trivially easy target (all-ones). VPS integration test can mine one token against the live covenant.
The Photonic Wallet TypeScript source (lib/dmint.ts) is the reference
implementation. pyrxd’s cbor2-based CBOR encoding already matches
Photonic’s payload format (verified by tests/test_cbor_cross_decoder.py).