Network layer
P2P (Peer-to-Peer) 网络,即对等网络,是一种在对等者(Peer)之间分配任务和工作负载的分布式应用架构。在 P2P 网络中,彼此连接的多台计算机都处于对等的地位,每个节点既是资源、服务和内容的提供者,又是资源、服务和内容的获取者。相比传统的 Client-Server 网络模型,P2P 网络具有去中心化、可扩展、抗攻击、隐私保护等优点,这些特性保证了区块链系统的正常运转,奠定了区块链“自由、自治、去中心化”的基石。
IOST 网络层设计
我们希望实现一个全分布式拓扑结构的网络,节点之间能快速发现,区块和交易能尽快广播至全网,同时网络中冗余的数据尽可能少,节点之间数据加密传输。
经过调研和测试,我们最终使用 libp2p 这个强大的库来构建我们的网络层。
节点发现与连接
我们的基础通信协议使用 TCP/IP 协议,为了防止数据被窃听和篡改,我们在 TCP 之上增加了一层类 TLS 协议来加密数据。为了更好利用每个 TCP 连接,我们使用码流多路传输 (stream-multiplexing) 来收发数据,通过在节点间动态建立多个 Stream,最大限度的利用了机器带宽资源。
在节点发现方面,我们使用了 Kademlia 算法来维护节点路由表。Kademlia 算法通过节点 ID 的异或值来定义节点间距离,根据离自身距离的不同,将不同节点放入不同的桶中。在查询某节点时,只需在相应的桶中查找距离最近的节点即可。通过有限次的查询,能确保找到指定节点的信息。Kademlia 算法具有简单灵活、能快速定位节点和资源位置等特点。
数据传播
为了减少网络带宽,加快数据传播,我们对所有结构化数据使用了 Protocol Buffer 进行序列化,然后采用 Snappy 算法进行压缩。经过测试,这一策略能减少数据包 5 倍以上的大小。
网络广播会造成数据的重复传输,浪费带宽和 CPU 计算资源。很多项目通过限制数据包的跳数(即同一个数据包在网络中被转发的次数)来防止数据的无限转发。这样的弊端是随着网络规模的增大,有限次的转发并不能保证数据被广播至全网。EOS 的策略是,通过在网络层记录每个邻居节点收到过哪些交易和区块来决定是否向其发送数据包,这样虽然能一定程度上减少数据的重复传输,但设计较为笨重,不够优雅,且需要花费较大存储空间。我们的方式是使用过滤器算法来过滤掉重复信息的传播。通过对比了 Bloom Filter 和 Cuckoo Filter 等多种过滤器算法之后,我们从计算性能、空间占用大小、容错性等方面选择了最适合我们的 Bloom Filter 算法。利用 Bloom Filter 算法,我们只需要 1.7 MB 大小的存储空间即可对一百万个数据包进行判重,而误判率只有 0.1%。
为了更进一步减少数据传输的冗余,我们还对区块和大交易采用了先广播 Hash,然后节点通过 Hash 主动下载自己缺失的数据的策略。
局域网穿透
我们使用了 UPnP 协议来实现局域网穿透。UPnP 与其他局域网穿透手段如 UDP 打洞、STUN 协议 的区别是,无需部署在公网环境下的服务器即可将内网的端口暴露出去。即使你没有自己的云服务器,在家用电脑上,你依然可以连入我们的网络,与其他节点互通有无。
彩蛋
在我们代码仓库的 P2P 网络包下,包含一个 example 目录,里面是一个利用我们的网络包构建的聊天应用。在终端进入该目录后,执行 go build
命令,然后执行编译好的二进制文件 ./example
即可与网络中的其他人进行聊天。Have fun!