本页面介绍了 go-ethereum (Geth) 中使用的点对点 (P2P) 网络系统。它解释了节点如何相互发现、建立连接以及在以太坊网络上进行通信。有关基于此 P2P 系统构建的区块链同步机制的信息,请参阅 Chain Synchronization。
Geth 中的 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 方法的发现协议
p2p/discover/v4_udp.go)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 = 0x00discMsg = 0x01pingMsg = 0x02pongMsg = 0x03baseProtocolLength = 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作为其传输协议,提供对等节点之间的加密和身份验证通信。
Server.SetupConn方法管理完整的连接建立
超时和限制
frameReadTimeout = 30 * time.SecondframeWriteTimeout = 20 * time.SeconddefaultDialTimeout = 15 * time.SecondinboundThrottleTime = 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结构体中定义。关键配置参数包括:
| 参数 | 类型 | 默认 | 描述 |
|---|---|---|---|
MaxPeers | int | 50 | 最大对等连接数 |
MaxPendingPeers | int | 50 | 最大挂起连接尝试次数 |
DialRatio | int | 3 | 出站与入站连接的比例 |
NoDiscovery | bool | false | 禁用节点发现 |
DiscoveryV4 | bool | true | 启用发现v4协议 |
DiscoveryV5 | bool | false | 启用发现v5协议 |
ListenAddr | 字符串 | ":30303" | 网络监听地址 |
BootstrapNodes | []*enode.Node | 网络特定 | 初始发现节点 |
StaticNodes | []*enode.Node | nil | 持久化对等连接 |
TrustedNodes | []*enode.Node | nil | 绕过限制的对等节点 |
NetRestrict | *netutil.Netlist | nil | IP网络限制 |
发现行为由这些常量控制
defaultMaxPendingPeers = 50defaultDialRatio = 3inboundThrottleTime = 30 * time.SecondframeReadTimeout = 30 * time.SecondframeWriteTimeout = 20 * time.Second来源: p2p/server.go45-61 p2p/server.go547-560 p2p/dial.go40-52
P2P系统通过一个复杂的生命周期来管理对等节点连接,并进行适当的清理和错误处理。
系统处理各种断开连接场景
关键常量
pingInterval = 15 * time.SecondbaseProtocolVersion = 5baseProtocolLength = 16来源: p2p/peer.go106-121 p2p/peer.go271-327 p2p/peer.go92-103 p2p/peer_error.go57-75 p2p/server.go973-1004
P2P系统在以太坊区块链同步中起着至关重要的作用。下载器组件使用P2P连接来获取区块链数据
来源: eth/downloader/downloader.go98-160/eth/downloader/peer.go43-54
下载器通过 RegisterPeer 方法注册对等节点,并跟踪对等节点的性能,优先考虑更快的节点以供将来请求。
go-ethereum 中的 P2P 系统为以太坊客户端中的所有网络操作提供了强大的基础。它管理对等节点发现、安全连接和协议特定的消息交换。模块化设计允许多个协议在同一连接上运行,从而实现不同的功能,例如块同步、交易传播和状态快照同步。
理解这个系统对于开发和扩展以太坊的网络功能以及诊断客户端中与网络相关的问题至关重要。