Skip to content

Echelon Protocol

Version 1.0.4
The echelon specification repository can be found here.

The stratum protocol is used by ASIC miners, devices created specifically for performing Bitcoin mining.

The echelon protocol is a modified version of the stratum v1 protocol for mining nexa.

Miners use the echelon protocol to reach out to one or more servers (e.g. a mining pool) in order to obtain a mining candidate for a new block. The miner tests solutions by increasing the nonce until a candidate block that meets the specified difficulty requirements is successfully created.

Message Format

Echelon uses the JSON-RPC 2.0 message format. That is, JSON-encoded messages, separated by newline (line feed) characters. There are two high-level message formats: requests and responses.

Requests

Requests all contain the following fields:

Field Format Description
id number or string A message ID that must be unique per request that expects a response. For requests not expecting a response (called notifications), this is null.
method string Indicates the type of request the message represents.
params array Additional data which varies based on the request method.

Responses

Responses all contain the following fields:

Field Format Description
id number or string The ID of the request that this message is a response to.
result any Data being returned in response to the request. Must be present, but may be a string, number, array, object, or null.
error error array Indicates that the request could not be fulfilled and provides information about what went wrong.

Error Array Format

The error array is a JSON array containing the following elements:

Field Format Description
error code number An error code indicating the type of error.
message string A description of the error.
data object Additional data associated with the error (nullable).

Example error: {"result":null,"id":2,"error":[24,"Unauthorized worker",null]}

Beyond those specified by JSON-RPC, the following error codes are used:

Code Description
20 Other/Unknown
21 Job not found (=stale)
22 Duplicate share
23 Low difficulty share
24 Unauthorized worker
25 Not subscribed

Echelon Protocol Flow

Client                                Server   
  |                                     |   
  | --------- mining.subscribe -------> |   
  | --------- mining.authorize -------> |   
  | <-------- mining.set_difficulty --- |   
  |                                     |----   
  | <---------- mining.notify --------- |<--/   
  |                                     |   
  | ---------- mining.submit ---------> |   

Full Protocol

Client Methods

mining.subscribe

Upon connecting to a server, clients are expected to send a subscribe request, described as follows.

Field Format Description
method string "mining.subscribe"
params[0] - user_agent_version string User agent name and version, separated by a forward slash (e.g. "nxminer/2.0.0").

Example request: {"id": 1, "method": "mining.subscribe", "params": ["nxminer/2.0.0"]}

In response, the server will send the following data in its result object, which is a JSON array:

Field Format Description
subscriptions array An array containing sub-array that described intended subscriptions. The first value in sub-arrays is the subscription type (e.g. "mining.set_difficulty"), the second is a subscription ID.
extranonce string The 64 bit big endian hex encoded value that is to be used the first 8 bytes of the solution nonce.
extranonce2_size int The number of bytes that the miner users for its extranonce2 counter.

Example response: {"result":[[["mining.set_difficulty", 0.1 ]],"0000000000000001", 8],"id":1,"error":null}

mining.authorize

In order to authenticate itself, the client send an authorize message:

Field Format Description
method string "mining.authorize"
params[0] - username string The client's user name.
params[1] - password string The client's password (if required by the server).

Example request: {"id": 1, "method": "mining.authorize", "params": ["username", "p4ssw0rd"]}

Response format:

Field Format Description
result boolean The value true if the client has been authorized; false otherwise.

Example response: {"id": 2, "result": true, "error": null}

mining.submit

Once the client has completed a job (received via mining.notify following an accepted mining.authorize), it returns its result using a submit message. This message is also used to submit shares to a mining pool. The format is as follows:

Field Format Description
method string "mining.submit"
params[0] - username string The client's user name.
params[1] - job_id string The job ID for the work being submitted.
params[2] - solution_nonce string A 128 bit hex encoded value where the first 64 bits are the extranonce and the second 64 bits are the miner nonce.
params[3] - time string The 64 bit big endian hex-encoded value of the time. (same value as received in mining.notify)

Example request: {"id": 1, "method": "mining.submit", "params": ["username", "4f", "000000000000000100003e05486566fd", "0000000063b1fb60"]}

Response format:

Field Format Description
result boolean The value true if the submission has been accepted; false if it was rejected.

Example response: {"id": 2, "result": true, "error": null}

mining.suggest_difficulty(preferred share difficulty Number)

Used to indicate a preference for share difficulty to the pool. Servers are not required to honour this request, even if they support the stratum method.

Server Methods

mining.notify

Once a client successfully connects using the mining.subscribe and mining.authorize messages, the server may send a job to the client, informing it of everything it needs to know in order to mine a new block. The notify message is a notification (does not expect a response) and has the following format:

