diff --git a/doc/stratum.md b/doc/stratum.md new file mode 100644 index 000000000..450e97c7b --- /dev/null +++ b/doc/stratum.md @@ -0,0 +1,556 @@ +# Grin Stratum RPC Protocol + +This document describes the current Stratum RPC protocol implemented in Grin. + +## Table of Contents + +1. [Messages](#messages) + 1. [getjobtemplate](#getjobtemplate) + 2. [job](#job) + 3. [keepalive](#keepalive) + 4. [login](#login) + 5. [status](#status) + 6. [submit](#submit) +1. [Error Messages](#errormessages) +1. [Miner Behavior](#minerbehavior) +1. [Reference Implementation](#referenceimplementation) + +## Messages + +In this section, we detail each message and the potential response. + +At any point, if miner the tries to do one of the following request (except login) and login is required, the miner will receive the following error message. + +| Field | Content | +| ------------- |:---------------------------------------:| +| id | ID of the request | +| jsonrpc | "2.0" | +| method | method sent by the miner | +| error | {"code":-32500,"message":"login first"} | + +Example: + +```JSON +{ + "id":"10", + "jsonrpc":"2.0", + "method":"getjobtemplate", + "error":{ + "code":-32500, + "message":"login first" + } +} +``` + +if the request is not one of the following, the stratum server will give this error response: + +| Field | Content | +| ------------- |:--------------------------------------------:| +| id | ID of the request | +| jsonrpc | "2.0" | +| method | method sent by the miner | +| error | {"code":-32601,"message":"Method not found"} | + +Example: + +```JSON +{ + "id":"10", + "jsonrpc":"2.0", + "method":"getgrins", + "error":{ + "code":-32601, + "message":"Method not found" + } +} +``` + +### ```getjobtemplate``` + +A message initiated by the miner. +Miner can request a job with this message. + +#### Request + +| Field | Content | +| ------------- |:------------------------------:| +| id | ID of the request | +| jsonrpc | "2.0" | +| method | "getjobtemplate" | +| params | null | + +Example: + +``` JSON + +{ + "id":"2", + "jsonrpc":"2.0", + "method":"getjobtemplate", + "params":null +} + +``` + +#### Response + +The response can be of two types: + +##### OK response + +Example: + +``` JSON + +{ + "id":"0", + "jsonrpc":"2.0", + "method":"getjobtemplate", + "result":{ + "difficulty":1, + "height":13726, + "job_id":4, + "pre_pow":"00010000000000003c4d0171369781424b39c81eb39de10cdf4a7cc27bbc6769203c7c9bc02cc6a1dfc6000000005b50f8210000000000395f123c6856055aab2369fe325c3d709b129dee5c96f2db60cdbc0dc123a80cb0b89e883ae2614f8dbd169888a95c0513b1ac7e069de82e5d479cf838281f7838b4bf75ea7c9222a1ad7406a4cab29af4e018c402f70dc8e9ef3d085169391c78741c656ec0f11f62d41b463c82737970afaa431c5cabb9b759cdfa52d761ac451276084366d1ba9efff2db9ed07eec1bcd8da352b32227f452dfa987ad249f689d9780000000000000b9e00000000000009954" + } +} + + ``` + +##### Error response + +If the node is syncing, it will send the following message: + +| Field | Content | +| ------------- |:---------------------------------------------------------:| +| id | ID of the request | +| jsonrpc | "2.0" | +| method | "getjobtemplate" | +| error | {"code":-32701,"message":"Node is syncing - Please wait"} | + +Example: + +```JSON +{ + "id":"10", + "jsonrpc":"2.0", + "method":"getjobtemplate", + "error":{ + "code":-32000, + "message":"Node is syncing - Please wait" + } +} +``` + +### ```job``` + +A message initiated by the Stratum server. +Stratum server will send job automatically to connected miners. + +#### Request + +| Field | Content | +| ------------- |:-------------------------------------------------------------------------:| +| id | ID of the request | +| jsonrpc | "2.0" | +| method | "job" | +| params | Int ```difficulty```, ```height```, ```job_id``` and string ```pre_pow``` | + +Example: + +``` JSON + +{ + "id":"Stratum", + "jsonrpc":"2.0", + "method":"job", + "params":{ + "difficulty":1, + "height":16375, + "job_id":5, + "pre_pow":"00010000000000003ff723bc8c987b0c594794a0487e52260c5343288749c7e288de95a80afa558c5fb8000000005b51f15f00000000003cadef6a45edf92d2520bf45cbd4f36b5ef283c53d8266bbe9aa1b8daaa1458ce5578fcb0978b3995dd00e3bfc5a9277190bb9407a30d66aec26ff55a2b50214b22cdc1f3894f27374f568b2fe94d857b6b3808124888dd5eff7e8de7e451ac805a4ebd6551fa7a529a1b9f35f761719ed41bfef6ab081defc45a64a374dfd8321feac083741f29207b044071d93904986fa322df610e210c543c2f95522c9bdaef5f598000000000000c184000000000000a0cf" + } +} + +``` + +#### Response + +No response is required for this message. + +### ```keepalive``` + +A message initiated by the miner in order to keep the connection alive. + +#### Request + +| Field | Content | +| ------------- |:----------------------:| +| id | ID of the request | +| jsonrpc | "2.0" | +| method | "keepalive" | +| params | null | + +Example: + +``` JSON + +{ + "id":"2", + "jsonrpc":"2.0", + "method":"keepalive", + "params":null +} + +``` + +#### Response + +| Field | Content | +| ------------- |:------------------------------:| +| id | ID of the request | +| jsonrpc | "2.0" | +| method | "keepalive" | +| result | "ok" | +| error | null | + +Example: + +``` JSON + +{ + "id":"2", + "jsonrpc":"2.0", + "method":"keepalive", + "result":"ok", + "error":null +} + +``` + +### ```login``` + +*** + +A message initiated by the miner. +Miner can log in on a Grin Stratum server with a login, password and agent (usually statically set by the miner program). + +#### Request + +| Field | Content | +| ------------- |:------------------------------:| +| id | ID of the request | +| jsonrpc | "2.0" | +| method | "login" | +| params | Strings: login, pass and agent | + +Example: + +``` JSON + +{ + "id":"0", + "jsonrpc":"2.0", + "method":"login", + "params":{ + "login":"login", + "pass":"password", + "agent":"grin-miner" + } +} + +``` + +#### Response + +The response can be of two types: + +##### OK response + +| Field | Content | +| ------------- |:------------------------------:| +| id | ID of the request | +| jsonrpc | "2.0" | +| method | "login" | +| result | "ok" | +| error | null | + +Example: + +``` JSON + +{ + "id":"1", + "jsonrpc":"2.0", + "method":"login", + "result":"ok", + "error":null +} + +``` + +##### Error response + +Not yet implemented. Should return error -32500 "Login first". + +### ```status``` + +A message initiated by the miner. +This message allows a miner to get the status of its current worker and the network. + +#### Request + +| Field | Content | +| ------------- |:----------------------:| +| id | ID of the request | +| jsonrpc | "2.0" | +| method | "status" | +| params | null | + +Example: + +``` JSON + +{ + "id":"2", + "jsonrpc":"2.0", + "method":"status", + "params":null +} + +``` + +#### Response + +The response is the following: + +| Field | Content | +| ------------- |:--------------------------------------------------------------------------------------------------------:| +| id | ID of the request | +| jsonrpc | "2.0" | +| method | "status" | +| result | String ```id```. Integers ```height```, ```difficulty```, ```accepted```, ```rejected``` and ```stale``` | +| error | null | + +Example: + +```JSON +{ + "id":"5", + "jsonrpc":"2.0", + "method":"status", + "result":{ + "id":"5", + "height":13726, + "difficulty":1, + "accepted":0, + "rejected":0, + "stale":0 + }, + "error":null +} +``` + +### ```submit``` + +A message initiated by the miner. +When a miner find a share, it will submit it to the node. + +#### Request + +The miner submit a solution to a job to the Stratum server. + +| Field | Content | +| ------------- |:---------------------------------------------------------------------------:| +| id | ID of the request | +| jsonrpc | "2.0" | +| method | "submit" | +| params | Int ```nonce```, ```height```, ```job_id``` and array of integers ```pow``` | + +Example: + +``` JSON + +{ + "id":"0", + "jsonrpc":"2.0", + "method":"submit", + "params":{ + "height":16419, + "job_id":0, + "nonce":8895699060858340771, + "pow":[ + 4210040,10141596,13269632,24291934,28079062,84254573,84493890,100560174,100657333,120128285,130518226,140371663,142109188,159800646,163323737,171019100,176840047,191220010,192245584,198941444,209276164,216952635,217795152,225662613,230166736,231315079,248639876,263910393,293995691,298361937,326412694,330363619,414572127,424798984,426489226,466671748,466924466,490048497,495035248,496623057,502828197, 532838434 + ] + } +} + +``` + +#### Response + +The response can be of three types. + +##### OK response + +The share is accepted by the Stratum but is not a valid cuckoo solution at the network target difficulty. + +| Field | Content | +| ------------- |:------------------------------:| +| id | ID of the request | +| jsonrpc | "2.0" | +| method | "submit" | +| result | "ok" | +| error | null | + +Example: + +``` JSON + +{ + "id":"2", + "jsonrpc":"2.0", + "method":"submit", + "result":"ok", + "error":null +} + +``` + +##### Blockfound response + +The share is accepted by the Stratum and is a valid cuckoo solution at the network target difficulty. + +| Field | Content | +| ------------- |:------------------------------:| +| id | ID of the request | +| jsonrpc | "2.0" | +| method | "submit" | +| result | "block - " + hash of the block | +| error | null | + +Example: + +``` JSON + +{ + "id":"6", + "jsonrpc":"2.0", + "method":"submit", + "result":"blockfound - 23025af9032de812d15228121d5e4b0e977d30ad8036ab07131104787b9dcf10", + "error":null +} + +``` + +##### Error response + +The error response can be of two types: stale and rejected. + +##### Stale share error response + +The share is a valid solution to a previous job not the current one. + +| Field | Content | +| ------------- |:---------------------------------------------------------:| +| id | ID of the request | +| jsonrpc | "2.0" | +| method | "submit" | +| error | {"code":-32503,"message":"Solution submitted too late"} | + +Example: + +```JSON +{ + "id":"5", + "jsonrpc":"2.0", + "method":"submit", + "error":{ + "code":-32503, + "message":"Solution submitted too late" + } +} +``` + +##### Rejected share error responses + +Two possibilities: the solution cannot be validated or the solution is of too low difficulty. + +###### Failed to validate solution error + +The submitted solution cannot be validated. + +| Field | Content | +| ------------- |:---------------------------------------------------------:| +| id | ID of the request | +| jsonrpc | "2.0" | +| method | "submit" | +| error | {"code":-32502,"message":"Failed to validate solution"} | + +Example: + +```JSON +{ + "id":"5", + "jsonrpc":"2.0", + "method":"submit", + "error":{ + "code":-32502, + "message":"Failed to validate solution" + } +} +``` + +###### Share rejected due to low difficulty error + +The submitted solution is of too low difficulty. + +| Field | Content | +| ------------- |:----------------------------------------------------------------:| +| id | ID of the request | +| jsonrpc | "2.0" | +| method | "submit" | +| error | {"code":-32501,"message":"Share rejected due to low difficulty"} | + +Example: + +```JSON +{ + "id":"5", + "jsonrpc":"2.0", + "method":"submit", + "error":{ + "code":-32501, + "message":"Share rejected due to low difficulty" + } +} +``` + +## Error Messages + +Grin Stratum protocol implementation contains the following error message: + +| Error code | Error Message | +| ----------- |:--------------------------------------:| +| -32000 | Node is syncing - please wait | +| -32500 | Login first | +| -32501 | Share rejected due to low difficulty | +| -32502 | Failed to validate solution | +| -32503 | Solution Submitted too late | +| -32600 | Invalid Request | +| -32601 | Method not found | + +## Miner behavior + +Miners SHOULD, MAY or MUST respect the following rules: + +- Miners SHOULD randomize the job nonce before starting (not the way it is now, the way it should be) +- Miners MUST continue mining the same job until the server sends a new one, though a miner MAY request a new job at any time +- Miners MUST NOT send an rpc response to a job request from the server +- Miners MAY set the RPC "id" and expect responses to have that same id +- Miners MAY send a keepalive message +- Miners MAY send a login request (to identify which miner finds shares / solutions in the logs), the login request MUST have all 3 params. +- Miners MUST return the supplied job_id with submit messages. + +## Reference Implementation + +The current reference implementation is available at [mimblewimble/grin-miner](https://github.com/mimblewimble/grin-miner/blob/master/src/bin/client.rs). \ No newline at end of file diff --git a/doc/table_of_contents.md b/doc/table_of_contents.md index 0d61209db..510e7a190 100644 --- a/doc/table_of_contents.md +++ b/doc/table_of_contents.md @@ -15,6 +15,7 @@ - [merkle_proof graph](merkle_proof/merkle_proof.png) - Example merkle proof with pruning applied - [pruning](pruning.md) - Technical explanation of pruning - [rangeproofs](rangeproofs.md) - Technical explanation of range proofs +- [stratum](stratum.md) - Technical explanation of Grin Stratum RPC protocol - [transaction UML](transaction/aggregating transaction without lock_height) - UML of an interactive transaction ## Build and use