Geth v1.9.0 发布已一年半有余。在这期间,我们确实发布过 26 个版本(大约 3 周一次),但是主要版本发布总是更特殊一些。我的心情很微妙:一方面,新功能上线令我兴奋不已,另一方面,我又担心会出现重大失误。无论如何,以太坊正在发展,我们需要突破极限,跟上它的步伐。

言归正传,让我们欢迎 Geth v1.10.0 加入以太坊大家族。

风险提示

在详细介绍最新版本之前,我们有必要强调一下:任何新功能的推出总伴随着新的风险。为了满足风险状况不同的用户和项目的需求,许多重要功能(暂时)可以单独开启或关闭。无论你想要阅读这篇文章的所有内容,还是只阅读你感兴趣的部分,请不要略过文末的 “兼容性” 一节。

接下来,就让我们来看看 Geth v1.10.0 究竟有哪些特性!

柏林硬分叉

首先要声明一点。Geth v1.10.0 尚不可用于柏林硬分叉,因为 Solidity 团队担心 EIP 2315 最后会出现变数。由于v1.10.0 是大版本,我们不想让发布时间太接近柏林分叉。我们很快就会发布 v1.10.1,加入最终的 EIP 及相关区块编号的名单。

快照

我们一直在说快照加速(中文译本),说了很久了,现在终于出现在新发布版本中,我们心中也五味杂陈。本文不会涉及太多细节(见上面的超链接),快照(snapshot)是基于以太坊状态的加速数据结构,可大大加快读取 账户和合约存储项的速度。

具体来说,快照功能可以将访问账户的成本从 O(logN) 降低至 O(1)。乍看之下,这可能不是很多,但是在实际情况下,假设主网上有 1.4 亿个账户,快照可以为每次账户读取节省大约 8 次数据库查询。这几乎将磁盘查询量减少了一个数量级,确保其成为与状态大小无关的常量。

哇偶,这是不是说我们可以将 gas limit 提高 10 倍?很遗憾的是,不能。虽然快照确实能将读取性能提高 10 倍,但是 EVM 执行还需要写入 数据。数据写入需要经过默克尔验证。考虑到默克尔证明,磁盘写入的成本必须是 O(logN)。

既然如此,这又有什么意义呢?!虽然加快账户和合约存储的读取速度并不足以提高 gas limit,但它确实解决了一些棘手的问题:

DoS。在 2016 年,以太坊遭受了有史以来最严重的 DoS 攻击(“上海” 攻击),持续了大约 2 至 3 个月。这次攻击通过以太坊状态膨胀以及滥用各种gas 定价过低的操作码来导致以太坊网络瘫痪。经过无数次客户端优化和硬分叉再定价之后,这次危机才得以平息。但是问题的根源依然存在:状态访问操作码有着固定的 EVM gas消耗量 O(1),但是执行成本 O(logN) 是缓慢增加的。我们已经通过 “橘子口哨”(Tangerine Whistle)、“伊斯坦布尔”(Istanbul)以及即将到来的 “柏林”(Berlin)分叉状态操作码的 gas 消耗量,让 EVM 成本(名义开销)与运行时成本更加一致,但这些都只是权宜之计。快照可以将状态读取的执行成本降低至O(1)(使之与 EVM 成本更加一致),从而长期解决基于状态读取的 DoS 问题(请勿在他处引用这句话)。调用。检查以太坊上智能合约的状态需要一次微 EVM 执行。一方面是运行字节码,另一方面是从磁盘中读取状态插槽。如果你运行了一个只供自己使用的以太坊节点,当前的状态访问速度应该绰绰有余。如果你运行一个供多名用户使用的以太坊节点,快照所带来的 10 倍性能提升可以让你以同样的成本完成 10 倍数量的查询。同步。同步以太坊节点的方法主要有两种。你可以下载区块并执行区块中的所有交易。或者,你可以下载区块,验证其 PoW 证明,并下载与最新区块相关的状态。后者要快得多,但是需要通过其它节点获取最新状态的副本。在当前的 Merkle-Patricia 状态模型中,这些节点需要从磁盘上读取 16TB 的数据,才能满足节点同步需求。有了快照之后,这些节点只需从磁盘中读取 96GB 的数据,就能让新的节点加入网络。欲知更多详细信息,请阅读快照同步 部分。

