菜单

P2P 系统

相关源文件

本页面介绍了 go-ethereum (Geth) 中使用的点对点 (P2P) 网络系统。它解释了节点如何相互发现、建立连接以及在以太坊网络上进行通信。有关基于此 P2P 系统构建的区块链同步机制的信息,请参阅 Chain Synchronization

概述

Geth 中的 P2P 系统为所有网络通信提供了基础,使节点能够相互发现、建立安全连接并交换协议特定的消息。它实现了一个模块化设计,支持在同一连接上运行多个协议。

P2P 系统架构

来源: p2p/server.go74-116 p2p/peer.go106-121 p2p/dial.go94-128 p2p/discover/table.go64-89

服务器

服务器(Server)是 P2P 系统的核心组件,负责管理所有对等连接。它处理对等发现、连接建立、身份验证和生命周期管理。

服务器结构

来源: p2p/server.go74-116 p2p/dial.go94-128 p2p/server.go134-158 p2p/discover/table.go64-89

服务器初始化时会带有一个配置,该配置指定了诸如以下参数:

  • 最大对等节点数
  • 用于初始发现的引导节点
  • 用于维护持久连接的静态节点
  • 是否启用或禁用对等节点发现

对等节点连接过程

节点启动时,会按照此顺序建立与对等节点的连接

来源: p2p/server.go521-541 p2p/server.go884-938 p2p/dial.go226-316 p2p/peer.go271-327

发现机制

Geth 实现了两种使用类 Kademlia DHT 方法的发现协议

  1. UDPv4:原始的以太坊节点发现协议(p2p/discover/v4_udp.go
  2. UDPv5:一个改进版本,对主题发现提供了更好的支持(p2p/discover/v5_udp.go

发现系统组件

表格结构和存储桶管理

Table维护了一个 Kademlia 式的路由表,包含 17 个存储桶,每个存储桶最多可容纳 16 个节点

来源: p2p/discover/table.go64-89 p2p/discover/table.go100-107 p2p/discover/node.go35-43 p2p/server.go444-519

引导和节点种子

发现过程从 Config.Bootnodes中配置的引导节点开始。 Table在其 nursery字段中维护这些节点,并使用它们进行初始节点发现

用于发现的常量

  • bucketSize = 16 每个存储桶的节点数
  • nBuckets = 17 总存储桶数
  • seedCount = 30 从数据库查询的节点数
  • seedMaxAge = 5 * 24 * time.Hour

来源: p2p/discover/table.go41-59 p2p/discover/table.go201-217 p2p/discover/table.go445-459 p2p/server.go444-519

对等节点管理

P2P 系统通过 dialScheduler 和连接标志来管理不同类型的对等连接。每个连接由一个带有特定 connFlag 值的 conn 结构体表示。

连接类型和管理

对等节点限制和拨号比例

服务器(Server)通过以下计算来强制执行连接限制

限制计算

  • MaxDialedConns() = MaxPeers / DialRatio (默认值:50 / 3 = 16)
  • MaxInboundConns() = MaxPeers - MaxDialedConns() (默认值:34)
  • 受信任的对等节点会绕过这些限制

来源: p2p/server.go547-560 p2p/dial.go94-128 p2p/server.go125-132 p2p/dial.go367-374

默认配置允许最多50个连接,拨号比例为3(意味着节点将维持的出站连接数量最多为允许的入站连接数量的3倍)。这些限制可以通过命令行标志进行配置。

协议协商

Geth的P2P系统通过在protoHandshake期间进行能力协商,支持在同一连接上运行多个协议。

握手与能力匹配

协议结构和匹配

matchProtocols函数为两个对等节点都支持的每个协议创建一个protoRW,消息代码偏移量根据baseProtocolLength计算。

来源: p2p/protocol.go28-66 p2p/peer.go59-69 p2p/peer.go438-461 p2p/peer.go499-540

每个协议都有一个名称、版本和长度参数,定义了它使用的消息代码范围。

消息交换

P2P系统中的消息使用Msg结构体,并通过具有协议特定消息代码映射的MsgReadWriter接口进行交换。

消息结构和接口

消息流和协议多路复用

基础协议消息

  • handshakeMsg = 0x00
  • discMsg = 0x01
  • pingMsg = 0x02
  • pongMsg = 0x03
  • baseProtocolLength = 16

协议特定的消息从baseProtocolLength + protocol.offset开始。

来源: p2p/message.go32-48 p2p/message.go89-95 p2p/peer.go51-57 p2p/peer.go509-540 p2p/peer.go369-403

传输层

P2P系统使用RLPx作为其传输协议,提供对等节点之间的加密和身份验证通信。

RLPx传输实现

连接设置过程

Server.SetupConn方法管理完整的连接建立

超时和限制

  • frameReadTimeout = 30 * time.Second
  • frameWriteTimeout = 20 * time.Second
  • defaultDialTimeout = 15 * time.Second
  • inboundThrottleTime = 30 * time.Second

来源: p2p/server.go45-61 p2p/server.go146-158 p2p/server.go861-938 p2p/server.go134-144 p2p/dial.go40-52

配置

P2P系统的配置在嵌入Server中的Config结构体中定义。关键配置参数包括:

核心P2P配置参数

参数类型默认描述
MaxPeersint50最大对等连接数
MaxPendingPeersint50最大挂起连接尝试次数
DialRatioint3出站与入站连接的比例
NoDiscoveryboolfalse禁用节点发现
DiscoveryV4booltrue启用发现v4协议
DiscoveryV5boolfalse启用发现v5协议
ListenAddr字符串":30303"网络监听地址
BootstrapNodes[]*enode.Node网络特定初始发现节点
StaticNodes[]*enode.Nodenil持久化对等连接
TrustedNodes[]*enode.Nodenil绕过限制的对等节点
NetRestrict*netutil.NetlistnilIP网络限制

连接限制和默认值

发现配置常量

发现行为由这些常量控制

  • defaultMaxPendingPeers = 50
  • defaultDialRatio = 3
  • inboundThrottleTime = 30 * time.Second
  • frameReadTimeout = 30 * time.Second
  • frameWriteTimeout = 20 * time.Second

来源: p2p/server.go45-61 p2p/server.go547-560 p2p/dial.go40-52

对等节点生命周期管理

P2P系统通过一个复杂的生命周期来管理对等节点连接,并进行适当的清理和错误处理。

对等节点结构和状态管理

对等节点事件生命周期

错误处理和断开连接

系统处理各种断开连接场景

关键常量

  • pingInterval = 15 * time.Second
  • baseProtocolVersion = 5
  • baseProtocolLength = 16

来源: p2p/peer.go106-121 p2p/peer.go271-327 p2p/peer.go92-103 p2p/peer_error.go57-75 p2p/server.go973-1004

以太坊同步中的P2P系统

P2P系统在以太坊区块链同步中起着至关重要的作用。下载器组件使用P2P连接来获取区块链数据

来源: eth/downloader/downloader.go98-160/eth/downloader/peer.go43-54

下载器通过 RegisterPeer 方法注册对等节点,并跟踪对等节点的性能,优先考虑更快的节点以供将来请求。

结论

go-ethereum 中的 P2P 系统为以太坊客户端中的所有网络操作提供了强大的基础。它管理对等节点发现、安全连接和协议特定的消息交换。模块化设计允许多个协议在同一连接上运行,从而实现不同的功能,例如块同步、交易传播和状态快照同步。

理解这个系统对于开发和扩展以太坊的网络功能以及诊断客户端中与网络相关的问题至关重要。