難度與算力
-
難度
根據(jù)block hash計(jì)算所得:
(power(2, 128)-1)/(little-endian-int(hash) / power(2, 160))
寂玲。 -
算力
單節(jié)點(diǎn)的算力是直接統(tǒng)計(jì)出來的hash次數(shù)碑诉。
全網(wǎng)算力是根據(jù)難度值轉(zhuǎn)換出來的,難度取的是4個(gè)小時(shí)的平均值鳖谈。
挖礦流程
下面是pool和miner之間的挖礦交互流程。
pool端:
-
每個(gè)周期(64s)開始時(shí)些己,pool創(chuàng)建一個(gè)主塊傍药。
這個(gè)主塊會(huì)盡可能更多的鏈接截至當(dāng)時(shí)已知的孤塊(個(gè)數(shù)不超過可用的field),有可能無法鏈接完所有當(dāng)前的孤塊靴姿,則多出來的孤塊只能等待下個(gè)周期的主塊繼續(xù)鏈接沃但,也就是有部分交易的確認(rèn)時(shí)間會(huì)延長(zhǎng)。
為了使得每個(gè)周期的孤塊盡可能的被盡早鏈接(確認(rèn)交易)空猜,鏈接塊起到了關(guān)鍵作用绽慈,如果鏈接塊生成的足夠快且足夠多,使得整個(gè)圖收斂到足夠小的寬度上辈毯,比如孤塊頂點(diǎn)小于12,則原則上可以一次都被主塊鏈接搜贤。
-
計(jì)算前15個(gè)field的hash累加中間值(hash state)谆沃,并發(fā)送給各個(gè)礦機(jī)。
pool發(fā)送任務(wù)給各個(gè)礦機(jī)時(shí)仪芒,并不是直接把整個(gè)block內(nèi)容發(fā)送出去唁影,而是只發(fā)送了前15個(gè)field計(jì)算的hash中間變量耕陷,這里叫hash-state。
這個(gè)hash-state据沈,加上一個(gè)lastfield再計(jì)算一次hash哟沫,效果等同于一次計(jì)算16個(gè)field的hash結(jié)果,不會(huì)因?yàn)闆]有原始的前15個(gè)field而不同锌介。這樣pool就只需要發(fā)送一個(gè)中間變量給礦機(jī)嗜诀,發(fā)送的字節(jié)數(shù)會(huì)大大減少,同時(shí)又不影響計(jì)算結(jié)果孔祸。之所以可以這樣發(fā)送隆敢,是由hash算法的特性決定的,后面單獨(dú)說明崔慧。
-
發(fā)送完成后拂蝎,pool進(jìn)入等待提交狀態(tài)。
pool進(jìn)入等待期后惶室,各個(gè)礦機(jī)會(huì)不斷周期性的提交自己探索出的lastfield温自。
pool每次收到新的lastfield,都跟當(dāng)前miner已知的最小進(jìn)行比較皇钞,如果更小則保存在miner狀態(tài)中悼泌。
-
周期結(jié)束,pool打包生成主塊鹅士。
在周期結(jié)束時(shí)刻券躁,pool把各個(gè)礦機(jī)提交的lastfield拿出來,一個(gè)個(gè)跟hash-state做一次合并計(jì)算掉盅,看誰提交的lastfield能得到最小的hash也拜,也就是最大的難度,誰的提交就勝出趾痘。pool就用這個(gè)lastfield完成主塊的組裝慢哈,然后加上自己的簽名,提交到網(wǎng)絡(luò)上去永票。
至此卵贱,一個(gè)新的主塊就產(chǎn)生了,但是每個(gè)pool都會(huì)用同樣的方法產(chǎn)生一個(gè)自己的主塊侣集,所以最終只能有一個(gè)主塊競(jìng)爭(zhēng)勝出键俱,成為真正的鏈上主塊。
-
主塊與周期的關(guān)系
通過前面的分析可以看出世分,主塊時(shí)間戳與自身鏈接的交易周期實(shí)際上差了一個(gè)周期编振。
如上圖所示,t5作為Time Frame2
周期的主塊臭埋,鏈接的是Time Frame2
周期的交易踪央,但是t5真正打包成功生成主塊的時(shí)間戳是Time Frame4
周期的起點(diǎn)臀玄,或者說Time Frame3
周期的終點(diǎn)。
也就是說畅蹂,主塊時(shí)間戳所在的周期健无,是主塊中交易所在周期的下一個(gè)周期。
miner端:
-
miner接收到一個(gè)新的task
task包含一個(gè)hash-state液斜。
-
miner不斷探索最小hash
不斷生成隨機(jī)數(shù)累贤,填充組成一個(gè)新的lastfield,嘗試跟hash-state組合后計(jì)算hash旗唁。
在一個(gè)固定周期中畦浓,選擇上面多次計(jì)算中結(jié)果中最小的一個(gè),提交給pool检疫。這個(gè)固定周期通常至少要小于32s讶请,以此保證一個(gè)64s中至少提交過一次。通常會(huì)盡可能短屎媳,這樣能把因跨周期計(jì)算的算力浪費(fèi)最小化夺溢。但不能過于頻繁的提交,浪費(fèi)資源烛谊。
Hash算法
前面提到风响,挖礦中pool并不需要把block的全部數(shù)據(jù)發(fā)給miner,只需要發(fā)送前15個(gè)field累加出的hash-state丹禀,miner找到lastfield后直接與hash-state組合就可以得到真正的block hash状勤。之所以可以這么做,與hash算法特點(diǎn)有關(guān)双泪。
假設(shè)總block是512字節(jié)持搜,hash結(jié)果是32字節(jié),我們定義一種叫Stupid-Hash的算法焙矛,算法過程如下:
- 先設(shè)置一個(gè)32字節(jié)的最終數(shù)組葫盼,result-array。
- 把block的第一個(gè)32字節(jié)先復(fù)制到result-array村斟。
- 接著把第二個(gè)32字節(jié)按照某種累加運(yùn)算法則贫导,與當(dāng)前的result-array運(yùn)算一次,結(jié)果放回result-array蟆盹。
- 后面每一個(gè)32字節(jié)都按照相同的思路與result-array運(yùn)算并把結(jié)果放回result-array孩灯。
- 直到最后一個(gè)32字節(jié)迭代計(jì)算完成,最后一次得到的result-array就是最后的hash結(jié)果逾滥。
在Stupid-Hash算法下钱反,對(duì)一個(gè)很長(zhǎng)的二進(jìn)制數(shù)據(jù)做hash,可以把累加到中間任意步驟的result-array保存起來匣距,發(fā)送給另一個(gè)機(jī)器面哥,另一個(gè)機(jī)器用result-array加上剩下的數(shù)據(jù)繼續(xù)這個(gè)hash算法,得到的結(jié)果與第一個(gè)機(jī)器把這個(gè)計(jì)算一直進(jìn)行到底得到的結(jié)果是一致的毅待。
xdag中hash算法的思路與這個(gè)Stupid-Hash的思路是一致的尚卫,只不過真實(shí)hash算法(sha256)中間的運(yùn)算過程更復(fù)雜一些,但是整體計(jì)算思路沒有不同尸红。
mining收益分配
單個(gè)pool鏈接了眾多miner吱涉,當(dāng)挖礦成功后,需要在各個(gè)miner間分配收益外里。
分配基本策略主要是依據(jù)各個(gè)miner在當(dāng)前周期中探索到的最大難度怎爵,比如有三個(gè) miner,各自在當(dāng)前task周期的最大難度是1盅蝗、2鳖链、3,最終給第一個(gè)miner的比例就是1/(1+2+3)墩莫。
在這個(gè)基本分配策略之外芙委,增加了一些特殊分配。
- 給基金會(huì)賬戶一個(gè)固定比例的分成狂秦。
- 給pool賬戶一個(gè)固定比例的分成灌侣。
- 給找到最小hash的miner一個(gè)其難度比例之外的特殊分成。
上面這些分配比例可以在pool啟動(dòng)的時(shí)候自由配置裂问。
T周期對(duì)T-15周期的挖礦進(jìn)行分配侧啼。
錢包與pool的交互
在當(dāng)前的實(shí)現(xiàn)中,對(duì)pool來說堪簿,錢包實(shí)際上與miner角色一樣痊乾,pool對(duì)兩者的處理策略一致。差別在于錢包不做挖礦戴甩,也不提交計(jì)算符喝。
pool會(huì)周期性的向錢包推送錢包賬戶的余額下去,錢包并不向pool去查詢余額甜孤,只查看本地存儲(chǔ)已知的賬本协饲。