比特币2MB分叉仅仅只是改一行代码么?

2016-02-12 21:47 来源:巴比特资讯 阅读:4707
比特币区块大小上限从1百万字节(1MB)扩容至2百万字节(2MB),乍听起来似乎很简单:只需要在源代码中将数字“1”改成“2”,然后我们就大功告成了,对么?

GAVIN ANDRESEN

比特币区块大小上限从1百万字节(1MB)扩容至2百万字节(2MB),乍听起来似乎很简单:只需要在源代码中将数字“1”改成“2”,然后我们就大功告成了,对么?

如果我们并不关心什么平滑的升级,那么它可能就是那么简单的。只需要将下面这行代码(在src/consensus/consensus.h下):

... MAX_BLOCK_SIZE=1000000

改成:

... MAX_BLOCK_SIZE=2000000

如果你修改完后重新进行编译,再运行Bitcoin Core,那么它就会奏效。你的计算机会下载整个区块链,将与网络上的其他计算机互操作运算,也不会出现什么问题。

如果你的计算机正在将交易装配到区块当中(如果你是独自solo挖矿,或者你是一位矿池运营者),那事情就会变得更加复杂。我将在本文的剩余部分,解释它的复杂性,希望能让你了解下这个问题,并确保共识层的改变是安全的。

Github上有一个方便的功能,它能让你并行地比较代码;你可以访问 https://github.com/bitcoin/bitcoin/compare/v0.11.2…gavinandresen:two_mb_bump ,查看这个2MB分叉的代码更变。你应该会看到下面这个界面:

vetbbbiyb6dujq_small

上面有五个实施区块扩容的“commits”(指代码更改组) ,请忽略掉第一个David Harding的commit,那是Bitcoin Core 0.11.2的最后一个commit).

其中有22个文件发生了更改,大约有900行新的代码,其中约有一半以上(500行)是新的测试,这些更改是用来确保新的代码能够正常运行。

第一个commit是“最小共识/矿工要求2MB区块扩容, Minimal consensus/miner changes for 2mb block size bump”,更改有20行新的代码。你可以看到其中一行的变化是 MAX_BLOCK_SIZE 从 1,000,000字节变成了 2,000,000字节;剩余的变化对矿工而言是需要的,他们可以看到产出更大的区块是否是安全的。一个新的MaxBlockSize() 方法被定义为返回旧的或者是新的最大区块大小,它是根据80字节区块头中的时间戳。我可能会写一篇完整的博客文章,来解释为什么要使用时间戳来替代区块高度或者过去11个区块的中位时间,又或者其他的东西…但不是在今天。

共识变化是写在了main.cpp当中的第2816行,用的是CheckBlock() method,并采用了新的MaxBlockSize() method,来确定一个区块是否是过大的,而不是MAX_BLOCK_SIZE。一个类似的改变发生在了 miner.cpp当中的CreateNewBlock()函数,以及‘getblocktemplate’ 远程过程调用,这样矿工就可以创建更大的区块。

下一个commit(“测试基础设施修复”,Testing infrastructure fixes )增加了一些功能,并修复了用于测试比特币源代码的代码的一个漏洞。

这个代码测试代码(code-testing-code)有两个level;单元测试被放入到了 src/test/当中的tree当中,它是用C++写的,这个level是非常low的,它用来确保各部分代码的行为是得当的。在qa/rpc-tests/当中的tree,也有回归测试。它们是用 Python 写的,并使用了RPC(远程过程调用)接口命令行运行“-regtest mode”,以确保一切都是正常运作的。

“矿工投票后的2MB分叉和宽限期,Two megabyte fork after miner vote and grace period” 是迄今为止最大的一个commit,大概有700行新的代码。它实现了roll-out规则:当75%的算力所产出的区块设有特殊位的区块版本号,然后再经过28天后,才允许产出更大的区块。

75%以及28天是相当武断的选择。我讨厌武断的选择,主要是因为,关于它们每个人都会有不同的看法(也被称为“bikeshedding”,意指过于关心细节和边缘的问题,而忽视主要问题),花费数天的时间在一个徒劳的问题上进行争论。我已经在另一篇博文中解释了,为什么我们认为这些数字是很好的选择。

矿工投票以及宽限期代码,是源自我为Bitcoin XT写的BIP 101实施方案,它已经过了三个层次的测试。