和其它功能一样,快照也存在权衡取舍。虽然快照的诸多优点让我们相信它值得推广,但是需要付出一定的代价:

快照就是 Merkle Patricia trie 的叶节点中已经包含的原始以太坊状态的冗余副本。目前,快照在主网上额外需要大约 20 至 25 GB 的磁盘成本。好在,快照有望让我们进一步实现状态存储优化,并降低当前 Merkle trie 的磁盘成本。由于目前还没有人在网络中构建快照,节点最初需要自行承担迭代状态 trie 以及创建初始快照的开销。根据你的节点的负载,这可能需要耗时一天至一周,但是(一切顺利的话)每个节点在整个生命周期内只需完成一次。快照创建是在后台运行的,与其它节点操作同时执行。我们的计划是,当全网节点都可获得快照时,就不再要求节点迭代状态 trie 并创建初始快照。预知详情,请阅读快照同步 部分。

如果你对该快照功能有所顾虑,可以通过 --snapshot=false 在 Geth 1.10.0 中禁用该功能,但是请注意,未来我们将强制启用该功能,以保证网络的基准健康度。

快照同步

如果你觉得我们的效率真差、一个快照功能做了这么久,那是因为你还不了解快照同步!我们早在 2017 年 10 月就实现了一种新型同步算法的初始原型…… 那我们中间这三年干什么去了?!在讲述事情始末之前,我们先来了解一点历史背景。

以太坊上线时,你可以选择通过两种不同的方式来同步网络:完全同步 和快速同步(此处不考虑轻客户端)。完全同步就是下载整条区块链,并执行所有事务;快速同步需要信任较新的区块,直接下载与之相关的状态(然后就像完全同步一样进行区块执行)。虽然这两种操作模式最终会产生相同的数据集,但是它们各自的权衡不同:

完全同步是信任最小化的,选择执行从创世块到链首块之间的所有事务。虽然这可能是最安全的模式,但是以太坊主网目前有超过 10.3 亿笔事务,而且每天会新增 125 万笔。另外,这也意味着,完全同步的成本永远都在增加。目前,一台性能优秀的计算机也需要 8 到 10 天才能处理完所有事务。快速同步选择依靠 PoW 的安全性。快速同步无需执行所有事务,而是认为如果某个区块后面跟着 64 个拥有有效 PoW 的区块,那么对于作恶者来说,从这个区块开始分叉的成本太高。因此,下载与HEAD-64相关的状态不会有太大问题。快速同步信任较新区块的状态根,可以直接下载状态 trie。如此一来,该模式放低了对 CPU 和磁盘 IO 的需求,提高了对网络带宽和延迟的需求。具体来说,以太坊主网目前有大约 6.75 亿个状态 trie 节点。一台网络连接良好的计算机需要 8 至 10 小时才能下载完成。

只要愿意负担高昂的成本,任何人都可以通过完全同步来验证以太坊的完整历史。但是,对于绝大多数人来说,快速同步就足够了。这里存在一个计算机科学悖论,即,一旦某个系统的使用量达到设计目标的 50 倍,这个系统就会奔溃。此处的逻辑是,无论某个东西是如何运作的,只要给足压力,就会出现意料之外的瓶颈。

在快速同步模式中,意料之外的瓶颈是由以太坊数据模型导致的 延迟。以太坊的状态 trie 是一个默克尔树,其叶节点包含有用的数据,每个分支节点都是基于 16 个子节点计算得到的哈希值。如果从默克尔树的根节点开始同步(其哈希值包含在区块头内),下载所有数据的唯一方法就是逐个请求所有节点。有 6.75 亿个节点需要下载,即使每次都请求批量下载 384 个节点的数据,最终也需要 175 万次往返。假设网络中有 10 个对等节点作为数据提供方,向这些节点请求数据的往返时间为 50 毫秒,则快速同步需要等待 150 分钟以上。但是,网络延迟只是三个问题中的一个。

