美文网首页P2P和以太坊
以太坊文档翻译1-discv4

以太坊文档翻译1-discv4

作者: jection | 来源:发表于2018-08-01 23:23 被阅读0次

    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

        本文链接:https://www.haomeiwen.com/subject/zjcevftx.html