Skip to content

Latest commit

 

History

198 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

dinero-sv2

Stratum V2 for Dinero, in Rust. Protocol messages, wire codec, Noise NX transport, reference pool server, Template Provider binary, and miner-side Job Declaration — the sovereignty loop that lets a miner (including a phone) pick its own coinbase outputs and let the pool independently verify every byte, including the header's Utreexo root.

Pure Rust, no FFI. Works anywhere a Rust crate works: DineroDPI (iOS), future pool operators, TP processes running beside dinerod, tests.

Mine in one minute

Install with one pasted command, then launch directly with your Dinero reward address. No node, configuration file, or chain sync is required.

macOS / Linux / Chromebook:

curl -fsSL https://raw.githubusercontent.com/DineroLabs/dinero-sv2/main/scripts/install.sh | sh

Windows (PowerShell):

irm https://raw.githubusercontent.com/DineroLabs/dinero-sv2/main/scripts/install.ps1 | iex

Then start shared CPU mining on macOS or Linux (replace the placeholder with your own complete din1p… reward address):

cd "$HOME/.local/bin" && ./dinero-miner --address "YOUR_DIN1_ADDRESS" --reward-mode shared --threads 2

On Windows PowerShell:

cd "$env:LOCALAPPDATA\DineroMiner\bin"; .\dinero-miner.exe --address "YOUR_DIN1_ADDRESS" --reward-mode shared --threads 2

--threads 2 uses two CPU threads; choose a different positive number for more or less CPU usage. The miner validates and saves the address, connects to pool.dinerolabs.org:4444, and opens a dedicated full-screen terminal with:

  • a pinned Dinero header and complete reward address;
  • the Noise NX security, channel, worker, target, and uptime state;
  • 31 rolling rows of real nonces and complete 256-bit candidate hashes;
  • accepted/rejected share telemetry, session work, and reconnect health; and
  • a timestamped network feed. Ctrl-C restores the original shell screen.

Running dinero-miner without --address remains supported and prompts for a reward address interactively.

No node in either reward mode: the pool's node serves templates. shared = PPLNS split; solo = miner-owned coinbase via the pool (whole reward if your hash wins).

Your address is validated up front and saved to ~/.config/dinero-miner/config.json; the next run offers it back with Enter-to-reuse. Flags > config file > built-in defaults, so --pool, --server-pubkey, --reward-mode, and --threads all override.

Chromebook: enable Linux (Settings → Advanced → Developers → "Linux development environment"), open the Terminal app, and paste the same Linux one-liner.

Behavior change in miner-v0.1.0: an unspecified --reward-mode now resolves to shared (it used to default to solo). Pass --reward-mode solo explicitly to keep miner-owned all-or-nothing coinbases.

Current public releases ship the CPU miner (dinero-miner). The GPU worker (dinero-sv2-gpu-miner, Metal/OpenCL) has the same interactive UX and builds from source today; prebuilt GPU release binaries come later.

What's in here

crates/
├── dinero-sv2-common       messages + header layout + Utreexo invariants
├── dinero-sv2-codec        strict wire codec (fixed + var-len)
├── dinero-sv2-jd           Job Declaration primitives + pure-Rust Utreexo
├── dinero-sv2-transport    Noise NX + SV2-shaped framing
├── dinero-sv2-tp-sim       in-memory Template Provider simulator
├── dinero-tp               TP binary — binds dinerod, serves miners
├── dinero-sv2-pool         reference pool server (two-tier target,
│                           vardiff, submitblock, JD acceptance)
├── dinero-sv2-miner        CPU SV2 pool worker
└── dinero-sv2-gpu-miner    GPU SV2 pool worker (Metal/OpenCL)

Binary roles

Binary Role Who runs it
dinero-sv2-pool Reference Stratum V2 pool server. Accepts workers, assigns share targets, validates shares, and submits found blocks. Pool operators
dinero-tp Template Provider. Talks to dinerod RPC and emits block templates to the SV2 side. Pool operators
dinero-sv2-miner CPU pool worker. Connects to an SV2 pool over Noise/SV2 and submits shares. Pool miners
dinero-sv2-gpu-miner GPU pool worker. Uses Metal on Apple Silicon and OpenCL on Linux/Windows. GPU pool miners

In casual language, "SV2 pool worker" means the miner-side process: dinero-sv2-miner for CPU or dinero-sv2-gpu-miner for GPU. The pool it connects to is dinero-sv2-pool.

The sovereignty loop

Phase 5 is the finish line. With a dinerod running at 127.0.0.1:20998 and the daemon's cookie in ~/.dinero/.cookie:

