P2P Network
比特币网络协议允许全节点(对等体)协作维护一个点对点的网络,进行区块和交易的交换。
Introduction
全节点在向其他节点转发之前下载并验证每个区块和交易。
存档节点(Archival nodes)是存储整个区块链的完整节点,可以向其他节点提供历史区块。
修剪过的节点(Pruned nodes)不存储整个区块链的完整节点。许多SPV客户端也使用比特币网络协议连接到完整节点。
共识规则不包括网络,所以比特币程序可以使用替代的网络和协议,比如一些矿工使用的 high-speed block relay network 和一些钱包使用的 dedicated transaction information servers 提供SPV级别的安全。
为了提供比特币点对点网络的实际例子,本节使用Bitcoin Core 作为代表性的全节点,使用BitcoinJ作为代表性的SPV客户端。这两个程序都很灵活,所以只描述了默认行为。另外,为了隐私保护,下面的例子输出中的实际IP地址已被替换为RFC5737保留的IP地址
Peer Discovery
当第一次启动时,程序不知道任何活跃的完整节点的IP地址。为了发现一些IP地址,他们查询一个或多个硬编码到Bitcoin Core和BitcoinJ的DNS名称(称为DNS 种子)。查询的响应应该包括一个或多个DNS A 记录,其中有可能接受新的传入连接的完整节点的IP地址。
例如,使用Unix的“dig"命令 https://en.wikipedia.org/wiki/Dig_(Unix_command)`__:
DNS种子由比特币社区成员维护:其中一些人提供DNS种子服务器,通过扫描网络自动获得活跃节点的IP地址;另一些人提供静态的DNS种子,手动更新,更有可能提供一些不活跃的节点的IP地址。在这两种情况下,如果节点运行在默认的比特币端口8333端口(主网)或18333端口(测试网),就会被添加到DNS种子中。
DNS种子的结果没有经过验证,恶意的种子运营商或网络中间人可以只返回攻击者控制的节点的IP地址,将程序隔离在攻击者自己的网络上,并允许攻击者给它提供虚假的交易和块。出于这个原因,程序不应完全依赖DNS种子。
一旦一个程序连接到网络,它的对等体就可以开始向它发送addr(地址)信息,其中包括网络上其他对等体的IP地址和端口号,提供一个完全分散的对等体发现方法。Bitcoin Core在一个持久的磁盘数据库中保存已知对等体的记录,这通常允许它在随后的启动中直接连接到这些对等体,而不需要使用DNS种子。
然而,对等体经常离开网络或改变IP地址,因此程序很可能需要在启动时进行几次不同的连接尝试,然后才能成功连接。这可能会给连接到网络的时间增加很大的延迟,迫使用户在发送交易或检查支付状态之前等待。
为了避免这种可能的延迟,BitcoinJ总是使用动态DNS种子来获取被认为是当前活跃的节点的IP地址。Bitcoin Core也试图在最小化延迟和避免不必要的DNS种子使用之间取得平衡。如果Bitcoin Core在其对等数据库中有条目,它将花费1秒的时间尝试连接到至少其中一个,然后再返回到种子;如果在这段时间内建立连接,则不会查询任何中子节点。
Bitcoin Core和BitcoinJ还包括一个IP地址和端口号的硬编码列表,这些节点在该软件的特定版本首次发布时是活跃的。如果在60秒内没有DNS种子服务器响应查询,Bitcoin Core将开始尝试连接到这些节点,提供一个自动后备选项。
作为一个手动回退选项,Bitcoin Core还提供了几个命令行连接选项,包括通过IP地址从特定节点获得一个对等体列表,或通过IP地址与特定节点建立持久连接。详情见-help文本。BitcoinJ可以被编程来做同样的事情。
Connecting To Peers
连接到一个对等体是通过发送一个 "版本 "消息来完成的,该消息包含你的版本号、区块和当前时间到远程节点。远程节点用它自己的 "版本 "消息作出回应。然后,两个节点都向另一个节点发送一个 "verack "消息,表示连接已经建立。
一旦连接,客户端可以向远程节点发送getaddr和 "addr "消息以收集更多的对等体。
为了保持与对等体的连接,节点默认会在30分钟不活动之前向对等体发送消息。如果90分钟过去了,对等体没有收到消息,客户端将认为该连接已经关闭。