BlockTrain网络

  

  BlockTrain网络-LMLPHP

  1、每个节点都参与全⽹络的路由功能,同时也可能包含其他功能。每个节点都参与验证并传播交易及区块信息,发现并维持与对等节点的连接。在图6-1所⽰的全节点⽤例中,名为“⽹络路由节点”的橙⾊圆圈即表⽰该路由功能。

  2、⼀些节点保有⼀份完整的、最新的区块链拷⻉,这样的节点被称为“全节点”。全节点能够独⽴⾃主地校验所有交易,⽽不需借由任何外部参照。另外还有⼀些节点只保留了区块链的⼀部分,它们通过⼀种名为“简易⽀付验证(SPV)”的⽅式来完成交易验证。这样的节点被称为“SPV节点”,⼜叫“轻量级节点”。

     在如上图所⽰的全节点⽤例中,名为完整区块链的蓝⾊圆圈即表⽰了全节点区块链数据库功能。上图中,SPV节点没有此蓝⾊圆圈,以⽰它们没有区块链的完整拷⻉。

  3、挖矿节点通过运⾏在特殊硬件设备上的⼯作量证明(proof-of-work)算法,以相互竞争的⽅式创建新的区块。⼀些挖矿节点同时也是全节点,保有区块链的完整拷⻉;还有⼀些参与矿池挖矿的节点是轻量级节点,它们必须依赖矿池服务器维护的全节点进⾏⼯作。在全节点⽤例中,挖矿功能如图中名为“矿⼯”的⿊⾊圆圈所⽰。

  4、当前,越来越多的⽤⼾钱包都是SPV节点,尤其是运⾏于诸如智能⼿机等资源受限设备上的⽐特币钱包应⽤;⽽这正变得越来越普遍。在图6-1中,名为“钱包”的绿⾊圆圈代表钱包功能。

常见节点类型

  Stratum协议就被应⽤于挖矿、以及轻量级或移动端⽐特币钱包之中。

  Stratum服务器通过Stratum协议将所有的Stratum挖矿节点连接⾄⽐特币主⽹络、并将Stratum协议桥接(bridge)⾄⽐特币P2P协议之上。

  BlockTrain网络-LMLPHP

  SPV轻量钱包 vs SPV轻量Stratum钱包:

  BlockTrain网络-LMLPHPBlockTrain网络-LMLPHP

  核心客户端:

  BlockTrain网络-LMLPHP

  BitCoin网络架构:

  BlockTrain网络-LMLPHP

