跳至内容
0%

如何调试待处理的 Ethereum 交易

作者:Alchemy Team

最后更新:2021年10月20日2 分钟阅读

当你向 Ethereum 区块链发送一笔交易时,它会去往哪里?什么是 pending 交易?在它被挖出之前会发生什么?什么是 mempool?为什么有些交易成功,而另一些失败?

我们将深入探讨 Ethereum 网络上一笔交易的流转过程,从你点击"发送"的那一刻,到交易被完全挖出为止。我们还会讨论其中可能出错的地方,以及 Alchemy 的开发者工具套件如何帮助你调试并深入了解这一过程。

虽然本指南是针对 Ethereum 的,但核心原理基本适用于所有区块链!

什么是 Ethereum 交易?

一笔 Ethereum 交易,简单来说,是用户请求将新信息编码到区块链永久状态中的一种请求。这类请求的内容通常有以下几种形式:

  1. 从用户的公开账户向另一方进行简单的价值转移(例如向商家发送 ETH)
  2. 在公开区块链上编码一个新的智能合约,供第三方访问(例如发起一个新的抽奖智能合约)
  3. 向现有智能合约发送信息以与其交互(例如将你的名字和资金存入一个抽奖智能合约)

什么是 mempool?

在理解 Ethereum 的交易流转之前,我们首先需要了解什么是 mempool!mempool 是 Ethereum 节点中一个用于存放未确认交易的等候室,专门配置作为暂存区域。根据你使用的客户端不同,它也可能被称为 TX-POOL 或 TX-QUEUE。

发送到节点的交易首先会进入 mempool,并一直停留在那里,直到被网络完全确认。mempool 处理这一过程中的几个关键步骤,包括:

  1. 运行一系列验证测试,确保交易一旦提交给矿工就能成功执行。节点可能执行的验证包括:是否有足够的资金支付 gas?交易签名是否有效?该发送地址的下一个 nonce 是否正确?
  2. 根据 gas 价格对待处理的交易列表进行排序。更高的 gas 价格意味着该交易更可能被矿工优先处理。
  3. 将 pending 交易与对等节点的 mempool 共享,这些节点再继续转发给其他 mempool,从而让整个网络都能查看 pending 交易列表。当一个区块被挖出时,整个网络中 gas 价格最高的交易将被确认。

Ethereum 交易流转是什么样的?

了解了 mempool 之后,从用户发送一笔交易到这笔交易被永久存储到区块链上,中间经历了哪些步骤?

  1. 用户生成一笔新交易,用自己的私钥对交易签名,并通过调用 eth_sendTransaction 或 eth_sendRawTransaction 方法将其发送到区块链上的某个节点,这通常是通过类似 Alchemy’s Node API. 这样的服务实现的。
  2. 该交易被发送到某个节点的 mempool。
  3. mempool 运行一系列验证测试。如果交易通过这些验证,它将进入 pending 状态。
  4. 该节点会将交易广播给区块链上的其他节点,交易最终会进入它们各自的 mempool。
  5. 一旦区块链上的某个节点挖出新区块,大约 200 笔 gas 价格最高的 pending 交易将被打包进下一个区块。这些交易会从 mempool 中移除,新区块和 mempool 状态会在网络中传播。
  6. 再确认 5 - 7 个区块之后,区块链重新组织并转向另一条分叉(带有不同的已确认交易集合)的可能性将变得微乎其微。此时,可以认为该交易已经永久存在于区块链上。
从签名到区块确认的 Ethereum 交易流程图
Ethereum 交易流程

一笔 pending 的 Ethereum 交易可能会出什么问题?

1. mempool 可能已满

先从简单的说起。mempool 的大小是有限制的(除非你使用像 Alchemy 这样的工具!),无论是整个节点范围内,还是每个地址在节点中的限制都是如此。以 Geth 为例,通常限制为 4096 笔 pending 交易,Geth 会丢弃较旧的 pending 交易,优先保留较新的。

2. 你的参数可能无效

发起一笔交易时,你需要提供一系列相关参数,例如:

  • 发送地址和目标地址是什么?
  • 要转移的价值是多少?
  • 你愿意为这笔交易花费多少 gas?
  • 这笔交易当前应使用的 nonce 是多少?

如果你在填写这些内容时出错,节点通常会返回一个错误代码来说明问题所在。如果你看不懂错误信息,也无法通过 Google 找到答案,可以访问 Alchemy support center。

