比特币之P2P通讯

之前看了下比特币P2P通讯的代码,记录一下

大家都知道比特币是去中心化的,那么节点与节点之间是如何通讯的呢,新节点怎么加入到节点网络呢,读完本文就知道大概流程了;如有不对的地方欢迎留言讨论

比特币线程

比特币代码启动之后会开启五个线程用于P2P通讯

ThreadDNSAddressSeed

    从配置好的DNS服务器获取节点的ip地址添加到addrman;这就解决了新节点怎么加入到网络

ThreadOpenAddedConnections

    处理rpc客户端添加的节点信息,然后连接到节点

ThreadOpenConnections

    根据addrman中的ip连接到对应节点,创建节点CNode(连接别人fInbound为false,被连接为true)。默认最多连接到8个节点。默认连接总数不大于125个,包括被连接的节点数

ThreadSocketHandler

    收发各个节点相关的socket数据。监听到有其他节点连接创建CNode(fInbound为true)

ThreadMessageHandler

    处理其他CNode发来的消息与发送消息到其他CNode

节点通讯

全部在线程ThreadMessageHandler中处理消息,每个节点自身遍历连接的所有节点CNode,ProcessMessage处理收到的消息,SendMessages发送消息到其他节点

消息交互

以新加入网络的NodeA和运行全节点的NodeB为例

NodeA connect NodeB的IP地址(比如通过DNS Seed获取到Node B的IP地址),创建CNode B,fInbound为false,同时发送’version’消息,包含自身的版本信息、block高度等信息

NodeB监听到NodeA连接,创建CNode A,fInbound为true

NodeB收到’version’消息后,回复一个’version’消息,同时发送’verack’消息

NodeA收到NodeB发送的’version’消息后,发送’verack’消息。同时发送’getaddr’消息获取NodeB连接的更多节点信息(只有fInbound为false才发送此消息)

NodeA/B收到对方的’verack’消息后,对方的版本号大于等于70012发送’sendheaders’信息,版本号大于等于70014发送’sendcmpct’消息(关于cmpct,即compact block,请参看后续介绍)

NodeB收到’getaddr’消息,发送自己的addrman保存的节点IP信息,最多发送1000个,带在’addr’消息中

NodeA收到’addr’消息后,添加到自己的addrman,然后在ThreadOpenConnections继续连接其他节点直到达到8个的限制

NodeA/B收到对方的’sendheaders’消息,设置fPreferHeaders为true,SendMessages中继续处理。从自己的vBlockHashesToAnnounce中查找到对方blockindex的位置开始发送,附带在’headers’消息中(对于不支持此消息的版本会发送’inv’消息,每次最多发送50000个。区别是inv消息中带的是Block Header的hash,header中带的Block Header)

NodeA/B收到对方的’sendcmpct’消息,设置fProvidesHeaderAndIDs、fWantsCmpctWitness、fSupportsDesiredCmpctVersion等变量后续使用

NodeA收到’headers’消息后,如果自己没有这些header,新建blockindex到mapBlockIndex(保存着全部的block header等信息),然后发送’getdata’消息获取block内容。如果不支持headers信息,会收到’inv’消息,然后发送’getheaders’消息带hash start和stop参数让对方发送hash范围的headers,对方节点NodeB收到’getheaders’消息发送’headers’信息就跟此条开始一样的处理了

NodeB收到’getdata’消息,如果type是block,就发送’block’消息带block内容;如果type是filter block(SPV节点),就发送’merkleblock’带merkle节点信息;如果是cmpct block就发送’cmpctblock’消息带CBlockHeaderAndShortTxIDs信息

NodeA收到’blcok’消息写把block内容写入磁盘,然后更新bestchain(参看后续介绍);如果收到’cmpctblock’(关于compact block请参看后续介绍)消息,会发送’getblocktxn’消息获取更多的tx记录

NodeB收到’getblocktxn’消息,发送’blocktxn’消息带tx记录

NodeA收到’blocktxn’消息,组织成完整的block写入磁盘等

消息交互图示

节点不支持sendheaders和sendcmpct消息

节点支持sendheaders消息不支持sendcmpct消息

节点支持所有消息(即最新版本)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • P2P网络 - 比特币开发指南 原文链接: https://bitcoin.org/en/developer-gu...
    terryc007阅读 10,763评论 0 6
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,422评论 19 139
  • 本文参与#漫步青春#征文活动,作者:章瑶瑶,本人承诺,文章内容为原创,且未在其他平台发布。 白墙青瓦 斗转星移间沦...
    章瑶瑶阅读 1,222评论 0 0
  • 帝国的一群士兵正在森林的边缘进行例行巡视,对于其他人来说,今天的巡视与平常没有区别,可是对于刚刚入伍的新兵来说,确...
    艾伦沃克阅读 1,716评论 0 1
  • 农夫死了 妻儿将他埋葬 他的尸身 就埋在田地后的山冈 那田地曾给予他一生的口粮 野狗饿了 农夫被它吃光 它的小窝 ...
    李泽贤阅读 1,696评论 1 4