随笔-53  评论-1  文章-9 

比特币网络架构及节点发现分析

一、P2P网络架构
比特币采用了基于互联网的点对点(P2P:peer-to-peer)分布式网络架构。
比特币网络可以认为是按照比特币P2P协议运行的一系列节点的集合。
本文来分析下比特币网络,了解它跟传统中心化网络的区别,以及比特币网络是如何发现相邻节点的。
 

 

二、节点类型及分工
尽管比特币P2P网络中的各个节点相互对等,但是根据所提供的功能不同,各节点可能具有不同的分工。每个比特币节点都是路由、区块链数据库、挖矿、钱包服务的功能集合。一个全节点(full node)包括下图所示的四个功能:
下图为一个包含四个完整功能的比特币网络节点:钱包、矿工、完整区块链、网络路由节点。每个节点都参与全网络的路由功能,同时也可能包含其他功能。每个节点都参与验证并传播交易及区块信息,发现并维持与对等节点的连接。名为“网络路由节点”的橙色圆圈即表示该路由功能。
 
一些节点保有一份完整的、最新的区块链拷贝,这样的节点被称为“全节点”。全节点能够独立自主地校验所有交易,而不需借由任何外部参照。
另外还有一些节点只保留了区块链的一部分,它们通过一种名为“简易支付验证(SPV)”的方式来完成交易验证。这样的节点被称为“SPV节点”,又叫“轻量级节点”。
 
 

 

三、对等节点发现
 
为了能够加入到比特币网络,比特币客户端会做一下几件事情:
a、节点会记住它最近成功连接的网络节点,当重新启动后它可以迅速与先前的对等节点网络重新建立连接。
b、节点会在失去已有连接时尝试发现新节点。
c、当建立一个或多个连接后,节点将一条包含自身IP地址消息发送给其相邻节点。相邻节点再将此消息依次转发给它们各自的相邻节点,从而保证节点信息被多个节点所接收、保证连接更稳定。
d、新接入的节点可以向它的相邻节点发送获取地址getaddr消息,要求它们返回其已知对等节点的IP地址列表。节点可以找到需连接到的对等节点。
e、在节点启动时,可以给节点指定一个正活跃节点IP, 如果没有,客户端也维持一个列表,列出了那些长期稳定运行的节点。这样的节点也被称为种子节点(其实和BT下载的种子文件道理是一样的),就可以通过种子节点来快速发现网络中的其他节点。
 
1、比特币的核心部分维护一个在启动时可以连接的对等节点列表。当一个完整的节点第一次启动时,它必须被自举(bootstrapped)到网络。这个过程如今在比特币的核心部分通过一个短名单上的DNS种子自动执行。选项-dnsseed可以被用来定义这种行为,默认的设置是1。DNS请求返回一个可连接的IP地址列表。比特币客户端从那里可以连接到整个比特币网络。
 
2、自举的另外一种方法是使用参数-seednode=<ip>。通过这个参数,用户可以预先定义连接到哪个服务器,并在建立对等节点列表之后断开连接。另外一个方法是在启动比特币核心时配置-connect=<ip>参数来选择连接到哪些对等节点(未被配置的IP将不会被连接)。添加对等节点的最后一种方法是通过参数-addnode=<ip>添加一个单独的节点到对等节点列表中。
自举过程完成后,节点向其对等节点发送一个包含其自身IP地址的addr消息。其对等的每个节点向它们自己的对等节点转发这个信息,以便进一步扩大连接池。
通过getpeerinfo命令可以查看某个节点所连接的对等节点及相关的数据。
 
3、连接到对等节点
节点通过发送version消息连接到一个对等节点。消息version 包含了节点的版本信息、块信息和距离远程节点的时间。一旦这个消息被对等节点收到,它必须回复一个verack。如果它愿意建立对等关系,它将发送自己的version消息。
一旦建立对等关系,节点可以向远程节点发送getaddr和addr消息来获得其它的对等节点信息。为了维持与对等节点的连接,节点默认情况下每30分钟内会给对等节点至少发送一次信息。如果超过90分钟没有收到回复,节点会认为连接已经断开。
 