Field Format Description
method string "mining.notify"
params[0] - job_id string The job ID for the job being sent in this message.
params[1] - header_commitment string The 256 bit big endian hex-encoded header commitment.
params[2] - nbits string The 32 bit big endian hex-encoded network difficulty required for the block.
params[3] - time string The 64 bit big endian hex-encoded current time for the block.
params[4] - clean boolean string (true/false) Indicates whether the client should forget any prior jobs. If true, the server will reject any submissions for prior jobs and the miner should forget any prior job IDs so that they can be reused by the server.

Example request: {"id": null, "method": "mining.notify", "params": ["4f", "e9c64cfd6711c5eaa8d20dc4c4a430b1e22141ecc1ad701471492420432d8a4b", "1b02fab2", "0000000063b1fb60", false]}

mining.set_difficulty

The server can adjust the difficulty required for miner shares with the "mining.set_difficulty" method. The miner should begin enforcing the new difficulty on the next job received. Some pools may force a new job out when set_difficulty is sent, using clean_jobs to force the miner to begin using the new difficulty immediately.

Field Format Description
method string "mining.set_difficulty"
params[0] - new_difficulty number The new difficulty threshold for share reporting. Shares are reported using the mining.submit message.

Example request: { "id": null, "method": "mining.set_difficulty", "params": [2]}

mining.set_extranonce

These values, when provided, replace the initial subscription values beginning with the next mining.notify job.

Field Format Description
method string "mining.set_extranonce"
params[0] - extranonce1 string The new 64 bit big endian hex encoded value that is to be used the first 8 bytes of the solution nonce.
params[1] - extranonce2_size number The new size of extranonce2.

Example request: { "id": null, "method": "mining.set_extranonce", "params": ["0000000000000002", 8]}

Full hashing examples

NexaPow uses the following C++ code to calculate mining hashes

// CHashWriter is a sha256 class that runs a double sha256 hash
CHashWriter ret(SER_GETHASH, 0);
// push header_commitment then the nonce into the hashing buffer
ret << header_commitment << nonce;
// returns a double sha256 for the mining_hash
uint256 mining_hash = ret.GetHash();

// h1 is a single sha256 of the mining_hash
uint256 h1 = sha256(mining_hash);
// make a private key
CKey k;
// Use mining_hash as a private key
k.Set(mining_hash.begin(), mining_hash.end(), false);
if (!k.IsValid())
{
    // If key is invalid, POW fails
    return false;
}
// byte array for signature
std::vector<uint8_t> vchSig;
// generate a signature from the h1 hash
if (!k.SignSchnorr(h1, vchSig))
{
    return false; // Signing h1 with mining_hash failed
}

uint256 final_hash;
// CSHA256 is a sha256 class that runs a single sha256
CSHA256 sha;
// write the signature to the hash buffer
sha.Write(&vchSig[0], vchSig.size());
// single sha256 the signature bytes to get back to 32 bytes, store this hash in final_hash
sha.Finalize(final_hash.begin());

// final_hash is the the final result to be returned
return final_hash;

The mining pool provides the miner with header_commitment hash 0a4ac49b2d02e3c8d12c7093255ba7c49624f9c374d9f1c2f8e37c58705e74b0 and mining nonce 10000000000000001182dc5800000000.

When these two values are used in the NexaPoW algorithm, the final result produced should be 00000042cbc240375242e14641488a0e2dca7b54458a2cea23dc1d2c178bb188.

To assist with debugging this algorithm these are the different intermediary hashes and signature produced by the algorithm above.

Please note hashes are printed in big endian but internally should be little endian.

mining_hash: 7077c3549e088001ff681c2291bbc171f6ea681b5bc79bca9f2e0f563ad3dfef

h1: f97e4711d32f29f4f9f3aa254290eaf486330b3b43507cc03ba93b596c6cce36

vchSig: 93bb5bd98bb9d0817c5594782d4648a995e76755a3c94fdd96673115a06b8483efe485e73c1e4732ce9c34ef6891e7f25ff7c080aacbf71660bf782b067bc4f1

final_hash: 00000042cbc240375242e14641488a0e2dca7b54458a2cea23dc1d2c178bb188

Another example using pool provided header_commitment hash 0a4ac49b2d02e3c8d12c7093255ba7c49624f9c374d9f1c2f8e37c58705e74b0 and mining nonce 1000000000000000b787915d00000000.

mining_hash: 5cddd556e7972ee8b3e4ce01f954336cbb223813c1f01c768f299b82f20a0ea9

h1: 6c55ec4a361007edaf6561e20a2eccfb51572309f66bf7b04aea315fadc039f9

vchSig: fc1894a100e6b33d19abac5289403b4c942d75d061b5453904be740681526cae30ed3a59f1a9d3ca165151ddb1ca3069de832cd5cc5fc95a7339f058f1fd155b

final_hash: 0000005f0b59e110863566e77d85e1b4fc713754e5c75f8fc3df44133866a669