diff --git a/EthereumStratum_NiceHash_v1.0.0.txt b/EthereumStratum_NiceHash_v1.0.0.txt new file mode 100644 index 0000000..ce5188a --- /dev/null +++ b/EthereumStratum_NiceHash_v1.0.0.txt @@ -0,0 +1,365 @@ +------------------------------------------------------------------------- + NiceHash presents +========================================================================= + Ethereum stratum mining protocol v1.0.0 +========================================================================= +revision of this document: R2 + +I. Introduction +II. Concept +III. Specifications (RFC) +IV. Real world scenario +V. Planned improvements +VI. Contact + + +I. Introduction +--------------- + +Ethereum does not have official stratum protocol. It supports only +GetWork, which is very resource hoggy as miners need to constantly +poll pool to obtain possible new work. GetWork thus affects performance +of miners and pools. Due to demand for more professional Ethereum +mining, several versions of "stratum" for Ethereum emerged. These +"stratums" utilize GetWork on server side (pool side) to obtain work, +which would be fine, if careful considerations and precautions were +taken when creating such protocols. But this was not done. Issues of +these protocols are following: + +1. No unique data per miner/worker. Extranonce is ignored (but still +sent). Each miner gets seedhash (which is always the same for every +30k blocks) and headerhash (which changes every block). Then miner uses +these two values and own nonces to generate hashes. Miners may be +doing duplicate work (if they choose same nonces). + +2. Difficulty redundancy. Difficulty is sent in mining.notify message +as a third parameter named target. This is not needed, because miners +can calculate target hash on their own out of provided difficulty. + +3. Overall data redundancy. There are several fields that are not needed +to be sent over network. Firstly; if extranonce is not used, it does not +have to be sent. Secondly; seedhash changes every 30k blocks - there is +no need to send it with every mining.notify. Thirdly; as already pointed +out in 2 - target in mining.notify is redundant as set_difficulty is +being used. Fourthly; mining.submit actually only needs to send nonce. +Pool needs to verify nonce for validity and will calculate hash and +mixhash. Bandwidth usage can be easily reduced by 50% or more if removing +all mentioned redundancies. + +4. There are some inconsistencies compared to original slush's stratum +specifications. One of them are ids. Ids should increase so that the pool +can keep track of data being received. Another thing are HEX marks '0x' +starting with each string field. This is, again, redundant and we will +save some bandwidth if not using them. + +5. No specifications, only projects with implemented solutions. This +usually lead to several similar versions of protocol; exactly what +happened. + +Our goal is to make a solid, non-redundant, bullet-proof stratum mining +protocol for Ethereum that does not have issues pointed out above. + + +II. Concept +----------- + +Ethereum's GetWork gives us 3 values: + +{ ... "result":[ +"0x645cf20198c2f3861e947d4f67e3ab63b7b2e24dcc9095bd9123e7b33371f6cc", +"0xabad8f99f3918bf903c6a909d9bbc0fdfa5a2f4b9cb1196175ec825c6610126c", +"0x0000000394427b08175efa9a9eb59b9123e2969bf19bf272b20787ed022fbe6c" +]} + +First value is headerhash, second value is seedhash and third value is +target. Seedhash is used to identify DAG file, headerhash and 64 bit +nonce value chosen by our miner give us hash, which, if below provided +target, yield block/share. + +Since nonce is 64 bit (8 bytes) wide and considering very bad possible +scenario, that Ethereum does not find a block in 5 minutes time, 8 bytes +of nonce can support miner with speed of up to: + + (2^64 / 300) / 1G ~ 61,489,147 GH/s + +This is a very big number so we can easily consider taking some bytes off +for our stratum protocol. + + --------------------------------------- + | Bytes | Max supported hashing speed | + | 8 | ~61,489,147.000 GH/s | + | 7 | ~240,192.000 GH/s | + | 6 | ~938.000 GH/s | + | 5 | ~3.665 GH/s | + | 4 | ~0.014 GH/s | + --------------------------------------- + +Having only 4 bytes for nonce is not an option, since we already have +miners capable of reaching 14 MH/s and more. Nonce width of 5 bytes +allows max speed of 3.665 GH/s which shall be enough for quite some time, +even if ASICs arrive. + +The miner needs to get seedhash, headerhash, difficulty and part of +nonce (called extranonce) from pool. Miner chooses on it's own second +part of the nonce (called minernonce). Extranonce glued with minernonce +gives us 64 bit Ethereum nonce. + + +III. Specifications (RFC) +------------------------- + +Handshake happens after TCP connection is established from miner to the +pool. Miner sends data first: + +{ + "id": 1, + "method": "mining.subscribe", + "params": [ + "MinerName/1.0.0", "EthereumStratum/1.0.0" + ] +}\n + +First parameter is miner name and version (as with standard stratum +protocol). Second parameter must be "EthereumStratum/Version" where +Version is version of EthereumStratum miner is using according to this +document's version. If pool does not support this version, it may +terminate the connection or respond back with error. + +Note that miner iterates ids and can start with any number. Each message +from miner to the pool needs to have unique id for miner to properly read +responses as pool may not process miner's messages in FIFO manner. + +Server replies back: + +{ + "id": 1, + "result": [ + [ + "mining.notify", + "ae6812eb4cd7735a302a8a9dd95cf71f", + "EthereumStratum/1.0.0" + ], + "080c" + ], + "error": null +}\n + +Response is almost the same as with standard stratum protocol with +following differences; Third parameter of first parameter of result array +is "EthereumStratum/Version"; If pool does not report this parameter or +version is different than supported by miner, miner can expect +compatibility issues and should terminate connection. Second parameter +of result array is extranonce (in HEX) set by pool. There is no third +parameter, because there is no extranonce2 (as with standard stratum). +Extranonce may be max 3 bytes in size. + +Miner shall authorize during initial handshake; this is done the same way +as in standard stratum protocol and will not be explained here in +details. + +Before first job (work) is provided, pool MUST set difficulty by sending: + +{ + "id": null, + "method": "mining.set_difficulty", + "params": [ + 0.5 + ] +}\n + +First item of params array is difficulty in double data type. Conversion +between difficulty and target is done the same way as with Bitcoin; +difficulty of 1 is transformed to target being in HEX: +00000000ffff0000000000000000000000000000000000000000000000000000 + +If pool does not set difficulty before first job, then miner can assume +difficulty 1 was being set. + +When difficulty is changed, miner starts using new difficulty for every +NEXT job that arrives. + +If miner has subscribed to extranonce notifications (detailed explanations +is here: https://www.nicehash.com/?p=software#devs), then pool may change +miner's extranonce by sending: + +{ + "id": null, + "method": "mining.set_extranonce", + "params": [ + "af4c" + ] +}\n + +New extranonce is valid for all NEXT jobs sent by the pool. + +Pool informs miners about job (work) by sending: + +{ + "id": null, + "method": "mining.notify", + "params": [ + "bf0488aa", + "abad8f99f3918bf903c6a909d9bbc0fdfa5a2f4b9cb1196175ec825c6610126c", + "645cf20198c2f3861e947d4f67e3ab63b7b2e24dcc9095bd9123e7b33371f6cc", + true + ] +}\n + +First parameter of params array is job ID (must be HEX number of any +size). Second parameter is seedhash. Seedhash is sent with every job to +support possible multipools, which may switch between coins quickly. +Third parameter is headerhash. Last parameter is boolean cleanjobs. +If set to true, then miner needs to clear queue of jobs and immediatelly +start working on new provided job, because all old jobs shares will +result with stale share error. + +Miner uses seedhash to identify DAG, then tries to find share below +target (which is created out of provided difficulty) with headerhash, +extranonce and own minernonce. + +When share below target is found, miner submits it to the pool: + +{ + "id": 244, + "method": "mining.submit", + "params": [ + "username", + "bf0488aa", + "6a909d9bbc0f" + ] +}\n + +Second parameter of params array is job ID, third parameter is +minernonce. Note in above example that minernonce is 6 bytes, because +provided extranonce was 2 bytes. If pool provides 3 bytes extranonce, +then minernonce must be 5 bytes. + +For every work submit, pool needs to respond back with standard stratum +response: + +{ + "id": 244, + "result": true, + "error": null +}\n + +Or if share was not accepted (standard stratum response): + +{ + "id": 244, + "result": false, + "error": [ + -1, + "Job not found", + NULL + ] +}\n + + +IV. Real world scenario +----------------------- + +Miner connects to the pool and sends: +{ + "id": 1, + "method": "mining.subscribe", + "params": [ + "EthereumMiner/1.0.0", "EthereumStratum/1.0.0" + ] +}\n + +Pool responds: +{ + "id": 1, + "result": [ + [ + "mining.notify", + "ae6812eb4cd7735a302a8a9dd95cf71f", + "EthereumStratum/1.0.0" + ], + "a2eea0" + ], + "error": null +}\n + +Miner then authorize: +{ + "id": 2, + "method": "mining.authorize", + "params": [ + "test", + "password" + ] +}\n + +And pool confirms: +{ + "id": 2, + "result": true, + "error": null +}\n + +Pool sends difficulty: +{ + "id": null, + "method": "mining.set_difficulty", + "params": [ + 1.0 + ] +}\n + +And job: +{ + "id": null, + "method": "mining.notify", + "params": [ + "bf0488aa", + "abad8f99f3918bf903c6a909d9bbc0fdfa5a2f4b9cb1196175ec825c6610126c", + "fc12eb20c58158071c956316cdcd12a22dd8bf126ac4aee559f0ffe4df11f279", + true + ] +}\n + +After a while, miner finds share and submits it: +{ + "id": 3, + "method": "mining.submit", + "params": [ + "test", + "bf0488aa", + "cfae7df760" + ] +}\n + +Response from the pool: +{ + "id": 3, + "result": true, + "error": null +}\n + +The share was valid considering data: +seedhash=abad8f99f3918bf903c6a909d9bbc0fdfa5a2f4b9cb1196175ec825c6610126c +headerhash=fc12eb20c58158071c956316cdcd12a22dd8bf126ac4aee559f0ffe4df11f279 +nonce=a2eea0cfae7df760 + +Result is share with difficulty of 1.863 which is above 1.0. + + +V. Planned improvements +----------------------- + +Ethereum has RPC method eth_getBlockByNumber which can return some data about +next block that is yet to be mined. Among data is next block number (block +height). This number could be used instead of seedhash; every miner would then +calculate seedhash on it's own thus bandwidth usage would be reduced even more. + +There are plans to make eth_getBlockTemplate method. When this is made, this +stratum protocol may get very similar to standard stratum. + + +VI. Contact +----------- + +www.nicehash.com +info@nicehash.com