前言
p2p(peer to peer)负责以太坊底层节点间的通信,主要包括底层节点发现(discover)和上层协议运行两大部分。
节点发现
节点发现功能主要涉及 Server Table udp 这几个数据结构,它们有独自的事件响应循环,节点发现功能便是它们互相协作完成的。其中,每个以太坊客户端启动后都会在本地运行一个Server,并将网络拓扑中相邻的节点视为Node,而Table是Node的容器,udp则是负责维持底层的连接。这些结构的关系如下图
Server
p2p/server.go
type Server struct {
PrivateKey *ecdsa.PrivateKey
Protocols []protocol
StaticNodes[] *discover.Node
newTransport func(net.Conn) transport
ntab disvocerTable
ourHandshake *protoHandshake
addpeer chan *conn
......
}
PrivateKey - 本节点的私钥,用于与其他节点建立时的握手协商
Protocols - 支持的所有上层协议
StaticNodes - 预设的静态Peer,节点启动时会首先去向它们发起连接,建立邻居关系
newTransport - 下层传输层实现,定义握手过程中的数据加密解密方式,默认的传输层实现是用newRLPX()创建的rlpx,这不是本文的重点
ntab - 典型实现是Table,所有peer以Node的形式存放在Table
ourHandshake - 与其他节点建立连接时的握手信息,包含本地节点的版本号以及支持的上层协议
addpeer - 连接握手完成后,连接过程通过这个通道通知Server
Server.listenLoop()
Server的监听循环,启动底层监听socket,当收到连接请求时,Accept后调用setupConn()开始连接建立过程
Server.run()
Server的主要事件处理和功能实现循环
进行主动的节点发现,详见之后的节点发现部分
posthandshake channel 接收已经完成第一阶段的连接,这些连接的身份已经被确认,但还需要验证
addpeer channel 接收已经完成第二阶段的连接,这些连接已经验证,调用runPeer()运行本节点与Peer连接上的协议
Node
Node唯一表示网络上的一个节点
p2p/discover/node.go
type Node struct { <