> ## Documentation Index
> Fetch the complete documentation index at: https://docs.monad.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# 常见问题

## 执行

<Accordion title="操作码定价是否存在任何差异？">
  一些操作码和预编译已重新定价，以便更准确地反映其相对成本。详情见[此处](/zh/developer-essentials/opcode-pricing)。
</Accordion>

<Accordion title="Monad 的乐观并行执行如何处理相互依赖的交易？">
  在 Monad 中，与以太坊一样，交易在一个区块内按线性顺序排序。Monad 提供的保证是，每个区块结束时的结果就像交易被串行执行一样，即使实际上底层是并行完成的工作。

  Monad 通过将**计算**（可以并行完成）与**提交**（仍然串行完成）的关注点分开，优雅地处理相互依赖的交易。

  交易被乐观地并行计算（即假设执行期间读取的任何存储槽都是正确的），为每笔交易生成一个**待定结果**。待定结果由输入存储槽（及其值）和输出存储槽（及其值）的集合组成。

  待定结果按交易的原始顺序**串行**提交，在提交时检查每个输入的正确性。（如果输入被之前提交的待定结果之一变更过，则输入将不正确。）如果待定结果有任何不正确的输入，将被重新执行；在此之前不能提交其他待定结果。

  串行提交待定结果确保始终保持正确性。

  <Note>
    最好用一个例子来说明。假设在区块开始时，Alice、Bob 和 Charlie 各自都有 100 USDC 余额。以下是前两笔交易：

    | 交易 # | 发生了什么                    |
    | ---- | ------------------------ |
    | 0    | Alice 向 Bob 发送 5 USDC    |
    | 1    | Bob 向 Charlie 发送 10 USDC |

    当交易 0 和 1 并行执行时，它们产生以下待定结果：

    | 待定结果 # | 输入                          | 输出                         |
    | ------ | --------------------------- | -------------------------- |
    | 0      | Alice: 100<br /> Bob: 100   | Alice: 95<br /> Bob: 105   |
    | 1      | Bob: 100<br /> Charlie: 100 | Bob: 90<br /> Charlie: 110 |

    现在我们串行提交待定结果。待定结果 0 被提交。当我们尝试提交待定结果 1 时，我们注意到其中一个输入是错误的 —— 期望 Bob 的余额为 100，但实际为 105。这会重新触发交易 1 的执行。在重新执行交易 1 之前不能提交其他交易。
  </Note>
</Accordion>

