事实证明,有一些重要且相当微妙的技术因素限制了区块链的扩容,无论是否实施了分片。在很多情况下,我们都会有相应的可扩展性解决方案,但即使存在解决方案也会有局限性。本文将介绍这些问题。
撰文:Vitalik Buterin 编辑:南风
特别感谢 Felix Lange, Martin Swende, Marius van der Wijden 和 Mark Tyneway 的反馈和审查。
你能把区块链的可扩展性推进到什么程度?你真的能像埃隆·马斯克所希望的那样,“将出块时间加快 10 倍,将区块大小增加 10 倍,从而将费用降低 100 倍”,而不导致极度的中心化,且不损害区块链的基本属性吗?如果不能,区块链的可扩展性能达到何种程度?如果你改变共识算法呢?更重要的是,如果你更改技术以引入 ZK-SNARKs 或分片 (sharding) 等特性,那会如何呢?理论上来说,一条实施分片的区块链可以持续添加更多的分片 (shards),那么是否可以增加非常多的分片呢?
事实证明,有一些重要且相当微妙的技术因素限制了区块链的扩容,无论是否实施了分片。在很多情况下,我们都会有相应的可扩展性解决方案,但即使存在解决方案也会有局限性。本文将介绍这些问题。
只是增加参数,所有问题都解决了。但代价是什么?
凌晨2点35分,你接到了来自世界另一端的搭档的紧急电话,这个搭档帮助管理你们的矿池 (也可能是一个质押池)。你的搭档告诉你,大约14分钟前,你们的矿池和其他几个矿池从区块链上分裂出来了,而这条链仍然拥有 79% 的网络共识节点。根据你的节点,这条拥有大多数节点的区块链的区块是无效的。且发生了余额错误:密钥区块似乎错误地将 450 万枚额外的币分配给了一个未知的地址。
一小时后,你与另外两个和你一样被打了个措手不及的小矿池,还有一些区块浏览器和交易所,在 Telegram 上聊天。最后你看到某人在聊天中粘贴出了一条推文链接,这条推文的开头写道:“新的链上可持续协议发展基金正式发布。”
到了早上,在 Twitter 上的争论,以及在某个不审查讨论的社区论坛上,到处都在讨论。但到那时,这 450 万枚币中的很大一部分已经在链上转换为其他资产,并发生了数十亿美元的 DeFi 交易。这 79% 的共识节点、所有的主要区块浏览器和轻钱包端点都在跟随这条新链了。也许新的开发基金将资助一些开发项目,或者也许这些资金将全部被领先的矿池、交易所以及他们的亲信侵吞。但无论结果如何,该基金在所有意图和目的上都是既成事实,普通用户没有办法反击。
好戏即将上演。也许它可以由 MolochDAO 或其他机构资助。
这可能发生在你的区块链上吗?你的区块链社区的精英,包括矿池、区块浏览器和托管节点,可能是非常协调一致的;很可能他们都在同一个 Telegram 群和微信群。如果他们真的想要组织一次突然的协议规则更改以助长他们自己的利益,那么他们可能可以做到。以太坊区块链曾在 10 小时内完全解决了一次共识失败问题;如果你的区块链只有一个客户端实现,并且你仅需将代码更改部署到几十个节点,那么协调一次对客户端代码的更改可以更快地完成。要让这种协调的社会攻击无效,唯一可靠的方法是通过一个去中心化的选民阵营来进行被动防御,也即用户。
想象一下,如果用户在运行验证区块链的节点 (无论是直接运行节点还是通过更高级的间接技术),且节点自动拒绝接受那些违反了协议规则的区块,即使超过 90% 的矿工或者质押者 (stakers) 支持这些区块,那么故事将如何发展呢?如果每个用户都运行一个验证节点,那么这场攻击将很快就会失败:一些矿池和交易所会以分叉的方式退出,使他们在这一过程中看起来非常愚蠢。但是,即使有一些用户运行验证节点,攻击也不会使攻击者获得彻底的胜利;相反,这会导致混乱,不同的用户会看到不同的区块链视图。至少,随之而来的市场恐慌和可能持续的链分裂将大大减少攻击者的利润。驾驭这样一场持久的冲突的想法本身就能阻止大多数袭击。
看看 Hasu 对此的看法。
如果你的社区由 37 个节点运行者和 80000 个负责检查签名和区块头的被动监听器,那么攻击者会获胜;但如果你的社区中每个人都运行一个节点,那么攻击者就会失败。我们不知道群体对协同攻击产生免疫的确切阈值是多少,但有一件事是绝对清楚的:节点越多越好,越少越糟糕,且我们肯定需要不止几十个或几百个节点。
为了最大化能够运行节点的用户数量,我们将重点关注常规消费级硬件。通过要求 (用户) 购买一些容易获得的专门硬件 (例如通过亚马逊购买) ,可以实现一些网络容量的增加,但是实际上这并没有给扩展性带来太多增加。
全节点 (full node) 处理大量交易的能力存在三个关键的限制:
对于区块链通过使用“简单的”技术能够扩容到什么程度,许多错误的结论都源于对上述这些数字的估计过于乐观。我们可以逐一分析这三个因素:
之所以限制如此之低,有四个关键原因:
请注意,直到最近,大多数关于“为什么只使用5-10%?”的解释都集中在一个不同的问题上:因为 PoW 的出块是随机的,需要很长时间来验证区块,从而增加了同时创建多个区块的风险。有很多方法可以解决这个问题 (比如 Bircoin NG,或者使用 PoS),但是这些解决方式不能解决其他四个问题,因此不能像许多人最初认为的那样在可扩展性方面获得很大的好处。
并行化 (parallelism ) 也不是万能的。通常,即使是看似单线程区块链的客户端也已经被并行化了:签名可能由一个线程进行验证,而执行由其他线程完成,并且有一个单独的线程在后台处理交易池逻辑。所有线程的使用率越接近 100%,运行节点的能耗就越高,抵御 DoS 的安全边际也越低。
如今,我们经常听到关于互联网连接能提供多少带宽的广告数据:100 Mbps 甚至 1 Gbps 都很常见。然而,广告中的带宽和预期的实际带宽之间有很大的差异,原因如下:
1)“Mbps”指的是“百万比特每秒”;比特 (bit) 是字节的 1/8,因此你需要将广告中的比特数除以 8 来得到字节数。
2) 就像所有的公司一样,互联网供应商经常撒谎。 3) 总是有多个应用程序使用同一个互联网连接,所以一个节点无法独占整个带宽。 4) P2P 网络不可避免地引入了其自身的开销:节点通常最终会多次下载并重新上传同一个区块 (更不用说交易在被打包进入某个区块之前会通过交易池 (mempool) 被广播)。
Starkware 在 2019 年做了一个实验,他们首次发布了 500 kB的区块,因为当时在交易数据 Gas 成本的降低首次使这种可能性成为可能,但实际上一些节点无法处理这种大小的区块。此后,处理较大区块的能力已经得到了改善,并将继续得到改善。但无论我们做什么,我们还远不能简单地以MB/秒为单位获取平均带宽,让自己相信我们可以接受1秒的延迟,并且能够拥有那么大的区块。
正如你可能猜到的那样,这里的主要争论与其他地方一样:理论和实践之间的差异。理论上,你可以在亚马逊上买到 8TB 的固态硬盘 (你确实需要 SSD 或 NVME;HDD 存储区块链状态太慢)。但实际上,用来写这篇博文的笔记本电脑有 512 GB,如果你让人们去买他们自己的硬件,他们中的许多人会懒得去购买 (或者他们买不起 800 美元的 8TB SSD),而是使用某个中心化的提供商。即使你可以把区块链放入某个存储空间,高水平的活动也可以轻松地快速刻录到磁盘上,迫使你不断地购买新的磁盘。
区块链协议研究人员对每个人拥有多少磁盘空间发起的投票。样本量小,我知道,但仍然可以说明问题…
此外,存储大小 (storage size) 决定了新节点能够联机并开始参与区块链网络所需的时间。现有节点必须存储的任何数据都是新节点必须下载的数据。这个初始同步时间 (和带宽) 也是用户能够运行节点的主要障碍。在写这篇博客的时候,同步一个新的 geth 节点花了我大约 15 个小时。如果以太坊的使用量超过 10 倍 (即意味着数据量增加10倍),那么同步一个新的 geth 节点将需要至少一周的时间,而且更有可能导致你的互联网连接受到限制。在攻击期间,这一点更加重要,因为对攻击的成功响应可能会涉及到许多用户在之前没有运行节点的情况下运行新节点。
此外,这三种成本 (计算能力、带宽 & 存储) 之间存在交互效应 (interaction effects)。由于数据库在内部使用树结构 (tree structures) 来存储和检索数据,因此从数据库中获取数据的成本随着数据库大小的对数而增加。实际上,由于顶层 (或顶部的几层) 可以缓存到 RAM 中,因此磁盘访问成本与数据库大小成正比,是缓存在RAM中的数据大小的好几倍。
不要从字面上理解这个图表;不同的数据库以不同的方式工作,内存中的部分通常只是一个单一 (但很大) 的层 (参见 leveldb 中使用的 LSM 树)。但基本原理是一样的。
举个例子,如果缓存是 4 GB,我们假设数据库的每一层都比前一层大4倍,那么以太坊当前的~64GB 状态将需要~2次访问。但是如果状态大小增加 4倍 到 ~256 GB,那么这将增加到~3次访问。因此,增加 4 倍的 Gas 上限实际上意味着增加 ~6 倍的区块验证时间。其影响可能更大:硬盘满的时候比几乎空的时候需要更长的时间来读写。
今天在以太坊区块链中,运行一个节点对许多用户来说已经是一个挑战,虽然至少在常规硬件上仍然是可能运行 (我在写这篇文章时刚刚在我的笔记本电脑上同步了一个节点!) 因此,我们接近遇到瓶颈。以太坊核心开发人员最关心的问题是存储大小 (storage size)。因此,目前勇敢地努力解决计算和数据的瓶颈,甚至改变共识算法,都不太可能使得 Gas 上限的大幅提高被接受。即使解决了以太坊最大的未解决的 DoS 弱点,也只会使 Gas 上限增加了20%。
存储大小问题的唯一解决方案是无状态性 (statelessness) 和状态保质期 (state expiry)。无状态性允许一类节点在无需维护永久性存储的情况下验证区块链;状态保质期会从状态中移除那些近期没有被访问的状态对象,迫使用户手动提供证明来更新它。这两种方法已经被研究了很长一段时间,关于无状态性的概念验证实现已经开始。这两种改进结合起来可以极大地缓解这些问题,并为显著提高 Gas 上限开辟了空间。但即使在无状态性和状态保质期被实施之后,Gas 上限可能也只能安全地增加 3 倍,直到其他限制开始占主导地位。
分片从根本上解决了上述限制,因为它将区块链上包含的数据与单个节点需要处理和存储的数据解耦。节点不是通过自己下载和执行区块来验证区块,而是使用先进的数学和密码技术来间接验证区块。
因此,实施分片的区块链可以安全地拥有非常高的交易吞吐量,而非分片区块链不能。这确实需要大量的密码学智慧来创建替代当前这种 (单个节点) 执行全部验证的方式,并成功地拒绝无效区块,但这是可以做到的:理论已经很完善,基于Eth2规范草案的概念证明已经在研究中。
以太坊正计划使用二次分片 (quadratic sharding),由于节点必须能够同时处理单个分片和信标链,而信标链必须为每个分片执行一定量的管理工作,因此总体的可扩展性受到了限制。如果分片太大,节点就无法再处理单个分片,如果分片数量太多,节点就不能再处理信标链。这两个限制因素带来了可扩展性的上限。
可以想象,通过三次分片 (cubic sharding),甚至指数分片 (exponential sharding),我们可以更进一步。在这样的设计中,数据可用性抽样肯定会变得复杂得多,但这是可以做到的。但以太坊只走了二次分片路线。原因是,我们从 shards-of-transactions (交易分片) 到 shards-of-shards-of-transactions (交易分片的分片) 获得的额外可扩展性提升,是无法在不使其他风险高得不可接受的情况下实现的。
那么这些风险是什么呢?
可以想象,只要有一个用户 (节点) 愿意参与其中,一条非分片的区块链就可以运行。但实施分片的区块链不是这样的:没有任何单个节点可以处理整条链,所以你需要足够的节点,让它们至少可以一起处理这条链。如果每个节点可以处理 50 TPS,而整条链可以处理 10000 TPS,那么这条链至少需要 200 个节点才能存活。如果这条链在任何时候少于 200 个节点,那么要么节点无法跟上这条链,要么节点无法检测到无效区块,或者可能发生许多其他糟糕的事情,这取决于节点软件的设置方式。
在实践中,由于需要冗余 (包括数据可用性抽样),安全的最少节点计数要比单纯的“区块链的TPS除以单个节点的TPS”高出好几倍;就上面的例子而言,不妨说需要 1000 个节点。
如果分片区块链的容量增加了10倍,那么最少节点数也增加10倍。现在,你可能会问:为什么我们不从一点点容量开始,只在我们看到大量节点时才增加容量,然后在节点数量下降时减少容量?
这有几个问题:
几乎可以肯定,如果需要的最少节点计数小于 1,000 几乎是没问题的。另一方面,如果需要至少 100 万的节点数肯定是不行的。即使需要的最小的节点计数是1万,也开始变得有风险了。因此,似乎很难证明一个实施分片的区块链拥有超过几百个分片的合理性。
用户真正看重区块链的一个重要属性是永久性 (permanence)。当公司破产或失去了维护生态系统的兴趣,存储在某个服务器上的数字资产可能会在10年后停止存在。而另一方面,以太坊上的 NFT 是永久性的。
是的,到了2371年,人们还会下载并检查你的加密猫。
但一旦区块链的容量太高,就很难存储所有这些数据,直到某个时刻,区块链历史记录的某个部分最终不再被任何人存储。
量化这种风险很容易。以区块链的数据容量MB/秒为单位,乘以~30就得到每年以 TB 为单位存储的数据量。目前的分片计划的数据容量约为 1.3 MB/秒,因此大约为 40 TB/年。如果数据容量增加10倍,这就变成 400 TB/年。如果我们希望数据不仅可以访问,而且可以方便地访问,我们还需要元数据 (例如解压 rollup 交易),那么每年就是 4 PB,10年后 40 PB。相比较而言,目前互联网档案 (Internet Archive) 使用 50 PB。这是一个合理的分片区块链的安全数据量上限。
因此,看起来在这两个维度上,以太坊分片设计实际上已经大致以相当接近合理的最大安全值为目标。常量可以增加一点,但不能增加太多。
有两种方法可以尝试扩展区块链:基本的技术改进 & 简单地增加参数。一开始,增加参数听起来非常吸引人:如果你在餐巾纸上计算一番,很容易说服自己一台消费型笔记本电脑每秒可以处理数千笔交易,不需要 ZK-SNARKs 或 rollups 或分片。不幸的是,有许多微妙的原因导致这种方法从根本上是有缺陷的。
运行区块链节点的计算机不能使用 100% 的 CPU 能力来验证区块链;它们需要很大的安全边际来抵御意外的 DoS 攻击,需要空闲容量来处理交易池中的交易等任务,并且你不希望在计算机上运行一个节点导致该计算机同时无法用于运行任何其他应用程序。带宽也有类似的开销:一个 10MB/秒的互联网连接并不意味着你每秒可以拥有一个 10MB 的区块!也许每12秒才能有1-5 MB 的区块。存储也是如此:增加运行节点的硬件需求并将节点运行限制于专业的参与者并不是一种解决方案。要想让区块链实现去中心化,让普通用户能够运行节点并拥有一个使运行节点成为常见活动的文化是至关重要的。
另一方面,基础技术的改进是可行的。目前,以太坊的主要瓶颈是存储大小 (storage size),无状态性 (statelessness) 和**状态保质期 (state expiry) 可以解决这个问题,并允许其容量增加到大约 3 倍,但不会更多,因为我们希望运行节点比现在更容易。对区块链实施分片可以进一步扩展*,因为一个实施分片的区块链中的任何单个节点都不需要处理每笔*交易。但即使这样,容量也是有限制的:随着容量的增加,最少安全节点数量也会增加,而归档整条的成本 (以及如果没人愿意去对链进行归档,数据存在丢失的风险) 也会增加。但我们不必太担心:这些限制足够高,我们可能安全地使用区块链每秒处理超过 100 万笔交易。但在不牺牲去中心化的前提下做到这一点需要付出努力,而正是去中心化让区块链变得如此有价值。
本文首发于Unitimes App
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!