# Terminal 1 — pool
ADDR=din1p6zd8mnxf3fz0kcsjrmsrtjkymnmfjz9gkrpqhed07g3n4hdfn4pq6nxmch
cargo run --release -p dinero-sv2-pool -- \
  --bind 127.0.0.1:4444 \
  --payout-address "$ADDR" \
  --share-leading-bits 0

# Terminal 2 — print the pool's static Noise pubkey for pinning
cargo run --release -p dinero-sv2-pool -- \
  --payout-address "$ADDR" --print-pubkey
# → 47e4c132fefc04bce63f87b2d5d0a70575541da47d4dbe23247ea135eafcfb58

# Terminal 3 — a miner that picks its own payout and runs the full JD loop
cargo run --release -p dinero-tp --example testclient -- \
  --server-pubkey 47e4c132fefc04bce63f87b2d5d0a70575541da47d4dbe23247ea135eafcfb58 \
  --jd

The miner prints:

handshake ok; server static pubkey = 47e4c132…
SetupConnection.Success: used_version=2
OpenStandardMiningChannel.Success: channel_id=1 target=FF..FF
SetNewPrevHash: prev_hash=b07ae72d… nbits=0x1d00ffd2
UtreexoStateAnnouncement: num_leaves=15993 num_roots=10
  pre_block_commitment=2af38633…