<Accordion title="在乐观并行执行中，如果交易首次执行的输入随后被变更，则会重新执行。如果存在长串的串行依赖交易怎么办？">
  *（注：此问题询问的是[此处](/zh/monad-arch/execution/parallel-execution#optimistic-execution)讨论的重新执行。）*

  虽然重新执行待定结果确实比立即提交它慢，但重新执行通常也比原始执行快得多，因为输入存储在缓存（RAM）中。还请注意每笔交易最多执行两次：初始一次，重新执行一次。

  更一般地，您可以将乐观并行执行视为两遍策略。第一遍并行开始执行许多交易，从而并行揭示许多存储槽依赖关系并将它们全部拉入缓存。第二遍串行遍历交易，要么立即提交待定结果，要么重新执行它（但从大多数存储槽已缓存的位置）。此策略结合来自 [MonadDb](/zh/monad-arch/execution/monaddb) 的高效 SSD 查找，交付出可以更高效地利用全部 SSD 吞吐量的工作负载。
</Accordion>

<Accordion title="我需要更改我的代码以利用 Monad 的并行性吗？为了降低两笔交易接触同一合约的概率，将合约拆分成许多合约是否有意义？">
  不需要！与您的智能合约交互的交易表现得就像每笔交易都在串行执行。并行执行严格来说是一种实现细节。

  另外，重要的是要注意所有状态争用都是按槽评估的。例如，假设交易 1 涉及 Alice 向 Bob 发送 USDC，交易 2 涉及 Charlie 向 David 发送 USDC。两笔交易都涉及同一智能合约（USDC ERC-20 合约）并无关系；交易 1 中受影响的两个存储槽与交易 2 中受影响的两个存储槽完全独立。
</Accordion>

<Accordion title="MonadDB 相较于传统数据库在 EVM 状态存储方面引入了哪些具体优化？">
  MonadDb 原生存储 Merkle Patricia Trie 数据，而不是将 trie 嵌入到通用数据库（如 LevelDB 或 RocksDB）中，后者有自己的数据库条目到磁盘位置的映射逻辑。这消除了一层间接性，并大幅减少了查找一个值所需的 IOPS 和页读取次数。诸如在每个区块结束时重新计算 merkle 根之类的 trie 操作效率更高。

  MonadDb 通过使用 `io_uring` 实现异步 I/O 并绕过文件系统，进一步降低了延迟并提高了吞吐量。`io_uring` 是一种新的 linux 内核技术，允许执行线程在不阻塞或占用线程的情况下发出 I/O 请求。这允许许多 I/O 请求并行发出、由内核排序、并在返回时由第一个可用线程处理。

  最后，在 MonadDb 中，trie 中的每个节点都是版本化的，允许直观地维护 merkle trie 和高效的状态同步算法。在 statesync 期间仅发送必要的 trie 组件，使引导和恢复更快。
</Accordion>

<Accordion title="为什么 Monad 不将 EIP-2930 访问列表设为强制？这不会使执行更高效吗？">
  1. 使用访问列表通常会增加交易的大小；长期来看，我们认为带宽是最大的瓶颈

  2. 在以太坊中，用户使用访问列表提交交易的工作流是：模拟交易，注意访问了哪些存储槽，然后使用访问列表中提到的这些槽提交交易。然而，世界状态可能在模拟和真实执行之间发生变化；我们认为系统应该在底层优雅地处理这一点。

  3. 这会破坏与不支持 EIP-2930 的现有钱包的集成。

  4. 请注意，EIP-2930 访问列表实际上是欠规范的，至少从预测状态争用的角度来看。如果两笔交易都从同一存储槽读取（但都不写入），那么就该存储槽而言，没有状态争用 —— 任一交易都无法使另一笔交易的计算无效。仅当较早的交易写入较晚的交易将读取的存储槽时，争用才会发生。EIP-2930 访问列表提到访问了哪些存储槽，但不注明交易是从该存储槽读取还是写入。
</Accordion>

## 共识

<Accordion title="Leader 是如何被选择的？">
  Leader 时间表由确定性、按质押权重加权的过程构建，每个 epoch 计算一次：

  * epoch 大约每 4 小时 12 分钟（50,000 个区块）发生一次。验证者的质押权重被锁定提前一个 epoch（即 epoch N+1 的任何变化必须在 epoch N 开始之前注册）。
  * 在每个 epoch 开始时，每个验证者基于对质押权重运行确定性伪随机函数来计算 leader 时间表。由于函数是确定性的，每个人都会得出相同的 leader 时间表。
</Accordion>

<Accordion title="有多少节点可以参与共识？参与是否无需许可？">
  客户端代码库有一个称为 [`ACTIVE_VALSET_SIZE`](/zh/monad-arch/consensus/staking#constants) 的参数，当前设置为 200。因此，排名前 200 的 validator（按质押权重排序）可以直接参与共识。此参数可能会随时间变化。

  参与无需许可；只需成为前 `ACTIVE_VALSET_SIZE` 名 validator 之一即可。
</Accordion>

### Raptorcast

<Accordion title="在哪里可以找到 RaptorCast 的详细描述？">
  请查看[这篇](https://www.category.xyz/blogs/raptorcast-designing-a-messaging-layer)博文！
</Accordion>

<Accordion title="为什么 RaptorCast 选择 UDP 而不是 TCP？">
  请参见[这篇](https://www.category.xyz/blogs/raptorcast-designing-a-messaging-layer)博文中的讨论。选择 UDP，接受其损耗特性但通过添加额外的数据完整性（Raptor 码）和消息认证（对 merkle 根的签名）来缓解，因为这些策略在 UDP 上的组合比使用 TCP 效率高得多。
</Accordion>

<Accordion title="Raptorcast 与以太坊、Solana 或 L2 中的传播方法有何不同？">
  以太坊使用 [libp2p](https://blog.libp2p.io/libp2p-and-ethereum/)。它基于 gossip（每个节点将其消息传播到一组对等节点），效率低得多（更多重复消息以及更曲折的传播过程）。因此，以太坊为区块在网络中的传播预算了数秒。

  Solana 使用 [Turbine](https://www.helius.dev/blog/turbine-block-propagation-on-solana)。Turbine 和 RaptorCast 在使用擦除码、将数据包切分为 MTU 大小的块、并通过广播树发送交易以提高效率方面相似。一些差异包括：

  * Monad 使用 Raptor 码，而 Turbine 使用 Reed-Solomon
  * Monad 使用两级广播树，每隔一个 validator 作为一级节点，而 Solana 使用更深、结构更少的广播树，一级节点更少，确定广播树的逻辑更复杂。Solana 没有 Monad 那样的区块交付 BFT 保证。

  在 L2 中只有 1 个 sequencer，因此没有用于共识的区块传播概念。Sequencer 只是偶尔将交易批次推送到 L1。
</Accordion>

### Mempool

<Accordion title="如果 nonce 存在缺口，缺口之后的交易是否会保留在 mempool 中？">
  例如，如果我的 EOA 当前 nonce 为 0，然后我发送一笔 nonce 为 3 的交易，然后我再发送 nonce 为 0、1、2 的交易。nonce 为 3 的交易会被执行还是被丢弃？

  答：交易 3 会被执行。
</Accordion>

## 区块状态与最终确认

<Accordion title="节点何时可以开始执行区块？">
  一旦收到新区块提议，节点就可以开始[推测性](/zh/monad-arch/consensus/asynchronous-execution#speculative-execution)执行。执行一个区块只是生成新的状态和新的 merkle trie 根 —— 但官方指针仍然指向旧的。这就像从老师那里收到一份即将确定的可能作业 —— 您可以在新纸上开始做，如果结果不需要这份作业就扔掉。
</Accordion>

<Accordion title="节点何时可以确定状态？">
  一旦区块进入 [Finalized](/zh/monad-arch/consensus/block-states) 状态，该区块推测执行的 merkle 根就成为该区块的官方本地 merkle 根。该 merkle 根还要再过 `D=3` 个区块才会被共识验证，但它在本地已知，因为在固定交易顺序下状态是确定性的。

  如果您想确保您的本地节点没有出现计算错误（例如由于宇宙射线），您可以等待 `D=3` 个区块以获得延迟的 merkle 根，这会使相关区块进入 [Verified](/zh/monad-arch/consensus/block-states) 状态。
</Accordion>

## RPC

<Accordion title="在用旧区块编号调用 `eth_call` 时，我收到此响应：`Block requested not found. Request might be querying historical state that is not available. If possible, reformulate query to point to more recent blocks`。这是怎么回事？">
  由于 Monad 的高吞吐量，全节点不提供对任意旧状态的访问，因为这需要过多存储。有关更完整的讨论，请参见[历史数据](/zh/developer-essentials/historical-data)。

  编写智能合约时，建议使用事件记录以后需要的任何状态，或使用[智能合约索引器](/zh/tooling-and-infra/indexers/indexing-frameworks)在链下计算它。
</Accordion>

## 特性

<Accordion title="是否支持 EIP-7702？">
  是的，支持 EIP-7702。

  请注意，在账户根据 EIP-7702 进行委托时，它们在 Monad 的[储备余额](/zh/developer-essentials/reserve-balance)规则下的处理会略有变化。您可以在[此处](/zh/developer-essentials/eip-7702)了解更多。
</Accordion>

<Accordion title="是否支持 EIP-7951（或 RIP-7212）？">
  是的，它是遵循 EIP-7951 位于 `0x0100` 的预编译。这使得可以使用 P256 曲线在链上验证 WebAuthn/passkey 签名。有关使用详情和 Solidity 示例，请参见[预编译](/zh/developer-essentials/precompiles#p256-signature-verification)。
</Accordion>

## 杂项

<Accordion title="如果只有 100-200 个投票节点，那么低验证者硬件要求（32 GB RAM、2x 2TB SSD、16 核 CPU）的意义是什么？">
  Monad 的核心目标是去中心化。如果运行节点非常昂贵，只有拥有大量质押的专业 validator 公司才能证明成本合理。使节点经济实惠对于任何人都能运行全节点以及支持大型 validator 集至关重要 —— 100-200 节点的主网首日目标只是一个起点。
</Accordion>

<Accordion title="为什么共识客户端选择 rust，而执行选择 C++？">
  Rust 和 C++ 都是很好的高性能语言。C++ 被选中用于数据库和执行系统，以更精细地控制文件系统，并使用 `io_uring` 和 `boost::fibers` 等库。Rust 被选中用于共识，以利用更严格的内存安全性，因为共识关注的是稍高级别的系统工程问题。
</Accordion>