3. 你的 gas 价格可能过低

为了决定优先处理哪些交易,Ethereum 交易必须附带 gas 价格提交。就像普通拍卖一样,gas 价格越高,你的交易就越可能被纳入下一个区块——而 gas 价格过低则可能导致交易永远无法上链。

由于 gas 价格在一天中会因需求变化而快速且不可预测地波动,正确设置这个字段非常重要。你有几种选择:

  • 如果你是手动发送单笔交易,可以访问 ETH Gas Station website 查看最新的 gas 价格,并据此设置你的价格。
  • 如果你是通过像 Alchemy 这样的节点提供商发送请求,Ethereum JSON-RPC 规范提供了一个名为 eth_estimateGas 的端点,可以帮你估算出交易被挖出所需的 gas 量!你可以用它来实现 gas 价格的程序化自动设置。
  • 如果你希望在 gas 价格高于或低于某个特定值时收到推送通知,我们提供了一个名为 Gas Price Notifications in Alchemy Notify 的工具,可以在这些情况下专门提醒你!由于它是 webhook,因此非常容易集成到你的代码中,在 gas 价格较低时自动发送交易。
Alchemy Dashboard Demo
Free video demo

查看 Alchemy 控制台的实际操作

30 分钟引导演示:控制台中的每个工具,实时演示。

Watch the demo

4. 你的 nonce 可能不正确

啊,每个人心中都憋着一个问题——nonce 到底是什么,我为什么需要它??这是个很合理的问题,我们很高兴你问了。

简单来说,nonce 就是某个地址已发送的交易数量。如果你已经成功确认了五笔交易(nonce 0-4),那么你下一笔 pending 交易的 nonce 将是 5。

Nonce 遵循几条规则:

  • Nonce 必须按顺序发生。 nonce 为 4 的交易严格先于 nonce 为 5 的交易发生。
  • Nonce 不能重复或跳过——每笔成功的交易对应恰好一个 nonce。如果你还没有 nonce 为 5 的交易,就不能提交 nonce 为 6 的交易。同样地,你也不能提交两笔 nonce 都为 5 的交易——只有一笔会通过。

我们为什么需要它们?从密码学角度来看,nonce 是确保某个地址发出的交易按照你发送的顺序执行所必需的,同时也能保护你的交易免受双花问题的影响。

实际上,nonce 只是你在创建交易时必须设置的一个参数。这使你可以对交易顺序进行精细的手动控制。

举个实际的例子,假设你想从某个市场购买一个 NFT,然后向 Bob 支付一笔小额的"介绍费",感谢他帮你发现了这个 NFT。在这种情况下,你只想在成功购买 NFT 之后才付钱给 Bob。如果没有 nonce,你就无法同时提交这两笔交易并确保它们按特定顺序发生。使用 nonce,你只需将一笔交易标记为 nonce N,另一笔标记为 nonce N + 1!

然而,这种精细控制意味着你每次都需要以正确的 nonce 提交交易!如果你的交易卡住了,你需要检查你的 nonce,确保它按照上述规则被正确设置。

5. 你的区块可能被分叉

你会"喜欢"这一条:即使你的交易成功被挖出,你也 仍然 没有完全安全 😡 。

由于区块链是去中心化的,网络中不同的节点集合可能对网络状态有不同的看法。具体来说,偶尔会有两个矿工几乎同时挖出一个新区块,而对等节点会以相同的速率跳转到这两条新链上。在这种情况下,两条新链会并行增长——但最终其中一条会获得稍多一点的共识!

当整个网络都转向其中一条链并放弃另一条时,已经在旧链上"挖出"的交易会变成分叉交易,从而失效。这些分叉区块也被称为"叔块"(uncle blocks)。

这意味着即使你的交易已经被挖出,它仍然可能因为区块分叉而失效!你可以在这里查看 Etherscan 上的分叉区块历史记录。幸运的是,在 Ethereum mainnet 上这种情况并不常见,通常深度不超过 5 个区块,但这也是为什么 DeFi 交易协议在至少 5 - 7 个区块确认之前,永远不会认为你的交易"完全"确认。

我可以使用哪些工具来管理我的 mempool 和 Ethereum pending 交易?

Alchemy mempool watcher

假设你四十分钟前向某个节点的 mempool 发送了一笔交易,但一直没看到它在区块链上被确认。你想了解它当前的状态、发送时使用的 gas 价格,以及 nonce,以便进行核实。该怎么做?