CoinbaseContext: height=5332 value_una=10000000000 …
NewMiningJob: template_id=1 utreexo_root=5cec2b43…
JD locally computed: coinbase_txid=c78077d7…
                     utreexo_root=ceded42b7…  (pool's was 5cec2b43…)
SubmitShares.Success: accepted=1

The pool prints:

accepted extended share
  hash=46bc4e92…
  template_id=1 utreexo_root=ceded42b7…

That match — ceded42b7… — is the whole point. The miner chose its payout, built its own coinbase, derived the header's utreexo_root locally. The pool reassembled the candidate from the miner's submitted outputs, applied the same Utreexo math, and got the same 32 bytes. Neither side's result relied on the other.

Public stats API

The pool can serve a second, unauthenticated, read-only HTTP listener for aggregator sites (MiningPoolStats, minerstat) and for a human landing on the pool's hostname. It is OFF unless you pass --public-stats-bind:

dinero-sv2-pool ... --public-stats-bind 127.0.0.1:8080 --public-stratum-addr pool.example.org:4444

--public-stratum-addr is required alongside it (the pool refuses to start without it — the internal --bind is not something to advertise). Bind on loopback and put a TLS reverse proxy in front; a port that is already taken fails startup rather than silently running without the page.

Route Returns
GET / A small HTML page: hashrate, miners, last block, recent blocks, install one-liners. Fetches /api/stats from the browser.
GET /api/stats { pool_hashrate_hs, miners, workers, blocks_found_24h, blocks_found_total, last_block_height, last_block_hash, last_block_time, fee_bps, payout_scheme: "PPLNS", min_payout_una, stratum, network_height, network_difficulty, updated_at }
GET /api/blocks?limit=N Newest first, N clamped to 1..100 (default 50): [{ height, hash, time, reward_una, status }]
GET /api/miner/<din1p…> { address, hashrate_hs, shares_1h, window_bps, est_next_block_una, paid_una, last_share_time } — 404 for any address that never submitted a share. There is no miner listing.

Field notes: pool_hashrate_hs, hashrate_hs and miners describe shared-mode (PPLNS) work only — expected hashes per second from shares in the PPLNS window over the last 10 minutes (share weight is calibrated to expected hashes), and distinct payout addresses with such a share. Solo-mode miners are not credited to the window and do not appear in those numbers. workers is Stratum sessions that completed the Noise handshake, shared and solo alike, so it can exceed what miners accounts for. est_next_block_una is an estimate of what the address would receive if the next block were found right now (reward less fee, times window_bps); PPLNS holds no balance, so it is a standing, not a debt. paid_una sums coinbase outputs to that address in blocks the pool built and dinerod accepted. network_difficulty uses the Bitcoin 0x1d00ffff convention. Times are Unix seconds; amounts are una.

Safe to expose: every route is GET/HEAD only, nothing takes a body, and the listener shares no token, route, or code path with the operator endpoint. It cannot show the payout address, fee controls, ban controls, daemon endpoint, or any configuration; /status, /payout-address, /fee-bps, /ban are 404 on it, and /api/* is 404 on the ops listener (crates/dinero-sv2-pool/tests/public_stats.rs pins both). Responses carry Access-Control-Allow-Origin: * on GET and are served from one sample rendered every 10 s. Abuse limits: 60 requests/minute per client (429 + Retry-After beyond that; when the peer is loopback — a local reverse proxy — the client is X-Real-IP, else the last hop of X-Forwarded-For (the one the proxy appended; earlier hops are client-supplied), otherwise the peer itself, so no client can pick its own bucket; IPv6 is bucketed by /64), at most 256 concurrent connections (extra ones are closed on accept), and a 10 s deadline per connection. It speaks plain HTTP; put a TLS reverse proxy in front of it for https://pool.example.org/api/stats and make sure the proxy sets X-Real-IP $remote_addr (nginx) or appends to X-Forwarded-For.

Found blocks are appended to found-blocks.jsonl next to the PPLNS journal so blocks_found_total and /api/blocks survive a restart.

Phase history

Each phase is one commit. git log --oneline reads like a story from messages-on-paper to a running sovereignty loop.

Phase Commit Deliverable
1 b0796aa Codec foundation: 128-byte header, NewTemplateDinero, SubmitSharesDinero, HeaderAssembly, byte-for-byte parity against 9 live mainnet headers
2.1 7277201 dinero-tp binds real daemon via HTTP JSON-RPC, emits real templates
2.2 8064bc9 Noise NX wrapping (ChaChaPoly + BLAKE2s), static key pinning
3 2af044a JD message + coinbase assembly + merkle path computation
4 b657531 Reference pool server: two-tier target + submitblock on block-target shares
A c7220cc SV2-shaped framing: u24 outer length prefix, 6-byte inner header (ext_type u16 + msg_type u8 + msg_length u24)
B 229278c Setup / OpenStandardMiningChannel / SubmitShares.Success+Error
C 9e4e478 Explicit SetNewPrevHash before every NewMiningJob
3b 63a12b7 Utreexo accumulator state + delta-addition primitives
3c 07a1098 Pure-Rust port of Dinero's Utreexo primitives; byte-for-byte verified against the live getutreexocommitment RPC
4b c1b7e46 Pre-block Utreexo state on the wire (UtreexoStateAnnouncement)
5 24cf530 Miner-owned coinbase end-to-end: CoinbaseContext + SubmitSharesExtended + pool-side reassembly

99 tests across the workspace at Phase 5 head, all green. cargo clippy -- -D warnings clean.

Consensus-critical invariants (encoded, not just documented)

  • 128-byte header with reserved[12] = 0. Not extranonce, not pool scratch, not miner entropy. Enforced at encode and decode in dinero-sv2-common::HeaderAssembly.
  • timestamp: u64. Dinero dodged 2038; no u32 shortcuts anywhere.
  • utreexo_root at offset 0x44 is a first-class header field — Dinero-specific. Miners compute it locally in JD mode.
  • Leaf hash = SHA256("DINERO-UTXO-LEAF-v1" || txid || vout_LE32 || amount_LE64 || CompactSize(script_len) || script). Matches HashUTXO in dinerod/src/consensus/utreexo_accumulator.cpp:216-266.
  • Node hash = SHA256("DINERO-UTREEXO-NODE-v1" || left || right). Matches HashNode in the same file, 201-214.
  • Commitment = SHA256(num_leaves_LE64 || slot[0] || … || slot[63]) with 32-byte zeros for empty slots. Fixed 2056-byte preimage. Matches UtreexoForest::getCommitment at 1845-1874. Cross-verified byte-for-byte against the live getutreexocommitment RPC (cb8592403b46beee… at num_leaves=15939).

SV2 wire shape (Pass A-C)

After Noise NX:

| u24 LE ciphertext_len | ChaChaPoly ciphertext |

plaintext inside the cipher:
| u16 LE ext_type | u8 msg_type | u24 LE msg_length | payload |

Pool → miner message order per tip:

SetNewPrevHash 0x20
→ UtreexoStateAnnouncement 0x21          (Dinero ext; JD-capable pools)
→ CoinbaseContext 0x17                   (Dinero ext; JD-capable pools)
→ NewMiningJob 0x15

Miner → pool shares:

Standard:  SubmitSharesStandard 0x1A → SubmitShares.Success 0x1C / .Error 0x1D
JD:        SubmitSharesExtended 0x1B → same ack messages

Spec drift observed

docs/DINERO-UTREEXO-SPEC.md §3.5 in the Dinero repo publishes three golden leaf-hash vectors computed before the C++ added a CompactSize varint before the script. Current consensus code (and this Rust port) include the varint, so the spec's goldens are stale. See the Phase 3c commit for details.

License

MIT.

About

Stratum V2 pool, Template Provider, CPU miner, and native Metal/OpenCL/CUDA GPU miners for Dinero

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages