比特币通信协议 - 币圈消息

比特币通信协议篇11、二、TURN简介。在典型的情况下,TURN客户端连接到内网中,并且通过一个或者多个NAT到 详细

比特币底层代码 - 币圈消息

[复制链接]
51 0
wangjia 发表于 2022-11-3 15:44:26 | 只看该作者 |阅读模式 打印 上一主题 下一主题
比特币底层代码篇11、以太坊作为一个去中心化的系统,其底层个体相互间的通信显然非常重要,所有数据的同步,各个个体状态的更新,都依赖于整个网络中每个个体相互间的通信机制。以太坊的网络通信基于peer-to-peer(p2p)通信协议,又根据自身传输数据类型(区块,交易,哈希值等),网络节点业务相关性等需求,在各方面做了特别设计!
2、在无限循环中启动handleMsg(),当对方peer发出任何msg时,handleMsg()可以捕捉相应类型的消息并在己方进行处理!
3、pm.syncTransactions(p)。
4、对于以太坊通信机制的借鉴。第二层属于pkgp2p,可认为是泛化的p2p通信结构,比较典型的结构类型包括代表远端通信对象的p2p.Peer{},封装自更底层连接对象的conn{},通信用通道对象protoRW{},以及启动监听、处理新加入连接或断开连接的Server{}。这一层中,各种数据类型的界限比较清晰,尽量不出现揉杂的情况,这也是泛化结构的需求。值得关注的是p2p.Protocol{},它应该是针对上层应用特意开辟的类型,主要作用包括容纳应用程序所要求的回调函数等,并通过p2p.Server{}在新连接建立后,将其传递给通信对象peer。从这个类型所起的作用来看,命名为Protocol还是比较贴切的,尽管不应将其与TCP/IP协议等既有概念混淆!
5、p2p通信的管理模块ProtocolManager。
6、以上这四段相对独立的业务流程的逻辑分别是:。
7、Fetcher类型成员累积所有其他个体发送来的有关新数据的宣布消息,并在自身对照后,安排相应的获取请求!
8、ifrw,ok:=p.rw.(*meteredMsgReadWriter);ok{。
9、小结:。不需要结构化,经过改进的非结构化(比如设计好相邻个体列表)网络模型可以满足需求;。
10、根据以太坊的运行特点,我们可以大概勾勒出以太坊个体也就是客户端所组成网络的一些需求特征:。

比特币底层代码篇21、第一层处于pkgeth中,可以直接被eth.Ethereum,eth.ProtocolManager等顶层管理模块使用,在类型声明上也明显考虑了eth.Ethereum的使用特点。典型的有eth.peer{},eth.peerSet{},其中peerSet是peer的集合类型,而eth.peer代表了远端通信对象和其所有通信操作,它封装更底层的p2p.Peer对象以及读写通道等!
2、p.Handshake(pm.networkId,td,head,genesis)。
3、尽管如此,这样的p2p网络缺点也很明显:由于每个个体需要存有数量不少的相邻个体列表,所以当网络中发生大量新旧个体频繁加入和离开的“churn”事件时,整个网络的性能会大幅恶化,因为每个个体的很大一部分资源消耗在相邻列表更新上(包括自身相邻列表的更新,和相互之间更新所储列表),同时许多peer所在的key也需要重新定义;另外,哈希表本身容量是有使用限制的,当哈希表中存储的数据空间大于其设计容量的一半时,哈希表就会大概率出现“碰撞”事故,这样的限制也使得依据DHT建立的p2p网络的整体效率大打折扣!
4、广播新出现的交易对象。txBroadcastLoop()会在txCh通道的收端持续等待,一旦接收到有关新交易的事件,会立即调用BroadcastTx()函数广播给那些尚无该交易对象的相邻个体!
5、并非每个个体与网络中其他同类均有通信。这其实也是p2p网络的一个很重要的特点:一个个体只需要与相邻的一部分同类有通信即可,每个个体可与多少相邻个体、哪些个体有通信,是可以加以设计的,。
6、小小说明:这里提到的 远端 个体,即非本peer的其他peer对象。以太坊的p2p网络中,所有进行通信的两个peer都必须率先经过相互的注册(register),并被添加到各自缓存的peer列表,也就是peerSet{}对象中,这样的两个peers,就可以称为“相邻”。所以,这里提到的“远端 个体,如果处于可通信状态,则必定已经“相邻”!
7、由Start()启动的四个函数在业务逻辑上各有侧重,。
8、eth.ProtocolManager中,会对每一个远端peer发起主动传输数据的操作,这组操作按照数据类型区分,可分为交易和区块;而若以发送数据方式来区分,亦可分为广播单项数据,和同步一组同类型数据。这样两两配对,即可形成4组主动传输数据的操作!
9、handle():交给其他peer的回调函数。
10、ProtocolManager主要成员包括:。
比特币底层代码篇31、在运行方面,Start()函数是ProtocolManager的启动函数,它会在eth.Ethereum.Start()中被主动调用。ProtocolManager.Start()会启用4个单独线程(goroutine,协程)去分别执行4个函数,这也标志着该以太坊个体p2p通信的全面启动!
2、调用syncTransactions(),用当前txpool中新累计的tx对象组装成一个txsync{}对象,推送到内部通道txsyncCh。还记得Start()启动的四个函数么?其中第四项txsyncLoop()中用以等待txsync{}数据的通道txsyncCh,正是在这里被推入txsync{}的!
3、td,head,genesis:=pm.blockchain.Status()。
4、Start():全面启动p2p通信。
5、综合这两部分代码逻辑,可以发现:。
6、iferr:=pm.handleMsg(p);err!=nil{。
7、ProtocolManager通过在p2p.Protocol{}对象中埋入回调函数,可以对远端peer的任何事件及状态更新作出响应。这些Protocol对象,会由p2p.Server传递给每一个新连接上的远端peer!
8、结构化的。定时与相邻个体进行区块全链的强制同步。syncer()首先启动fetcher成员,然后进入一个无限循环,每次循环中都会向相邻peer列表中“最优”的那个peer作一次区块全链同步。发起上述同步的理由分两种:如果有新登记(加入)的相邻个体,则在整个peer列表数目大于5时,发起之;如果没有新peer到达,则以10s为间隔定时的发起之。这里所谓 最优 指的是peer中所维护区块链的TotalDifficulty(td)最高,由于Td是全链中从创世块到最新头块的Difficulty值总和,所以Td值最高就意味着它的区块链是最新的,跟这样的peer作区块全链同步,显然改动量是最小的,此即 最优 !
9、无结构化的。以太坊中每个peer接收新连接的过程,源于标准的TCP/IP监听来访连接的方式(listener)。而每个新连接上的peer,都会由p2p.Server交给ProtocolManager!
10、由于以太坊中p2p通信相关代码量较大,打算分为上下两篇文章来加以详解:上篇主要介绍管理p2p通信的核心类ProtocolManager内部主要流程,以及通信相关协议族的设计;下篇主要介绍ProtocolManager的两个成员Fetcher和Downloader,这里是上篇!
比特币底层代码篇41、广播新挖掘出的区块。minedBroadcastLoop()持续等待本个体的新挖掘出区块事件,然后立即广播给需要的相邻个体。当不再订阅新挖掘区块事件时,这个函数才会结束等待并返回。很有意思的是,在收到新挖掘出区块事件后,minedBroadcastLoop()会连续调用两次BroadcastBlock(),当该参数为true时,会将整个新区块依次发给相邻区块中的一小部分;而当其为false时,仅仅将新区块的Hash值和Number发送给所有相邻列表!
2、ProtocolManager.handle()就是这样一个函数,它会在ProtocolManager对象创建时,以回调函数的方式“埋入”每个p2p.Protocol对象中(实现了Protocol.Run()方法)。之后每当有新peer要与己方建立通信时,如果对方能够支持该Protocol,那么双方就可以顺利的建立并开始通信。以下是handle()的基本代码:。
3、Node.Start()中首先会创建p2p.Server{},此时Server中的Protocol[]还是空的;然后将Node中载入的所有实现体中的Protocol都收集起来,一并交给Server对象,作为Server.Protocols列表;然后启动Server对象,并将Server对象作为参数去逐一启动每个实现体!
4、}。func(pm*ProtocolManager)handle(p*peer)error{。
5、returnerr。之后的章节中,我们可以逐步了解以太坊中的这个p2p网络通信是如何完善并实现的!
6、诸如以太坊这种去中心化的数字货币运行系统,天生适用p2p通信架构。不过原理虽然简单,在系统架构的层面,依然有很多实现细节需要加以关注!
7、初始化一个读写通道,用以跟对方peer相互数据传输!
8、希望对于理解以太坊中p2p通信相关代码有所帮助!
9、所有远端peer与己方之间的通信,都是通过p2p.Server{}来管理的,Server在整个客户端最早的启动步骤Node.Start()中被创建并启动,而node.Node是用来承载客户端中所有node.实现体的容器,。
10、刚才提到,handle()函数以回调函数的形式被放入一个p2p.Protocol{}里,那么Protocol对象是如何交给新peer的呢?这部分细节,隐藏在新peer连接建立的过程中!
比特币底层代码篇51、第三层处于golang自带的网络代码包中,也可分为两部分:第一部分pkgnet,包括代表网络连接的接口,包括更底层的网络相关系统调用类等,可视为封装了网络层(IP)和传输层(TCP)协议的系统实现!
2、一般意义上的p2p网络。将新出现的交易对象均匀的同步给相邻个体。txsyncLoop()主体也是一个无限循环,它的逻辑稍微复杂一些:首先有一个数据类型txsync{p,txs},包含peer和tx列表;通道txsyncCh用来接收txsync{}对象;txsyncLoop()每次循环时,如果从通道txsyncCh中收到新数据,则将它存入一个本地map[]结构,k为peer.ID,v为txsync{},并将这组tx对象发送给这个peer;每次向peer发送tx对象的上限数目100*1024,如果txsync{}对象中有剩余tx,则该txsync{}对象继续存入map[]并更新tx数目;如果本次循环没有新到达txsync{},则从map[]结构中随机找出一个txsync对象,将其中的tx组发送给相应的peer,重复以上循环!
3、pm.downloader.RegisterPeer(p.id,p.version,p)。
4、可以看到,Server.Start()中启动一个单独线程(listenLoop())去监听某个端口有无主动发来的IP连接;另外一个单独线程启动run()函数,在无限循环里处理接收到的任何新消息新对象。在run()函数中,如果有远端peer发来连接请求(新的p2p.conn{}),则调用Server.newPeer()生成新的peer对象,并把Server.Protocols全交给peer!
5、建立新peer连接和传递Protocol[]。
6、rm.Init(p.version)。
7、///eth/handler.go。
8、pm.peers.Register(p)。
9、在上文的介绍中,出现了多处有关p2p通信协议的结构类型,比如eth.peer,p2p.Peer,Server等等。这里不妨对这些p2p通信协议族的结构一并作个总解。以太坊中用到的p2p通信协议族的结构类型,大致可分为三层:。
10、ProtocolManager用到的这些通道的另一端,可能是其他的个体peer,也可能是系统内单例的数据源比如txPool,或者是事件订阅的管理者比如event.Mux!
比特币底层代码篇61、注册对方peer,存入己方peer列表;只有handle()函数退出时,才会将这个peer移除出列表!
2、上述函数的实现中,很多地方都体现出巧妙的设计,比如BroadcastBlock()中,如果发送区块block,由于数据量相对重量级,则仅仅选择一小部分相邻peer,而如果发送hash值+Number值,则发给所有相邻peer;又比如txsyncLoop()中,会从map[]中随机选择一个peer进行发送(随机选择的txsync{}中包含peer)。这些细节,很好的控制了单次业务请求的资源消耗对于定向区域的倾向性,使得整个网络资源消耗愈加均衡,体现出非常全面的设计思路!
3、 。根据p2p网络中节点相互之间如何联系,可以将p2p网络简单区分为无结构化的(unstructured),和结构化的(structured)两大类!
4、在开始介绍以太坊的p2p通信机制之前,不妨先来看看一般意义上的p2p网络通信的一些特征,以下部分内容摘自peer-to-peer_wiki。
5、那么Server.Start()中做了什么呢?与新peer创建相关的主要逻辑:。
6、Downloader成员注册这个新peer;Downloader会自己维护一个相邻peer列表!
7、个体间的相互同步更新需要仔细设计;。
8、这种p2p网络中的个体分布经过精心设计,主要目的是为了提高查询数据的效率,降低查询数据带来的资源消耗。提高查询效率的基本手段是对数据建立索引,结构化p2p网络最普遍的实现方案中使用了分布式哈希表(DistributedHashTable,DHT),它会对每项数据(value)分配一个key以组成(key,value)键值对,同时网络中每个个体的分布 这里的分布主要指相互通信关系-根据key键进行关联和扩展。这样,当要查找某项数据时,只要跟据其key键就能不断的缩小查找区域,大大减少资源消耗!
9、以上四段流程就是ProtocolManager向相邻peer主动发起的通信过程。尽管上述各函数细节从文字阅读起来容易模糊,不过最重要的内容还是值得留意下的:本个体(peer)向其他peer主动发起的通信中,按照数据类型可分两类:交易tx和区块block;而按照通信方式划分,亦可分为广播新的单个数据和同步一组同类型数据,这样简单的两两配对,便可组成上述四段流程!
10、这当然仅仅是特例,大家可能在工作中遇到各种各样拓扑形状的C/S架构,而其核心特征是不变的:C/S网络中的个体地位和功能是不平等的,client个体主要消耗资源,发起请求,server个体主要提供资源并处理请求,这使得C/S架构天然是中心化的!
极客公园 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:比特币底层代码
喜欢 (0)

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
收藏
收藏0
转播
转播
分享
分享
分享
淘帖0
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关注0

粉丝0

帖子2930859

发布主题
阅读排行更多+

Powered by 顺水鱼MT4外汇EA网! X3.2© 2001-2017 顺水MT4外汇EA公司.( 陕ICP备17014341号-1