网络发现】 

  节点通常采⽤TCP协议、使⽤8333端⼝(该端⼝号通常是⽐特币所使⽤的,除8333端⼝外也可以指定使⽤其他端⼝)与已知的对等节点建⽴连接。

  在建⽴连接时,该节点会通过发送⼀条包含基本认证内容的version消息开始“握⼿”通信过程(如下图)。这⼀过程包括如下内容:

    1)PROTOCOL_VERSION

     2)nLocalServices:⼀组该节点⽀持的本地服务列表,当前仅⽀持NODE_NETWORK

     3)nTIme:当前时间。

     4)addrYou:当前节点可见的远程节点的IP地址。

     5)addrMe:本地节点所发现的本机IP地址。

     6)subver:指⽰当前节点运⾏的软件类型的⼦版本号(例如:”/Satoshi:0.9.2.1/”)

     7)BaseHeight:当前节点区块链的区块⾼度。

  ⽹络中的对等节点通过对verack消息的响应进⾏确认并建⽴连接;有时候,如果接收节点需要互换连接并连回起始节点,也会传回该对等节点的version消息。

    BlockTrain网络-LMLPHP

  新节点是如何发现⽹络中的对等节点的呢?

  1、客⼾端会维持⼀个列表,那⾥列出了那些⻓期稳定运⾏的节点。这样的节点被称为“种⼦节点(seed nodes)”。

    在⽐特币核⼼客⼾端中,是否使⽤种⼦节点是通过 “-dnsseed” 控制的。默认情况下,该选项设为1,即意味着使⽤种⼦节点。

  2、另⼀种⽅式是,起始时将⾄少⼀个⽐特币节点的IP地址提供给正在启动的节点。在这之后,启动节点可以通过后续指令建⽴新的连接。⽤⼾可以使⽤命令⾏参数“-seednode”把启动节点“引荐”并连接到⼀个节点,并将该节点⽤作DNS种⼦。在初始种⼦节点被⽤于形成“引荐”信息之后,客⼾端会断开与它的连接、并与新发现的对等节点进⾏通信。

  

  当建⽴⼀个或多个连接后,新节点将⼀条包含⾃⾝IP地址的addr消息发送给其相邻节点。相邻节点再将此条addr消息依次转发给它们各⾃的相邻节点,从⽽保证新节点信息被多个节点所接收、保证连接更稳定。

  另外,新接⼊的节点可以向它的相邻节点发送getaddr消息,要求它们返回其已知对等节点的IP地址列表。通过这种⽅式,节点可以找到需连接到的对等节点,并向⽹络发布它的消息以便其他节点查找。

    BlockTrain网络-LMLPHP

    由于节点可以随时加⼊和离开,通讯路径是不可靠的。因此,节点必须持续进⾏两项⼯作:

      1)在失去已有连接时发现新节点。

      2)并在其他节点启动时为其提供帮助。

     在启动完成后,节点会记住它最近成功连接的对等节点;因此,当重新启动后它可以迅速与先前的对等节点⽹络重新建⽴连接。如果先前的⽹络的对等节点对连接请求⽆应答,该节点可以使⽤种⼦节点进⾏重启动。

    在运⾏⽐特币核⼼客⼾端的节点上,您可以使⽤ getpeerinfo 命令列出对等节点连接信息:

      BlockTrain网络-LMLPHP

    ⽤⼾可以通过提供 -connect=<IP地址> 选项来指定⼀个或多个IP地址,从⽽达到复写⾃动节点管理功能并指定IP地址列表的⽬的。如果采⽤此选项,节点只连接到这些选定的节点IP地址,⽽不会⾃动发现并维护对等节点之间的连接。

     如果已建⽴的连接没有数据通信,所在的节点会定期发送信息以维持连接。如果节点持续某个连接⻓达90分钟没有任何通信,它会被认为已经从⽹络中断开,⽹络将开始查找⼀个新的对等节点。