作为数据提供方的对等节点收到关于 trie 节点的请求时,需要在磁盘中检索它们。这里,以太坊的Merkle trie 帮不上什么忙。由于 trie 节点是以哈希值作为键的,没有什么好的方法可以批量 存储/检索 这些 trie 节点,需要逐个从数据库中读取。更糟糕的是,(Geth 使用的)LevelDB 将数据存储在 7 个层级(level)上,因此一次随机读取通常会触及 7 个文件。将这些数据全部相乘,一个批量下载 384 个节点的网络请求(每个请求需要 7 次读取)相当于 2700 次磁盘读取。速度最快的 SATA SSD 能够达到 100.000 IOPS,也就是说,会额外增加 37 毫秒的延迟。还是假设网络中有 10 个对等节点作为数据提供方,快速同步会额外增加 108 分钟的等待时间。但是,数据提供延迟是第二个问题。

请求那么多 trie 节点意味着,要上传同样多的哈希值给远程节点。有 6.75 亿个节点要下载,就有 6.75 亿个哈希值要上传,即,675 * 32 bytes = 21GB。假设全球范围内的平均上传速度是 51Mbps(存疑), 快速同步会额外增加 56 分钟的等待时间。平均下载速度是平均上传速度的 2 倍多,达到 97 Mbps,快速同步会再额外增加 63 分钟。带宽延迟是最后一个问题。

总之,快速同步模式下,仅等待数据就要花费 6.3 小时之久,而且前提条件是:

你的网络连接高于平均水平有足够数量的对等节点提供数据你的对等节点只为你提供数据

快照同步旨在解决上述三个问题。核心思想非常简单:快照同步并非逐个逐个下载 trie节点,而是下载连续的状态数据块,并在本地重构 Merkle trie:无需下载中间的 Merkle trie 节点,即可批量获取状态数据,从而解决因网络延时而导致的延迟问题。无需下载 Merkle 节点,下行数据减少一半;无需单独处理每单位数据,上行数据变得无关紧要,从而解决因带宽而导致的延迟问题。无需请求按照随机键值对排序的数据,对等节点仅执行几次连续的磁盘读取来作出响应,从而解决因磁盘 IO 而导致的延迟问题(在对等节点已经以扁平的格式存储数据的情况下)。

虽然我们的快照同步与 Parity 的压缩同步(Warp Sync)惊人地相似(也确实借鉴了后者的一些设计想法),但是相比后者有很大改进:

压缩同步依赖于每 3 万个区块创建的静态快照。这意味着,作为数据提供方的节点需要每 5 天左右重新生成快照,但是迭代整个状态 trie 实际上可能需要花费更多时间。也就是说,warp sync 不具备长期可持续性。快照同步则依赖于动态快照。无论多慢,动态快照只需生成一次,然后就会随着区块链的增长保持动态更新。压缩同步的快照格式没有采用 Merkle trie 的结构,因此无法 单独验证每个压缩数据块。同步节点需要先下载整个 20+ GB 数据集,才能对其进行验证。因此,从理论上来说,压缩同步模式对节点来说并不方便。相比之下,快照同步的快照格式是连续的默克尔树叶节点,支持验证任意大小的数据块,因此可以立即发现不良数据。

现在,我们来对比一下快照同步和快速同步的具体数据。在区块 #11,177,000,通过 3 个对等节点同步主网状态(忽略区块和收据,因为它们也一样)得到的数据如下表所示:

 时间上传下载数据包磁盘读取快速同步10 小时 50 分钟20.38GB43.8GB1607M15.68TB快照同步2 小时 6 分钟0.15GB20.44GB0.099M0.096TB-80.6%-99.26%-53.33%-99.993%-99.39%

请注意,Geth v1.10.0 已经上线快照同步功能,但是尚未启用。原因是,快照同步要求节点必须创建快照加速结构,但是目前还没有节点这么做,因为快照加速结构功能也是 Geth v1.10.0 推出的。你可以通过 --syncmode=snap 手动启用快照同步,但是我们预期要等到柏林硬分叉过去几周后才能找到合适的对等节点。等我们觉得有足够多的对等节点采用快照同步功能时,我们将默认启用该功能。

离线  “剪枝”(pruning)

过去几年来,我们对 Geth 取得的成就感到无比自豪。然而,任何人都会有羞于提及的短板。就 Geth 而言,这块短板就是状态 “剪枝” (state pruning)。那么, “剪枝” 究竟是什么意思?为什么要这么做?

