Filecoin技术架构分析之六:协议层hello握手协议

目录6 filecoin源码协议层分析之hello握手协议

6.3.1 数据结构

6.3.2 方法

6.3.3 函数

6.3.4 实例化及业务逻辑

6.1 目的

6.2 源码信息

6.3 源码分析


6.1 目的处理节点上线后的区块同步握手。


6.2 源码信息version

master分支 619b0eb1(2019年3月2日)

package

hello

location

protocol/hello

node/node.go

6.3 源码分析
6.3.1 数据结构定义协议名称

//Protocolisthelibp2pprotocolidentifierforthehelloprotocol.constprotocol=”/fil/hello/1.0.0″

定义hello协议消息体结构

TipSet切片

TipSet高度

创世区块cid

//Messageisthedatastructureofasinglemessageinthehelloprotocol.typeMessagestruct{

HeaviestTipSetCids[]cid.Cid

HeaviestTipSetHeightuint64

GenesisHashcid.Cid

}

同步回调函数类型定义

typesyncCallbackfunc(frompeer.ID,cids[]cid.Cid,heightuint64)

获取Tipset函数类型定义

typegetTipSetFuncfunc()types.TipSet

Handler结构体,当连接到其他节点的时候,其一,会发送包含本节点信息的hello 消息给对端节点; 其二, 对端也会回复一个包含对端节点信息的消息体过来。

host 对应libp2p上的主机

创世区块cid

区块同步回调函数

获取TipSet的函数

//Handlerimplementsthe’Hello’protocolhandler.Uponconnectingtoanew//node,wesendthemamessagecontainingsomeinformationaboutthestateof//ourchain,andreceivethesameinformationfromthem.Thisisusedto//initiateachainsyncanddetectconnectionstoforks.typeHandlerstruct{

hosthost.Host

genesiscid.Cid//chainSyncCBiscalledwhennewpeerstellusabouttheirchain

chainSyncCBsyncCallback//getHeaviestTipSetisusedtoretrievethecurrentheaviesttipset

//forfillingoutourhellomessages.

getHeaviestTipSetgetTipSetFunc

}

错误的创世区块

//ErrBadGenesisistheerrorreturnedwhenamissmatchingenesisblockshappens.varErrBadGenesis=fmt.Errorf(“badgenesisblock”)

以上基本是作为hello客户端的一些定义,以下作为hello服务端的一些定义

//NewpeerconnectionnotificationstypehelloNotifyHandler// 连接超时时间consthelloTimeout=time.Second*10


6.3.2 方法
6.3.2.1 Handler 方法流函数处理,接收远端节点的hello消息

func(h*Handler)handleNewStream(snet.Stream){

defers.Close()//nolint:errcheck

//获取远端节点实例

from:=s.Conn().RemotePeer()varhelloMessage//读取流信息到hello结构体中

iferr:=cbu.NewMsgReader(s).ReadMsg(&hello);err!=nil{

log.Warningf(“badhellomessagefrompeer%s:%s”,from,err)return

}//调用processHelloMessage方法对接收到的消息进行处理

switcherr:=h.processHelloMessage(from,&hello);err{//如果创世区块不一样,关闭流连接退出,不予处理

caseErrBadGenesis:

log.Warningf(“genesiscid:%sdoesnotmatch:%s,disconnectingfrompeer:%s”,&hello.GenesisHash,h.genesis,from)

s.Conn().Close()//nolint:errcheck

return

casenil://ok,noop

default:

log.Error(err)

}

}

处理hello消息

func(h*Handler)processHelloMessage(frompeer.ID,msg*Message)error{//如果创世区块不一样,报错

if!msg.GenesisHash.Equals(h.genesis){returnErrBadGenesis

}//调用区块同步方法

//此回调函数实在node包实例化hello协议的时候中定义的

h.chainSyncCB(from,msg.HeaviestTipSetCids,msg.HeaviestTipSetHeight)returnnil

}

响应远端节点的连接,回复hello消息体

func(h*Handler)getOurHelloMessage()*Message{

heaviest:=h.getHeaviestTipSet()

height,err:=heaviest.Height()iferr!=nil{

panic(“somehowheaviesttipsetisempty”)

}return&Message{

GenesisHash:h.genesis,

HeaviestTipSetCids:heaviest.ToSortedCidSet().ToSlice(),

HeaviestTipSetHeight:height,

}

}

