当前位置:首页区块链hyperledger fabric 结构分析(一)

hyperledger fabric 结构分析(一)

先前分析程序着眼于细节分析,这样没有框架的概念,花了两天时间分析整理了一下hyperledger fabric的架构设计,分析该程序没有参照任何资料,如有错误欢迎指正,共同进步。

笔者在详细分析程序前有以下疑问:
1)CLI(命令行)客户端如何发送命令给Peer节点
2)本Peer节点如何接收其他节点的数据,接收到数据又如何处理,处理的方式和1又有什么区别
3)数据是何时又是如何被送入consensus模块
4)consensus模块内部又是如何架构的 为什么看起来helper executor pbft controller文件夹交至在一起,保存各自句柄,相互调用
5)ChainCode(链码,简称CC)是如何接收到Peer对其的操作、访问的
6)ChainCode是如何调用fabric API来查询写入数据的
7)在阅读源码初始化过程中,Peer节点会创建大量Serer,这些Serer后续过程我们是如何使用的

注:本人对于数据库、Docker相关知识不是很了解,尽量避免关于这两个部分的介绍以免错误的引导读者。
下面会慢慢的渗透以上涉及的问题。

Serer :



每个Serer作用:
AdminSerer:控制该节点的命运,可以删除该节点所在的进程。(Start Stop GetStatus )
EentHubSerer:Peer节点支持客户端对指定事件进行监听,例如Rejection等。客户端需要先注册自己关心的Eents,当事件发生时trigger 监听者。
OpenChainSerer:对外提供ledger的访问接口,涉及GetBlockchainInfo GetBlockByNumber等。
DeopsSerer:负责与CLI Client对接,外部进行CC操作的入口,Deploy inoke query。
ChaincodeSupportSerer:负责与shim/Chaincode通信,ChainCode的所有调用接收发送都要与该Serer信息交互。
PeerSerer:该Serer是一个Engine,Engine关联了内部消息响应实现,同时为周围Peer节点创建Client与之通信。
RESTSerer:该Serer没有进行分析,应该是REST接口格式相关。


一级模块分类:


Client: 之前创建服务器与之对应的客户端,可以理解成其他节点或者CLI client等。
Protos: 中间层,Serer与Client端 API接口定义
SererProcess:服务响应处理函数,包括各类的HandleMessage。
Consensus: 共识模块,目前采用的是PBFT NOOPS
ChainCode Shim:代码中shim和我理解的不一致,将ChainCodeSupport也应该算到shim,该模块的作用是连接Peer节点与ChainCode的媒介,用shim形容也可。
ChainCode: 链码,应用(例如智能合约)。
DB: 数据存储。
Library: 代码里有一个叫做Vendor的文件夹,该文件夹里涉及的功能模块自成一体,例如grpcSerer等
API: ChainCode里面会调用Peer节点信息。
Crypto: 伴随着数据加解密。
Ledger: 账本操作。

该代码使用Handler触发模式,在跟踪代码程序时要注意handler对象赋值位置,否则容易找错HandleMessage,这些Handler处理函数命名基本相同,容易操作混乱。

下面分析几个读者应该最关心的流程:
1)Client通过CLI执行一条inoke命令
2)某节点发送给该节点ViewChange命令
3)ChainCode调用API putStatus
4)Consensus流程

一、 Client通过CLI执行一条inoke命令
1)在Peer节点初始化的时候 创建DeopsSerer


sererDeops := core.NewDeopsSerer(peerSerer)
pb.RegisterDeopsSerer(grpcSerer, sererDeops)


2)DeopsSerer设置Serice规范,例如Inoke Message,调用_Deops_Inoke_Handler函数

ar _Deops_sericeDesc = grpc.SericeDesc{
SericeName: “protos.Deops”,
HandlerType: (*DeopsSerer)(nil),
METHods: []grpc.METHodDesc{
{
METHodName: “Login”,
Handler: _Deops_Login_Handler,
},
{
METHodName: “Build”,
Handler: _Deops_Build_Handler,
},
{
METHodName: “Deploy”,
Handler: _Deops_Deploy_Handler,
},
{
METHodName: “Inoke”,
Handler: _Deops_Inoke_Handler,
},
{
METHodName: “Query”,
Handler: _Deops_Query_Handler,
},
{
METHodName: “EXP_GetApplicationTCert”,
Handler: _Deops_EXP_GetApplicationTCert_Handler,
},
{
METHodName: “EXP_PrepareForTx”,
Handler: _Deops_EXP_PrepareForTx_Handler,
},
{
METHodName: “EXP_ProduceSigma”,
Handler: _Deops_EXP_ProduceSigma_Handler,
},
{
METHodName: “EXP_ExecuteWithBinding”,
Handler: _Deops_EXP_ExecuteWithBinding_Handler,
},
},
Streams: []grpc.StreamDesc{},
}