处理一个新区块时,节点会将网络的当前状态作为输入数据,并根据区块中的事务将其转化成新的输出数据。输出状态与输入状态几乎相同,仅修改了几千项。由于我们无法立即覆盖旧的状态(否则无法处理区块重组),旧状态和新状态最终都会存储在磁盘上。(好吧,我们实际上比这里说的要机灵点,只有遇上在接下来几个区块都不会删除的新差异,我们才会将它们存储在磁盘上,但是先让我们暂且忽略这部分。)

如何逐个区块将这些新的状态数据发送至数据库是一个问题。状态数据会不断累积。从理论上来说,我们可以 “径直删除” 不存在重组风险的旧的状态数据,但是结果证明,这是一个非常棘手的问题。因为以太坊中的状态是以树型数据结构存储的(而且大多数区块只会改变状态的一小部分),所以这些(因网络不断出块而形成的一棵又一棵)树存储的数据有很高的重合度。我们可以轻而易举地判定旧的 trie 的根节点是否稳定且可以删除,但是要弄清楚旧状态深处的某个节点是否依然被新的节点引用需要很高的成本。

多年来,我们已经实现了一系列 “剪枝” 算法(记不清了,大概 10 个吧)来删除冗余数据,但是这些解决方案全都因为数据量达到上限而失败。因此,人们已经逐渐习惯 Geth 的数据库在快速同步之后本来很小,然后持续增长,直到你受不了并重新同步为止。这点确实很令人反感,因为重新下载只会浪费带宽,并增加节点无意义的停机时间。

Geth v1.10.0 并不能彻底解决这一问题,但是它可以极大改善用户体验。如果你已启用并完全生成快照,Geth 可以使用这些快照作为加速结构,较快决定哪些 trie 节点应该保留,以及哪些 trie 节点应该删除。基于快照修剪 trie 节点确实存在缺点,即,区块链可能会在 “剪枝” 期间停止增长。也就是说,你需要停止运行 Geth,修剪其数据库,然后重新启动客户端。

就执行时间而言, “剪枝” 需要几个小时(这很大程度上取决于你的磁盘速度和垃圾累积量),其中三分之一的时间用来从快照中为较新的 trie 节点生成索引,另外三分之一的时间用来删除旧的 trie 节点,最后三分之一的时间用来压缩数据库以释放空间。完成修剪后,你的磁盘使用情况应该与完成一次新的同步后大致相同。如需对数据库进行 “剪枝” ,请运行 geth snapshot prune-state。

请注意, “剪枝”是一个新功能,存在一定的风险。如果失败,可能会导致不良数据块。我们相信这个功能是可靠的,但是如果出现问题,就有可能对数据库造成无法挽回的破坏。我们的建议是,(至少等到该功能经过充分测试后),在 “剪枝” 之前先备份你的数据库,在进入主网之前先尝试测试网节点。

删除事务索引

以太坊诞生已有 6 年。在此期间,以太坊用户已经发布超过 10 亿笔事务。这是很大的体量。

节点运营者想当然地认为,只要有了哈希值,就可以查询过去任意一笔事务。说实说,这看似简单,但是只要算一下,你就会知道有多繁杂。为便于搜索事务,我们(至少)需要将所有事务哈希映射到它们所在的区块。即使我们通过一切权衡来尽可能减少存储,我们也需要存储区块编号(4 字节/个)及其对应的哈希值(32 字节/个)。

每笔事务 36 字节看似不多,但是乘以 10 亿笔事务之后得出的结果是,节点运营者需要存储 36 GB 的数据,才能说出事务 0xdeadbeef位于区块 N。这是很庞大的数据量,而且需要查询很多数据库条目。如果你想查询 6 年前的事务,存储 36 GB 的数据并非难以接受。但是实际上,绝大多数用户都不想。对于他们来说,额外的磁盘使用量和 IO 开销都是在浪费资源。请注意,事务索引并非共识的一部分,也非网络协议的一部分。它们纯粹是在本地创建的加速结构。

