以太坊經典(Ethereum Classic)的難度計算

之前的一篇文章以太坊(Ethereum ETH)是如何計算難度的發布後,有小夥伴私信我,說他根據文中介紹的演算法計算出的難度與區塊鏈里查到的不同,按照他提供給我的區塊Hash,我居然在以太坊的區塊鏈中查不到這個區塊。這是怎麼回事兒呢?

原來他在查看的是以太坊經典的區塊鏈,現在就讓我們來看看這個以太坊經典究竟有什麼獨特之處。

以太坊經典(Ethereum Classic)

以太坊經典(Ethereum Classic)是由以太坊(Ethereum)分叉而來的另一種區塊鏈系統。分叉的起因是2016年6月發生的轟動事件:The DAO攻擊,黑客盜取了The DAO眾籌合約中的以太幣。關於如何應對這個事件,社區內有兩種觀點:

  1. 既然大家都同意,並且可以達成新的「共識規則」,那麼區塊鏈的內容是可以修改的。
  2. 修改區塊鏈的內容違背了區塊鏈不可篡改的初衷,任何情況下區塊鏈的內容都不應修改。

這兩個觀點各自都有支持者,支持觀點1的人決定通過硬分叉的方式將以太幣追回,並歸還給原來的眾籌參與者(這個分支也就是現在的以太坊)。支持觀點2的人決定繼續在原來的鏈上挖礦(這個分支就是現在的以太坊經典)。

最後,大約在北京時間2016年7月20日晚9點20分左右,區塊高度1,920,000,以太坊正式進行硬分叉,產生了兩條鏈。

以太坊1,920,000區塊

以太坊經典1,920,000區塊

可以看到,在同樣的高度1,920,000,出現了兩個Hash不同的區塊,分叉正式完成。從此以太坊和以太坊經典走上了各自的發展道路,天各一方,不相往來。

以太坊和以太坊經典自分叉後就是兩個區塊鏈系統,其上的電子幣雖然都叫以太幣,但是互不通用。為了區分,一般把以太坊中的以太幣簡稱ETH,把以太坊經典中的以太幣簡稱ETC

注意:千萬不要把以太坊和以太坊經典的地址弄混,一旦把ETH發到ETC地址,或者ETC發到ETH地址,將會導致以太幣丟失。

以太坊經典的難度計算

以太坊經典的代碼同樣是開源的,區塊鏈也完全公開,沒什麼問題是讀一遍代碼弄不明白的,如果有,就再讀一遍。

