---
title: "如何调试待处理的 Ethereum 交易"
description: "了解 Ethereum 交易从发送到挖矿的全过程，包括内存池（mempool）、待处理交易，以及 Alchemy 的工具如何提供帮助。"
---

# 如何调试待处理的 Ethereum 交易

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

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

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

## 什么是 Ethereum 交易？

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

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

## 什么是 mempool？

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

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

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

## Ethereum 交易流转是什么样的？

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

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

<ImageBlock
  src="https://media.alchemy.com/1703772601-ethereum-transaction-flow.jpeg"
  alt="从签名到区块确认的 Ethereum 交易流程图"
  width={1335}
  height={1600}
  caption="Ethereum 交易流程"
/>

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

### 1. mempool 可能已满

先从简单的说起。mempool 的大小是有限制的（除非你使用像 Alchemy 这样的工具！），无论是整个节点范围内，还是每个地址在节点中的限制都是如此。以 [Geth](https://www.alchemy.com/overviews/what-is-a-geth-node-and-how-to-run-one) 为例，通常限制为 4096 笔 pending 交易，Geth 会丢弃较旧的 pending 交易，优先保留较新的。

### 2. 你的参数可能无效

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

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

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

### 3. 你的 gas 价格可能过低

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

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

- 如果你是手动发送单笔交易，可以访问 **ETH Gas Station website** 查看最新的 gas 价格，并据此设置你的价格。
- 如果你是通过像 Alchemy 这样的节点提供商发送请求，Ethereum JSON-RPC 规范提供了一个名为 [**eth_estimateGas**](https://www.alchemy.com/docs/node/ethereum/ethereum-api-endpoints/eth-estimate-gas) 的端点，可以帮你估算出交易被挖出所需的 gas 量！你可以用它来实现 gas 价格的程序化自动设置。
- 如果你希望在 gas 价格高于或低于某个特定值时收到推送通知，我们提供了一个名为 [**Gas Price Notifications in Alchemy Notify** ](https://www.alchemy.com/docs/reference/notify-api-quickstart)的工具，可以在这些情况下专门提醒你！由于它是 webhook，因此非常容易集成到你的代码中，在 gas 价格较低时自动发送交易。

<VideoCta
  title="查看 Alchemy 控制台的实际操作"
  description="30 分钟引导演示：控制台中的每个工具，实时演示。"
  ctaHref="/resources/dashboard-demo"
  thumbnail={{
    src: "https://media.alchemy.com/alchemy-dashboard-demo-thumbnail.png",
    alt: "Alchemy Dashboard 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 是确保某个地址发出的交易按照你发送的顺序执行所必需的，同时也能保护你的交易免受[双花问题](https://en.wikipedia.org/wiki/Double-spending)的影响。

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

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

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

### 5. 你的区块可能被分叉

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

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

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

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

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

### Alchemy mempool watcher

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

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

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

<ImageBlock
  src="https://media.alchemy.com/1704722572-successful-request-to-the-mempool-to-fetch-its-status.jpg"
  alt="mempool 状态请求返回的原始 JSON 响应，内容密集，难以阅读"
  width={1600}
  height={683}
  caption="祝你阅读这堆内容愉快。"
/>

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

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

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

<ImageBlock
  src="https://media.alchemy.com/1704724124-alchemy-mempool-watcher.png"
  alt="这是使用我们的工具查看 mempool 的效果！"
  width={1600}
  height={579}
  caption="这是使用我们的工具查看 mempool 的效果！"
/>

### Alchemy explorer

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

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

<ImageBlock
  src="https://media.alchemy.com/1704724183-alchemy-explorer.png"
  alt="Alchemy Explorer 列出的历史 JSON-RPC 请求与响应"
  width={1600}
  height={928}
  caption="Alchemy Explorer"
/>

我们的 [**Alchemy Explorer**](https://dashboard.alchemy.com/explorer) 允许你搜索通过我们基础设施发送的历史请求和响应，时间跨度从 1 秒前到 7 天前都可以！不再需要翻找日志——现代技术就在你手边。

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

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

Alchemy 是一个节点提供商，这意味着我们管理着向 Ethereum 区块链（以及其他几条链！）发送和接收请求所需的所有基础设施。以下是关于[你为什么需要节点提供商的一些信息。](https://www.alchemy.com//overviews/blockchain-node-providers)

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

除此之外，我们还将为你提供：

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

## 开始使用 Alchemy
解锁 Alchemy 的 Node API 和开发者工具非常简单——事实上，只需要一行代码！如果你一直在使用 [web3.js](https://www.alchemy.com/dapps/web3-js) 或 [ethers.js](https://www.alchemy.com/dapps/ethers-js)，那么只需[免费创建一个 Alchemy 账户](https://alchemy.com/?a=a437fb8d33)，生成一个 API key，然后用类似这样的内容替换实例化代码即可：

如果你想要完整的教程，请阅读我们的 [Getting Started with Alchemy guide](https://www.alchemy.com/docs/alchemy-quickstart-guide)。如果你需要更多帮助，请访问 [Alchemy support center](https://www.alchemy.com/support)。
