# 以太坊节点同步区块的过程

By [daguoyuan](https://paragraph.com/@daguoyuan) · 2024-09-08

---

节点同步
----

当一个新的节点加入以太坊网络时，它需要同步网络上的所有数据，以便成为一个完全验证节点（full node）。这个过程被称为区块链同步（blockchain synchronization）。有几种不同的同步模式，每种模式的工作原理略有不同，但总体过程包括以下几个主要步骤：

### 1.连接到网络

新的节点首先需要连接到以太坊网络。这涉及以下步骤：

发现节点：新节点使用以太坊的节点发现协议（基于 Kademlia DHT）找到并连接到其他节点。这些其他节点被称为“对等节点”（peers）。 握手：新节点与对等节点进行握手，交换协议版本、网络 ID 和其他信息。

### 2.同步区块链数据

有几种不同的同步模式，新节点可以选择其中一种来同步数据：

*   完整同步（Full Sync） 在完整同步模式下，新的节点从创世区块（genesis block）开始下载每个区块及其所有交易，并重放所有交易以验证区块链的状态。这是最慢的同步方式，但它确保节点拥有完整的区块链数据和状态。
    

下载区块头：新节点从对等节点下载区块头（block headers），这些区块头包含区块的基本信息。 下载区块体和交易：节点下载区块体（block bodies），包括所有的交易和其他数据。 重放交易：节点重放每个区块中的交易，以重新计算区块链的状态。

*   快速同步（Fast Sync） 快速同步模式是以太坊的默认同步模式。它的目标是比完整同步更快，但仍然可以验证区块链的状态。
    

下载区块头：类似于完整同步，节点首先下载区块头。 下载区块体和收据：节点下载区块体和交易收据，但不重放所有交易。 状态下载：节点直接下载当前的状态数据（包括账户余额、智能合约代码和存储），而不是通过重放交易来计算状态。

*   快速区块同步（Snap Sync） Snap Sync 是一种更快的同步方式，它使用了一种新的状态快照（snapshot）机制。它的主要步骤如下：
    

下载区块头：下载区块头。 下载快照：从网络中的其他节点下载最新的状态快照。这比重放所有交易要快得多。 补全区块数据：下载自快照以来的所有区块和交易数据，以确保节点状态是最新的。

*   轻客户端同步（Light Sync） 轻客户端不同于上述三种模式，因为它不保存整个区块链的数据，只保存区块头并请求其他节点来验证特定的交易和状态。轻客户端的步骤如下：
    

下载区块头：轻客户端只下载区块头。 请求证明：当需要验证交易或状态时，轻客户端从全节点请求默克尔证明，以验证数据的有效性。

### 3.验证数据

在同步过程中，节点会验证收到的数据。这包括验证区块头、区块体、交易和状态数据的正确性。如果节点发现数据不一致，它会请求其他对等节点提供正确的数据。

### 4\. 保持同步

在完成初始同步后，节点会继续保持与网络的同步。这意味着它会持续接收和处理新的区块和交易，以确保它的状态是最新的。

### 5\. 总结

一个新加入以太坊网络的节点会通过下载区块头、区块体、交易和状态数据来同步区块链。具体的同步模式可以是完整同步、快速同步、快速区块同步或轻客户端同步。每种模式的性能和要求有所不同，但它们都确保节点能够验证和参与以太坊网络。

节点数据存储
------

在以太坊网络中，状态数据存储在每个全节点的本地数据库中。这个状态数据包括账户余额、智能合约代码、智能合约的存储状态等。具体来说，以太坊节点使用一种称为“Merkle Patricia Trie”的数据结构来存储和管理状态数据。

### 状态数据的存储位置

以太坊节点使用不同的数据库来存储状态数据，具体取决于使用的客户端实现。常见的以太坊客户端包括 Geth（Go Ethereum）和 Parity（OpenEthereum）。

#### Geth（Go Ethereum）

Geth 使用 LevelDB 或 RocksDB 作为其底层存储引擎。

以下是 Geth 的数据目录结构：

chaindata：这是主要的数据库目录，包含区块链数据，包括区块头、区块体和状态数据。LevelDB 数据文件：存储在 chaindata 目录中，使用 LevelDB 的文件格式（通常是 .ldb 文件）。

lightchaindata：如果节点运行在轻客户端模式下，状态数据会存储在这个目录中。

Geth 的默认数据目录路径如下：

*   Linux：~/.ethereum/geth/chaindata
    
*   macOS：~/Library/Ethereum/geth/chaindata
    
*   Windows：%APPDATA%/Ethereum/geth/chaindata
    

#### Parity（OpenEthereum）

Parity 使用 RocksDB 作为其底层存储引擎。以下是 Parity 的数据目录结构：

chains：这个目录包含区块链数据，包括区块头、区块体和状态数据。

数据库文件：存储在 chains 目录中的子目录里，使用 RocksDB 的文件格式。

Parity 的默认数据目录路径如下：

*   Linux：~/.local/share/io.parity.ethereum/chains
    
*   macOS：~/Library/Application Support/io.parity.ethereum/chains
    
*   Windows：%APPDATA%/io.parity.ethereum/chains
    

### 状态数据的管理

以太坊使用一种称为 Merkle Patricia Trie 的数据结构来管理状态数据。Merkle Patricia Trie 是一种结合了 Merkle 树和 Patricia Trie 的数据结构，具有以下特点：

*   高效存储：通过键值对的方式存储状态数据，每个节点都可以高效地存储和查找数据。
    
*   数据完整性：Merkle 树的特性保证了数据的完整性和可验证性。任何对数据的修改都会影响到根哈希（state root），并且可以通过默克尔证明来验证特定数据的有效性。
    
*   紧凑性：Patricia Trie 的特性保证了数据存储的紧凑性，减少了冗余数据的存储。
    

### 状态数据的更新

每当一个新的区块被添加到区块链时，区块中的所有交易都会被依次执行，更新节点的状态数据。每个区块头中包含一个 stateRoot 字段，表示在该区块执行完所有交易后的状态根哈希值。节点通过更新其本地的 Merkle Patricia Trie 来反映这些状态变化。

### 总结

以太坊节点将状态数据存储在本地数据库中，具体取决于所使用的客户端实现（例如 Geth 使用 LevelDB 或 RocksDB，Parity 使用 RocksDB）。这些状态数据通过一种称为 Merkle Patricia Trie 的数据结构进行管理，以确保高效存储和数据完整性。在同步和处理交易时，节点会不断更新其本地的状态数据库，以保持与网络的最新状态一致。

---

*Originally published on [daguoyuan](https://paragraph.com/@daguoyuan/C523Vab3WGhhJmzVa6bH)*
