网络架构
Last updated
Last updated
在以太坊中,p2p 作为通信链路,用于负载上层协议的传输,可以将其分为三层结构:
最上层是以太坊中各个协议的具体实现,如 eth 协议、les 协议。
中间层即 p2p 通信链路层,主要负责启动监听、处理新加入连接或维护连接,为上层协议提供了信道。
最下面的一层,是由 Go 语言所提供的网络 IO 层,也就是对 TCP/IP
中的网络层及以下的封装。
其中,P2P通讯链路层主要司职以下工作:
由上层协议的数据交付给 p2p 层后,首先通过 RLP 编码(可见上文编码方式)。
RLP 编码后的数据将由共享密钥加密(/p2p/transport/doEncHandshake()
),保证通信过程中数据的安全。
「迪菲-赫尔曼密钥交换」 p2p 网络中使用到的是(英语:Diffie–Hellman key exchange,缩写为D-H) 是一种安全协议。它可以让双方在完全没有对方任何预先信息的条件下通过不安全信道创建起一个密钥。
简单来说,链接的两方生成随机的私钥,通过随机的私钥得到公钥。然后双方交换各自的公钥,这样双方都可以通过自己随机的私钥和对方的公钥来生成一个同样的共享密钥(shared-secret)。后续的通讯使用这个共享密钥作为对称加密算法的密钥。
ECDH(A私钥, B公钥) == ECDH(B私钥, A公钥)
。
将数据流转换为 RLPXFrameRW 帧(/p2p/transport/readMsg()&Write()
),便于数据的加密传输和解析。
目的:在单个连接上支持多路复用(Multiplexing)协议,以便高效传输
帧结构:五个数据包
以太坊所实现的P2P协议成为:devp2p
(/cmd/p2p/server.go
)
启动服务目录及堆栈:
/cmd/geth/main.go => geth() => startNode() => utils.StartNode() => stack.Start() => openEndpoints() => server.Start()
启动p2p网络细节,主要会做以下几件事:
初始化server的字段
设置本地节点setupLocalNode
设置监听TCP连接请求setupListening
设置最大可以主动发起的连接遵循50/3规则
最大主动连接数量:这意味着节点会尝试主动连接到其他节点,直到它达到这个限制。在许多以太坊客户端中,这个值默认是 50。
保留(reserved):这个值表示即使达到了最大主动连接数量,还有多少连接是“保留”的,可以被特定的节点(例如,你事先知道并信任的节点)使用。在很多以太坊客户端中,这个值默认是 3。
srv.run(dialer) 发起建立TCP连接请求