我们是否可以删除节点存储的一些无用数据?可以!Geth v1.10.0 默认开启删除事务索引功能,并设置为 235 万个区块(大约 1 年)删除一次。事务索引删除机制将在后台运行,随着新区块不断挖出,该机制将确保只有最近N个区块内的事务能被索引到,之前区块内的事务都会被删除。如果有用户想要访问之前的事务,可以设置较高的 

--txlookuplimit 值,并重启 Geth,然后原本不在查询范围内的事务将重新被索引(请注意,必须等到下一个区块才会触发)。

由于以太坊上大约 1/3 的事务负载都发生在 2020 年,这一整年的事务索引会在数据库中占据很大比重。删除事务索引的目的并非打着节省存储空间的旗号删除现有功能,而是实现一种避免存储空间随区块链历史无限增长的运营模式。

如果你想要 禁用 删除事务索引这一功能,可以在运行 Geth 时设置 --txlookuplimit=0。这样一来,你的节点就会像之前那样保留自创世块以来每笔事务的映射,以便查询。

原像丢弃

以太坊将所有数据都存储在 Merkle Patricia trie 中。叶节点中存储的值都是原始数据(如,存储插槽内容、账户内容),通往叶节点的路径就是代表数据存储位置的键。然而,这些键本身并非账户地址或存储项地址,而是账户地址或存储项地址的Keccak256哈希值。这有助于平衡状态 trie 的分支深度。使用哈希值作为键是可行的,因为以太坊用户只会引用原地址,这些原地址可以随时进行哈希计算。

然而,有一个用例是,有人在状态 trie 中存储了一个哈希值,想要恢复其原像:调试。单步执行 EVM 字节码时,开发者可能想要查看智能合约中的所有变量。即使有了数据,在没有原像的情况下,我们也很难将该数据与 Solidity 变量对应起来。

最开始的时候,Geth 采取了一种不成熟的解决方案。我们将所有源自用户调用(如,发送事务)而非 EVM 调用(如,访问插槽)的原像存储在数据库中。对于 Remix 来说,这并不够,因此我们扩展了我们的追踪 API 调用,以便存储所有 SHA3(Keccak256)操作的原像。虽然该方案解决了 Remix 的调试问题,但是非调试节点未使用的数据成了新的问题。

这些原像需要占用的存储空间并不大。如果你从创世块开始进行完全同步(重新执行所有事务),你最终只需额外承担 5 GB 的负载量。但是,对于不需要使用这些数据的用户来说,没必要保留它们,否则只会增加 LevelDB 压缩的负担。因此,Gethv1.10.0 默认禁用原像采集功能,但是没有机制可以主动删除已存储的原像。

如果你正在使用你的 Geth 实例调试事务,你可以通过 --cache.preimages 保留之前的设置。请注意,事后无法再生成原像。如果你在禁用原像采集功能的情况下运行 Geth,却又改变了主意,你需要重新导入区块。

ETH/66 协议

eth/66协议是很小的改动,但是带了很多好处。简而言之,该协议为所有双向数据包引入了请求与应答 ID。这些 ID 的目标是,降低响应与请求之间的配对难度,以便将响应传递给发出原始请求的子系统。

这些 ID 不是必不可少的。实际上,在过去 6 年中,没有这些 ID 我们也有其它变通的方法。可惜的是,如果多个子系统可以同时请求相同类型的数据(例如,同步区块链的下载器、执行区块公告的获取器以及分叉挑战都可以同时请求区块头),则所有需要向网络发出请求的代码都会变得过于复杂。此外,超时可能会导致延迟/意外交付或重新请求。在所有这些情况下,每当有区块头数据包到达时,每个子系统都会查看其数据,试图弄清楚该数据是对自己还是其他人有用。非针对特定子系统的应答会导致其它地方出现故障,需要进行适当处理。综上,这个方案虽然可行,但是会很麻烦。

就本文而言,eth/66协议的重要性并不在于它能解决某个特定问题,而在于它是在柏林分叉前引入的。由于所有节点都将在分叉时进行升级,这就意味着 Geth 可以在分叉后开始弃用旧协议。只有等到所有旧协议弃用后,我们才能重写 Geth 的内部结构,以利用请求 ID。按照我们的协议弃用计划表,我们将很快弃用eth/64,并在今年夏末弃用eth65。

