声明:本文旨在传递更多市场信息,不构成任何投资建议。文章仅代表作者观点,不代表火星财经官方立场。
边肖:记得要集中注意力。
投资区块链,戳:火星财经App下载
资料来源:乔峰
原标题:精通Filecoin的Hello协议:Filecoin源代码
当调用Filecoin all nodes的start方法启动所有节点时,调用hello协议的新方法。该方法的处理过程如下:
生成一个Hello对象。Hello:=handler {Host: h,genesis: gen,chainsynccb: synccallback,getheaviessttipset:getheaviessttipset,net: net,commitsha: commitsha,}其中主机对象是底层libp2提供的主机对象;创世纪是CID创作区块的;ChainSyncCB是所有节点对象的syncCallBack函数,用来同步来自远程节点的块;getheaviesettipset;是瓷器的链头法。API对象(该对象继承自管道。API对象,并在后者中定义了ChainHead方法),用于返回区块链头的TipSetNet代表当前的网络环境,如测试网、官方网;调用host对象的SetStreamHandler方法,将自己的handleNewStream方法设置为/fil/hello/1.0.0协议的处理器。H. SetStreamHandler(协议,你好。HandleNewStream)当连接建立后,通过后来注册的notifier,调用sayHello方法,打开Hello协议流,发送hello消息。调用主机对象(即群对象)的网络对象的Notify方法,将自己注册为网络对象上的被通知人。h . Network . Notify((* helloNotify)(hello))这一步通过调用host对象的network方法返回底层swarm对象,然后将hello对象转换成helloNotify对象,最后调用swarm对象的notify方法,这样当底层swarm对象发生任何事件时,hello notify对象(即hello对象)都会得到通知。在Hello协议中,我们只关心连接建立事件,所以helloNotify类型只实现这个方法,其他所有方法都是null实现,如下:
键入hello notify Handler func(HN * hello notify)hello * Handler { return(* Handler)(HN)}
const helloTimeout=time。第二个* 10
func (hn *helloNotify)连接(n网。网络,c网。Conn) { go func { ctx,cancel :=context。WithTimeout(上下文。Background,hello time out)defer cancel p:=c . remote peer if err:=HN . hello . say hello(CTX,p);呃!=nil { log。警告f('向对等方%s发送问候握手失败:%s 'p,err) } }
当一个节点作为客户端拨号到远程对等节点时,底层swarm对象会调用自己的notifyAll方法通知所有notify对象一个连接打开,即调用所有Notify对象的Connected方法,包括之前注册的Notify对象。当调用helloNotify对象的Connected方法时,该方法在内部调用自己的hello方法,该方法返回自身并将其转换为Handler类型,然后调用其sayHello方法来问候我们当前连接的远程。同时,当远程节点作为服务器,接收到我们发送的连接请求生成连接时,它的swarm对象也会通知它的所有notify对象,从而调用它之前注册的Notify对象,也就是服务器厂商的Connected方法,然后调用它的sayHello方法向我们发送它的block信息;第二步,我们将Hello对象的handleNewStream方法注册为Hello协议的处理器,这样当一个节点收到远程节点发来的块时,就会调用这个方法进行处理,这个方法会调用所有节点的syncCallBack方法进行块同步。
一般来说,Hello协议通过sayHello和handleNewStream启动块同步,前者向远程节点发送自己的块信息,后者处理远程节点发送的块信息。
所说的方法处理如下:
调用主持对象的新闻流,生成一个处理你好协议的流对象。s,err :=h.host.NewStream(ctx,p,protocol) if err!=nil {返回错误}延迟关闭//nolint: errcheck调用自身的getOurHelloMessage方法,获取自身区块链顶端的信息消息:=h.getOurHelloMessage这个方法内部执行流程如下:调用自身getheaviessttipset方法,获取区块链顶端的信息这个方法是管道工程。应用程序接口对象链头方法的引用。使用获取到的区块链信息,生成并返回消息对象消息。通过流发送区块信息到远程节点handleNewStream .方法处理如下:
生成消息对象消息,并从流中读取远程对等节点发送过来的内容到消息对象中var你好消息如果err :=cbu .NewMsgReader .ReadMsg(你好);呃!=nil { log .Debugf('来自对等方%s的错误你好消息:%s 'from,err) helloMsgErrCt .公司(上下文TODO,1)s . conn . close//nolint:err check return }调用自身的进程消息方法,处理远程节点发送的消息。这个方法代码如下:func(h * Handler)processHelloMessage(来自对等方. ID,msg *Message)错误{如果!味精创世纪哈希。equals(h . genesis){ return errbadgesings } if(h . net==' devnet-test ' | | h.net==' devnet-user ')msg .CommitSha!=h . commit sha { return error version } h . chain syncb(from,msg .重磅炸弹,味精.HeaviestTipSetHeight)返回nil }它的处理逻辑比较简单:首先,检查远程节点发送的创世区块哈希是否自身的创世区块哈希相等。如果不等,直接返回错误。然后,检查网络类型。最终,调用自身的链式同步commandcontrolblock命令控制块方法,处理远程节点发送的区块信息。这个同步回调方法对象在全节点的启动方法开始中生成。它的主要生成就是根据远程节点发送的区块链最顶层的信息,生成一个types/SortedCidSet对象,然后调用chain/syncer.go中的HandleNewTipset方法来处理远程发送的区块信息。根据前面处理消息的结果进行不同的处理。switch err:=h . processhellomessage(from,hello);err { case errb genesis:log .Debugf('源cid: %s不匹配:%s,正在断开与对等方的连接:%s '你好.GenesisHash,h.genesis,from) genesisErrCt .公司(上下文TODO,1)s . conn . close//nolint:err check返回案例错误版本:日志.Debugf('代码版本不同:对等方的版本为%s,守护程序的版本为%s,正在从对等方断开连接:%s '你好.CommitSha,h.commitSha,from) versionErrCt .公司(上下文TODO,1)s . conn . close//nolint:err check return case nil://ok,noop default: log .错误(呃)}