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

# Leafage 是什么

> Leafage 是一套 EVM 状态查询与区块数据分发架构：一个写节点执行区块，任意数量的查询节点消费执行结果并对外提供 RPC。

Leafage 是一套 **EVM 状态查询与区块数据分发架构**。它把传统全节点里耦合在一起的同步执行、状态存储、RPC 服务和数据导出拆开：**一个写节点**参与 P2P 同步并执行区块，执行产生的**状态差异**和**区块数据**经 Kafka + S3 分发给**任意数量的查询节点**和外部消费者。客户端不直接访问任何节点，而是通过网关按**区块上下文**被路由到合适的查询节点。

## 一次执行，多处消费

Leafage 的本质是把“执行”和“消费执行结果”分开：

* **写侧**：这条链原本的执行客户端加上 pipeline 库。它是唯一执行区块的角色，执行时把状态差异、区块头、交易 / 追踪 / 事件导出到 S3，并向 Kafka 发布区块变更通知。
* **读侧**：leafage-evm 查询节点。它不同步、不执行区块、不维护 Merkle Patricia Trie，只按通知顺序把状态差异应用到本地状态，并用 revm 执行只读调用。

所有查询节点消费同一条单分区 Kafka 通知流，按相同顺序应用相同差异，因此不存在 P2P 同步的非确定性。新增查询能力只需要多启动一个查询节点，而不是再同步一次全链。

|       | 传统全节点                      | Leafage                            |
| ----- | -------------------------- | ---------------------------------- |
| 执行区块  | 每个节点各执行一次                  | 只有写节点执行                            |
| 状态来源  | 自己执行得到                     | 应用写节点导出的状态差异                       |
| 状态存储  | MPT + 交易 + 收据              | 只存账户状态（balance、nonce、code、storage） |
| 副本一致性 | 取决于各自的同步进度                 | 由 consistency-checker 观测并确认        |
| 数据导出  | `debug_traceBlock` 与查询争抢资源 | 执行时顺带导出，写入 S3                      |

## 五个组件与它们的角色

| 组件                                                     | 侧  | 角色                                                    |
| ------------------------------------------------------ | -- | ----------------------------------------------------- |
| [写节点](/components/go-ethereum-x)                       | 写侧 | 执行客户端 + pipeline 集成，唯一的区块执行者                          |
| [pipeline](/components/pipeline)                       | 写侧 | 嵌入写节点的库：序列化执行数据、写 S3、Leader 向 Kafka 发通知               |
| [leafage-evm](/components/leafage-evm)                 | 读侧 | 查询节点：应用状态差异，提供 `eth_call` 等状态查询                       |
| [consistency-checker](/components/consistency-checker) | 校验 | 等待副本收敛、标记分叉块、维护节点状态、发布已确认的区块通知                        |
| [nodex-proxy](/components/nodex-proxy)                 | 网关 | 通过 etcd 发现节点，按区块上下文把请求路由到 State / Archive / Native 节点 |

组件之间不直接调用，只通过三样中间件协作：Kafka 传通知，S3 传数据体，etcd 传运行时状态。

## 在链路上流动的数据

写节点每执行一个区块，产出四类对象和一条通知：

| 数据                      | 通道             | 内容                           | 消费者                                |
| ----------------------- | -------------- | ---------------------------- | ---------------------------------- |
| Header                  | S3 内部桶         | 区块头                          | leafage-evm                        |
| StateDiff               | S3 内部桶         | 该区块相对父块的状态变更集                | leafage-evm                        |
| BlockFile               | S3 外部桶         | 交易、调用追踪、事件日志                 | 外部消费者                              |
| BlockValidation         | S3 外部桶         | 校验摘要，兼作按高度的索引，带 `is_fork` 标记 | consistency-checker、leafage-evm 追赶 |
| BlockChangeNotification | Kafka 内部 topic | 新块 / 重组通知，只含哈希、高度等元信息        | leafage-evm、consistency-checker    |

内部桶和内部 topic 服务于 Leafage 自身的查询节点；外部桶和外部 topic 面向索引器、分析平台这类外部消费者。外部 topic 由 consistency-checker 发布，只包含**已确认**的区块。

## 三种查询节点

leafage-evm 按启动参数决定保留多少历史，分成 State 和 Archive 两种；Native 节点是原链的全节点，用来兜底。

| 类型         | 保留的状态                 | 适合的查询                        |
| ---------- | --------------------- | ---------------------------- |
| State 节点   | 最新状态，磁盘上只有每个账户和槽位的最新值 | `latest` 与接近链头的查询，也就是绝大多数请求  |
| Archive 节点 | 每个区块高度的完整历史状态         | 任意历史高度的 `eth_call` 与状态读取     |
| Native 节点  | 原链客户端的全部能力            | 触及 leafage-evm 无法本地执行的预编译的调用 |