有些人可能会认为,这是 Geth 在利用它的权重迫使其它客户端执行协议更新。我们想要强调一点,柏林硬分叉引入的 typed transaction 功能最初要求新的协议版本(译者注:此处应指 eth/66)。由于只有 Geth 实现了完整的eth/xy协议,其它客户端要求将该功能加入旧的协议版本(译者注:此处应指 eth/66 之前的此类协议,如 eth/64),以免不得不将全部精力集中在联网组件上。最终达成的协议是,Geth 将 typed transaction 功能向后移植到之前协议的代码中,为其他开发者争取时间,但是作为交换条件,Geth 将在 6 个月内淘汰旧版本,以免停滞不前。

ChainID 执行措施

回到 2016 年,TheDAO 硬分叉发生之后,以太坊就引入了 “链 ID” 的概念。目的是让用户签名的事务中带上特殊标识符,来区分以太坊区块链上的事务和以太坊经典区块链上的事务(以及测试网上的事务)。使得一笔事务仅在一个网络中被认定为有效,可以保证这些事务不会在当事人不知情时在另一个网络上重复发生。

为了最小化这一转变带来的问题,新的/受(重放)保护的 事务和 旧的/不受保护的 事务都被当成是有效的。5 年以后的今天,以太坊区块链上仍有约 15% 的事务是没有重放保护的。这并不意味着存在漏洞,除非你在不同的网络上重用同一把私钥。警告:千万别这么做 !当然,也有意外发生,已知有一些基于以太坊协议的网络因为重放问题而整体掉线。

因此,尽管我们不想当老大哥,我们还是决定尝试推动用户和工具都抛弃旧的、不受保护的签名,并在一切地方都使用链 ID。最简单的办法当然是在协议层让缺乏重放保护的事务无效化,但这 15% 的用户就会陷入困境,并且病急乱投医地去寻找修复程序。为了渐进地推动大家走向更安全的替代手段,而不是把桌子掀掉,Geth v1.10.0 在 RPC 中会拒绝没有重放保护的事务;但通过 P2P 协议传播的事务则保持现状,不过,我们在未来也会逐渐推动拒绝措施。

如果你在使用由 abigen 生成的代码,我们已经在 go-ethereum 代码库中加入了额外的签名建构器,可以容易地创建锁定了链 ID 的事务。遗存的那个开箱即用的签名器是在 EIP155 实施之前编写的,所以现在你要自己构筑受保护的签名。这很容易出错,而且用户会假设我们能在内部预测好链 ID,所以我们决定引入直接的 API。我们会在未来弃用并移除当前遗存的签名器。

我们知道,仍在使用不带重放保护签名的 用户/工具 不可能在一夜之间改变,所以 Geth v1.10.0 支持回复到旧版本的行为,并通过 --rpc.allow-unprotected-txs 来接收非 EIP-155 的事务。请注意,这只是暂时的。最终我们会移除这个机制。

标签弃用

在 v1.9.x 家族发展的过程中,我们已经弃用了许多命令行标签(CLI flag)。有一些是重新命名,以更恰当地遵循我们的命名规则;另一些则是因为一些功能已被丢弃(最著名的就是 Whisper),所以遭到移除。在 v1.9.x 的小更新中,我们都会保证旧的标签仍然可用,只在使用旧标签(而非推荐的新标签)时打印警告信息。

Geth v1.10.0 终于找到机会可以完全移除旧命令行标签了。如果你去年没有更新到新版本的话,下面这个列表可以帮助修正自己所用的命令:

--rpc->--http,开启 HTTP-RPC 服务器--rpcaddr->--http.addr,HTTP-RPC 服务器监听接口(listeninginterface)--rpcport->--http.port,HTTP-RPC 服务器监听端口(listeningport)--rpccorsdomain->--http.corsdomain,接受请求的域--rpcvhosts->--http.vhosts,接受请求的虚拟主机名--rpcapi->--http.api,通过 HTTP-RPC 接口提供的 API--wsaddr->--ws.addr,WS-RPC 服务器监听接口--wsport->--ws.port,WS-RPC 服务器监听端口--wsorigins->--ws.origins,接受 websockets 请求的 Origins--wsapi->--ws.api,通过 WS-RPC 接口提供的 API--gpoblocks->--gpo.blocks,检查相应区块号区块的 gas price(Number of blocks to check for gas prices)--gpopercentile->--gpo.percentile,按近期事务的百分比提供 gas 建议--graphql.addr->--graphql,在 HTTP-RPC 服务器上开启 GraphQL--graphql.port->--graphql,在 HTTP-RPC 服务器上开启 GraphQL--pprofport->--pprof.port,分析器的 HTTP 服务器监听端口--pprofaddr->--pprof.addr,分析器的 HTTP 服务器监听接口--memprofilerate->--pprof.memprofilerate,按给定比率开启内存分析--blockprofilerate->--pprof.blockprofilerate,按给定比率开启区块分析--cpuprofile->--pprof.cpuprofile,向给定文件写入 CPU 分析

