blockchain_go节点间命令交互流程分析

区块链 18-07-12 22:45 1745  

1.背景 blockchain_go是一个go语言实现的简化的区块链项目,麻雀虽小五脏俱全,区块链涉及的各个方面都会有所体现,是入门区块链的一个好选择。作为分布式应用的区块链,新节点的加入需要同步已有节点的区块信息,使得自己保持最新,从而才能正常加入区块链中工作。加入到区块链网络中后,也会涉及到各个节点之间的信息和命令交互,本篇对节点间的交互流程进行分析整理。 2.通信协议机制 blockchain_go节点间的通信协议规则采用如下规则: 固定长度command + payload command固定长度12字节,payload是每个命令的消息体的gob打包二进制序列。 底层通信机制方面,blockchain_go采用了简化处理方式,并没有保存和维护每个邻居节点的链接信息,而是采用了“短连接”的方式处理每次消息的发送。 通信协议可以指定tcp或者udp,都兼容。每次发送数据都建立一个socket套接字(无论tcp还是udp),发送完毕后释放链接信息。这样的机制对于数据接收方有另外一个好处,不用处理黏包问题,每次接收数据时将数据全部读完(读到EOF)即可。如果采用场链接tcp协议,对于流式数据是必须要处理半包(协议包数据未收完)和黏包(多个协议包黏在一起,需要拆包),处理逻辑会更复杂。 3.节点间交互命令 节点间的交互命令command如下: version : 发送字节的版本信息 getblocks : 获取区块链中所有块的hash列表 inv : 返回区块hash列表目录 block : 新区块到来通知 addr : 通知其他节点自己的地址信息 getdata : 获取数据请求(获取block区块信息或者tx交易信息) tx : 交易信息到来通知 3.1 version命令 version命令发送给对方,告知对方自己节点的版本信息和区块高度,命令消息体定义: type verzion struct { Version int BestHeight int AddrFrom string } Version: 发送方自己节点区块链的版本号 BestHeight: 发送方区块链的最大高度(区块链中高度越高,表示自己越新),即区块最大个数 AddrFrom: 发送方消息接收地址(并没有让对方通过socket获取,而是发送方灵活指定自己的接收地址) 新节点启动时,发送自己的version信息给配置的知名节点,从而加入到网络中。 3.2 getblocks命令 getblocks命令请求,请求对方发送自己的所有区块的hash列表给自己,消息体定义: type getblocks struct { AddrFrom string } 只需要填充自己的接受地址即可,对方收到请求后,生成hash列表返回。 3.3 inv命令 inv命令是inventory的简写,表示节点得到了目录列表的请求(区块hash列表或者tx交易hash列表)后,发送给请求方的目录响应,消息定义: type inv struct { AddrFrom string Type string Items [][]byte } AddrFrom: 节点自己的信息接收地址 Type: 目录类型(block/tx) Items: 目录具体值(区块hash列表,交易hash列表) 3.4 addr命令 把自己的接收地址和自己知道的知名节点的接收地址发送给对方,消息定义: type addr struct { AddrList []string } AddrList: 地址列表 发送给了对方后,对方可以从这些节点获取信息。 3.5 getdata命令 请求命令,请求对方给自己发送数据,消息定义: type getdata struct { AddrFrom string Type string ID []byte } AddrFrom: 自己的接收地址 Type: 请求的数据类型(block or tx) ID: 请求的数据参数(block类型–>block hash;tx类型–>tx hash) 前面的getblocks只是得到了block的hash列表,并没有得到区块的详细信息,getdata就是提供获取区块或者交易的详细信息。 3.6 block命令 接收到getdata命令,且类型为block时,返回block命令,类型定义: type block struct { AddrFrom string Block []byte } AddrFrom: 自己的接收地址 Block: 请求区块的详细信息 3.7 tx命令 接收到getdata命令,且类型为tx时,返回tx命令,类型定义: type tx struct { AddrFrom string Transaction []byte } AddrFrom: 自己的接收地址 Transaction: 交易信息 4.交互流程 这里主要分析新节点启动加入到区块链的底层交互流程,以及加入成功后,产生一个新的区块后的节点间的交互。 4.1 新节点启动交互流程 新节点的启动交互流程如下图所示: 说明如下: 新节点A启动前配置好邻居节点B的地址,启动后向邻居节点B发送version命令,告知对方自己的区块链版本号,区块高度以及自己的信息接收地址。 节点B接收到version命令后,和自己的区块高度做比较。 如果A的区块高度更高(表示B的区块比A更旧),那么B向A发起getblocks命令,请求区块链的全部区块hash列表。 如果B发现自己的区块高度比A高,那么回应一个version命令给A,让A知道自己的基本信息。 A收到B的version信息,进行区块高度比较。 A发现B比自己的区块更高,自己落后了,需要获取最新区块,于是发送getblocks命令。 B收到getblocks后,将自己的完整区块链的区块hash列表返回给A,发送inv。 A计算收到的区块列表,将没有的所有区块都一次请求获取。 A向B发送getdata(类型为block),获取指定的一个区块详细信息。 B根据给定的查询区块hash,返回区块的详细给A,响应一个block命令。 依次循环,处理完所有区块后,A把自己的区块链更新成了最新状态。 4.2 新区块产生交互流程 新区开产生后的节点交互如下图: 说明如下: 节点A收到了一个新的交易信息,处理交易。 节点A在交易池中有了新信息,触发挖矿逻辑,产出一个block。 节点A把新的block循环依次发送给所有邻居。 通过inv发送新节点的hash信息给邻居。 邻居B收到hash列表后,通过block命令获取区块详细信息。 A返回新区块详细信息给B。 节点B存储新收到的区块,并更新本地的utxo信息。 5.总结 blockchain_go是一个简化版的区块链实现,相关功能都进行了精简,并不具备线上生成能力,不过对于初学区块链,了解区块链相关原理和实现逻辑还是很有意义。

insinty 2020-06-19 22:27

Dutasteride Get From Canada Amex Accepted Cash Delivery https://cheapcialisll.com/ - when will cialis be generic Levitra Generika 20mg Rezeptfrei <a href=https://cheapcialisll.com/#>Cheap Cialis</a> Cialis Online Prezzi