func(h*Handler)sayHello(ctxcontext.Context,ppeer.ID)error{

s,err:=h.host.NewStream(ctx,p,protocol)iferr!=nil{returnerr

}

defers.Close()//nolint:errcheck

//获取本节点的hello消息体

msg:=h.getOurHelloMessage()//向远端节点发送消息体

returncbu.NewMsgWriter(s).WriteMsg(&msg)

}


6.3.2.2 helloNotify方法hello方法,返回一个handler实例

func(hn*helloNotify)hello()*Handler{return(*Handler)(hn)

}

helloNotify实现了libp2p-net/interface.go中的Notifiee接口

func(hn*helloNotify)Connected(nnet.Network,cnet.Conn){gofunc(){

ctx,cancel:=context.WithTimeout(context.Background(),helloTimeout)

defercancel()

p:=c.RemotePeer()//有其他节点连接的时候调用sayHello,发送hello消息体

iferr:=hn.hello().sayHello(ctx,p);err!=nil{log.Warningf(“failedtosendhellohandshaketopeer%s:%s”,p,err)

}

}()

}

func(hn*helloNotify)Listen(nnet.Network,ama.Multiaddr){}

func(hn*helloNotify)ListenClose(nnet.Network,ama.Multiaddr){}

func(hn*helloNotify)Disconnected(nnet.Network,cnet.Conn){}

func(hn*helloNotify)OpenedStream(nnet.Network,snet.Stream){}

func(hn*helloNotify)ClosedStream(nnet.Network,snet.Stream){}


6.3.3 函数创建hello实例

//Newcreatesanewinstanceofthehelloprotocolandregistersitto//thegivenhost,withtheprovidedcallbacks.funcNew(hhost.Host,gencid.Cid,syncCallbacksyncCallback,getHeaviestTipSetgetTipSetFunc)*Handler{

hello:=&Handler{

host:h,

genesis:gen,

chainSyncCB:syncCallback,

getHeaviestTipSet:getHeaviestTipSet,

}//设置流处理回调函数

h.SetStreamHandler(protocol,hello.handleNewStream)//注册网络状态改变通知回调函数

//registerforconnectionnotifications

h.Network().Notify((*helloNotify)(hello))returnhello

}//上文中的helloNotify实现了libp2p-net/interface.go中的Notifiee接口//Notifieeisaninterfaceforanobjectwishingtoreceive//notificationsfromaNetwork.typeNotifieeinterface{

Listen(Network,ma.Multiaddr)//calledwhennetworkstartslisteningonanaddr

ListenClose(Network,ma.Multiaddr)//calledwhennetworkstopslisteningonanaddr

Connected(Network,Conn)//calledwhenaconnectionopened

Disconnected(Network,Conn)//calledwhenaconnectionclosed

OpenedStream(Network,Stream)//calledwhenastreamopened

ClosedStream(Network,Stream)//calledwhenastreamclosed

//TODO

//PeerConnected(Network,peer.ID)//calledwhenapeerconnected

//PeerDisconnected(Network,peer.ID)//calledwhenapeerdisconnected}


6.3.4 实例化及业务逻辑location: node/node.go

Node节点中定义了hello服务

typeNodestruct{

……

HelloSvc*hello.Handler

……

}

启动hello服务

//Startbootsupthenode.func(node*Node)Start(ctxcontext.Context)error{

……//Startup’hello’handshakeservice

//定义区块同步的回调函数

syncCallBack:=func(pidlibp2ppeer.ID,cids[]cid.Cid,heightuint64){//TODOitispossiblethesyncerinterfaceshouldbemodifiedto

//makeuseoftheadditionalcontextnotusedhere(fromaddr+height).

//Tokeepthingssimplefornowthisinfoisnotused.

//触发调用会启动同步区块的动作

err:=node.Syncer.HandleNewBlocks(context.Background(),cids)iferr!=nil{log.Infof(“errorhandlingblocks:%s”,types.NewSortedCidSet(cids…).String())

}

}//实例化hello服务

node.HelloSvc=hello.New(node.Host(),node.ChainReader.GenesisCid(),syncCallBack,node.ChainReader.Head)

……

}

Filecoin技术架构分析之六:协议层hello握手协议

gs2c5zkewgk.png (84.2 KB, 下载次数: 12)

下载附件

gs2c5zkewgk.png

2019-4-23 12:00 上传

该内容来自于互联网公开内容,非区块链原创内容,如若转载,请注明出处:https://htzkw.com/archives/31816

联系我们

aliyinhang@gmail.com