nodex-proxy 按请求携带的区块上下文在三个节点池之间路由，并在 State 节点返回 `-39006`、`-39008` 时自动改选 Archive 或 Native 节点重试。

## 区块的三种身份

同一个区块在链路上会经过三个阶段，分清它们才能读懂各组件的接口：

| 身份  | 谁决定                              | 含义                                         |
| --- | -------------------------------- | ------------------------------------------ |
| 已发布 | 写节点（Leader）                      | 已进入内部 Kafka topic，查询节点开始应用                 |
| 已确认 | consistency-checker              | 达到 `ready_ratio` 比例的查询节点已追上该高度，外部消费者可以放心去查 |
| 分叉块 | consistency-checker 回写 `is_fork` | 曾被发布但不在规范链上，S3 对象保留，通知里标记为 `is_fork: true` |

## 隔离单元：链与版本

一条链是一个独立的部署单元。Kafka topic、S3 键和 etcd 键都以 `chainID` 开头，多条链可以共用同一套 Kafka、S3 和 etcd。

启用版本模式后，键空间再加一段 `version`，让同一条链的两个数据版本在同一套基础设施上并行运行，并通过 etcd 的 `{chainID}/version` 切换，客户端无感知。

## 术语速查

| 术语                          | 含义                                           | 详细说明                                   |
| --------------------------- | -------------------------------------------- | -------------------------------------- |
| 写节点                         | 执行客户端 + pipeline，唯一执行区块的角色                   | [写节点与查询节点](/concepts/nodes)            |
| 查询节点 / leafage-evm          | 消费状态差异、提供 RPC 的轻量节点                          | [写节点与查询节点](/concepts/nodes)            |
| State / Archive / Native 节点 | 查询节点的三种类型，按保留的状态范围区分                         | [写节点与查询节点](/concepts/nodes)            |
| Leader                      | 多个写节点中唯一向 Kafka 发布通知的实例                      | [写节点与查询节点](/concepts/nodes)            |
| 状态差异（StateDiff）             | 一个区块执行前后账户状态的变更集                             | [状态与状态差异](/concepts/state)             |
| 差异层（DiffLayer）              | 查询节点内存中对应一个区块的状态差异                           | [状态与状态差异](/concepts/state)             |
| 终结化                         | 差异层超出内存窗口后刷入数据库                              | [状态与状态差异](/concepts/state)             |
| 区块变更通知                      | 写节点发布的新块 / 重组消息                              | [区块通知与规范链](/concepts/blocks)           |
| 规范链 / 分叉块                   | 当前 canonical head 所在的链 / 被重组丢弃的块             | [区块通知与规范链](/concepts/blocks)           |
| 已确认区块                       | consistency-checker 判定副本收敛后发布的区块             | [区块通知与规范链](/concepts/blocks)           |
| 区块上下文（`blockCtx`）           | 请求携带的“要哪个区块的状态”，含 `Equals` / `Contains` 两种语义 | [区块上下文与路由](/concepts/block-context)    |
| 内部桶 / 外部桶                   | S3 的两个桶，分别面向查询节点和外部消费者                       | [接口契约](/architecture/interfaces#s3)    |
| 内部 topic / 外部 topic         | Kafka 的两个 topic，分别承载已发布和已确认的区块               | [接口契约](/architecture/interfaces#kafka) |
| 版本命名空间                      | Kafka、S3、etcd 键里可选的 `version` 段              | [接口契约](/architecture/interfaces)       |

## 小结

* Leafage 是一套 **EVM 状态查询与区块数据分发架构**：只有写节点执行区块，其余角色消费执行结果。
* 写侧导出 **StateDiff、Header、BlockFile、BlockValidation** 四类对象和一条**区块变更通知**；Kafka 只传通知，数据体走 S3。
* 查询节点分 **State / Archive / Native** 三种，nodex-proxy 按**区块上下文**路由，并靠错误码自动兜底。
* 一个区块有**已发布、已确认、分叉块**三种身份，外部消费者应当只依赖已确认的通知。

继续阅读：

* [写节点与查询节点](/concepts/nodes)：两侧角色的边界、三种节点类型与节点生命周期。
* [状态与状态差异](/concepts/state)：查询节点为什么不需要 MPT，差异层如何组织与终结化。
* [区块通知与规范链](/concepts/blocks)：通知格式、重组、分叉标记与确认语义。
* [区块上下文与路由](/concepts/block-context)：`Equals` / `Contains` 的含义与 proxy 的路由规则。
* [架构总览](/architecture/overview)：组件划分、运行拓扑与设计取舍。