访问你的 mempool 交易状态曾经(现在也仍然)是一团乱麻。由于查看 mempool 状态的唯一接口是通过 Ethereum JSON-RPC API,开发者们不得不花费数小时查询他们发送交易的各个节点,合并并翻查大量日志,试图手动重建整个 mempool 的状态——而这仅仅是为了一次查询。

这就是对一个繁忙 mempool 发起普通调用的样子:

mempool 状态请求返回的原始 JSON 响应,内容密集,难以阅读
祝你阅读这堆内容愉快。

更糟糕的是,当开发者为了扩展规模开始向多个节点发送请求时,会出现严重的一致性问题——由于交易源自单个节点,针对某笔特定交易的请求每次都需要被"粘性路由"到同一个节点。

为了应对这些挑战,我们构建了 Mempool Watcher ——一个简化了大量这类复杂性的工具。首先,我们处理所有节点路由问题,因此即使你可能在使用数十个节点来扩展规模,你的 mempool 始终表现为一个单一实体——mempool 请求会被正确路由到我们基础设施内相应的节点。

其次,我们为你提供了一些非常实用的工具,可以实时查看你的交易状态。交易会被标记为已挖出(mined)、pending 或已丢弃(dropped)。每条交易记录都包含该交易处于 pending 状态的持续时间、所需的 gas 量,以及访问更多详情的入口。

这是使用我们的工具查看 mempool 的效果!
这是使用我们的工具查看 mempool 的效果!

Alchemy explorer

如果你通过脚本同时向某个节点发送了二十笔不同的交易,却发现其中一些甚至都没能到达该节点,你该怎么办?如何追踪这些失败的响应并找出规律,确定原因?

与上述情况类似,作为开发者,你通常需要翻查大量日志才能找出规律。为此,我们构建了一个请求/响应浏览器工具,让你能够追踪通过我们 API 发送的 JSON-RPC 请求的状态!

Alchemy Explorer 列出的历史 JSON-RPC 请求与响应
Alchemy Explorer

我们的 Alchemy Explorer 允许你搜索通过我们基础设施发送的历史请求和响应,时间跨度从 1 秒前到 7 天前都可以!不再需要翻找日志——现代技术就在你手边。

在这些请求中,你可以按各种参数进行过滤,例如方法类型、HTTP 响应或节点特定的错误!你可以根据时间戳、请求耗时等更多选项查看请求。

为什么我应该使用 Alchemy 来管理我的交易?

Alchemy 是一个节点提供商,这意味着我们管理着向 Ethereum 区块链(以及其他几条链!)发送和接收请求所需的所有基础设施。以下是关于你为什么需要节点提供商的一些信息。

一旦你通过我们的系统发送请求,你就能获得上文提到的所有针对 pending 交易的好处:可扩展的 mempool、dashboard 工具、gas 价格 webhook。

除此之外,我们还将为你提供:

  • 访问 Alchemy's Node API 的权限,其背后由专有基础设施支持,解决了困扰区块链的可扩展性和一致性问题。
  • 访问我们 Dashboard 的权限,它通过提供像上文所讨论的那些工具,帮助你构建和监控应用程序。
  • 访问 Alchemy Notify 的权限,这是一个为区块链上发生的交易等事件提供推送通知(webhook)的工具。
  • 访问我们 Enhanced APIs 的权限,让你能够发起原本计算成本高昂或无法实现的区块链请求。
  • 还有更多,包括在各种链上访问这些功能,例如 Flow、Crypto.org,以及 L2 如 Polygon、Optimism 和 Arbitrum!

开始使用 Alchemy

解锁 Alchemy 的 Node API 和开发者工具非常简单——事实上,只需要一行代码!如果你一直在使用 web3.js 或 ethers.js,那么只需免费创建一个 Alchemy 账户,生成一个 API key,然后用类似这样的内容替换实例化代码即可:

如果你想要完整的教程,请阅读我们的 Getting Started with Alchemy guide。如果你需要更多帮助,请访问 Alchemy support center。

Alchemy 新闻通讯

第一时间获取发布信息

订阅我们的新闻通讯

获取 Alchemy 的最新产品更新和资源

A
O
D
+
超过 80,000 名订阅者

填写您的电子邮箱地址即表示您同意接收我们的营销通讯和产品更新。您确认 Alchemy 按照我们的隐私声明处理我们收到的信息。您可以随时取消订阅。