Public repo: github.com/Blockvase/c_datum_prime
A C port of RATUM Prime by iohzrd.
License: GNU Affero GPL v3 or later. See LICENSE and NOTICE.
This repo is only the DATUM pool server (Prime). It is not a full mining stack, not a public Stratum server, and not the LAN miner gateway. Cloning and running this binary will not hash or pay anyone by itself.
To get a Knots node, CONVOY DATUM Gateway, and miners working first, follow
bitcoin-blake2b.org/mining. That guide
leaves you in solo mode (datum.pool_host empty,
datum.pooled_mining_only false).
CONVOY DATUM Gateway is separate MIT software. Do not merge this tree into it.
When Knots and CONVOY DATUM are up, replace the datum object in
datum_gateway_config.json with:
"datum": {
"pooled_mining_only": true,
"pool_host": "pool.blockvase.com",
"pool_port": 28915,
"pool_pubkey": "d89f714cfe7bd9022794b42e2b9b7c196cdd0e16165df0300d788a1b18a86da20654de460ece16e2a2e88d1f8ad316f728c2b5b731d259afd55229375c905439"
}Restart CONVOY DATUM. Keep your ASIC on the gateway's Stratum port (23334 in
the guide). Do not point miners at Prime.
If you run your own Prime instead of Blockvase's, use the pool_pubkey
printed at startup, pool_host 127.0.0.1 (or that host's public name),
and pool_port 28915. From this LAN, pool.blockvase.com:28915 may
time out (no hairpin); use 192.168.1.206.
Aligned with RATUM Prime (698a236) on the live path:
- Keys, listen, CONVOY DATUM/RATUM hello (v1 and v3), signed 0x99 config.
- Coinbaser split from a durable share ledger (RATUM window math, fee
--fee-bps, optional--fee-after-first-blockto stay at 0% until the first recorded pool block then apply--fee-bpspermanently,--min-payout546). Identities areusernameup to the first.. Mainnet P2PKH1..., P2SH3..., SegWitbc1q..., and Taprootbc1p...become scripts; up to 128 split outputs are served. require_splitafter a 10s grace (RATUM): keyed off the job's coinbaser id, not the share's stratum class.--no-require-splitto turn off.- Share PoW (header-v2, twelve zero bytes in the coinbase hole), replay guard, credit into the ledger.
- v3 ABW: 0xA8 notices, key in H1, mask, 0xA5 receipts, 0x8F exact ref,
rotate, delayed 0xA9 reveal. A submitted block header carries that XOR
key and clear-bits so the node hashes the same work the share did.
--abw-disabledif you need the old path. - Resume tokens honored (ABW keys + coinbaser id).
- Block relay: nbits,
0x50 0x12/0x92, merkle,submitblockviabitcoin-clicookie, hex underdata/blocks/. Parses0x90/0x91/0x94. - Bulk framing (
DBF\x01/DBA\x01) for large replies. - Stats HTTP (default
0.0.0.0:28917,/,/stats.json, and/pool.jsonfor the Blockvase website relay). - One thread per gateway.
--self-testcovers framing, handshake, header vectors, split 75/25 and >8 outputs, Base58Check, bech32, zero xor mask, andrequire_splitkeyed off the job coinbaser id.
AGPL section 13: corresponding source is this GitHub repo and
http://pool.blockvase.com:28916/ (also in the MOTD). Forward TCP 28916
(and 28917 if you want stats off-LAN). The tarball excludes data/
(keys, ledger) and build/.
systemd unit: contrib/c-datum-prime.service (TimeoutStopSec=15,
KillMode=mixed; SIGTERM can hang on an open DATUM session).
This host uses the user unit contrib/c-datum-prime.user.service
(systemctl --user enable --now c-datum-prime). The website relay is
blockvase-relay (systemctl --user). A system-wide template is
contrib/c-datum-prime.service.
GET /pool.json on the stats listener returns public pool metadata for the
Blockvase Pool tab. It includes schema_version, endpoint, source URL,
pubkey, fee, payout address types, connected DATUM clients,
status.connected_sv1_clients (live public Stratum V1 miners on the
public gateway, not the Prime --stratum-listen DATUM pipe), share-window
progress, blocks found, a 3-hour hashrate average (hashrate_hs, H/s:
accepted share difficulty × 2^32 / 10800), and miners by window work
percent plus that same 3-hour hashrate. GET /shares.json (also /tides.json)
is the ordered share log for that window: at, difficulty, id, hash,
oldest first. Page with ?after=<hash>&limit=500 (limit max 2000). The live
window is the share file plus the last known target (ledger.window). Prime
does not trim to the startup floor while getdifficulty is down. Optional
--stratum-listen is a second DATUM bind for a public Stratum V1 gateway.
Shares on that bind pay 2.3% (2% to DATUM identities in the window, 0.3%
to the payout script). DATUM clients keep --fee-bps only. Public miners
connect to stratum_v1_url (stratum+tcp://pool.blockvase.com:3333), not
the internal --stratum-listen port. Miner rows include kind (datum,
sv1, or mixed) plus datum_work / public_work.
window_percent is the payout split from window work, not the 3-hour
hashrate. GET /empty.json (also /api/empty) is the frozen window for those
subsidy-only finds: block hash (ledger and explorer order), fee, miners,
and the same split amounts a later sendmany would pay. links.empty
points at it. GET /finds.json (also /api/finds) is the same shape for
ordinary split finds from ledger.owed plus any ledger.blocks row whose
hash is not already there. Each find stores the window work and DATUM or SV1
kind the same way empty.json does. Older owed rows get that window backfilled
from ledger.shares when the share file still covers the find. links.finds
points at it. status.empty_finds / status.empty_unsettled count subsidy-only
pool blocks whose coinbase paid the pool script. Prime copies the window
just before submitblock, then writes ledger.empty only if the node
returns null or duplicate. A normal split find waits the same way before
blocks_found, --fee-after-first-block, or ledger.owed. --void-block HASH
drops the owed row and the ledger.blocks line so a rejected candidate
does not keep the fee flip. The later
sendmany uses that snapshot with the same split as a live coinbase
(DATUM --fee-bps, SV1 2.3% with 2% rebate, 128-output cap, 546 sat
floor). Fee sats stay on the pool script. After 100
confirmations, print a sendmany with --empty-block HASH (or list),
then mark it paid with --settle-empty HASH. --void-empty HASH drops an
orphaned record. The HASH is the ledger encoding (same as --settle-block),
not the reversed hash on the prime: BLOCK line. Stop the pool process
before these CLI flags; they open the ledger on their own. It
intentionally does not include RPC credentials, private keys,
or local ledger file paths.
Needs libsodium and CMake.
cmake -S . -B build
cmake --build build
./build/c-datum-prime --self-test
After the mining guide you already have Knots. Then:
./build/c-datum-prime
Keys, ledger, and submitted-block files default to data/ next to the
project root (the parent of build/), from /proc/self/exe. They do not
depend on the current working directory or a hardcoded home path. Bitcoin
RPC defaults to $HOME/.bitcoin. Override with --bitcoin-datadir,
--keys, --ledger, --block-dir, and --payout-script.
Do not forward 8332, 7152, or 23334. Forward 28915 when this Prime is public, and 28916 if remote users should fetch source (AGPL section 13).
Use a distinct process name from datum_gateway so Knots
blocknotify=killall -USR1 datum_gateway does not signal Prime.
User unit (starts at login, or at boot if linger is on):
mkdir -p ~/.local/lib ~/.config/systemd/user
ln -sfn /path/to/c_datum_prime ~/.local/lib/c-datum-prime
cp contrib/c-datum-prime.user.service ~/.config/systemd/user/c-datum-prime.service
loginctl enable-linger "$USER"
systemctl --user daemon-reload
systemctl --user enable --now c-datum-prime.service
System unit is contrib/c-datum-prime.service (WantedBy=multi-user.target).
If you move the checkout, retarget the symlink. Do not add --keys,
--ledger, or --block-dir to the unit.
- Own tree, keys, ports, and unit.
- Knots RPC stays on localhost.
- This binary binds loopback until you pass
--listenwith another address.