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

我的网站

当前位置: 主页 > 竞争币 > 以太坊

一文澄清以太坊开发者常见误解:Gas、交易与智能合约等

时间:2020-11-02 16:19来源:未知 作者:admin 点击:
梳理以太坊程序员常见的 7 类误解。 原文标题:《引介 | 以太坊程序员的常见误解》 撰文:spalladino 翻译 校对:闵敏 阿剑 最近,我偶然读到了一篇题为《程序员关于时区的误解》的文
梳理以太坊程序员常见的 7 类误解。

 

原文标题:《引介 | 以太坊程序员的常见误解》
撰文:spalladino
翻译 & 校对:闵敏 & 阿剑

最近,我偶然读到了一篇题为《程序员关于时区的误解》的文章,让我爆笑不已。这篇文章让我想到了程序员在其它方面的误解,如人名和时间,于是我开始寻找有没有关于以太坊的。奈何寻觅无果,我只得尽自己的绵薄之力。

关于 Gas 的误解

调用 estimateGas 会返回交易所需消耗的 gas 量

调用 estimateGas 确实会返回一个 gas 耗费量,但这是该笔交易在当前状态下被打包会花费的 gas 量。而区块链的当前状态可能与你需要该笔交易上链时的状态大相径庭。因此,当你的交易被有效打包进区块时,可能会采用不同的代码路径,需要消耗的 gas 量也有可能完全不同。

如果执行的代码相同,我的交易所需消耗的 gas 量也相同。

不对。即使你使用相同的参数来执行相同的指令,gas 成本也有可能不同。例如,相比已经有非零值的存储位置,如果你要写入新的存储位置,SSTORE (写入存储操作)的成本会高得多(参见 EIP2200)。这就意味着,如果你向一个新地址发送两笔 ERC20 代币转账,第一笔交易的成本会比第二笔高得多,即使二者执行的代码完全相同。

如果状态完全相同,我的交易所需消耗的 gas 量也相同

通常情况下是的,除非你很倒霉地碰上了硬分叉,导致一些操作重新定价。虽然这听起来很复杂,但说白了就是,你无法针对 dApp 中交易的 gas 上限进行安全的硬编码,除非你决心在每次发生硬分叉后都发布 dApp 更新。

如果代码相同,状态也相同,且没有发生硬分叉,我就可以相信 estimateGas 的返回值了吗?

这下你可以相信 estimateGas 的返回值就是你的交易所需消耗的 gas 量了,但是你不知道这笔交易是否会如你所愿的那般进行。所谓的 gas 估测,就是节点将使用不同的 gas 值来尝试你的交易,并返回确保你的交易不会失败的最低 gas 值。但是,节点只会看你的交易,不会看交易的内部调用。这就意味着,如果你调用的合约代码有一个 try/catch 块,导致内部调用发生后无法撤销,你获得的 gas 估测值对调用合约来说是够用的,但是对被调用合约来说就不够了。

在多签名钱包中,这种情况经常发生:即使是在交易失败的情况下,大多数多签钱包会将操作标记为已执行,也就是说它们无法撤销最外层的交易(所带来的影响)。因此,一个原生的 gas 估测返回的值可能对多签代码来说是足够的,对你实际想运行的操作来说不一定足够。这就是为什么 Gnosis Safe 有一个专门的 gas 估测方法。

请注意,这也就是为什么因为 gas 不够而导致操作失败的情况很难察觉。内部调用可能会因为被分配到的 gas 太少而将 gas 耗尽,而交易本身可能还有很多 gas 可用。这就意味着,查看交易的 gas 使用量和 gas 上限并非检测 gas 错误的可靠方式。

管他呢,我每次多发送点 gas 就好了

多数情况下,这个方法是管用的。但是请记住,合约是可以查看它在一笔交易中收到的 gas 的。因此,可以轻而易举地将合约编写成,一旦收到过多 gas,交易就会失败。不过我怀疑的是,除了证明这一点外,这么做没有任何意义。

关于交易的误解

只要节点接受了交易,交易就会被挖出

想得美哦。以太坊的网络拥堵会导致 gas 价格波动很大,因此你的交易可能会被逐出 mempool (等待被挖出的交易集合)。如果 gas 价格飙升,你就需要重新发送交易。

我可以略微提高 gas 价格然后重新提交交易

只要你将 gas 价格提高到与你交互的节点所需的最小量(参见 txpool.pricebump ),那就没什么问题,否则还是会被拒绝。

矿工总选择 gas 价格最高的交易

并不一定。矿工可以随心所欲进行选择。他们可能会为了自己的利益而塞入自己的交易,甚至可以开一个协议外通道,为符合自己要求的用户打包交易。

但是,即使他们依据收益来决定打包优先级,如何以最优方式填满区块也是一个背包问题(knapsack problem)。由于交易无法被分割成几部分,所以,在 gas 上限为 10M 的区块中打包两个 5M gas 交易,而不是一个 6M gas 的交易,可能更为有利可图,即使 5M gas 交易的 gas 价格低于 6M gas 交易。

如果我以更高的 gas 价格发送相同的交易,矿工会选择后一个交易来替换前一个交易吗

替换交易必须在旧交易上链之前发送到矿工那里。也就是说,如果你发送了替换交易,你依然需要监控你之前发送的同一个 nonce 下的所有交易的哈希值。

关于 Nonce 的误解

我可以通过 getTransactionCount 得到我的下一笔交易的 nonce

这取决于你所使用的区块参数。如果你根据最新区块来查询你的交易记数,就会忽略你的未打包交易,并进一步导致你不小心覆盖你的某笔未打包交易。

我可以通过 getTransactionCount('pending') 得到我的下一笔交易的 nonce

虽然这在大多数情况下可行,但是你不能保证你的所有未打包交易都在你所查询的节点的 mempool 中。如果你有很多未打包交易,你所通信的节点可能已经丢弃了其中一些交易,但是这些交易仍有可能存在于其它地方!

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