如何計算給定乙太坊區塊的難度?
我了解探勘一個塊涉及嘗試生成小於或等於所需難度所規定的目標的雜湊值。Ethash 上的乙太坊維基:
def mine(full_size, dataset, header, difficulty): # zero-pad target to compare with hash on the same digit target = zpad(encode_int(2**256 // difficulty), 64)[::-1] from random import randint nonce = randint(0, 2**64) while hashimoto_full(full_size, dataset, header, nonce) > target: nonce = (nonce + 1) % 2**64 return nonce
我還從這個 SE 主題中了解到,區塊雜湊本身並沒有針對目標進行檢查,而是它是
Ethash(hash(block header), nonce) < TARGET
,這解釋了為什麼乙太坊區塊沒有我們習慣於使用比特幣的前導零。為了計算難度,我們大概會將生成目標的操作從難度反轉為從
Ethash
?生成難度。並且是應用反轉的塊難度Ethash(hash(block header), nonce)
還是應用反轉target
以生成原始所需的難度?如果是前者,鑑於共識鏈具有最高的總累積難度,並且多個叉子共享這一點的機率實際上為零,我們是否應該能夠在不需要額外塊的情況下立即在分叉中重新獲得共識?
如果是後者,並且給出了對難度調整算法如何工作的出色解釋,並且考慮到難度炸彈繼續被推遲,我希望 Etherscan 上的連續塊以某種規律性共享難度,即在塊的情況下在其父節點的 10-20 秒內開採。但這與我在 Etherscan 上看到的最近區塊的情況相反。
回到中心問題:如何計算給定乙太坊區塊的難度?
您可以使用 ethers 和提供程序呼叫 JSON-RPC。的結果
eth_getBlockByNumber
包含一個稱為難度的欄位。JS 大致如下所示:
import ethers; async () => { const provider = new ethers.providers.JsonRpcProvider(<YOUR JSONRPC URL>); const block = await provider.getBlock(100004); const difficulty = block.difficulty; }
目前調整難度的算法可以在EIP-100,黃皮書 (Page 7, Equation 45)中找到,或者在 geth here中實現. 調整所需難度的算法也用於定義塊的難度。也就是說,一個區塊的難度是由它的父級難度以及它和它的父級之間的時間戳的差異,以及它的父級是否有叔叔來定義的。但至關重要的是,它獨立於 ethash 輸出。出於這個原因,如果兩個具有相同父級的區塊具有相似的時間戳,則它們可能具有相同的難度:它們需要要麼都在其共享父級的 9 秒內被開採,要麼都在 9 到 18 秒之間被開採(不包括端點)他們共同的父母。在拜占庭實施 EIP-100 後,叔叔確實對總困難很重要。
我在上面還建議,當且僅當它在其父區塊的 9 到 18 秒之間被開採時,我會期望一個區塊與它的父區塊具有相同的難度。我誤解了。即使是這種情況,一個區塊的難度也會高於其父區塊,其差異來自黃皮書中的 epsilon 項,等式 50。即使這個項不經常變化,每 100,000 個區塊,一個區塊的難度仍然增加這個數量相對於它的父母。因此,雖然您通常會發現區塊的難度與其他區塊不同,但您可能會發現,如果區塊 n+1 被開採,區塊 n+1 和區塊 n 之間的難度差異等於區塊 n 和區塊 n-1 之間的差異在塊 n 之後的 9 到 18 秒之間,假設叔包含插入沒有差異。