全节点

   辨别您是否在运⾏全节点是⼗分容易的:只需要查看您的永久性存储设备(如硬盘)是否有超过20GB的空间被⽤来存储完整区块链即可。如果您需要很⼤的磁盘空间、并且同步⽐特币⽹络耗时2⾄3天,那么您使⽤的正是全节点。这就是摆脱中⼼化管理、获得完全的独⽴⾃由所要付出的代价。

  尽管⽬前还有⼀些使⽤不同编程语⾔及软件架构的其他的完整区块链客⼾端存在,但是最常⽤的仍然是⽐特币核⼼客⼾端,它也被称为“Satoshi客⼾端”。⽐特币⽹络中超过90%的节点运⾏着各个版本的⽐特币核⼼客⼾端。如前⽂所述,它可以通过节点间发送的version消息或通过getpeerinfo命令所得到的⼦版本字符串“Satoshi”加以辨识,例如 /Satoshi: 0.8.6/。

  ⼀个全节点连接到对等节点之后,第⼀件要做的事情就是构建完整的区块链。如果该节点是⼀个全新节点,那么它就不包含任何区块链信息,它只知道⼀个区块——静态植⼊在客⼾端软件中的创世区块。新节点需要下载从0号区块(创世区块)开始的数⼗万区块的全部内容,才能跟⽹络同步、并重建全区块链。

  同步区块链的过程从发送version消息开始,这是因为该消息中含有的BestHeight字段标⽰了⼀个节点当前的区块链⾼度(区块数量)。节点可以从它的对等节点中得到版本消息,了解双⽅各⾃有多少区块,从⽽可以与其⾃⾝区块链所拥有的区块数量进⾏⽐较。

  对等节点们会交换⼀个getblocks消息,其中包含他们本地区块链的顶端区块哈希值。如果某个对等节点识别出它接收到的哈希值并不属于顶端区块,⽽是属于⼀个⾮顶端区块的旧区块,那么它就能推断出:其⾃⾝的本地区块链⽐其他对等节点的区块链更⻓。

  它会识别出第⼀批可供分享的500个区块,通过使⽤inv(inventory)消息把这些区块的哈希值传播出去。缺少这些区块的节点便可以通过各⾃发送的getdata消息来请求得到全区块信息,⽤包含在inv消息中的哈希值来确认是否为正确的被请求的区块,从⽽读取这些缺失的区块。

  于是它开始向所有与之相连的对等节点请求区块,并通过分摊⼯作量的⽅式防⽌单⼀对等节点被批量请求所压垮。该节点会追踪记录其每个对等节点连接上“正在传输”(指那些它已经发出了请求但还没有接收到)的区块数量,并且检查该数量有没有超过上限( MAX_BLOCKS_IN_TRANSIT_PER_PEER )。⽤这种办法,如果⼀个节点需要更新⼤量区块,它会在上⼀请求完成后才发送对新区块的请求,从⽽允许对等节点控制更新速度,不⾄于压垮⽹络。

  每当⼀个节点离线,不管离线时间有多⻓,这个与对等节点⽐较本地区块链并恢复缺失区块的过程就会被触发。如果⼀个节点只离线⼏分钟,可能只会缺失⼏个区块;当它离线⻓达⼀个⽉,可能会缺失上千个区块。但⽆论哪种情况,它都会从发送 getblocks 消息开始,收到⼀个inv响应

  BlockTrain网络-LMLPHP

简易支付验证结点

  随着⽐特币的使⽤热潮,SPV节点逐渐变成⽐特币节点(尤其是⽐特币钱包)所采⽤的最常⻅的形式。

  SPV节点只需下载区块头,⽽不⽤下载包含在每个区块中的交易信息。由此产⽣的不含交易信息的区块链,⼤⼩只有完整区块链的 1/1000

  SPV节点不能构建所有可⽤于消费的UTXO的全貌,这是由于它们并不知道⽹络上所有交易的完整信息。

  SPV节点验证交易时所使⽤的⽅法略有不同,这个⽅法需依赖对等节点“按需”提供区块链相关部分的局部视图。

   例如:

  1)对于全节点。

    ⼀个全节点要检查第300,000号区块中的某个交易,它会把从该区块开始⼀直回溯到创世区块的300,000个区块全部都链接起来,并建⽴⼀个完整的UTXO数据库,通过确认该UTXO是否还未被⽀付来证实交易的有效性。

  2)对于SPV节点。

    SPV节点则不能验证UTXO是否还未被⽀付。相反地,SPV节点会在该交易信息和它所在区块之间⽤merkle路径(⻅“7.7 Merkle 树”)建⽴⼀条链接。然后SPV节点⼀直等待,直到序号从300,001到300,006的六个区块堆叠在该交易所在的区块之上,并通过确⽴交易的深度是在第300,006区块~第300,001区块之下来验证交易的有效性。事实上,如果⽹络中的其他节点都接受了第300,000区块,并通过⾜够的⼯作在该块之上⼜⽣成了六个区块,根据代理⽹关协议,就可以证明该交易不是双重⽀付

