> ## 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.

# 历史数据

export const CopyToClipboard = ({value, children}) => {
  const [copied, setCopied] = useState(false);
  const handleCopy = async () => {
    try {
      await navigator.clipboard.writeText(value);
      setCopied(true);
      setTimeout(() => setCopied(false), 1000);
    } catch {
      const textarea = document.createElement("textarea");
      textarea.value = value;
      textarea.style.position = "fixed";
      textarea.style.opacity = "0";
      document.body.appendChild(textarea);
      textarea.select();
      document.execCommand("copy");
      document.body.removeChild(textarea);
      setCopied(true);
      setTimeout(() => setCopied(false), 1000);
    }
  };
  return <span style={{
    display: "inline",
    whiteSpace: "nowrap"
  }}>
      {children}
      <button onClick={handleCopy} title={copied ? "Copied!" : "Copy to clipboard"} style={{
    background: "none",
    border: "none",
    cursor: "pointer",
    padding: "2px",
    display: "inline-flex",
    alignItems: "center",
    verticalAlign: "middle",
    marginLeft: "4px",
    opacity: copied ? 1 : 0.4,
    transition: "opacity 0.15s"
  }} onMouseEnter={e => {
    if (!copied) e.currentTarget.style.opacity = "0.8";
  }} onMouseLeave={e => {
    if (!copied) e.currentTarget.style.opacity = "0.4";
  }}>
        {copied ? <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#22c55e" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
            <polyline points="20 6 9 17 4 12" />
          </svg> : <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
            <rect x="9" y="9" width="13" height="13" rx="2" ry="2" />
            <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" />
          </svg>}
      </button>
    </span>;
};

## 摘要

Monad 全节点提供对所有历史交易数据(区块、交易、收据、事件和 trace)的访问。

Monad 全节点不提供对任意历史状态的访问。

<Note title="solution">
  <div>
    有一个特殊的 RPC 服务位于

    <CopyToClipboard value="https://rpc-mainnet.monadinfra.com">
      [`https://rpc-mainnet.monadinfra.com`](https://rpc-mainnet.monadinfra.com)
    </CopyToClipboard>

    提供对历史数据的访问。该服务的以下方法支持引用历史状态的查询:

    <ul>
      <li>[`debug_traceCall`](/zh/reference/json-rpc/api)</li>
      <li>[`eth_call`](/zh/reference/json-rpc/api)</li>
      <li>[`eth_createAccessList`](/zh/reference/json-rpc/api)</li>
      <li>[`eth_estimateGas`](/zh/reference/json-rpc/api)</li>
      <li>[`eth_getBalance`](/zh/reference/json-rpc/api)</li>
      <li>[`eth_getCode`](/zh/reference/json-rpc/api)</li>
      <li>[`eth_getTransactionCount`](/zh/reference/json-rpc/api)</li>
      <li>[`eth_getStorageAt`](/zh/reference/json-rpc/api)</li>
    </ul>
  </div>
</Note>

## 背景

区块链是有状态的系统;主要有两种数据:

1. **交易数据**(交易列表及其产物);以及
2. **状态数据**(世界的当前状态,由按顺序应用这些交易得出;存储在 merkle trie 中)。

交易数据包括

* 区块
* 交易
* 执行这些交易产生的收据
* 智能合约在执行过程中发出的事件(日志)
* 每笔交易执行的详细 trace

状态数据包括

* 每个账户的原生代币余额
* 每个智能合约的存储映射(将存储槽映射到值)

区块链中的典型节点持有当前状态,该状态随着新交易的添加而不断更新。
最近的历史状态也可能可用,具体取决于每个增量版本的成本以及可用的磁盘空间。

作为参考,想象一下维护一个 MySQL 或 Postgres 表,其中每个 `INSERT` 或 `UPDATE` 查询都是一笔交易。
如果表足够小,那么缓存表的每个新版本可能是可行的,但如果是一个大表,您可能只能访问当前版本。

以下描述了 Monad 中的历史数据访问:

## 交易数据

Monad 全节点提供对所有历史交易数据(区块、交易、收据、事件和 trace)的访问。[^1]

## 状态

在以太坊中,"全节点"提供当前区块以及最多 128 个区块前每个区块的链状态,
而"归档节点"提供自创世以来每个区块的链状态。也就是说,以太坊的"归档节点"是配置不同的全节点,
运行在具有大磁盘的机器上。此术语在[此处](https://chainstack.com/evm-nodes-a-dive-into-the-full-vs-archive-mode/)有进一步描述。

在 Monad 中,从每个节点尽可能多地维护历史每区块状态 trie 的意义上讲,
每个"全节点"都是一个"归档节点"。这意味着回溯深度取决于 RPC 提供商选择的磁盘大小。
对于 2 TB SSD,最近这大约对应于 40,000 个区块,尽管这取决于每个区块中的状态差异量。

由于 Monad 的高吞吐量,**全节点不提供对任意历史状态的访问**,因为这将需要过多的存储。[^2]

`eth_call` 等方法可以引用直到状态 trie 被驱逐的近期状态。

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

[^1]: 实现细节:最近的交易数据直接存储在节点上,而较旧的数据存储在由 RPC 提供商配置和运维的单独归档节点中。

[^2]: 如果有足够的 SSD 容量,Monad 全节点在提供自创世以来的历史状态访问方面将与以太坊"归档"节点类似。
    但实际上,由于每个区块的变更集较大(每个区块最多 3,750 笔交易,而以太坊约为 200 笔,即区块大 18 倍)
    以及区块更频繁(Monad 为 0.3 秒,而以太坊为 12 秒,即频率高 40 倍),目前没有 RPC 提供商提供任意
    久远的历史状态的访问。
