大家好,如果您还对区块链交易网站源码分享不太了解,没有关系,今天就由本站为大家分享区块链交易网站源码分享的知识,包括区块链交易系统源码的问题都会给大家分析到,还望可以解决大家的问题,下面我们就开始吧!
免责声明:本文旨在传递更多市场信息,不构成任何投资建议。文章仅代表作者观点,不代表火星财经官方立场。
小编:记得关注哦
投资区块链,猛戳:火星财经App下载
来源:乔疯
原文标题:精通Filecoin:Filecoin源码之Hello协议
当调用Filecoin全节点的start方法启动全节点时,调用hello协议的New方法,这个方法的处理如下:
生成Hello对象。
hello:=&Handler{host:h,genesis:gen,chainSyncCB:syncCallback,getHeaviestTipSet:getHeaviestTipSet,net:net,commitSha:commitSha,}
其中host对象为底层libp2提供的Host对象;genesis为创世区块的CID;chainSyncCB为全节点对象的syncCallBack函数,用于从远程节点同步区块;getHeaviestTipSet为porcelain.API对象的ChainHead方法(这个对象继承自plumbing.API对象,ChainHead方法定义于后者),用于返回区块链头部的tipset;net表示当前的网络环境,比如测试网、正式网;调用host对象的SetStreamHandler方法,设置自身的handleNewStream方法作为/fil/hello/1.0.0协议的处理器。
h.SetStreamHandler(protocol,hello.handleNewStream)
当连接建立时,通过后面注册的通知者,从而调用sayHello方法,在这个方法中打开一个hello协议的流,并发送hello消息。调用Host对象的网络对象(即swarm对象)的Notify方法,把自身作为被通知者注册到网络对象上。
h.Network.Notify((*helloNotify)(hello))
在这一步,通过调用host对象的Network方法,返回底层的swarm对象,然后把hello对象转化为helloNotify对象,最后调用swarm对象的Notify方法,从而当底层的swarm对象有任何事件发生时都会通知helloNotify对象(即hello对象)。
在Hello协议中我们只关心建立连接事件,所以helloNotify类型只实现了这个方法,其他方法都为空实现,具体如下:
typehelloNotifyHandler
func(hn*helloNotify)hello*Handler{return(*Handler)(hn)}
consthelloTimeout=time.Second*10
func(hn*helloNotify)Connected(nnet.Network,cnet.Conn){gofunc{ctx,cancel:=context.WithTimeout(context.Background,helloTimeout)defercancelp:=c.RemotePeeriferr:=hn.hello.sayHello(ctx,p);err!=nil{log.Warningf(“failedtosendhellohandshaketopeer%s:%s”,p,err)}}}
当节点作为客户端,拨号连接到远程对等节点时,底层的swarm对象会调用自身的notifyAll方法,通知所有的Notify对象有连接被打开,即调用所有Notify对象的Connected方法,包括前面我们注册的通知对象。当调用helloNotify对象的Connected方法时,这个方法内部调用自身的hello方法,后者返回自身并强制转化为Handler类型,然后调用它的sayHello方法,对我们当前连接的远程进行打招呼。
与此同时,当远程节点作为服务器,接收到我们发送的连接请求生成连接时,它的swarm对象也会通知它的所有Notify对象,从而也会它的前面注册的通知对象,即调用服务器商的Connected方法,从而调用它的sayHello方法向我们发送它的区块情况;因为第二步中,我们把Hello对象的handleNewStream方法注册为Hello协议的处理器,所以当节点接收到远程节点发送区块情况时,就会调用这个方法进行处理,这个方法又会调用调用全节点的syncCallBack方法进行区块同步处理。
总体上来说,Hello协议通过sayHello和handleNewStream开启了区块同步,前者把自身的区块情况发送到远程节点,后者处理远程节点发送的区块情况。
sayHello方法处理如下:
调用Host对象的NewStream,生成一个处理Hello协议的流对象。
s,err:=h.host.NewStream(ctx,p,protocol)iferr!=nil{returnerr}defers.Close//nolint:errcheck
调用自身的getOurHelloMessage方法,获取自身区块链顶端的信息。
msg:=h.getOurHelloMessage
这个方法内部执行流程如下:调用自身getHeaviestTipSet方法,获取区块链顶端的信息这个方法是plumbing.API对象ChainHead方法的引用。使用获取到的区块链信息,生成并返回消息对象Message。通过流发送区块信息到远程节点。
handleNewStream方法处理如下:
生成消息对象Message,并从流中读取远程对等节点发送过来的内容到消息对象中。
varhelloMessageiferr:=cbu.NewMsgReader(s).ReadMsg(&hello);err!=nil{log.Debugf(“badhellomessagefrompeer%s:%s”,from,err)helloMsgErrCt.Inc(context.TODO,1)s.Conn.Close//nolint:errcheckreturn}
调用自身的processHelloMessage方法,处理远程节点发送的消息。这个方法代码如下:
func(h*Handler)processHelloMessage(frompeer.ID,msg*Message)error{if!msg.GenesisHash.Equals(h.genesis){returnErrBadGenesis}if(h.net==”devnet-test”||h.net==”devnet-user”)&&msg.CommitSha!=h.commitSha{returnErrWrongVersion}
h.chainSyncCB(from,msg.HeaviestTipSetCids,msg.HeaviestTipSetHeight)returnnil
}
它的处理逻辑比较简单:首先,检查远程节点发送的创世区块哈希是否自身的创世区块哈希相等。如果不等,直接返回错误。然后,检查网络类型。最终,调用自身的chainSyncCB方法,处理远程节点发送的区块信息。这个同步回调方法对象在全节点的启动方法Start中生成。它的主要生成就是根据远程节点发送的区块链最顶层的信息,生成一个types/SortedCidSet对象,然后调用chain/syncer.go中的HandleNewTipset方法来处理远程发送的区块信息。根据前面处理消息的结果进行不同的处理。
switcherr:=h.processHelloMessage(from,&hello);err{caseErrBadGenesis:log.Debugf(“genesiscid:%sdoesnotmatch:%s,disconnectingfrompeer:%s”,&hello.GenesisHash,h.genesis,from)genesisErrCt.Inc(context.TODO,1)s.Conn.Close//nolint:errcheckreturncaseErrWrongVersion:log.Debugf(“codenotatsameversion:peerhasversion%s,daemonhasversion%s,disconnectingfrompeer:%s”,hello.CommitSha,h.commitSha,from)versionErrCt.Inc(context.TODO,1)s.Conn.Close//nolint:errcheckreturncasenil://ok,noopdefault:log.Error(err)}
OK,本文到此结束,希望对大家有所帮助。