上面记录的旧标签中可能有一些在接下来几个版本中仍然可用,但你不应该依赖它们。

因为大部分全节点都不会通过 Geth 来使用 USB 硬件钱包 —— 而且在不同平台上,USB 的处理有点奇怪 —— 许多节点运营者需要手动通过 --nousb 来关闭 USB 功能。为迎合大部分人的默认需求,Geth v1.10.0 会默认禁用 USB 钱包支持,并取消 --nousb 标签。你仍然可以使用 USB 钱包,只不过要手动使用 --usb。

跟踪突然关闭

我们经常收到 Geth 客户端在启动时候加载旧区块时弹出 bug 的报告。一般来说,这种现象是因为节点的运营者突然关闭 Geth 客户端(断电、内存挤爆导致保护性关闭、关机超时时间过短,等等)。因为 Geth 在内存中存储着许多脏状态(dirty state,即已被修改过的状态),以避免向硬盘写入几个区块后就会过时的状态;突然关闭会导致这些数据来不及清洗(flushed)。当启动时发现丢失了近期的状态,Geth 客户端别无选择,只能倒带,回到它上一次完整完成了功能的区块链点位上。

为了避免争议节点运营者到底有没有干净地关闭节点,也避免引入清洗功能(clean cycle)会掩盖数据丢失的事实,Geth v1.10.0 会跟踪和报告节点宕机事件。我们希望这能帮助运营者在造成不可逆的数据丢失之前,先检测到他们的错误配置或者问题所在。

WARN [03-03|06:36:38.734] Unclean shutdown detected booted=2021-02-03T06:47:28+0000 age=3w6d23h

兼容性

在临近硬分叉时发布大更新,最起码,算不上是最优策略吧。但是,每一次为 Geth 客户端软件发布下一代的大更新,都比我们预计的时间多了两个月。为了测试和缓解升级后软件在生产环境中可能出现的问题,几乎所有新功能都可以用命令行标签来关闭。距我们计划的硬分叉在主网激活的时间还剩下 6 周,可以确保我们会拥有一个平滑的体验。但不管怎么说,我们想提前为所有可能出现的不便说一声抱歉。

若想让客户端软件回复成 1.9.x版本对应的功能集合,可使用下列标签:

--snapshot=false,禁用快照加速结构和快照同步功能--txlookuplimit=0,确保为主链上所有的交易建立索引(而不是仅为过去一年的交易建立索引)--cache.preimages,保持生成及保存账户的原象--rpc.allow-unprotected-txs,以允许非重放保护的签名(non-replay-protected signatures)--usb,以重新启用 USB 钱包支持

注意,eth_protocolVersion API 调用已经删除,因为没有用处。如果你能充分说明为什么需要这个功能,请联系我们。

结语

我们一向自豪于我们的大版本更新,这次也不例外。这次更新已经推迟了太久太久,但我们以稳定性为名,保证所有关键功能都尽我们所能做了测试。我们希望这个新版本号能打开一扇门,能为提高交易吞吐量、降低交易代价尽绵薄之力。

像往常一样,我们软件的:源代码、git 标签等,见 GitHub 软件版本发行页适用于所有平台的、预构建的二进制文件,见下载页Docker 镜像,见ethereum/client-goUbuntu 安装包,见 Launchpad PPA repositoryOSX 安装包,见 Homebrew Tap repository

(完)

原文链接: https://blog.ethereum.org/2021/03/03/geth-v1-10-0/作者: Péter Szilágyi翻译&校对: 闵敏 & 阿剑