织梦CMS - 轻松建站从此开始!

我的网站

当前位置: 主页 > 比特币 > 比特币资讯

技术简析柏林升级后 OpenEthereum 客户端出错始末

时间:2021-04-20 12:20来源:未知 作者:admin 点击:
以太坊柏林升级改变了 Gas 消耗量的计量方法,OpenEthereum 客户端对出错交易消耗的 Gas 计算与网络中其他客户端发生了分歧。 原文标头:《科普 | OpenEthereum 客户端 「柏林」 升级后出错

以太坊柏林升级改变了 Gas 消耗量的计量方法,OpenEthereum 客户端对出错交易消耗的 Gas 计算与网络中其他客户端发生了分歧。

原文标头:《科普 | OpenEthereum 客户端 「柏林」 升级后出错始末》
撰文:Alex Stokes
翻译:阿剑

你可能已经听说了,@OpenEthereum 客户端的一个错误导致了一些支撑以太坊网络的重要服务宕机。

我们来琢磨一下那笔造成事故的交易。

首先,我想感谢所有快速反应到 事故 并解决了问题的工程师。

另外,我没有自己跟踪所有的细节,下文中的重要事实都由用户 eb 在 Eth R&D; discord 服务器里提出。

先从那笔触发了错误的 交易 开始。

这是一笔合约调用交易,从 KuCoin 交易所发出,向许多地址分发 ETH。对该笔交易的 call data 的 ABI 编码错误,最终导致了链分裂。你可以在 Etherscan 上看看这笔交易的 「Input Data」。

1/ 在合约中调用 sendEths 时,需要提供两个参数:一个是关于目标地址的不定长数组(dynamically sized array);一个是关于转账数额(以 wei 为单位)的不定长数组;两者相搭配才知道要转移多少钱给哪个地址。

2/ 我们可以解析 call data 来看看到底哪里出了错:第一行(在 Etherscan 上标记为 「[0]」)表示地址列表从字节 64 (行 「[2]」)开始。第二行表示转移数额的列表从字节 416 (行 「[13]」)开始。

3/ 因此,大体上,我们是希望成对成对地、从上往下、向某个地址发送一定数量的 ETH —— 看起来很直接嘛。

4/ 然而,当我们开始遍历这个列表,我们先跳转到 call data 的正确字节,而 Solidity ABI 声明了数据的第一个字是整个不定长数组的长度。

5/ 这就是最终 bug 的根源:因为 call dada 中的值是 「0x10」(注意,这可是 16 进制!),但是 call data 只给出了 10 个 地址-数值对。对这个 call data 的正确 ABI 编码(填在行 [2] 和行 [13] 的)应该是 「0xA」 —— 不是 「0x10」!

6/ 你可能已经猜到了那时候会发生什么事,我们可以通过执行情况跟踪器(execution trace)来 看看。

7/ 合约成功地遍历了前 10 个地址。本来合约应该在此时停止执行,但根据 call data 的声明,还有很多个地址!那就继续执行吧。

但是,根据 call data 的结构,「第 11 个地址」 是用于编码列表长度的 0x10,所以合约就尝试发送 0 ETH 到地址 0x10

8/ 此外,似乎,当合约尝试读取并不存在的 call data 时,会返回 0 ETH —— 你可以想象成合约在这里跑出了一个错误,但它却继续发送 0 ETH 到它从 call data 中读取的另外 6 个 「地址」。

此时,你可能会注意到,0x10 有可能是我们所谓的 「特殊地址」 之一,它完全在 EVM 预编译合约的范围内(所谓 「预编译合约」,就是一类特殊合约,在 EVM 之外有最优的实现,但是编译起来与大多数合约一样)。 (责任编辑:admin)

织梦二维码生成器
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
推荐内容