Getwork
An RPC method used by a miner to get hashing work to try to solve. It has mostly been superceded by the newer getblocktemplate mining protocol, but the data format is still often used internal to some miner structures.
Protocol
getwork is a JSON-RPC method sent over a HTTP transport. It accepts one optional parameter; if provided, this must be the "data" provided by a prior request modified to meet the server's proof-of-work requirements.
getwork without arguments provides a block header for a miner to find a solution for:
getwork job | |||
---|---|---|---|
Key | Required | Type | Description |
data | String | Pre-processed SHA-2 input chunks, in little-endian order, as a hexadecimal-encoded string | |
target | String | Proof-of-work hash target as a hexadecimal-encoded string | |
algorithm | String | Brief specification of proof-of-work algorithm. Not provided by bitcoind or most poolservers. |
Because the data key has been preprocessed, if you have a generic SHA256 function you must first reverse the pre-processing. This is two steps:
- Because getwork provides the data in little endian, and SHA256 works in big endian, for every 32-bit chunk you need to swap the byte order
- Chop off the SHA-2 padding; for Bitcoin, you can just take the first 80 bytes, but otherwise you can find the correct length (in bits) as the last 64 bits of the (byteswapped) data
So for example, if you receive this data:
000000020597ba1f0cd423b2a3abb0259a54ee5f783077a4ad45fb6200000218 000000008348d1339e6797e2b15e9a3f2fb7da08768e99f02727e4227e02903e 43a42b31511553101a051f3c0000000000000080000000000000000000000000 0000000000000000000000000000000000000000000000000000000080020000
You first byteswap each 32-bit chunk from little-endian to big-endian:
020000001fba9705b223d40c25b0aba35fee549aa477307862fb45ad18020000 0000000033d14883e297679e3f9a5eb108dab72ff0998e7622e427273e90027e 312ba443105315513c1f051a0000000080000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000280
Then read the final 64 bits in big-endian - 0x0000000000000280 = 640 bits = 80 bytes - and chop off everything after that:
020000001fba9705b223d40c25b0aba35fee549aa477307862fb45ad18020000 0000000033d14883e297679e3f9a5eb108dab72ff0998e7622e427273e90027e 312ba443105315513c1f051a00000000
Note that since the result you must provide to getwork submissions is in the same format as data, you must reverse this process when you make your submission.
Many optimizations are possible with SHA256, so running a full SHA256 round is generally inadvisable. Most miners will precompute the SHA256 "midstate" from the first 512-bit chunk of data, and only repeat the 2nd SHA256 round with the final 512-bit chunk (which contains the nonce).
The target is in standard SHA256 order (big endian), but note that Bitcoin target comparisons are done as 256-bit little endian. This means for pdifficulty 1, you want to check that the last 32 bits are zero.
Pseudocode
(Just ignore the midstate until you understand the internals of SHA256.)
calculate: hash = SHA256(SHA256(EndianFlipForEach32Bits(First80BytesOf(data))))
If that meets the difficulty, you win (generated a block or share)!
If not, increment the Nonce that is a number stored in portion of the data that starts 608 bits in (bytes 76 to 79), and try again.
If the incremented portion overflows, get new work (see also rollntime extension).
Extensions
When getting new work, miners should send a X-Mining-Extensions header with a space-delimited list of supported extensions:
hostlist
Original specification from Deepbit
The server may include a X-Host-List header with a list of available servers formatted in JSON as an array of objects with server details. "host" specifies the server's hostname or IP address, "port" specifies a TCP port, and "ttr" is "time to return". If you use server with non-zero ttr you should try to return to the server with 0 ttr after this number of minutes.
Example:
X-Host-List: [{"host":"server.tld","port":8332,"ttr":0},{"host":"backup.tld","port":8332,"ttr":20}]
This string says that "server.tld" is the main server. When you detect connection problems, you need to try the next server - "backup.tld" for 20 minutes and then try to switch back to "server.tld". If the main server is still offline you should continue to use "backup.tld" for another 20 minutes.
Failover workflow:
- Choose the first working server while cycling from left to right
- if "ttr" of the server is greater than zero, go to 1) after this amount of minutes.
longpoll
Original specification from Deepbit
If mining pool does supports Long Polling, it should include a X-Long-Polling header with a relative or absolute URI. The absolute URI may specify a different port than the original connection. Miner must start a request to long polling URI with GET method and same basic authorization as on main connection. This request is not answered by server until it wishes to expire current block data, and new data is ready. The answer is the same as getwork on the main connection. Upon receiving this answer, miner should drop current calculation in progress, discard its result, and start working on received data and make a new request to a long polling URI. There is a 60 second limit before new work should be requested (the normal way) regardless of response from longpoll (though this may be overridden by the rollntime extension below).
midstate
This should be advertised if the miner supports generating its own midstates. In this case, the pool may decide to omit the now-deprecated "midstate" and "hash1" fields in the work response.
noncerange
noncerange discussion forum thread
In addition to X-Mining-Extensions, the miner should also send X-Mining-Hashrate, with an integer value of expected hashrate measured in full hashes per second. The server may then add an additional field to the JSON response, "noncerange", which contains two 32-bit integers specifying the starting and final nonce the miner is allowed to scan. While both values are given in big endian, miners should iterate over the range in their native 32-bit integer type (SHA256 works with 32-bit integers, not character data). The miner should implement rollntime by starting from the first nonce in the range every second.
Example:
"noncerange": "000000001fffffff"
Response:
solution: "...dddddd1f..."
reject-reason
NOTE: Clients should not need to advertise this feature in X-Mining-Extensions.
When a share is rejected, the server may include a X-Reject-Reason header indicating the reason why it was rejected. Values for this header are undefined.
rollntime
rollntime expiration discussion forum thread
Iff the getwork response includes a "X-Roll-NTime" header with any value other than "N" or the null string, the miner may (within reason) change the ntime field in addition to the nonce. The server may send a value of "expire=<N>", where <N> is an integer number of seconds it is willing to accept the other headers for. Note that if the "X-Roll-NTime" header is NOT present in a work response, that work may NOT be rolled, even if earlier work from the same server allowed it. Also note that the headers of a share submission should not influence the behaviour of work-- specifically, if a share submit does not have the header, it should not disable rollntime for the current work (which did).
Due to network latency, Luke-Jr recommends the following design for miners:
- getwork, record <duration of getwork request> and <time+getwork expire> , and begin mining on it
- every second, update ntime and reset nonce to <first nonce>
- when a share is found, submit it. record the duration of the submit request.
- if a share submission fails due to a network error, save the share and retry it a second later the same as step 3; also immediately (regardless of how long the current work has been active) begin trying to get new work (which is treated the same as step 5+6 when done)
- when current time is past <time@1+getwork expire> minus <duration of longest getwork/submit since we started this work> times 4, begin a request for new work
- when new work arrives, discard old work and begin using the new work.
stratum
The server may include a X-Stratum header containing URL to its Stratum interface. If this header is present, the Stratum-capable miner should switch to the specified URL immediately
Example:
X-Stratum: stratum+tcp://example.com:3333
Stratum+tcp indicates Stratum protocol with TCP transport. Theoretically pool can implement other transports as well, although at this date Stratum miners implement only TCP transport.
submitold
This feature should only be advertised with a longpoll request. If received with a regular request, it should be ignored.
If supported, the server may include a "submitold" key in the JSON result. If this key is present and true, the miner should NOT discard the result of old work (default per longpoll specification), but instead submit them to the server. The miner should still stop working on the old work, and begin working on the new work as soon as it can without losing the result of the old work.
switchto
Original specification from Deepbit
The server may include a X-Switch-To header containing a single JSON object formatted in the same fashon as items in the hostlist array extension. If this header is present, the miner should switch to the specified server for at least ttr minutes after finishing current "getwork" and submitting its results.
Example:
X-Switch-To: {"host":"temporary.tld","port":8332,"ttr":10}