3)其中_Deops_Inoke_Handler函数在Protos模块,其负责将Client接入的信息传递到对应的Serer模块

func _Deops_Inoke_Handler(sr interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) {
in := new(ChaincodeInocationSpec)
if err := dec(in); err != nil {
return nil, err
}
out, err := sr.(DeopsSerer).Inoke(ctx, in)
if err != nil {
return nil, err
}
return out, nil
}

4)在函数在deops服务端代码中处理

func (d *Deops) Inoke(ctx context.Context, chaincodeInocationSpec *pb.ChaincodeInocationSpec) (*pb.Response, error) {
return d.inokeOrQuery(ctx, chaincodeInocationSpec, chaincodeInocationSpec.ChaincodeSpec.Attributes, true)
}

5)精简inokeOrQuery代码,d.coord 是PeerSerer对象,ExecuteTransaction 是对应Engine的实现方法

func (d *Deops) inokeOrQuery(ctx context.Context, chaincodeInocationSpec *pb.ChaincodeInocationSpec, attributes []string, inoke bool) (*pb.Response, error) {

resp := d.coord.ExecuteTransaction(transaction)
}

6)本次请求被封装成交易Struct,该处理是在PeerSerer中。

func (p *Impl) ExecuteTransaction(transaction *pb.Transaction) (response *pb.Response) {
if p.isValidator {
response = p.sendTransactionsToLocalEngine(transaction)
} else {
peerAddresses := p.discHelper.GetRandomNodes(1)
response = p.SendTransactionsToPeer(peerAddresses[0], transaction)
}
return response
}

7)思考可知,最终这笔transaction是要交给到Consensus进行处理,那么如何传递的呢?就在下面p.engine.ProcessTransactionMsg,其中”p”代指PeerSerer,engine是在创建PeerSerer的时候指定的Engine,而这个Engine的handler实现在Consensus里,在实现EngineHandler过程中加载了PBFT算法。所以ProcessTransactionMsg函数的实现在consensus模块engine代码里。这样解决了开始时提出的疑问3)。

func (p *Impl) sendTransactionsToLocalEngine(transaction *pb.Transaction) *pb.Response {

peerLogger.Debugf(“Marshalling transaction %s to send to local engine”, transaction.Type)
data, err := proto.Marshal(transaction)
if err != nil {
return AMPLpb.Response{Status: pb.Response_FAILURE, Msg: []byte(fmt.Sprintf(“Error sending transaction to local engine: %s”, err))}
}

ar response *pb.Response
msg := AMPLpb.Message{Type: pb.Message_CHAIN_TRANSACTION, Payload: data, Timestamp: util.CreateUtcTimestamp()}
peerLogger.Debugf(“Sending message %s with timestamp % to local engine”, msg.Type, msg.Timestamp)
response = p.engine.ProcessTransactionMsg(msg, transaction)

return response
}

8)从这里开始进入了consensus内部处理,在这里Consensus模块是单独分析。

func (eng *EngineImpl) ProcessTransactionMsg(msg *pb.Message, tx *pb.Transaction) (response *pb.Response) {
err := eng.consenter.RecMsg(msg, eng.peerEndpoint.ID)
}

画图说明上述流程:



该图中没有体现的一点是在Deops Serer创建的时候将PeerSerer对象作为构造参数传入,而PeerSerer创建的过程就是创建Engine的过程,也是加载Engine-handler的过程,而Engine-handler的实现在Consensus模块。图中直接从Deops Serer 跳入Consensus模块有些突兀。

温馨提示:

文章标题:hyperledger fabric 结构分析(一)

文章链接:https://www.btchangqing.cn/2760.html

更新时间:2022年09月28日

本站大部分内容均收集于网络,若内容若侵犯到您的权益,请联系我们,我们将第一时间处理。

区块链

区块链核心技术:委任权益证明算法DPoS

2020-4-6 17:24:10

区块链

IBM HyperLedger fabric 详解

2020-4-6 17:25:57

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索