SPV节点毫⽆疑问可以证实某个交易的存在性,但它不能验证某个交易(譬如同⼀个UTXO的双重⽀付)不存在。SPV节点也容易受到⽹络分区攻击或Sybil攻击。在后者情况中,SPV节点被连接到虚假节点或虚假⽹络中,没有通向可靠节点或真正的⽐特币⽹络的连接。

  

  SPV节点使⽤的是⼀条getheaders消息,⽽不是getblocks消息来获得区块头。发出响应的对等节点将⽤⼀条headers消息发送多达2000个区块头。这⼀过程和全节点获取所有区块的过程没什么区别。SPV节点还在与对等节点的连接上设置了过滤,⽤以过滤从对等节点发来的未来区块和交易数据流。任何⽬标交易都是通过⼀条getdata的请求来读取的。对等节点⽣成⼀条包含交易信息的tx消息作为响应。

    BlockTrain网络-LMLPHP

    监控⽹络的第三⽅可以跟踪某个SPV节点上的钱包所请求的全部交易信息,并且利⽤这些交易信息把⽐特币地址和钱包的⽤⼾关联起来,从⽽损害了⽤⼾的隐私。

Bloom过滤器

  在引⼊SPV节点/轻量级节点后不久,⽐特币开发⼈员就添加了⼀个新功能:Bloom过滤器,⽤以解决SPV节点的隐私⻛险问题。Bloom过滤器通过⼀个采⽤概率⽽不是固定模式的过滤机制,允许SPV节点只接收交易信息的⼦集,同时不会精确泄露哪些是它们感兴趣的地址。

  ⽤我们之前的例⼦,⼀位⼿中没有地图的游客需要询问去特定地⽅的路线。如果他向陌⽣⼈询问“教堂街23号在哪⾥”,不经意之间,他就暴露了⾃⼰的⽬的地。Bloom过滤器则会这样问,附近有带‘堂’字的街道吗?”这样的问法包含了⽐之前略少的关键词。

  BlockTrain网络-LMLPHP

交易池

  被称为内存池或交易池。节点们利⽤这个池来追踪记录那些被⽹络所知晓、但还未被区块链所包含的交易。

  

  当⼀个交易被添加到交易池中,会同时检查孤⽴交易池,看是否有某个孤⽴交易引⽤了此交易的输出(⼦交易)。任何匹配的孤⽴交易会被进⾏验证。如果验证有效,它们会从孤⽴交易池中删除,并添加到交易池中,使以其⽗交易开始的链变得完整。对新加⼊交易池的交易来说,它不再是孤⽴交易。前述过程重复递归寻找进⼀步的后代,直⾄所有的后代都被找到。通过这⼀过程,⼀个⽗交易的到达把整条链中的孤⽴交易和它们的⽗级交易重新结合在⼀起,从⽽触发了整条独⽴交易链进⾏

级联重构。

  

  交易池和孤⽴交易池(如有实施)都是存储在本地内存中,并不是存储在永久性存储设备(如硬盘)⾥。更准确的说,它们是随⽹络传⼊的消息动态填充的。节点启动时,两个池都是空闲的;随着⽹络中新交易不断被接收,两个池逐渐被填充。

  有些⽐特币客⼾端的实现还维护⼀个UTXO数据库,也称UTXO池,是区块链中所有未⽀付交易输出的集合。“UTXO池”的名字听上去与交易池相似,但它代表了不同的数据集。UTXO池不同于交易池和孤⽴交易池的地⽅在于,它在初始化时不为空,⽽是包含了数以百万计的未⽀付交易输出条⽬,有些条⽬的历史甚⾄可以追溯⾄2009年。UTXO池可能会被安置在本地内存,或者作为⼀个包含索引的数据库表安置在永久性存储设备中。

警告消息

  警告消息并不经常使⽤,但在⼤多数节点上都有此功能。警告消息是⽐特币的“紧急⼴播系统”,⽐特币核⼼开发⼈员可以借此功能给所有⽐特币节点发送紧急⽂本消息。

  收到警告消息的节点会验证该消息,检查是否过期,并传播给其所有对等节点,从⽽保证了整个⽹络中的快速传播。

05-11 18:25