以太坊stratum協(xié)議原理
參照比特幣的stratum協(xié)議 和NiceHash的stratum協(xié)議規(guī)范編寫(xiě)了一版以太坊版本的stratum協(xié)議說(shuō)明.
stratum協(xié)議是目前最常用的礦機(jī)和礦池之間的TCP通訊協(xié)議。
一、挖礦的網(wǎng)絡(luò)架構(gòu)
以太坊是一個(gè)去中心化的網(wǎng)絡(luò)架構(gòu),通過(guò)安裝Mist客戶端的節(jié)點(diǎn)來(lái)轉(zhuǎn)發(fā)新交易和新區(qū)塊。而礦機(jī)、礦池也同時(shí)形成了另一個(gè)網(wǎng)絡(luò),我們稱之為礦工網(wǎng)絡(luò)。
礦工網(wǎng)絡(luò)分成礦機(jī)、礦池、錢包等幾個(gè)主要部分,有時(shí)礦池軟件與錢包安裝在一起,可合稱為礦池。
礦機(jī)與礦池軟件之間的通訊協(xié)議是stratum,而礦池軟件與錢包之間的通訊是bitcoinrpc接口。
stratum是JSON為數(shù)據(jù)格式.
二、stratum協(xié)議
1. 任務(wù)訂閱
礦機(jī)啟動(dòng),首先以mining.subscribe方法向礦池連接,用來(lái)訂閱工作。
礦池以mining.notify返回訂閱號(hào)、ExtraNonce1和ExtraNonce2_size。
Client:
{
"id": 1,
"method": "mining.subscribe",
"params": [
"MinerName/1.0.0", "EthereumStratum/1.0.0"
]
}
Server:
{
"id": 1,
"result": [
[
"mining.notify",
"ae6812eb4cd7735a302a8a9dd95cf71f",
"EthereumStratum/1.0.0"
],
"080c"
],
"error": null
}
其中:
ae6812eb4cd7735a302a8a9dd95cf71f是訂閱號(hào);
080c是extranonce,Extranonce可能最大3字節(jié);
2. 礦機(jī)登錄
礦機(jī)以mining.authorize方法,用某個(gè)帳號(hào)和密碼登錄到礦池,密碼可空,礦池返回true登錄成功。該方法必須是在初始化連接之后馬上進(jìn)行,否則礦機(jī)得不到礦池任務(wù)。
Client:
{"params":["miner1","password"],"id":2,"method":"mining.authorize"}
Server:
{"error":null,"id":2,"result":true}
3. 難度調(diào)整
難度調(diào)整由礦池下發(fā)給礦機(jī),以mining.set_difficulty方法調(diào)整難度,params中是難度值。
Server:
{"id":null,"method":"mining.set_difficulty","params":[2]}
礦機(jī)會(huì)在下一個(gè)任務(wù)時(shí)采用新難度,礦池有時(shí)會(huì)馬上下發(fā)一個(gè)新任務(wù)并且把清理任務(wù)設(shè)為true,以便礦機(jī)馬上以新難度工作。
4. 任務(wù)分配
該命令由礦池定期發(fā)給礦機(jī),當(dāng)?shù)V機(jī)以mining.subscribe方法登記后,礦池應(yīng)該馬上以mining.notify返回該任務(wù)。
Server:
{
"id": null,
"method": "mining.notify",
"params": [
"bf0488aa",
"abad8f99f3918bf903c6a909d9bbc0fdfa5a2f4b9cb1196175ec825c6610126c",
"645cf20198c2f3861e947d4f67e3ab63b7b2e24dcc9095bd9123e7b33371f6cc",
true
]
}
任務(wù)ID:bf0488aa;
seedhash:abad8f99f3918bf903c6a909d9bbc0fdfa5a2f4b9cb1196175ec825c6610126c。每一個(gè)任務(wù)都發(fā)送一個(gè)seedhash來(lái)支持盡可能多的礦池,這可能會(huì)很快地在貨幣之間交換。
headerhash: 645cf20198c2f3861e947d4f67e3ab63b7b2e24dcc9095bd9123e7b33371f6cc。
boolean cleanjobs: true。如果設(shè)為true,那么礦工需要清理任務(wù)隊(duì)列,并立即開(kāi)始從事新提供的任務(wù),因?yàn)樗信f的任務(wù)分享都將導(dǎo)致陳舊的分享錯(cuò)誤。如果是false則等當(dāng)前任務(wù)結(jié)束才開(kāi)始新任務(wù)。
5. 結(jié)果提交
礦工使用seedhash識(shí)別DAG,然后帶著headerhash,extranonce和自己的minernonce尋找低于目標(biāo)的share(這是由提供的難度而產(chǎn)生的)。
礦機(jī)找到合法share時(shí),就以”mining.submit“方法向礦池提交任務(wù)。礦池返回true即提交成功,如果失敗則error中有具體原因。
Client:
{
"id": 244,
"method": "mining.submit",
"params": [
"username",
"bf0488aa",
"6a909d9bbc0f"
]
}
任務(wù)ID: bf0488aa
minernonce: 6a909d9bbc0f。注意minernonce是6個(gè)字節(jié),因?yàn)樘峁┑膃xtranonce是2個(gè)字節(jié)。如果礦池提供3字節(jié)的extranonce,那么minernonce必須是5字節(jié)
Server:
- 接受結(jié)果:
{
"id": 244,
"result": true,
"error": null
}
- 不被接受:
{
"id": 244,
"result": false,
"error": [
-1,
"Job not found",
NULL
]
}
三、一般通訊過(guò)程
一般的礦機(jī)與礦池通訊過(guò)程就如下所示:
sequenceDiagram
礦機(jī)->> 礦池: mining.subscribe
Note left of 礦機(jī): 礦機(jī)任務(wù)訂閱
礦池->> 礦機(jī): mining.notify
Note right of 礦池: 回復(fù)當(dāng)前EthereumStratum/Version和extranonce
礦機(jī)->> 礦池: mining.authorize
Note left of 礦機(jī): 礦機(jī)認(rèn)證
礦池->> 礦機(jī): 返回認(rèn)證結(jié)果
礦池->> 礦機(jī): mining.set_difficulty
Note right of 礦池: 礦池更新難度
礦池->> 礦機(jī): mining.set_extranonce
Note right of 礦池: 礦池更新extranonce
礦池->> 礦機(jī): mining.notify
Note right of 礦池: 通知礦工工作
礦機(jī)->> 礦池: mining.submit
Note left of 礦機(jī): 礦機(jī)提交任務(wù)對(duì)應(yīng)的minernonce
礦池->> 礦機(jī): 是否接收share
