灵魂4问:以太坊2.0为什么一直“放鸽子”?
本文系以太坊Python客户端开发者Piper Merriam撰写于2020年7月7日。白计划Yaoyao经过编译整理,如有偏颇,欢迎留言指证。
Piper Merriam撰写这篇文章时,正值出现以太坊2.0可能会推迟的消息,其中Vitalik与Justin Drake对以太坊2.0的phase0阶段何时上线有不同的看法,但两位都曾表示对多客户端测试网的重视,本文即可全面理解:为什么以太坊会在主网上线前如此重视以太坊多客户端测试网?
同时,我们可以确认的是:以太坊2.0密切决定了以太坊的未来,需要谨慎为上,长久为计。
本文重点摘录:
Geth客户端的市场份额过高,超过51%;
理想情况下,希望有3个或3个以上客户端,且市场占有率相差不大;
很难相信“人月神话”;
以太坊开发者在做的事情大部分是底层的事情,表层用户看不到。
近期在Core Devs call #90进行过程中,所有开发者几乎都在讨论一个问题。
(白计划编注:CoreDevscall#90是以太坊在7月初的核心开发者会议,记录链接如下:https://www.youtube.com/watch?v=IZEcukn9J0Y)
在连线讨论中,Alexey提到了客户端开发者的“倦怠”问题。虽然我认为这是这次对话重要的开端,但我也认为需要在充分理解问题之前要先有解决方案。花点时间来规划问题是很重要的。探索问题的一个简单而有效的框架是五个为什么。
所以,废话不多说,让我们来看看我们的第一个“为什么”。
问题一:
为什么Geth团队在紧张的环境下运作,以致于耗尽精力?
查看来自etherscan的客户端市场份额统计数据,我们可以看到以下分布情况。
Geth: 75%
Parity & OpenEthereum: 20%
Nethermind: 1%
剩下的4%分布在市场份额低于1%的客户端类别中,我们将忽略这一点。
重要的是Geth的市场份额超过了算力攻击的51%。假设在即将到来的Berlin硬分支中,Geth对包含的某一个EIP的实现存在bug,即使其他客户端实现都没有这个bug,当遇到这个bug的块时,网络将会分叉。 而这个块是无效的,其他所有的客户端也将认为是无效的,但在所有挖矿节点中超过51%运行Geth的情况下,整个网络将遵循错误的链。
这样的“可能”要求Geth客户端和团队具备极高的正确性要求。
所以面对我们第一个“为什么”,我们的答案是:
因为以太坊网络缺乏足够的客户端多样性。
值得注意的是,客户端多样性不会突然让客户端开发成为一项轻松的工作。这仍然是一个值得单独探索以尝试找到让客户端开发更有回报、更轻松的方法,但我们也必须承认,我们似乎无法通过简单聚焦Geth团队来有效地解决这个问题。
问题二:
为什么以太坊网络缺少客户端多样性?
当以太坊主网启动时,我们有多个客户端。其中最突出的是Geth和CPP-Ethereum。随后,Parity加入了,CPP-Ethereum则解散了。
(白计划编注:CPP-Ethereum是C++版本的客户端)
自那以来,除了Parity之外,没有客户端获得过任何更可观的市场份额。去年,Nethermind出现了,并且看起来很有前途,但Nethermind目前的市场占有率仅为1%。最近,由于Parity未来的确定性,Parity的市场份额也大幅下降。
我们理想的情况是: 存在3个或3个以上的客户端 ,每个客户都占有相当大的市场份额,并且没有一个客户的份额超过51%。最理想的情况是有多个客户端,但我们已经习惯了一个绝对占比的客户端。
那我们为什么没有更多的客户端呢?
从我个人的经验来看,建立一个以太坊客户端是非常困难的。Geth充满了复杂的运行优化问题。这也耗费了Geth团队几年的时间来构建这个复杂级别,现在他们还在继续优化。
有些人可能会建议我们找到方法,为处于劣势的客户端提供支持和帮助。我对依靠“人月神话”得到的解决方案是非常谨慎的——在软件开发中,把更多的工程师投入到一个困难的问题上很少会成功,我也不期望它在这里成功。
(白计划编注:人月神话是编程领域的梗,可以解释为一个人干10月的工作量不等于10个人干一个月,意思是即使很多人加入编程,并不能把效率成倍提升。)
相反,我认为关注复杂性本身是更合适的。
问题三:
为什么建立一个以太坊客户端很难?
现在我们正在接近问题的根源。
事实证明,networking协议中存在很多困难,也就是Ethereum客户端用来相互连接和共享关于区块链信息的工具集。Ethereum(在devp2p中定义)的网络规则最终影响甚至决定了Ethereum客户端的设计和需求。
一些网络工具规定了局部最优的体系结构,甚至要求客户端操作可能并不需要的功能。而客户端开发人员需要在这些约束条件下工作。
问题四:
为什么网络协议使客户端实现困难?
我相信这个问题的答案大致可以分为两类。
1.状态管理
2.整体网络需求
对于状态管理,Ethereum客户端需要能够通过网络同步完整状态,并维护状态的本地副本。这两方面都很困难。对于正在同步的客户端和读取状态并其提供服务的服务器而言,同步状态涉及生成数百万个请求并且将使磁盘的I/O过程饱和。随后还需要维护和精简新同步的状态,以保持数据库足够快地执行新块。这是一个重要的工程挑战!
我们唯一的状态同步的网络工具,GetNodeData针对特定的状态数据库格式进行了优化。由Turbo Geth推广的“扁平”数据库结构在维护状态方面有很大的性能优势(在编写时约为44GB),但使用这种结构会使网络上处理GetNodeData请求变得更加困难。
当我们把注意力转移到网络堆栈上,特别是DevP2P ETH协议时,我们发现其他东西增加了客户端的复杂性。为了使这个网络的一个客户端需要能够:
为最近块的任意状态访问提供GetNodeData请求。
为链数据的整个历史(包括区块头、区块体和收据)提供请求。
为这些请求提供服务所需的底层数据对于许多客户端操作来说并不是必要的,但目前必须支持这些特性。这就要求所有的客户端要构建大量的功能,而这些功能对于客户端来说,并不是必需的。例如,主要充当发送事务网关的客户端不需要历史链数据,可能只需要状态的一个小子集,但是在Ethereum的当前版本中,它仍然必须保留完整的副本。
问题五(此处很调皮)
似乎我只需要4个“为什么”就能找到根本原因。以太坊协议并没有很好地成长。在它被设计出的时候,我们今天看到的大多数问题还没有被理解,或者它们还不是问题,因为整体规模还小,链还很短。
如何解决?
去年的大部分时间我都在关注这个问题。我仍然惊讶于Ethereum中有多少问题可以追溯到底层的网络层。
最突出的例子可能是,磁盘I/O一直是客户端的瓶颈。而存在瓶颈的原因是,客户端倾向于使用trie的简单表示来实现状态数据库。而状态数据库构造方式的选择是由GetNodeData网络结构决定的。
要解决这个问题,我们需要对实际的以太坊共识层和底层网络层的部分内容进行全面检查。在过去的8个月里,Alexey和我领导的“无状态以太坊”项目已经进行了大量的工作。通过去年的SNAP同步协议,Geth团队已经缓解了其中的一些问题。但其中一些仍然需要有才能的人来集中精力,深入理解问题然后找出可行的解决方案。
DevP2P ETH协议仍然有一部分没有解决。我们对如何将网络分成三个独立的专用网络有了基本的了解,但目前还没有人直接对此进行研究。
还有像再生这样的想法提供一种机制来完全规避一些问题。这是一个激进的方法,如果它成功了,可能会给我们带来很多好处。
你应该从获取的信息是是,以太坊网络有很多困难的工作需要做,有这样技能且完成这项工作的人是有限的。虽然每天都有开发人员加入进来,但是要想做出有意义的贡献,需要花时间和精力去学习所有的东西。我们添加的每一个EVM特性都占用了客户端开发人员的时间,他们关注的是底层的问题,这些问题在很大程度上是网络的日常用户看不到的。
长远来看,如果我们想要成功的以太坊网络,作为一个社区,我们需要一起思考这些问题,确保引发问题的根本原因得到有效的关注和讨论,最重要的是,我们需要集中精力共同努力,找到有意义的技术解决方案。