-
Notifications
You must be signed in to change notification settings - Fork 0
Stratum Protocol
voidmap-bot edited this page Jun 5, 2026
·
1 revision
Voidmap uses a modified Stratum protocol for communication between miners and pools. Stratum is the standard mining protocol used in Bitcoin, adapted here for Proof of Useful Work.
- Protocol: WebSocket (ws:// or wss://)
- Format: JSON-RPC 2.0
- Encoding: UTF-8
Request:
{
"id": 1,
"method": "mining.subscribe",
"params": ["miner_id"]
}Response:
{
"id": 1,
"result": [1, "extranonce", 4],
"error": null
}Notification (server → client):
{
"method": "mining.notify",
"params": [...]
}Miner subscribes to work notifications.
Request:
{
"id": 1,
"method": "mining.subscribe",
"params": ["miner_id"]
}Response:
{
"id": 1,
"result": [
["mining.notify", 1],
"extranonce_hex",
4
],
"error": null
}Fields:
-
params[0]: Miner ID (string) -
result[0]: Subscription IDs -
result[1]: Extranonce (hex string) -
result[2]: Extranonce size (bytes)
Miner authenticates with pool.
Request:
{
"id": 2,
"method": "mining.authorize",
"params": ["miner_id", "worker_name", "password"]
}Response:
{
"id": 2,
"result": true,
"error": null
}Fields:
-
params[0]: Miner ID -
params[1]: Worker name -
params[2]: Password (optional) -
result: true if authorized
Pool sends new work to miner.
Notification:
{
"method": "mining.notify",
"params": [
"job_id",
"prev_hash",
"coinbase1",
"coinbase2",
["merkle_branches"],
"version",
"bits",
"timestamp",
"height",
true,
1,
"cnn",
32,
"data_hash",
"challenge_hash",
"ipfs_cid"
]
}Fields:
-
params[0]: Job ID (string) -
params[1]: Previous block hash (hex) -
params[2]: Coinbase TX part 1 (hex) -
params[3]: Coinbase TX part 2 (hex) -
params[4]: Merkle branches (array of hex) -
params[5]: Version (string) -
params[6]: Bits/difficulty (string) -
params[7]: Timestamp (integer) -
params[8]: Block height (integer) -
params[9]: Clean jobs (boolean) -
params[10]: Task ID (integer: 1=exoplanet, 2=galaxy, 3=anomaly) -
params[11]: Model variant (string: cnn/transformer/mamba/convnext) -
params[12]: Batch size (integer: 16-128) -
params[13]: Data hash (hex) -
params[14]: Challenge hash (hex) -
params[15]: IPFS CID (string)
Miner submits completed work.
Request:
{
"id": 3,
"method": "mining.submit",
"params": [
"miner_id",
"job_id",
"extranonce2",
"timestamp",
"output_hash",
75,
{"prediction": "PLANET", "confidence": 0.87},
"Qm1234567890"
]
}Response:
{
"id": 3,
"result": true,
"error": null
}Fields:
-
params[0]: Miner ID -
params[1]: Job ID -
params[2]: Extranonce2 (hex) -
params[3]: Timestamp (string) -
params[4]: Output hash (hex, 64 chars) -
params[5]: Quality score (integer: 50-100) -
params[6]: Predictions (object) -
params[7]: IPFS CID (string)
Pool sets difficulty target for miner.
Notification:
{
"method": "mining.set_difficulty",
"params": [75]
}Fields:
-
params[0]: Difficulty (integer: 50-100)
Pool sets new extranonce for miner.
Notification:
{
"method": "mining.set_extranonce",
"params": ["new_extranonce", 4]
}Fields:
-
params[0]: New extranonce (hex) -
params[1]: Extranonce size (bytes)
Keepalive message.
Request:
{
"id": 10,
"method": "mining.ping",
"params": []
}Response:
{
"id": 10,
"result": "pong",
"error": null
}| Code | Message | Description |
|---|---|---|
| 0 | Stale job | Job ID no longer valid |
| 1 | Duplicate share | Same nonce submitted twice |
| 2 | Low difficulty | Quality below threshold |
| 3 | Invalid hash | Output hash malformed |
| 4 | Unauthorized | Miner not authorized |
| 5 | No work | No work available |
| 6 | Invalid params | Missing required fields |
Miner Pool
│ │
│──── mining.subscribe ──────────▶│
│◀─── subscribe response ────────│
│ │
│──── mining.authorize ──────────▶│
│◀─── authorize response ────────│
│ │
│◀─── mining.set_difficulty ─────│
│◀─── mining.notify ─────────────│
│ │
│──── mining.submit ─────────────▶│
│◀─── submit response ───────────│
│ │
│◀─── mining.notify ─────────────│
│ (new work) │
│ │
import websockets
import json
async def mine():
async with websockets.connect("ws://pool.voidmap.org:3333") as ws:
# Subscribe
await ws.send(json.dumps({
"id": 1,
"method": "mining.subscribe",
"params": ["my_miner"]
}))
resp = json.loads(await ws.recv())
extranonce = resp["result"][1]
# Authorize
await ws.send(json.dumps({
"id": 2,
"method": "mining.authorize",
"params": ["my_miner", "worker1"]
}))
resp = json.loads(await ws.recv())
# Receive work
work_msg = json.loads(await ws.recv())
job_id = work_msg["params"][0]
# Process and submit
await ws.send(json.dumps({
"id": 3,
"method": "mining.submit",
"params": ["my_miner", job_id, "0000", "1234567890", "abc...", 75, {}, ""]
}))
resp = json.loads(await ws.recv())
print(f"Share accepted: {resp['result']}")from stratum import StratumProtocol, WorkUnit
# Create subscribe message
msg = StratumProtocol.subscribe("my_miner")
print(msg.to_json())
# Parse response
resp = StratumMessage.from_json('{"id":1,"result":[1,"abcd1234",4]}')
print(resp.result)