以太坊文档翻译1-discv4

devP2P是以太坊的P2P实现库,包含两个模块:

  • rlpx
  • discv4

本文翻译自以太坊官方文档,原文请参考:
https://github.com/ethereum/devp2p/blob/d3f99e3fbcfeb17399e6e97ee738f89ea441b317/discv4.md

节点发现协议(discv4)


节点发现协议(Node Discovery Protocol v4),包括:

  • 发现 RLPx 节点并连接
  • 基于UDP的RPC协议
  • k桶(kademlia)结构
  • 定义四种报文类型:ping, pong, findnode and neighbors

使用k桶来存储以太坊节点,因为k桶结构采用了一种短路径的拓扑图。

节点标识(Node Identities)

每个节点都有一个密码标识,使用椭圆曲线secp256k1算法生成的公钥,这个公钥作为节点的唯一标识,也叫node ID。

节点表(Node Table)

每个节点根据节点之间的距离,将邻居节点存储在一个由k-buckets(k桶)组成的路由表中,这个路由表就是节点表。
因为两个节点最大距离是256,所以节点表一共有256个k桶,每个桶中最多放k=16个节点。

终端证明(Endpoint Proof)

如果两个节点之间超过12h没有通讯,节点应该主动向对方节点发送ping来验证对方节点是否活跃,通过是否收到pong来得到一个终端证明。

递归查找(Recursive Lookup)

节点使用递归查找的方式来获取邻居节点。
开始时,查找发起节点从Node Table中提取α(比如3)个距离最closest节点,并发向这α个节点发送FindNode请求, 一次请求最多将返回k(比如16个)个距离发起节点最closest的节点。
收到Neighbors响应后,发起节点又从这些返回节点中抽取α个最closest节点(没有发送过请求的),重发FindNode请求,就这样递归下去(递归次数8次)。
在递归查找中,没有响应FindNode请求的节点,将会从Node Table删除。

报文协议(wire protocol)

发现节点协议使用udp发送数据包,并限定数据包最大大小为1280bytes。

  • udp报文格式

packet = packet-header || packet-data

  • 报文头部格式

packet-header = hash || signature || packet-type
hash = keccak256(signature || packet-type || packet-data)
signature = sign(packet-type || packet-data)

hash:摘要,用于标识对应的ping和pong包。
signature:签名,被编码成一个65bytes数组,包括(r,s,v)
packet-type:包类型,占1个字节,有四种类型Ping Packet (0x01),Pong Packet (0x02),FindNode Packet (0x03),Neighbors Packet (0x04);
packet-data:包数据,不同的packet-type数据不一样,统一被编码成rlp格式列表;

Ping Packet (0x01)

packet-data = [version, from, to, expiration]
version = 4
from = [sender-ip, sender-udp-port, sender-tcp-port]
to = [recipient-ip, recipient-udp-port, 0]

expiration:有效期,是一个unix时间戳,用于定义过期的ping报文不再处理;
节点接收到ping报文,应该向发送节点回复pong,同时,考虑将发送节点加入路由表。

Pong Packet (0x02)

packet-data = [to, ping-hash, expiration]

pong是对ping的应答。
ping-hash:与ping包的hash对应,如果节点从pong包找不到对应hash的ping包,将忽略pong包;

FindNode Packet (0x03)

packet-data = [target, expiration]

target:目标节点的公钥, 占65个字节。
FindNode包用于发送请求,查找最接近target的节点信息。
接收者收到FindNode后,应该从本地Node Table中找出距离目标节点最closest的16个节点,回复Neighbors包。
注意:为了防止流量放大攻击,接收者只对通过endpoint proof的节点回复Neighbors包。

Neighbors Packet (0x04)

packet-data = [nodes, expiration]
nodes = [[ip, udp-port, tcp-port, node-id], ... ]

Neighbors是 FindNode 的应答。

已知问题和实施建议

expiration:容易出错,依赖节点时钟的准确性。
endpoint proof:不精确,因为FindNode的发送节点永远无法确定接收节点是否收到“pong”响应。Geth处理如下:如果没有与接收人沟通发生超过12 h,先发送一个ping过去,然后等待接收节点发送ping过来,回复pong,然后发送FindNode。

疑问:

framed
framing 帧 组装 分段 框架
Multiplexing 多路复用

你可能感兴趣的:(以太坊文档翻译1-discv4)