【译】以太坊节点发现协议V4

By | 2018年7月14日

本规范定义了第四版的节点发现协议,这是一个类Kadamlia的DHT,用来存储关于以太坊节点的信息。

节点身份(Node Identities)

每个节点都有一个密码学“身份”——这个“身份”是一个椭圆曲线secp256k1的密钥。节点用其公钥作为身份认证或“节点ID”

两个节点之间的“距离”是按位异或(将两个数字转为二进制后,相同你的位置上相比较。相同为0,相异为1)的或公钥的hash(即数字)

distance(n₁, n₂) = keccak256(n₁) XOR keccak256(n₂) //XOR=”Exclusive OR”

 

节点表(Node Table)

发现协议(Discovery Protocol)中的节点中都存储有它们临近节点的信息。临近节点被存在一个包含“k-桶”(k-buckets)的路由表中。每个节点都在k桶中保存和它的距离在2i和2i+1之间的节点(0≤i<256)

本协议中k=16,即每个k桶至多包涵16个实体节点。这些实体被按最后发现的时间排序——最近被发现的排在头部,反之在尾部。

每当遇到新节点N1时,这个节点都会被插入到它对应的桶中。如果桶中的实体数小于k,N1直接被添加并作为第一个实体。反之则会通过发送一个ping包的方式对原桶中排在末端的N2进行验证,如果N2没有回音(这样就可以认为N2挂了),就移除N2后把N1加在桶头。

 

端点证明(Endpoint Proof)

为防止流量放大攻击(traffic amplification attack),在协议的实现中必须验证【一个发送查询的参与人是否参与发现协议】(implementations must verify that the sender of a query participates in the discovery protocol)。若包的发送者在12小时内发送了与ping hash相符的有效pong回应,则我们可以认为此发送者是有效的。

 

递归查找(lookup)

查找发生在k中和节点id距离最近的位置

查询发起人(initiator)首先选择最接近他所知道的目标的α个节点。随后,查找人同时(并发)向这些节点发送FindNode包(Packets)。α是一个全系统尺度(system-wide)的并发参数,比如3。在递归阶段,查找人重复地向【他在【之前的查找过程中】获知的节点】发送FindNode包。对查找人找到的最靠近目标的k个节点,它会抓取还没有查询过的α并向他们重新发送FindNode。没有回应的节点会被迅速从查找范围中移除。

 

线协议(Wire Protocol)

节点发现信息被以UDP数据报的形式发送。任何包大小的最大值均为1280bytes

packet = packet-header || packet-data

每个包都以一个包头开始:

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

“hash”存在的意义是使得:同一个UDP端口在运行多个合约的时候,数据包的格式能够被识别出来。除此之外别无它用。

每个数据包都被节点用它的identity密钥签名过。“signature”被编码成长度为65的字节数组,来与签名值r,s及“recovery id”v串联起来。

“packet-type”是一个定义了消息类型的单一byte。有效的包类型列举如下。在包头之后的数据与包头中的类型相符,并被编码为一个RLP列表。对每个EIP-8,实现都应该忽略【列表中的任何额外元素、列表后的任何额外数据】

 

Ping包(Ping Packet)(0x01)

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

“expiration”域是一个UNIX的绝对时间戳。包含过期时间戳的数据包可能不会被处理。

当一个ping包被收到时,收件人需要用pong包回复。收件人也可以考虑将发件人添加进自己的节点列表。

如果收件人和发件人在上一个12小时中没有进行通信,双方需要再进行一次ping/pong通信以进行端点证明(Endpoint Proof)。

 

Pong包(Pong Packet)(0x02)

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

Pong是对ping的回应。

“ping-hash”应与对应ping包的“hash”相等。协议实现应该忽略不请自来的、没有包含【最近发来的ping包hash的】pong包

 

FindNode包(FindNode Packet)(0x03)

packet-data = [target, expiration]

FindNode包请求靠近target的节点的信息。Target是一个65byte的secp256k1公钥。当接收到FindNode时,接收人应回复【在他自己的本地表中【最靠近找到的节点的】16个节点】的邻居包(the recipient should reply with neighbors packets containing the closest 16 nodes to target found in its local table.)

为防止流量放大攻击,邻居回复(Neighbors replies)应该只有在【FindNode被【端点证明进程】验证为有效】后发送

 

邻居包(Neighbors Packet)(0x04)

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

邻居包是对FindNode的回复。其中包含了邻居们的地址。

 

 

 

附:

 

原文链接:https://github.com/ethereum/devp2p/blob/master/discv4.md

 

DHT:

Distribute Hash Table,一种分布式存储方法。每个客户端负责一小范围的路由,并负责存储一小部分数据,从而实现整个DHT网络的寻址和存储。进入DHT网络的用户就是节点,节点之间互相有路有记录。

 

Kademlia

这是一种结构化P2P覆盖网络(Structed P2P OverlayNetwork),主要解决:以分布式的应用层网络进行信息的存储和检索。

点击量:356

发表评论

邮箱地址不会被公开。 必填项已用*标注