XELIS Stratum Protocol
Version: 0.1.1
Last Updated: 5/5/2024
Authors: Vipor.net
This document describes a protocol, that allows a group of miners to connect to a server, which coordinates the distribution of work packages among miners.
The initial protocol was written for Bitcoin and contains several pieces that need adjustment in order to be usable with XELIS.
Specification
Conventions
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119 .
The stratum protocol mostly adheres to the JSON RPC 2.0 specification.
Overview
Communication happens over a bidirectional channel with messages encoded as
JSON with LF delimiter—in this document written as \n.
Since requests can be handled out of order, each request in a session SHOULD
have an unique id. In order to be able to match request and response,
responses MUST have the same id as their matching request. Notifications
sent by the server or calls that do not trigger any response MAY have an id of
null.
For further details on the members of request and response objects consult the JSON RPC 2.0 specification .
Protocol flow example
The following shows what a session might look like from subscription to submitting a solution.
Client Server
| |
| --------- mining.subscribe -------> |
| --------- mining.authorize -------> |
| <-------- mining.set_difficulty --- |
| |----
| <---------- mining.notify --------- |<--/
| |
| ---------- mining.submit ---------> |New difficulty protocol flow example
The following shows what communication may look like when a new difficulty is set for a miner.
Client Server
| |
| <-------- mining.set_difficulty --- |
| <---------- mining.notify --------- |
| |
| ---------- mining.submit ---------> |Methods
- mining.subscribe
- mining.authorize
- mining.notify
- mining.submit
- mining.set_difficulty
- mining.set_extranonce
- mining.ping
- mining.pong
- mining.print
- mining.hashrate
Errors
Whenever an RPC call triggers an error, the response MUST include an error field which maps to a list of the following values:
code:intmessage:stringdata:object
{"id": 10, "result": null, "error": {"code": 20, "message": "Invalid request", "data": null}}Errors SHOULD be identified by their code and programs SHOULD do error handling based on the code and not the message.
Available error codes, in addition to the codes defined in the JSON RPC 2.0 specification, are:
20- Other/Unknown21- Job not found (=stale)22- Duplicate share23- Low difficulty share24- Unauthorized worker
The message field SHOULD be a concise description of the error for human
consumption.
Implementors MAY choose to include an optional data object with additional
information relevant to the error.
Including null value in error object is against the JSON RPC spec. Error should only be included in the response when there is an actual error.
MinerWork Structure
112bytes total32bytes (0-31) Header work hash8bytes (32-39) timestamp provided in mining.notify8bytes (40-47) nonce miner value32bytes (48-79) extra nonce provided in mining.subscribe32bytes (80-111) public key provided in mining.subscribe
mining.subscribe
In order to initiate a session with the server, a client needs to call the subscribe method.
This method call will only be executed by clients.
Request:
{
"id": 1,
"method": "mining.subscribe",
"params": ["MyMiner/1.0.0", ["xel/v2"]]
}id:int: request idmethod:string: RPC method nameparams:[ string, [ string ] ]- MUST be the name and version of the mining software in the given format or an empty string.
- OPTIONAL, specifies a list of supported mining algorithms. If omitted, a default algorithm
xel/v2or the most recent algorithm will be used. As of 7/11/2024 XELIS only supports one algoxel/v2
Miners please use xel/v2
Pool operators, for backwards compatibility, you should also support xel/1. The stratum protocol originally used xel/0 and xel/1 but the node uses xel/v1 and xel/v2. As a pool operator, if a miner sends xel/1 you should consider this to be xel/v2
Response
{
"id": 1,
"result": [
"ABC123",
"EXTRANONCE",
32,
"7e40899c7bcc885fad6dd3bdc68fa73141c1d8b917a1f399afeb1fb191376b16"
]
}id:int: request idresult:[ string, string, int, string ]:- This SHOULD be a unique session id
- Extra nonce for the miner to use (in hex format)
- The length of the extra nonce in bytes
- The public key to use (in hex format)
mining.authorize
Before a client can submit solutions to a server it MUST authorize at least one worker.
This method call will only be executed by clients.
Request
{
"id": 2,
"method": "mining.authorize",
"params": ["xel:WALLET_ADDRESS", "WORKER_NAME", "WORKER_PASSWORD"]
}id:int: request idmethod:string: RPC method nameparams:[ string, string, string ]- The miner wallet address
- The worker name
- The worker password
Response
{"id": 2, "result": true }id:int: request idresult:boolean:- MUST be
trueif the worker was authorized - MUST be
falseif the worker was not authorized - If the worker was not authorized, the server MUST respond with an error message
- MUST be
mining.notify
The notify call is used to supply a worker with new work to be processed.
This method call will only be executed by the server.
Request
{
"id": 1,
"method": "mining.notify",
"params": [
"abc123",
"19726D97F49",
"d9da51a0c3f8a1784911d370fdb617ea7f41581f5059d31e35f176b85efa5570",
"xel/0",
true
]
}id:int: request idmethod:string: RPC method nameparams:[ string, int, string, string, bool ]- Job ID
- Timestamp milliseconds (in hex format)
- Header work hash (
32bytes) - Blake3 hash of the block header (immutable) - Algorithm name
- A boolean indicating whether the miners job queue should be emptied or not (“clean jobs”)
- Majority of the time this is meant for signifying to the miner that the block they are mining has already been found, and they should start mining on a new block height.
Miner should use the timestamp and header work hash to generate the MinerWork Structure, updating the nonce until a solution is found and then submit the nonce from any solutions found (below in mining.submit).
Response
There is no explicit response for this call.
mining.submit
With this method a worker can submit solutions for the mining puzzle. This method call will only be executed by clients.
Request
{
"id": 4,
"method": "mining.submit",
"params": [
"WORKER_NAME",
"abc123",
"0011223344556677"
]
}id:int: request idmethod:string: RPC method nameparams:[ string, string, string ]parameters- Worker name
- Job ID
- Miner nonce (in hex format)
Response
{"id": 4, "result": true}id:int: request idresult:bool: submission accepted- MUST be
trueif accepted
- MUST be
mining.set_difficulty
The target difficulty for a share can change and a server needs to be able to notify clients of that.
This method call will only be executed by the server.
Request
{
"id": 1,
"method": "mining.set_difficulty",
"params": [1]
}id:int: request idmethod:string: RPC method nameparams:[ int ]:- The target difficulty
Any subsequent jobs started by a client after receiving this update MUST honor the new target and servers will reject any shares below this difficulty.
This SHOULD be followed by a mining.notify call.
Response
There is no explicit response for this call.
mining.set_extranonce
The extra nonce for a share can change and a server needs to be able to notify clients of that.
This method call will only be executed by the server.
Request
{
"id": 1,
"method": "mining.set_extranonce",
"params": ["EXTRANONCE", 32, "PUBLIC KEY"]
}id:int: request idmethod:string: RPC method nameparams:[ string, int, string ]:- New extra nonce to use (in hex format)
- The length of the extra nonce in bytes
- New public key to use (in hex format). New public key parameter is optional and mandatory only if changed.
NOTE: If you don’t want to update the public key, you can just send 2 parameters: ["EXTRANONCE", 32].
Any subsequent jobs started by a client after receiving this update MUST honor the new extranonce and public key.
Servers will reject any shares below difficulty.
This SHOULD be followed by a mining.notify call.
Response
There is no explicit response for this call.
mining.ping
With this method a pool can check if a miner connection is still alive. This method call will only be executed by servers.
Request
{"id": 4, "method": "mining.ping"}id:int]: request idmethod:string]: RPC method name
Response
No response is required for this call. The client should respond with a mining.pong call.
mining.pong
With this method a client/miner can respond to signify that the connection is still alive. This method call will only be executed by clients.
Request
{"id": 4, "method": "mining.pong"}id:int]: request idmethod:string]: RPC method name
Response
No response is required for this call.
Optional
The methods below are optional, but preferred.
mining.print
With this method a server can send a message to the miner to print on screen.
Request
{"id": 4, "method": "mining.print", "params": [0, "Your wallet address is invalid, please check before attempting to reconnect."]}id:int]: request idmethod:string]: RPC method nameparams: (int,string) ]: list of method parameters- Print level
- Message to print
Print Levels
0- Information1- Warning2- Error3- Debug
Response
No response is required for this call.
mining.hashrate
With this method a client/miner can submit the reported hashrate (in miner) to the pool (similar to eth_submitHashrate in ethash).
Request
{"id": 4, "method": "mining.hashrate", "params": [1000]}id:int]: request idmethod:string]: RPC method nameparams: (int,string) ]: list of method parameters- Reported hashrate in H/s
Response
No response is required for this call.