在block_size_tests.cpp当中有一个新的单元测试。它测试了CheckBlock() 调用,创建精确的旧的或者新大小上限的区块,或者比旧的或者新区块大小上限要大上1个字节的区块,并对此进行测试,根据它们的时间戳是在之前还是在之后(又或者正好)在更大区块被允许的那个时刻,来确定它们是否被接受。

还有一个新的回归测试,bigblocks.py。它运行了bitcoind的四个备份,创建了一个区块-链,仅仅是用于开发人员的机器测试(在-regtest模式下,区块可即时地进行创建),然后测试了分叉激活代码,确保矿工投票是正确被计算在内的,即区块链的重新构筑是得到妥善处理的,在过渡期结束后,更大的区块才会被允许创建。这也可以确保,当2018年1月的截止日期内,75%的算力没有接受这种变化的话,那整个代码就会报告为失效。

我大部分的开发时间,都花在了确保回归测试以及单元测试上面。然后,一旦回归测试和单元测试通过,更多的测试就是在测试网络上进行了。写代码是较为容易的一部分。

最后,这部分rollout代码得到了Jonathan Toomim的验证,他已经在8MB区块和Bitcoin XT测试网络上进行了大量的测试(包括中国的长城防火墙)。

让我们继续探索代码的更改……

在main.cpp的 IsSuperMajority()函数中也有一些更改,在block.h中有一个新的VersionKnown() 函数,它们是用于计数支持各种变化区块的函数。当区块大小扩容时,它可以和BIP 009的 “version bits”以及各种软分叉 BIP(68, 112, 113, 141)在同一时间发生。

(除测试外),新代码最多的部分是在txdb.cpp。当矿工表决成功时,触发区块的哈希(hash)会写入到区块链索引。这并不是严格要求的,这部分代码会扫描区块链中所有的区块头,弄清楚投票在每一次启动时是否是成功的。它比将部分信息存储在区块链索引数据库当中,是更为有效的。

哎,描述所有这些可能的代码更改,远比写代码要花费更长的时间。这里还有2个commit要讲。

“精确sigop/sighash记账和限制,Accurate sigop/sighash accounting and limits”是很重要的,因为如果没有它,增加区块大小限制可能会是危险的。你可以看看我在去年11月份在DevCore会议上所呈现的一些细节,基本上来讲,关于交易是如何签名的,中本聪并没有考虑地非常仔细,因而可能会导致比特币创建非常大的交易,其验证代价过于的昂贵。这个commit 清理了一些“技术债”,实施了一个新的验证成本跟踪(ValidationCostTracker),它能够跟踪有多少工作是验证了交易,然后连同一个新的限制(MAX_BLOCK_SIGHASH)来使用它,确保没有人可以创建一个非常昂贵的验证区块,试图弄糟整个网络。

人们会有很强的动机不去创建昂贵的验证区块(矿工希望自己的区块能够尽快地通过这个网络,努力工作以尽量减少他们的孤块率)。但是,安全编码的原则之一是“腰带与背带”(如果你想要听起来专业点,或者不喜欢背带的说法,那就换成“深度防御”这个词)。

MAX_BLOCK_SIGHASH是另一个恼人的、主观武断的限制。它被设置为了1.3 GB , 这会是足够大的,以至于目前没有一个区块能够触及这个限制,但它也是足够小的,能够让创建需几分钟来验证的毒块(poison blocks)是可能的。

而最后一个 commit,“不要中继转发或挖取过多的sighash交易,Do not relay or mine excessive sighash transactions”,是另一种“腰带和背带”式的安全措施。当前已经有了限制,它能够拒绝非常大的,昂贵的验证交易,但是这个commit增加了另一项检查,以绝对确保一个聪明的攻击者,无法欺骗矿工将近乎疯狂的昂贵交易,放置于他们的区块当中。

如果你能坚持看完这些东西,那你的注意力跨度会比我更长。非程序员在阅读这篇文章时,我希望你能够从中了解到,从“1” 变为 “2”,需要有哪些注意的东西。

原文:http://gavinandresen.ninja/a-guided-tour-of-the-2mb-fork
作者:GAVIN ANDRESEN
译者:洒脱喜
稿源(译):巴比特资讯( http://www.8btc.com/guided-tour-of-the-2mb-fork ‎)


声明:此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述。本网站所提供的信息,只供参考之用。

点击阅读全文