- Feature Name: Stratum
- Start Date: 2019-01-04
- RFC PR:
- Hathor Issue:
Summary
Stratum is a protocol that allows efficient communication between miner clients and servers. From the Stratum homepage:
In a simplified manner, Stratum is a line-based protocol using plain TCP socket, with payload encoded as JSON-RPC messages.
That's all. Client simply opens TCP socket and writes requests to the server in the form of JSON messages finished by the newline character.
Every line received by the climient is again a valid JSON-RPC fragment containing the response.
This proposal introduces a Stratum protocol for Hathor and discusses the implementation of a Stratum server embedded on Hathor node.
Motivation
The major motivation to introduce Stratum in Hathor is allowing separation between mining client from Hathor core, providing a clear API for miners to talk efficiently to Hathor nodes and mining pools.
Guide-level explanation
Stratum allow mining (or stratum) clients to get and submit mining jobs to a stratum server.
To subscribe to mining jobs, miner should create a JSON RPC 2 subscribe
request, e.g.:
{
"id":"2085195499",
"jsonrpc":"2.0",
"method":"subscribe",
"params":{"mine_txs":true}
}
Server should be able to answer the request - asking for credentials or saying that everything is all right:
{
"id":"2085195499",
"jsonrpc":"2.0",
"result": "ok
}
And also send a new job
request to the miner:
{
"method":"job",
"result":{
"weight":27.235,
"job_id":1949732007,
"data":"e67be79550661604d9b9c646911c80d74f6c691613224c207fa7088c20698acd",
"nonce_size":16
}
}
Miner should look for a solution to the desined job. The client should look for a nonce_size
byte nonce
such that sha256d
function of the concatenation of data
and nonce
meets the target difficulty. Target difficulty diff
can be calculated from weight
using the formula diff = 2^(256 - weight) - 1
.
To notify the client of new jobs, the server sends new job
messages:
{
"jsonrpc":"2.0",
"method":"job",
"params":{
"weight":21,
"job_id":784707720,
"hash":"fba8f8b8821a83361c9c7567441b45c10bb4ce421997ff9cfc8d52fbceff0292",
"nonce_size":4
}
}
Since there is no id
field on the message, the client should not create any response for this request - it is just a notification.
When the miner finds a solution to the job
, it should submit
it:
{
"id":"42",
"jsonrpc":"2.0",
"method":"submit",
"params":{
"job_id":784707720,
"nonce":1200613,
}
}
The server should check if the solution indeed meets the dificulty and answer:
{
"id":"42",
"jsonrpc":"2.0",
"result":"ok",
}
Reference-level explanation
All messages should conform with the JSON-RPC 2.0 Specification.
This means that every messsage is a JSON object terminated by a \n
character and may contain the following fields:
Field | Content |
---|---|
id | ID of the request |
jsonrpc | "2.0" |
id
field should be a random 64
-bit integer. Requests without this field are notifications. They are not suposed to be answered.
All requests should also contain the fields:
Field | Content |
---|---|
method | Stratum method id |
params | nullable structured value containing the request parmameters |
And all the responses can have either - but never both:
Field | Content |
---|---|
result | nullable structured value containing result data |
error | Object containing error code and message |
Client to Server
subscribe
Miner subscribe for job notifications.
params
should be either null
or {}
if empty. If not empty, they may contain the following:
Field | Type | Content |
---|---|---|
mine_txs (optional) | bool | Enable mining of transactions (which yield no reward). When not present defaults to true. |
Request:
{
"id":"39821739821",
"jsonrpc":"2.0",
"method":"subscribe",
"params":null
}
Response:
{
"id":"39821739821",
"jsonrpc":"2.0",
"result": "ok
}
Errors may include messages with code 10
and 20
- see Error Messages secion for further details
.
submit
Miner submits a complete mining job. params
should contain:
Field | Type | Content |
---|---|---|
job_id | int | 64 -bit integer that identifies the job |
nonce | string | String that contains the nonce that solves the job |
Note that the nonce size depends on the type of the job. nonce_bytes = block_job ? 16 : 4
.
Request:
{
"id":"2312398",
"jsonrpc":"2.0",
"method":"submit",
"params":{
"job_id":784707720,
"nonce":1200613,
}
}
Response:
{
"id":"2312398",
"jsonrpc":"2.0",
"result":"ok",
}
Errors may include any of the messages listed in the Error Messages section.
authenticate
Miner authenticates itself with server.
params
should contain:
Field | Type | Content |
---|---|---|
username | string | Integer that identifies the job |
password | string | String that contains the nonce that solves the job |
method | string | password |
If the desired authentication method is password
.
If the miner wants to authenticate using an API key, it should include the fields:
Field | Type | Content |
---|---|---|
key | string | API Key to access server |
method | string | key |
This is not crucial for the communication between miners and servers to be stablished securily. So it won't be implemented in the first version.
Request example:
{
"id":"48971503",
"jsonrpc":"2.0",
"method":"authenticate",
"params":{
"username": "foo",
"password": "bar",
"method": "password"
}
}
Response example:
{
"id":"48971503",
"jsonrpc":"2.0",
"result":"ok",
}
Errors may include messages with code 10
and 21
. See Error Messages section for further information.
Server to Client
job
Server notifies the miner of a new job available. params
should contain:
Field | Type | Content |
---|---|---|
nonce_size | int | Size of the available nonce |
hash | string | Hash to be used as base for the job |
job_id | int | Identifier of the job |
weight | double | weight of the job, used to calculate the difficulty |
Since it is a notification the miner should not answer it.
Request:
{
"jsonrpc":"2.0",
"method":"job",
"params":{
"weight":21,
"job_id":784707720,
"hash":"fba8f8b8821a83361c9c7567441b45c10bb4ce421997ff9cfc8d52fbceff0292",
"nonce_size":4
}
}
Error Messages
Other than the error messages specified in the JSON RPC 2.0 Specification, this protocol defines the following error messages:
Error code | Error Message | Meaning |
---|---|---|
10 | Node syncing | Miner should wait for node to sync to network |
20 | Login required | Miner should authenticate with node |
21 | Authentication failed | Credentials were not accpeted |
30 | Invalid solution | Solution didn't meet required difficulty |
31 | Stale job submited | Job was already stale when submited |
32 | Job not found | Node couldn't find any job with submited id |
33 | Solution propagation failed | Node couldn't propagate the submited solution |
Drawbacks
From the point of view of chosing Stratum as the protocol, there's no major drawbacks of choosing Stratum other than the time spent on implementing it. This does not block any other similar solutions from being implemented since it's just an API.
From the point of view of what is communicated through Stratum, the major drawback that is faced is the fact that the whole serialized transaction is sent right now.
Rationale and alternatives
Other alternatives includes:
Getwork is a legacy protocol - Stratum and Getblocktemplate were developed to take it's place.
Getblocktemplate is a little bit more complicated, but also very similar to Stratum.
Stratum suffices as a standard API for miners to connect to a node, given it's simplicity and wide adoption.
Prior art
As shown in the references sections there are several coins that have Stratum implementation - some which have it natively integrated with the coin. For examples, please refer to References.
Unresolved questions
- Should we change the mining algorithm (e.g. hash the transaction without nonce and then with nonce), to reduce network traffic, allow miners to update timestamp, etc.?
Future possibilities
On the Stratum roadmap:
- Add
authorization
request, response and error messages. - Support pools - get feedback from pools on what is the best way to support them.
- Multi-mining support