Skip to content

Decred Getwork over Stratum

Tanguy Pruvot edited this page Apr 15, 2016 · 6 revisions

As reference : https://en.bitcoin.it/wiki/Stratum_mining_protocol

mining.subscribe

mining.subscribe("user agent/version"[, "extranonce1"])

The optional second parameter specifies a mining.notify subscription id the client wishes to resume working with (possibly due to a dropped connection). If provided, a server MAY (at it’s optional) issue the connection the same extranonce1. Note that the extranonce1 may be the same (allowing a resumed connection) even if the subscription id is changed!

The client receives a result:

[[["mining.notify", "subscription id"]], "extranonce1", extranonce2_size]

mining.submit

mining.submit("username", "JobId", "ExtraNonce2", "nTime", "nonce")

Miners submit shares using the method "mining.submit". Client submissions contain:

  • Worker Name.
  • Job ID.
  • ExtraNonce2 <in our protocol, decred extradata field>
  • nTime.
  • nonce.
  • votebits (optional)

mining.notify

[“id”:null, “method”:"mining.notify","params":[“JobId”,“prevhash”,“header”,“”,[],"Version", ”Bits”,”Time”,bClean]

The unsolicited mining.notify message is a push of new work data from the pool server to the miner. It is broadcasted to all miners when a change is detected in the wallet block data. That can happen on several events, like the introduction of new transactions, on a new block or on new votes in the case of decred.

See bellow the description of the fields with a real data exchange.

The difference with the “official” stratum protocol (which doesn’t exist, cf. Wiki) is in this data. With the other crypto currencies which doesn’t allow custom extra data, the stratum protocol uses a complicated hashing mechanism (merkle tree) to handle some layers of extra data but which also requires to transmit to all the encoded transactions (in the red array field).

So, as we don’t need all that in decred (it can be huge), we transmit, like getwork, the block data which require to be hashed. Unicity of the hashed solutions against the miners is handled by the unique authentication extranonce, which initialise the extradata field. Also, on a multithreaded miner (multi cpus/gpus), each thread id is statically inserted in this extradata (one byte is enough for that) and then incremented until a new stratum job is received.

Sample decred simplified stratum transaction

> {"id": 1, "method": "mining.subscribe", "params": ["ccminer/1.7.4"]}
< {"id":1,"result":[[["mining.notify","53cc83d33ce84ef81b332de26a64ea74"]],"0000000000000000e3001a62",12],"error":null}
> {"id": 2, "method": "mining.authorize", "params": ["DsUCcACGcyP8McNMRXQwbtpDxaVUYLDQDeU", "ubuntu"]}
< {"id":2,"result":true,"error":null}
> {"id": 3, "method": "mining.extranonce.subscribe", "params": []}
< {"id":3,"result":true,"error":null}
2 miner threads started, using 'decred' algorithm.
< {"id":null,"method":"mining.set_difficulty","params":[1]}
Stratum difficulty set to 1
< {"id":null,"method":"mining.notify","params":["222","78785d382baf93f926e53caa17d43baf8f642cf73b55e238000019cf00000000","eec4104cd637d4cce5e79dd75108885145208cfe80982e536e7f16fd4114d96a91a2bb54c29a4d5b1feb1577880f97158be602a42f80bf5b12a14bfa927cee810100c9eee649eede05000000cfa400006047411a3e79683700000000291b000026080000627ad7560000000000000000","",[],"01000000","1a414760","56d77a62",true]}
< {"id":null,"method":"mining.notify","params":["223","78785d382baf93f926e53caa17d43baf8f642cf73b55e238000019cf00000000","eec4104cd637d4cce5e79dd75108885145208cfe80982e536e7f16fd4114d96a91a2bb54c29a4d5b1feb1577880f97158be602a42f80bf5b12a14bfa927cee810100c9eee649eede05000000cfa400006047411a3e79683700000000291b000026080000a17ad7560000000000000000","",[],"01000000","1a414760","56d77aa1",true]}
> {"method": "mining.submit", "params": ["DsUCcACGcyP8McNMRXQwbtpDxaVUYLDQDeU", "223", "0100000000b06355e3001a62", "56d77aa1", "114b0667"], "id":4}
< {"id":4,"result":true,"error":null}
accepted: 1/1 (100.00%), 1336.09 MH/s yes!

Legend : extranonce + len (12 bytes in this sample), prev hash (32 bytes), block header (112 bytes), version (4 bytes), nbits (4 bytes), ntime (4 bytes) and the common nonce (4 bytes)

Note than the block header data (like ntime and nbits) should not be altered, an endian test could be done against the version or on nbits/ntime fields to detect this special kind of simplified stratum. But the easiest method is to detect the empty coinb2 string (the one before the transactions array).

In the current protocol draft, only the prevhash and version fields need a reversed 32bit (dword) endian adjustment on the miner side, it should have been done differently at the initial implementation, but was kept due to unsolicited releases on my current work via the cryptomining-blog web site. That means the header and the extradata can be a direct memcpy in the work data structure. see https://github.com/tpruvot/ccminer/blob/1.7.4-tpruvot/ccminer.cpp#L1381-L1402

Current extradata usage

In the above sample, we are using 12 bytes of the extradata field. This size can be adjusted later for vote or any other new requirements. Actually, the decred cgminer is using a complicated hash to fill the 2 first uint32. We do the same in ccminer in the getwork mode with an automatic increment and a static thread id.

"01000000 00b06355 e3001a62"

In the “getwork over stratum” method, the third field is only modified by the pool which can optionally require the same value in all submitted results. On yiimp This field contain an unique server id byte, here “e3” on yiimp.ccminer.org server and a 3 bytes worker counter (incremented on each new authentication).

The two first fields are customizable by the miners, but in ccminer the first uint32 acts as an extranonce counter and the second contains a thread id byte and and 3 random bytes per work (changed on each stratum job).

Optional vote field

In addition, there is an optional 6th field (used only with the --vote argument in 1.7.6+). The same vote submit method was used in the HeavyCoin currency.

> {"method": "mining.submit", "params":
> ["DsUCcACGcyP8McNMRXQwbtpDxaVUYLDQDeU", "223", "0100000000b06355e3001a62", "56d77aa1", "114b0667", "0001"],
> "id":4}