• Ethereum Classic的难度计算|猿创征文


    目录

    以太坊经典(Ethereum Classic)

    以太坊经典的难度计算

    实例

    为什么要延迟难度炸弹


    以太坊经典(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地址,将会导致以太币丢失。

    以太坊经典的难度计算

    以太坊经典的代码同样是开源的,区块链也完全公开,没什么问题是读一遍代码弄不明白的,如果有,就再读一遍。
    1. func CalcDifficulty(config *ChainConfig, time, parentTime uint64, parentNumber, parentDiff *big.Int) *big.Int {
    2. num := new(big.Int).Add(parentNumber, common.Big1) // increment block number to current
    3. f, fork, configured := config.GetFeature(num, "difficulty")
    4. if !configured {
    5. return calcDifficultyFrontier(time, parentTime, parentNumber, parentDiff)
    6. }
    7. name, ok := f.GetString("type")
    8. if !ok { name = "" } // will fall to default panic
    9. switch name {
    10. case "ecip1010":
    11. if length, ok := f.GetBigInt("length"); ok {
    12. explosionBlock := big.NewInt(0).Add(fork.Block, length)
    13. if num.Cmp(explosionBlock) < 0 {
    14. return calcDifficultyDiehard(time, parentTime, parentDiff,
    15. fork.Block)
    16. } else {
    17. return calcDifficultyExplosion(time, parentTime, parentNumber, parentDiff,
    18. fork.Block, explosionBlock)
    19. }
    20. } else {
    21. panic(fmt.Sprintf("Length is not set for diehard difficulty at %v", num))
    22. }
    23. case "homestead":
    24. return calcDifficultyHomestead(time, parentTime, parentNumber, parentDiff)
    25. case "frontier":
    26. return calcDifficultyFrontier(time, parentTime, parentNumber, parentDiff)
    27. default:
    28. panic(fmt.Sprintf("Unsupported difficulty '%v' for block: %v", name, num))
    29. }
    30. }
    可以发现,以太坊经典对难度计算做了些小手脚,增加了两个新的算法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

    难度计算公式的其余两项:父区块难度和难度调整,以太坊经典依然沿用了以太坊的计算方法。

    实例

    以太坊经典的用户较少,我只找到了两个区块链浏览器:

    遗憾的是,他们都不能精确显示难度。不过没关系,可以在自己的机器上运行一个Geth,同步完成后就可以查看所有区块的信息了。由于Geth是命令行工具,没有漂亮的界面。如果有谁知道更好的以太坊经典区块浏览器,请留言告知我,我会及时更新。

    还是随意挑一个区块,比如4,421,544,让我们来计算一下它的难度。

    想计算区块的难度,需要知道这些信息:

    • parent_timestamp:上一个区块产生的时间

    • parent_diff:上一个区块的难度

    • block_timestamp:当前区块产生的时间

    • block_number:当前区块的序号

    在Geth的Javascript控制台中可以使用debug.printBlock(blockNumber)函数查看区块的详细信息,首先我们查一下父区块4,421,543:
    1. $echo -e `geth --exec "debug.printBlock(4421543)" attach`
    2. Block(#4421543): Size: 837.00 B {
    3. MinerHash: f4d068b903a67890cac5ddaff94a66d99a0464dfeef1c0bab3c7b3a7bf2965e4
    4. Header(2762936eb0879e86c2b0309a69fdfa3566bb3101e3cf344acf54d2534f2f3498):
    5. [
    6. ParentHash: 40f5cd2ec0be0e819c8689307c24d38edb75450358922286ec2c48e532bca427
    7. UncleHash: 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347
    8. Coinbase: df7d7e053933b5cc24372f878c90e62dadad5d42
    9. Root: de7c6ce1ea8c74644eba0579d42163c969e2c6b04cd57c1059470ca124b618ba
    10. TxSha 497f1a6fd4d13db0f2eb4d90c11670485e5305a39a6782ec68417a9b060ae5f2
    11. ReceiptSha: 57bd177107249827f9a85e2d2b28d53180be4e4fb5069d0a1fd90f3822aa0097
    12. Bloom: 00000000000000000000000000000000000000000400000000000000000000000000000000000000000000000080000008000000000000000000000000000000000100000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000800000000000000000100000000000400000000000000000400000000000000000000000
    13. Difficulty: 132145956937056
    14. Number: 4421543
    15. GasLimit: 4700036
    16. GasUsed: 58209
    17. Time: 1504744551
    18. Extra: ETC ethermine - EU2
    19. MixDigest: 7f09929b10732bb47d2473adaf172d5dfc146d560a10a6ab98c80538135ad351
    20. Nonce: 6960c3d00b731872
    21. ]

    从父区块中,我们知道了:

            parent_timestamp = 1504744551

            parent_diff = 132145956937056

    再来查一下4,421,544区块:
    1. $echo -e `geth --exec "debug.printBlock(4421544)" attach`
    2. Block(#4421544): Size: 1.55 kB {
    3. MinerHash: 89a0ecdc93471ef468f96dcb97c757b744a4a93b1fe142bed6f416552c2fd818
    4. Header(601d2019900d12781fbc0788ca3b55535b4ba6ee5337e5d7dce822860e3f9699):
    5. [
    6. ParentHash: 2762936eb0879e86c2b0309a69fdfa3566bb3101e3cf344acf54d2534f2f3498
    7. UncleHash: 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347
    8. Coinbase: 9eab4b0fc468a7f5d46228bf5a76cb52370d068d
    9. Root: 1c59d3ab4e415e217f7544b38bd73bcdda21d56865315af8fafcf7bb8726c9a9
    10. TxSha 0ff3a73cedb8687b652df84baa46a98f6cdc24d5fa6a5e4e8335839ba7938304
    11. ReceiptSha: 2d45de0f095c9655204fca5c1e93db9f203b284c1e7b981a30693a9971dc3f3c
    12. Bloom: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000080000000000000000020000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000008000000000000000
    13. Difficulty: 132081700979477
    14. Number: 4421544
    15. GasLimit: 4704624
    16. GasUsed: 254912
    17. Time: 1504744574
    18. Extra: nanopool.org
    19. MixDigest: 278b40bb8843841d6d5fcf843beeb0aeb2948b953696d884c367d5716685946e
    20. Nonce: 2850d644089a46c5
    21. ]

    从区块中,我们知道了:

            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个区块,也就是大约一年的时间内,暂时停止难度炸弹的增长。

    网上的一些文章把这次“难度炸弹延迟”称为“拆弹”是不准确的,难度炸弹依然存在,没有被去掉,只是引爆时间延后了。只要还需要挖矿,难度炸弹就会一直保留,以防止矿工掌握过大的话语权,这也是设置难度炸弹的目的。

  • 相关阅读:
    Arm机密计算架构技术(Armv9 CCA) 白皮书
    新人SOHO如何接单!
    JavaWeb 初始cookie与session
    外汇天眼:亏亏亏,为什么亏损的总是我?大数据分析报告告诉你答案
    一文讲明 网络调试助手的基本使用 NetAssist
    前端新特性
    上机实验三 图的最小生成树算法设计 西安石油大学数据结构
    springboot+jaspersoft studio6制作报表
    【三维目标检测】3DSSD(一)
    计算机科学导论
  • 原文地址:https://blog.csdn.net/qq_62294245/article/details/125438994