[区块链技术] 深入讲解区块链技术 P2P网络
发布于 3 年前 作者 liuzhen 874 次浏览 来自 7*24快讯

(本内容主要来源于极客时间 陈浩 老师的 深入浅出区块链。 做了部分精简,并指示抽取区块链技术一章节,如果感兴趣的可以通过链接订阅完整内容 https://time.geekbang.org/column/intro/76

P2P 网络协议 P2P 网络协议是所有区块链的最底层模块,负责交易数据的网络传输和广播、节点发现和维护。 通常我们所用的都是比特币 P2P 网络协议模块,它遵循一定的交互原则。比如:初次连接到其他节点会被要求按照握手协议来确认状态,在握手之后开始请求 Peer 节点的地址数据以及区块数据。

这套 P2P 交互协议也具有自己的指令集合,指令体现在在消息头(Message Header) 的命令(command)域中,这些命令为上层提供了节点发现、节点获取、区块头获取、区块获取等功能。

网络连接与拓扑结构

  1. 网络连接 除去少数支持 UDP 协议的区块链项目外,绝大部分的区块链项目所使用的底层网络协议依然是 TCP 协议。 所以从网络协议的角度来看,区块链其实是基于 TCP/IP 网络协议的,这与 HTTP 协议、SMTP 协议是处在同一层,也就是应用层。 “区块链是否会颠覆互联网”这一说法,如果要是认真分析的话,它颠覆的层面其实最多只到 HTTP 协议,不能再多了。

比特币的 P2P 网络是一个非常复杂的结构,考虑到矿池内部的挖矿交互协议与轻节点。我们仅仅讨论全节点这种场景下的 P2P 网络发现与路由。

比特币的 P2P 网络基于 TCP 构建,主网默认通信端口为 8333。 以太坊的 P2P 网络则与比特币不太相同,以太坊 P2P 网络是一个完全加密的网络,提供 UDP 和 TCP 两种连接方式,主网默认 TCP 通信端口是 30303,推荐的 UDP 发现端口为 30301。

  1. 拓扑结构 P2P 网络拓扑结构有很多种,有些是中心化拓扑,有些是半中心化拓扑,有些是全分布式拓扑结构。

比特币全节点组成的网络是一种全分布式的拓扑结构,节点与节点之间的传输过程更接近“泛洪算法”,即:交易从某个节点产生,接着广播到临近节点,临近节点一传十十传百,直至传播到全网。 BITECOIN-topo.png (比特币全球节点图,图来自网络)

  1. 节点发现 节点发现是任何区块链节点接入区块链 P2P 网络的第一步。
  • 初始节点发现 在比特币网络中,初始节点发现一共有两种方式。 第一种叫做 DNS-seed,又称 DNS 种子节点,DNS 就是中心化域名查询服务,比特币的社区维护者会维护一些域名。比如 seed.bitcoin.sipa.be 这个域名就是由比特币的核心开发者 Sipa 维护的,如果我们通过 nslookup 会发现大约二十多个 A 纪录的 IPv4 主机地址。 第二种方式就是,代码中硬编码( hard-code )了一些地址,这些地址我们称之为种子节点(seed-node),当所有的种子节点全部失效时,全节点会尝试连接这些种子节点。用在以太坊中,思路也大致相同,也是在代码中硬编码(hard-code)了一些种子节点做类似的工作。

  • 启动后节点发现 在 Bitcoin 的网络中,一个节点可以将自己维护的对等节点列表 (peer list) 发送给临近节点,所以在初始节点发现之后,你的节点要做的第一件事情就是向对方要列表:“快把你的节点列表给我复制一份。”所以在每次需要发送协议消息的时候,它会花费固定的时间尝试和已存的节点列表中的节点建立链接,如果有任何一个节点在超时之前可以连接上,就不用去 DNS seed 获取地址,一般来说,这种可能性很小,尤其是全节点数目非常多的情况下。

  • 黑名单与长连接
    

公有区块链面临的网络环境是非常开放的,任何人只要下载好钱包,打开运行就进入了这个 P2P 网络,这也会带来被攻击的可能。 所以在比特币的代码中,会有一段去控制逻辑,你可以手动将你认为可疑的节点移除并加入禁止列表,同时去配置可信的节点。当然,以上并不属于客户端的标准协议的一部分,任何人都可以实现属于自己的 P2P 网络层。 以太坊上有针对账户进行的黑名单处理,但是这属于业务层。我没有找到很详尽的资料,所以你有兴趣的话,可以自己尝试一下。 不过总的来说,黑名单我们也可以通过操作系统的防火墙去处理,这并不算一个特别棘手的问题。

  • 局域网穿透
    

前面我们说到了区块链的 P2P 网络结构是一种全分布式的拓扑结构。但是,如今我们的网络环境是由局域网和互联网组成的。也就是说,当你在局域网运行一个区块链节点,在公网是发现不了的,公网上的节点只能被动接受连接,并不能主动发起连接。

如果这个局域网是你可以控制的,那么很好说,咱们只需要在 VPC 网络中配置路由,将公网 IP 和端口映射到局域网中你的 IP 和端口即可。

这个条件是非常苛刻的,那么到底有没有一种方案可以自行建立映射呢?答案是:有,就是 NAT 技术和 UPnP 协议。 一般家用路由也会提供简单的NAT支持。详细这方面的支持可以自己查阅资料了解

比特币和以太坊均使用了 UPnP 协议作为局域网穿透工具,只要局域网中的路由设备支持 NAT 网关功能、支持 UPnP 协议,即可将你的区块链节点自动映射到公网上。

节点交互协议 一旦节点建立连接以后,节点之间的交互是遵循一些特定的命令,这些命令写在消息的头部,消息体写的则是消息内容。

命令分为两种,一种是请求命令,一种是数据交互命令。

节点连接完成要做的第一件事情叫做握手操作。这一点在比特币和以太坊上的流程是差不多的,就是相互问候一下,提供一些简要信息。

比如先交换一下版本号,看看是否兼容。只是以太坊为握手过程提供了对称加密,而比特币没有。

握手完毕之后,无论交互什么信息,都是需要保持长连接的,在比特币上有 PING/PONG 这两种类型的消息,这很明显就是用于保持节点之间长连接的心跳而设计的;而在以太坊的设计中,将 PING/PONG 协议移到了节点发现的过程中。

请求命令一般分为发起者请求,比如比特币中的 getaddr 命令是为了获取对方的可用节点列表,inv 命令则提供了数据传输,消息体中会包含一个数据向量。

我们说区块链最重要的功能就是同步区块链,而同步区块恰巧是最考验 P2P 网络能力的。

区块同步方式分为两种, 第一种叫做 HeaderFirst,它提供了区块头先同步,同步完成以后再从其他节点获得区块体。 第二种叫做 BlockFirst,这种区块同步的方式比较简单粗暴,就是从其他节点获取区块必须是完整的。

第一种方案提供了较好的交互过程,减轻了网络负担。这两种同步方式会直接体现在节点交互协议上,他们使用的命令逻辑完全不同。

欢迎使用OKX交易所
回到顶部