区块链技术笔记第二弹(BTC)
网络结构--即共识机制后又一大核心
拓扑结构
比特币在中本聪的设计下,采用了点对点的P2P的去分布式网络架构。P2P网络是指位于同一网络中的每台计算机都彼此对等,各个节点共同提供网络服务,不存在任何“特殊”节点,每个网络节点以扁平(flat)的拓扑结构相互连通。对比中心化网络,在P2P网络中不存在任何服务端(server)、中央化的服务。
P2P网络的节点之间交互连接、协同,每个节点在对外提供服务的同时也使用网络中其他节点所提供的服务,每个节点即是服务端又是客户端。P2P网络模型除应用于比特币网络,使用广泛的BT下载就是基于P2P网络。P2P网络不仅仅去除了中心化带来的风险(中心化可能作恶),还可以提高传输的效率。(中心化网络当能也有优点)
下图为经典P2P网络拓扑。
每个网络节点都是平等的(是指在网络层面上节点是平等的,但各节点在功能上可以有不同的分工, 如钱包节点、挖矿节点等),不存在任何“特殊”中心节点。
发现节点
在中心化网络中,新加入的节点只要连接“特殊”的中心节点就可以加入网络。
为了能够加入到比特币网络,比特币客户端会做一下几件事情:
1. 节点会记住它最近成功连接的网络节点,当重新启动后它可以迅速与先前的对等节点网络重新建立连接。
2. 节点会在失去已有连接时尝试发现新节点。
3. 当建立一个或多个连接后,节点将一条包含自身IP地址消息发送给其相邻节点。相邻节点再将此消息依次转发给它们各自的相邻节点,从而保证节点信息被多个节点所接收、保证连接更稳定。
4. 新接入的节点可以向它的相邻节点发送获取地址getaddr消息,要求它们返回其已知对等节点的IP地址列表。节点可以找到需连接到的对等节点。
5. 在节点启动时,可以给节点指定一个正活跃节点IP, 如果没有,客户端也维持一个列表,列出了那些长期稳定运行的节点。这样的节点也被称为种子节点(其实和BT下载的种子文件道理是一样的),就可以通过种子节点来快速发现网络中的其他节点。
握手协议
当节点与对等节点建立好连接后,首先要做的就是握手。其过程如下:
节点向对等断发送version消息开始握手,此消息中包含如下一些内容:
PROTOCOL_VERSION:当前节点的比特币P2P协议的版本号;
nLocalServices:节点支持的本地服务列表,目前仅支持NODE_NETWORK;
nTime:当前时间;
addrYou:当前节点可见的远程节点的IP地址;
addrMe:本节点发现的本地IP地址;
subver:当前节点运行的软件类型的子版本号;
baseHeight:当前节点上的区块链的高度。
对等节点收到version消息后,会回应verack进行确认并建立连接。有时候对等端可能需要互换连接并连回起始节点,此时对等端也会发送该节点的version消息。
完成握手协议后,新节点将会发送一条包含自己IP地址的addr消息给对等端,对等端收到以后又向与它连接的相邻节点发送addr消息,这样新节点的ip地址就会在P2P网络中广播出去。此外新节点还可以发送getaddr消息,要求对等端把自己知道的节点的IP地址发送过来。通过这种方式,新节点可以找到需要连接的对等节点。如下图:
节点必须连接到若干不同的对等节点才能在比特币网络中建立通向比特币网络的种类各异的路径(path)。由于节点可以随时加入和离开,通讯路径是不可靠的。因此,节点必须持续进行两项工作:在失去已有连接时发现新节点,并在其他节点启动时为其提供帮助。节点启动时只需要一个连接,因为第一个节点可以将它引荐给它的对等节点,而这些节点又会进一步提供引荐。一个节点,如果连接到大量的其他对等节点,这既没必要,也是对网络资源的浪费。在启动完成后,节点会记住它最近成功连接的对等节点;因此,当重新启动后它可以迅速与先前的对等节点网络重新建立连接。如果先前的网络的对等节点对连接请求无应答,该节点可以使用种子节点进行重启动。
用户可以通过提供-connect=选项来指定一个或多个IP地址,从而达到复写自动节点管理功能并指定IP地址列表的目的。如果采用此选项,节点只连接到这些选定的节点IP地址,而不会自动发现并维护对等节点之间的连接。
如果已建立的连接没有数据通信,所在的节点会定期发送信息以维持连接。如果节点持续某个连接长达90分钟没有任何通信,它会被认为已经从网络中断开,网络将开始查找一个新的对等节点。因此,比特币网络会随时根据变化的节点及网络问题进行动态调整,不需经过中心化的控制即可进行规模增、减的有机调整。
至此,p2p网络基本形成,可以发现和维护自己的节点。具体请详见源码实现。