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

以太坊经典的难度计算

以太坊经典的代码同样是开源的,区块链也完全公开,没什么问题是读一遍代码弄不明白的,如果有,就再读一遍。
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

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

实例

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

遗憾的是,他们都不能精确显示难度。不过没关系,可以在自己的机器上运行一个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: f4d068b903a67890cac5ddaff94a66d99a0464dfeef1c0bab3c7b3a7bf2965e4
Header(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: 89a0ecdc93471ef468f96dcb97c757b744a4a93b1fe142bed6f416552c2fd818
Header(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个区块,也就是大约一年的时间内,暂时停止难度炸弹的增长。

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

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
)">
下一篇>>