func CalcDifficulty(config *ChainConfig, time, parentTime uint64, parentNumber, parentDiff *big.Int) *big.Int { num := new(big.Int).Add(parentNumber, common.Big1) // increment block number to current f, fork, configured := config.GetFeature(num, "difficulty") if !configured { return calcDifficultyFrontier(time, parentTime, parentNumber, parentDiff) } name, ok := f.GetString("type") if !ok { name = "" } // will fall to default panic switch name { case "ecip1010": if length, ok := f.GetBigInt("length"); ok { explosionBlock := big.NewInt(0).Add(fork.Block, length) if num.Cmp(explosionBlock) < 0 { return calcDifficultyDiehard(time, parentTime, parentDiff, fork.Block) } else { return calcDifficultyExplosion(time, parentTime, parentNumber, parentDiff, fork.Block, explosionBlock) } } else { panic(fmt.Sprintf("Length is not set for diehard difficulty at %v", num)) } case "homestead": return calcDifficultyHomestead(time, parentTime, parentNumber, parentDiff) case "frontier": return calcDifficultyFrontier(time, parentTime, parentNumber, parentDiff) default: panic(fmt.Sprintf("Unsupported difficulty %v for block: %v", name, num)) }}

可以發現,以太坊經典對難度計算做了些小手腳,增加了兩個新的演算法calcDifficultyDiehard和calcDifficultyExplosion。感興趣的小夥伴可以在這裡找到和難度計算相關的全部代碼:core/block_validator.go,代碼中使用的配置參數在這裡core/data_chainconfig.go。

相比以太坊,以太坊經典修改了難度炸彈部分。

  • 3,000,000區塊之前,難度計算方法與以太坊相同。
  • 3,000,000到5,000,000區塊,使用calcDifficultyDiehard演算法,難度炸彈暫停增長。
  • 5,000,000區塊之後,使用calcDifficultyExplosion演算法,難度炸彈恢復增長。

這個對難度炸彈的修改在以太坊經典的開發社區中被稱為「難度炸彈延遲」。與比特幣的BIP類似,以太坊經典也把共識規則的更新用文檔記錄下來,稱為以太坊經典改進提議(Ethereum Classic Improvement Proposal),簡稱ECIP。這次難度炸彈延遲被記錄於ECIP1010。

難度計算公式的其餘兩項:父區塊難度和難度調整,以太坊經典依然沿用了以太坊的計算方法。

實踐一下

以太坊經典的用戶較少,我只找到了兩個區塊鏈瀏覽器:

  • gastracker.io/
  • etcchain.com/

遺憾的是,他們都不能精確顯示難度。不過沒關係,可以在自己的機器上運行一個Geth,同步完成後就可以查看所有區塊的信息了。由於Geth是命令行工具,沒有漂亮的界面。如果有誰知道更好的以太坊經典區塊瀏覽器,請留言告知我,我會及時更新。

還是隨意挑一個區塊,比如4,421,544,讓我們來計算一下它的難度。

想計算區塊的難度,需要知道這些信息:

  • parent_timestamp:上一個區塊產生的時間
  • parent_diff:上一個區塊的難度
  • block_timestamp:當前區塊產生的時間
  • block_number:當前區塊的序號

在Geth的Javascript控制台中可以使用debug.printBlock(blockNumber)函數查看區塊的詳細信息,首先我們查一下父區塊4,421,543:

$echo -e `geth --exec "debug.printBlock(4421543)" attach`Block(#4421543): Size: 837.00 B {MinerHash: f4d068b903a67890cac5ddaff94a66d99a0464dfeef1c0bab3c7b3a7bf2965e4Header(2762936eb0879e86c2b0309a69fdfa3566bb3101e3cf344acf54d2534f2f3498):[ ParentHash: 40f5cd2ec0be0e819c8689307c24d38edb75450358922286ec2c48e532bca427 UncleHash: 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347 Coinbase: df7d7e053933b5cc24372f878c90e62dadad5d42 Root: de7c6ce1ea8c74644eba0579d42163c969e2c6b04cd57c1059470ca124b618ba TxSha 497f1a6fd4d13db0f2eb4d90c11670485e5305a39a6782ec68417a9b060ae5f2 ReceiptSha: 57bd177107249827f9a85e2d2b28d53180be4e4fb5069d0a1fd90f3822aa0097 Bloom: 00000000000000000000000000000000000000000400000000000000000000000000000000000000000000000080000008000000000000000000000000000000000100000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000800000000000000000100000000000400000000000000000400000000000000000000000 Difficulty: 132145956937056 Number: 4421543 GasLimit: 4700036 GasUsed: 58209 Time: 1504744551 Extra: ETC ethermine - EU2 MixDigest: 7f09929b10732bb47d2473adaf172d5dfc146d560a10a6ab98c80538135ad351 Nonce: 6960c3d00b731872]

從父區塊中,我們知道了:

parent_timestamp = 1504744551

parent_diff = 132145956937056

再來查一下4,421,544區塊:

$echo -e `geth --exec "debug.printBlock(4421544)" attach`Block(#4421544): Size: 1.55 kB {MinerHash: 89a0ecdc93471ef468f96dcb97c757b744a4a93b1fe142bed6f416552c2fd818Header(601d2019900d12781fbc0788ca3b55535b4ba6ee5337e5d7dce822860e3f9699):[ ParentHash: 2762936eb0879e86c2b0309a69fdfa3566bb3101e3cf344acf54d2534f2f3498 UncleHash: 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347 Coinbase: 9eab4b0fc468a7f5d46228bf5a76cb52370d068d Root: 1c59d3ab4e415e217f7544b38bd73bcdda21d56865315af8fafcf7bb8726c9a9 TxSha 0ff3a73cedb8687b652df84baa46a98f6cdc24d5fa6a5e4e8335839ba7938304 ReceiptSha: 2d45de0f095c9655204fca5c1e93db9f203b284c1e7b981a30693a9971dc3f3c Bloom: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000080000000000000000020000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000008000000000000000 Difficulty: 132081700979477 Number: 4421544 GasLimit: 4704624 GasUsed: 254912 Time: 1504744574 Extra: nanopool.org MixDigest: 278b40bb8843841d6d5fcf843beeb0aeb2948b953696d884c367d5716685946e Nonce: 2850d644089a46c5]

從區塊中,我們知道了:

block_timestamp = 1504744574

block_number = 4421544

難度公式:

block_diff = parent_diff + 難度調整 + 難度炸彈

難度調整 =

parent_diff // 2048 * MAX(1 - (block_timestamp - parent_timestamp) // 10, -99)

= 132145956937056 // 2048 * MAX(1 - (1504744551 - 1504744574) // 10, -99)

= 132145956937056 // 2048 * MAX(1 - 23 // 10, -99)

= 132145956937056 //2048 * MAX(1 - 2, -99)

= 132145956937056 //2048 * MAX(-1, -99)

= 132145956937056 //2048 * (-1)

= -64524393035

因為4,421,544區塊在3,000,000到5,000,000之間,難度炸彈固定在3,000,000區塊處。

難度炸彈 =

INT(2**((3000000// 100000) - 2))

= INT(2**(30 - 2))

= 2**28

= 268435456

所以,

block_diff =

132145956937056 - 64524393035 + 268435456

= 132081700979477

與前面查到的4,421,544區塊的難度一致。

為什麼要延遲難度炸彈

官方說法是,對共識和協議的更新需要足夠的時間進行論證、開發和測試,完成這些需要足夠的時間。如果難度炸彈在這些工作完成之前爆炸,會導致以太坊經典的網路不可用。而魯莽的趕在難度炸彈產生影響之前搶先部署未經充分論證和測試的軟體,可能會造成更大的風險。因此需要進行一次更新,在2,000,000個區塊,也就是大約一年的時間內,暫時停止難度炸彈的增長。

網上的一些文章把這次「難度炸彈延遲」稱為「拆彈」是不準確的,難度炸彈依然存在,沒有被去掉,只是引爆時間延後了。只要還需要挖礦,難度炸彈就會一直保留,以防止礦工掌握過大的話語權,這也是設置難度炸彈的目的。

從幾個方面對比以太坊和以太坊經典:

  • 在Github上對比以太坊和以太坊經典:

以太坊的項目頁面:

以太坊經典的項目頁面:

很容易就能發現在各項指標上,以太坊經典明顯落後於以太坊,以太坊擁有更強大的開發團隊。

  • 挖礦算力上

以太坊當前已經達到95.714TH/s,而以太坊經典僅有10.937TH/s,僅有前者的十分之一左右。

  • 以太幣的價格上

ETH當前價格$326.95,ETC當前價格$18.53,僅有前者的6%。

我個人認為,以太坊經典是以太坊分叉而來,分叉伊始支持者就遠少於以太坊,又沒有足夠的技術差異,很難擺脫淪為小眾的命運。

不過以太坊經典有可能在以太坊切換到PoS之後依然堅持PoW,用不同的工作量證明方式與以太坊相區別,如果能夠得到足夠多的礦工支持,在未來依然有可能東山再起。

近期以太坊經典將要應用更新挖礦獎勵機制的ECIP1017,從一定程度上刺激了ETC價格的上漲。

希望利用炸彈延遲的這一年時間,以太坊經典的開發者可以勵精圖治,讓以太坊經典走出自己的道路,擺脫以太坊小弟的名聲。

如果你覺得這篇文章有幫助,就請點贊或收藏吧。

如果有任何指正和不同的觀點,歡迎留言。

話題徵集:

小夥伴們對區塊鏈技術還有什麼感興趣和想知道的呢?快到碗里來。

聽我用大白話來解釋你不知道的區塊鏈。

推薦閱讀:

ICO : 人傻,錢多,速來
以太坊『大都會』硬分叉第一階段啟動,成功整合Zcash匿名技術
什麼時候數字加密貨幣可以不依賴法幣獨立存在?如何才能讓比特幣的幣值穩定?至少達到黃金價格的波動水平?
比特幣,萊特幣,以太坊,以太經典,BCH,Dash, XRP價格分析(81)--2/5/2018

TAG:以太坊 | 区块链Blockchain |