4、块广播
在与对等节点建立连接后,双方互发包含最新块哈希值的getblocks消息。如果某个节点坚信其拥有最新的块信息或者有更长的链,它将发送一个inv消息,其中包含至多500个最新块的哈希值,以此来表明它的链更长。收到的节点使用getdata来请求块的详细信息,而远程的节点通过命令block来发送这些信息。在500个块的信息被处理完之后,节点可以通过getblocks请求更多的块信息。这些块在被接收节点认证之后得到确认。
新块的确认也可通过矿工挖到并发布的块来发现。其扩散过程和上述类似。通过之前的连接,新块以inv消息发布出去,而接收节点可以通过getdata请求这些块的详细信息。
 
5、交易的广播
和对等节点的交易通过inv消息来实现。如果收到了getdata信息,那么交易通过发送tx实现。对等节点收到有效的交易的信息后会通过类似的方式将其扩散。如果交易的信息在一段时间内没有被放进块中,那么交易将被从内存池中清除,而原节点将重新发送交易信息。
 
6、行为不端的节点
对于所有的广播,那些行为不端的节点(占用带宽和通过发布错误信息来浪费计算资源)将收到惩罚。如果一个节点惩罚分数超过门限值-banscore=<n>,它将被禁止加入网络若干秒。这个时间由参数-bantime=<n>定义,默认值是86400秒,即24小时。
 
7、警告
为了应对可能出现的bug和攻击,比特币开发者提供了比特币警告服务RSS。比特币用户通过命令getinfo可以查看针对其特定客户端版本的错误信息。
这些信息通过allert消息尽可能多扩散出去给每一个连接的对等节点。
错误信息采用特定的ECDSA私有密钥签名,只被极少数的开发者控制。
补充资源:如果你想了解各种消息的详细结构和所有的消息类别,可以参考比特币Wiki上的协议说明。
 
四、通过dns seeds获取节点列表数据
1、dns seed是什么
返回比特币网络上完整节点IP地址的DNS服务器,用于协助发现节点。
 
2、哪里可以查看到
我们在bitcoin源码中,搜索关键词“seed.bitcoin.sipa.be”,目前最新的代码位置在chainparams.cpp中。
 
3、怎么得到节点列表
这里需要用到一个开源项目,项目地址
https://github.com/sipa/bitcoin-seeder
下面开始进行具体操作。
我们用的dns是seed.bitcoin.sipa.be
xiaoyu@xiaoyu-Parallels-Virtual-Platform:~/bitcoin-seeder$ dig -t NS testnet-seed.bitcoin.jonasschnelli.ch
 
再次查看项目文件夹,发现多了两个文件
dnsseed.dat
dnsseed.dump
 
查看dnsseed.dump文件,这样就得到了节点列表。
 
4、总结
dns seed数据是硬编码到项目中,这也就解决了分布式系统的关于鸡生蛋还是蛋生鸡的问题。
 
五、节点通信简述
比特币节点通常采用TCP协议、使用8333端口与相邻节点建立连接, 建立连接时也会有认证“握手”的通信过程,用来确定协议版本,软件版本,节点IP,区块高度等。
当节点连接到相邻节点后,接着就开始跟相邻节点同步区块链数据(轻量级钱包应用其实不会同步所有区块数据),节点们会交换一个getblocks消息,它包含本地区块链最顶端的哈希值。如果某个节点识别出它接收到的哈希值并不属于顶端区块,而是属于一个非顶端区块的旧区块,就说其自身的本地区块链比其他节点的区块链更长,并告诉其他节点需要补充区块,其他节点发送getdata消息来请求区块,验证后更新到本地区块链中。
 
参考文章:
http://blog.csdn.net/diandianxiyu_geek/article/details/78747618?ref=myread
http://8btc.com/article-1762-1.html
https://www.cnblogs.com/tinyxiong/p/7800198.html
 
 
 
posted on 2018-02-08 14:43 两万马力 阅读(...) 评论(...) 编辑 收藏