API
Stratum Protocol

XELIS Stratum Protocol

Version: 0.1.1
Last Updated: 5/5/2024
Authors: Vipor.net (opens in a new tab)

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 (opens in a new tab).

The stratum protocol mostly adheres to the JSON RPC 2.0 (opens in a new tab) 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 (opens in a new tab).

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

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 : int
  • message : string
  • data : 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/Unknown
  • 21 - Job not found (=stale)
  • 22 - Duplicate share
  • 23 - Low difficulty share
  • 24 - 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

  • 112 bytes total
  • 32 bytes (0-31) Header work hash
  • 8 bytes (32-39) timestamp provided in mining.notify
  • 8 bytes (40-47) nonce miner value
  • 32 bytes (48-79) extra nonce provided in mining.subscribe
  • 32 bytes (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 id
  • method : string: RPC method name
  • params : [ string, [ string ] ]
    1. MUST be the name and version of the mining software in the given format or an empty string.
    2. OPTIONAL, specifies a list of supported mining algorithms. If omitted, a default algorithm xel/v2 or the most recent algorithm will be used. As of 7/11/2024 XELIS only supports one algo xel/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 id
  • result : [ string, string, int, string ]:
    1. This SHOULD be a unique session id
    2. Extra nonce for the miner to use (in hex format)
    3. The length of the extra nonce in bytes
    4. 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 id
  • method : string: RPC method name
  • params : [ string, string, string ]
    1. The miner wallet address
    2. The worker name
    3. The worker password

Response

{"id": 2, "result": true }
  • id : int: request id
  • result : boolean:
    • MUST be true if the worker was authorized
    • MUST be false if the worker was not authorized
    • If the worker was not authorized, the server MUST respond with an error message

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 id
  • method : string: RPC method name
  • params : [ string, int, string, string, bool ]
    1. Job ID
    2. Timestamp milliseconds (in hex format)
    3. Header work hash (32 bytes) - Blake3 hash of the block header (immutable)
    4. Algorithm name
    5. 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 id
  • method : string: RPC method name
  • params : [ string, string, string ] parameters
    1. Worker name
    2. Job ID
    3. Miner nonce (in hex format)

Response

{"id": 4, "result": true}
  • id : int: request id
  • result: bool: submission accepted
    • MUST be true if accepted

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 id
  • method : string: RPC method name
  • params : [ int ]:
    1. 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 id
  • method : string: RPC method name
  • params : [ string, int, string ]:
    1. New extra nonce to use (in hex format)
    2. The length of the extra nonce in bytes
    3. 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 id
  • method : 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 id
  • method : 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 id
  • method : string ]: RPC method name
  • params : (int, string) ]: list of method parameters
    1. Print level
    2. Message to print

Print Levels

  • 0 - Information
  • 1 - Warning
  • 2 - Error
  • 3 - 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 id
  • method : string ]: RPC method name
  • params : (int, string) ]: list of method parameters
    1. Reported hashrate in H/s

Response

No response is required for this call.