资讯专栏INFORMATION COLUMN

区块链教程Fabric1.0源代码分析Peer(Endorser服务端)

leone / 3396人阅读

摘要:兄弟连区块链教程源代码分析服务端,年下半年,区块链行业正逐渐褪去发展之初的浮躁回归理性,表面上看相关人才需求与身价似乎正在回落。源代码笔记之服务端概述相关代码在目录下。,接口实现,即结构体及方法,以及服务端处理流程。

  兄弟连区块链教程Fabric1.0源代码分析Peer(Endorser服务端),2018年下半年,区块链行业正逐渐褪去发展之初的浮躁、回归理性,表面上看相关人才需求与身价似乎正在回落。但事实上,正是初期泡沫的渐退,让人们更多的关注点放在了区块链真正的技术之上。

Fabric 1.0源代码笔记 之 Peer #EndorserServer(Endorser服务端) 1、EndorserServer概述

EndorserServer相关代码在protos/peer、core/endorser目录下。

protos/peer/peer.pb.go,EndorserServer接口定义。

core/endorser/endorser.go,EndorserServer接口实现,即Endorser结构体及方法,以及Endorser服务端ProcessProposal处理流程。

2、EndorserServer接口定义 2.1、EndorserServer接口定义

</>复制代码

  1. type EndorserServer interface {
  2.     ProcessProposal(context.Context, *SignedProposal) (*ProposalResponse, error)
  3. }
  4. //代码在protos/peer/peer.pb.go
2.2、gRPC相关实现

</>复制代码

  1. var _Endorser_serviceDesc = grpc.ServiceDesc{
  2.     ServiceName: "protos.Endorser",
  3.     HandlerType: (*EndorserServer)(nil),
  4.     Methods: []grpc.MethodDesc{
  5.         {
  6.             MethodName: "ProcessProposal",
  7.             Handler: _Endorser_ProcessProposal_Handler,
  8.         },
  9.     },
  10.     Streams: []grpc.StreamDesc{},
  11.     Metadata: "peer/peer.proto",
  12. }
  13. func RegisterEndorserServer(s *grpc.Server, srv EndorserServer) {
  14.     s.RegisterService(&_Endorser_serviceDesc, srv)
  15. }
  16. func _Endorser_ProcessProposal_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
  17.     in := new(SignedProposal)
  18.     if err := dec(in); err != nil {
  19.         return nil, err
  20.     }
  21.     if interceptor == nil {
  22.         return srv.(EndorserServer).ProcessProposal(ctx, in)
  23.     }
  24.     info := &grpc.UnaryServerInfo{
  25.         Server: srv,
  26.         FullMethod: "/protos.Endorser/ProcessProposal",
  27.     }
  28.     handler := func(ctx context.Context, req interface{}) (interface{}, error) {
  29.         return srv.(EndorserServer).ProcessProposal(ctx, req.(*SignedProposal))
  30.     }
  31.     return interceptor(ctx, in, info, handler)
  32. }
  33. //代码在protos/peer/peer.pb.go
3、EndorserServer接口实现 3.1、Endorser结构体及方法

</>复制代码

  1. type Endorser struct {
  2.     policyChecker policy.PolicyChecker //策略检查器
  3. }
  4. //代码在core/endorser/endorser.go

涉及方法如下:

</>复制代码

  1. //构造Endorser
  2. func NewEndorserServer() pb.EndorserServer
  3. //执行提案
  4. func (e *Endorser) ProcessProposal(ctx context.Context, signedProp *pb.SignedProposal) (*pb.ProposalResponse, error)
  5. //检查SignedProposal是否符合通道策略,调用e.policyChecker.CheckPolicy()
  6. func (e *Endorser) checkACL(signedProp *pb.SignedProposal, chdr *common.ChannelHeader, shdr *common.SignatureHeader, hdrext *pb.ChaincodeHeaderExtension) error
  7. //检查Escc和Vscc,暂未实现
  8. func (*Endorser) checkEsccAndVscc(prop *pb.Proposal) error
  9. //获取账本的交易模拟器,调用peer.GetLedger(ledgername).NewTxSimulator()
  10. func (*Endorser) getTxSimulator(ledgername string) (ledger.TxSimulator, error)
  11. //获取账本历史交易查询器,调用peer.GetLedger(ledgername).NewHistoryQueryExecutor()
  12. func (*Endorser) getHistoryQueryExecutor(ledgername string) (ledger.HistoryQueryExecutor, error)
  13. //执行链码
  14. func (e *Endorser) callChaincode(ctxt context.Context, chainID string, version string, txid string, signedProp *pb.SignedProposal, prop *pb.Proposal, cis *pb.ChaincodeInvocationSpec, cid *pb.ChaincodeID, txsim ledger.TxSimulator) (*pb.Response, *pb.ChaincodeEvent, error)
  15. func (e *Endorser) disableJavaCCInst(cid *pb.ChaincodeID, cis *pb.ChaincodeInvocationSpec) error
  16. //通过调用chaincode来模拟提案
  17. func (e *Endorser) simulateProposal(ctx context.Context, chainID string, txid string, signedProp *pb.SignedProposal, prop *pb.Proposal, cid *pb.ChaincodeID, txsim ledger.TxSimulator) (*ccprovider.ChaincodeData, *pb.Response, []byte, *pb.ChaincodeEvent, error)
  18. //从LSCC获取链码数据
  19. func (e *Endorser) getCDSFromLSCC(ctx context.Context, chainID string, txid string, signedProp *pb.SignedProposal, prop *pb.Proposal, chaincodeID string, txsim ledger.TxSimulator) (*ccprovider.ChaincodeData, error)
  20. //提案背书
  21. func (e *Endorser) endorseProposal(ctx context.Context, chainID string, txid string, signedProp *pb.SignedProposal, proposal *pb.Proposal, response *pb.Response, simRes []byte, event *pb.ChaincodeEvent, visibility []byte, ccid *pb.ChaincodeID, txsim ledger.TxSimulator, cd *ccprovider.ChaincodeData) (*pb.ProposalResponse, error)
  22. //提交模拟交易,仅测试使用
  23. func (e *Endorser) commitTxSimulation(proposal *pb.Proposal, chainID string, signer msp.SigningIdentity, pResp *pb.ProposalResponse, blockNumber uint64) error
  24. //代码在core/endorser/endorser.go
3.2、Endorser服务端ProcessProposal处理流程

Endorser服务端ProcessProposal处理流程,即func (e Endorser) ProcessProposal(ctx context.Context, signedProp pb.SignedProposal) (*pb.ProposalResponse, error)方法实现。

3.2.1、校验SignedProposal合法性,并获取ChannelHeader和SignatureHeader

</>复制代码

  1. //校验SignedProposal合法性
  2. prop, hdr, hdrExt, err := validation.ValidateProposalMessage(signedProp)
  3. //获取ChannelHeader
  4. chdr, err := putils.UnmarshalChannelHeader(hdr.ChannelHeader)
  5. //获取SignatureHeader
  6. shdr, err := putils.GetSignatureHeader(hdr.SignatureHeader)
  7. //代码在core/endorser/endorser.go

validation.ValidateProposalMessage(signedProp)代码如下:

</>复制代码

  1. func ValidateProposalMessage(signedProp *pb.SignedProposal) (*pb.Proposal, *common.Header, *pb.ChaincodeHeaderExtension, error) {
  2.     prop, err := utils.GetProposal(signedProp.ProposalBytes) //获取type Proposal struct
  3.     hdr, err := utils.GetHeader(prop.Header) //获取Proposal.Header
  4.     chdr, shdr, err := validateCommonHeader(hdr) //校验Proposal.Header
  5.     //检查来自创建者的签名
  6.     err = checkSignatureFromCreator(shdr.Creator, signedProp.Signature, signedProp.ProposalBytes, chdr.ChannelId)
  7.     //校验交易TxID,TxID由Nonce和Creator构成
  8.     err = utils.CheckProposalTxID(
  9.         chdr.TxId, //ChannelHeader.TxId
  10.         shdr.Nonce, //SignatureHeader.Nonce
  11.         shdr.Creator) //SignatureHeader.Creator
  12.     switch common.HeaderType(chdr.Type) {
  13.     case common.HeaderType_CONFIG:
  14.         fallthrough
  15.     case common.HeaderType_ENDORSER_TRANSACTION:
  16.         //校验ChaincodeHeaderExtension
  17.         chaincodeHdrExt, err := validateChaincodeProposalMessage(prop, hdr)
  18.         return prop, hdr, chaincodeHdrExt, err
  19.     default:
  20.         return nil, nil, nil, fmt.Errorf("Unsupported proposal type %d", common.HeaderType(chdr.Type))
  21.     }
  22. }
  23. //代码在core/common/validation/msgvalidation.go
3.2.2、校验是否系统链码且提案不可调用,获取chainID和TxId,获取Ledger并校验txid是否已存在,非系统链码校验提案权限(是否符合通道策略)

</>复制代码

  1. //校验是否系统链码且提案不可调用
  2. if syscc.IsSysCCAndNotInvokableExternal(hdrExt.ChaincodeId.Name) {
  3.     //如果是系统链码且提案不可调用
  4. }
  5. //获取chainID,即ChannelId
  6. chainID := chdr.ChannelId
  7. //获取交易TxId
  8. txid := chdr.TxId
  9. if chainID != "" {
  10.     //获取Ledger
  11.     lgr := peer.GetLedger(chainID)
  12.     //校验txid是否已存在
  13.     _, err := lgr.GetTransactionByID(txid)
  14.     //非系统链码校验提案权限(是否符合通道策略)
  15.     if !syscc.IsSysCC(hdrExt.ChaincodeId.Name) {
  16.         err = e.checkACL(signedProp, chdr, shdr, hdrExt)
  17.     }
  18. }
  19. //代码在core/endorser/endorser.go
3.2.3、获取账本的交易模拟器和历史记录查询器,并模拟提案执行

</>复制代码

  1. var txsim ledger.TxSimulator
  2. var historyQueryExecutor ledger.HistoryQueryExecutor
  3. if chainID != "" {
  4.     //获取账本的交易模拟器
  5.     txsim, err = e.getTxSimulator(chainID)
  6.     //获取历史记录查询器
  7.     historyQueryExecutor, err = e.getHistoryQueryExecutor(chainID)
  8.     //HistoryQueryExecutorKey key = "historyqueryexecutorkey"
  9.     //context.WithValue,将Key与对象建立关系
  10.     ctx = context.WithValue(ctx, chaincode.HistoryQueryExecutorKey, historyQueryExecutor)
  11. }
  12. //模拟提案执行
  13. cd, res, simulationResult, ccevent, err := e.simulateProposal(ctx, chainID, txid, signedProp, prop, hdrExt.ChaincodeId, txsim)
  14. //代码在core/endorser/endorser.go

e.simulateProposal(ctx, chainID, txid, signedProp, prop, hdrExt.ChaincodeId, txsim)代码如下:模拟提案执行。

</>复制代码

  1. func (e *Endorser) simulateProposal(ctx context.Context, chainID string, txid string, signedProp *pb.SignedProposal, prop *pb.Proposal, cid *pb.ChaincodeID, txsim ledger.TxSimulator) (*ccprovider.ChaincodeData
  2. , *pb.Response, []byte, *pb.ChaincodeEvent, error) {
  3.     //获取ChaincodeInvocationSpec
  4.     cis, err := putils.GetChaincodeInvocationSpec(prop)
  5.     //禁用Java安装、实例化和立即升级
  6.     err = e.disableJavaCCInst(cid, cis)
  7.     //检查Escc和Vscc,暂未实现
  8.     err = e.checkEsccAndVscc(prop)
  9.     var cdLedger *ccprovider.ChaincodeData
  10.     var version string
  11.     if !syscc.IsSysCC(cid.Name) { //非系统链码
  12.         //获取链码数据ChaincodeData
  13.         cdLedger, err = e.getCDSFromLSCC(ctx, chainID, txid, signedProp, prop, cid.Name, txsim)
  14.         //获取链码数据版本
  15.         version = cdLedger.Version
  16.         //检查链码实例化策略
  17.         err = ccprovider.CheckInsantiationPolicy(cid.Name, version, cdLedger)
  18.     } else {
  19.         version = util.GetSysCCVersion() //获取系统链码版本
  20.     }
  21.     var simResult []byte
  22.     var res *pb.Response
  23.     var ccevent *pb.ChaincodeEvent
  24.     //执行链码
  25.     res, ccevent, err = e.callChaincode(ctx, chainID, version, txid, signedProp, prop, cis, cid, txsim)
  26.     if txsim != nil {
  27.         //获取交易模拟结果
  28.         simResult, err = txsim.GetTxSimulationResults()
  29.     }
  30.     return cdLedger, res, simResult, ccevent, nil
  31. }
  32. //代码在core/endorser/endorser.go

e.endorseProposal(ctx, chainID, txid, signedProp, prop, res, simulationResult, ccevent, hdrExt.PayloadVisibility, hdrExt.ChaincodeId, txsim, cd)代码如下:为提案背书。

</>复制代码

  1. func (e *Endorser) callChaincode(ctxt context.Context, chainID string, version string, txid string, signedProp *pb.SignedProposal, prop *pb.Proposal, cis *pb.ChaincodeInvocationSpec, cid *pb.ChaincodeID, txsim ledger.TxSimulator) (*pb.Response, *pb.ChaincodeEvent, error) {
  2.     var err error
  3.     var res *pb.Response
  4.     var ccevent *pb.ChaincodeEvent
  5.     if txsim != nil {
  6.         //TXSimulatorKey key = "txsimulatorkey",key与对象建立关系
  7.         ctxt = context.WithValue(ctxt, chaincode.TXSimulatorKey, txsim)
  8.     }
  9.     scc := syscc.IsSysCC(cid.Name) //是否系统链码
  10.     cccid := ccprovider.NewCCContext(chainID, cid.Name, version, txid, scc, signedProp, prop)
  11.     //执行链码
  12.     res, ccevent, err = chaincode.ExecuteChaincode(ctxt, cccid, cis.ChaincodeSpec.Input.Args)
  13.     //如果是生命周期管理系统链码,并且参数为实例化或升级
  14.     if cid.Name == "lscc" && len(cis.ChaincodeSpec.Input.Args) >= 3 && (string(cis.ChaincodeSpec.Input.Args[0]) == "deploy" || string(cis.ChaincodeSpec.Input.Args[0]) == "upgrade") {
  15.         var cds *pb.ChaincodeDeploymentSpec
  16.         //获取ChaincodeDeploymentSpec
  17.         cds, err = putils.GetChaincodeDeploymentSpec(cis.ChaincodeSpec.Input.Args[2])
  18.         //待实例化或升级的链码执行实例化或升级
  19.         cccid = ccprovider.NewCCContext(chainID, cds.ChaincodeSpec.ChaincodeId.Name, cds.ChaincodeSpec.ChaincodeId.Version, txid, false, signedProp, prop)
  20.         _, _, err = chaincode.Execute(ctxt, cccid, cds)
  21.     }
  22.     return res, ccevent, err
  23. }
  24. //代码在core/endorser/endorser.go

Chaincode更详细内容,参考:Fabric 1.0源代码笔记 之 Chaincode(链码)

3.2.4、为提案背书,构造ProposalResponse并返回给Endorser客户端

</>复制代码

  1. var pResp *pb.ProposalResponse
  2. //为提案背书,即调取escc系统链码
  3. pResp, err = e.endorseProposal(ctx, chainID, txid, signedProp, prop, res, simulationResult, ccevent, hdrExt.PayloadVisibility, hdrExt.ChaincodeId, txsim, cd)
  4. pResp.Response.Payload = res.Payload
  5. return pResp, nil
  6. //代码在core/endorser/endorser.go

e.endorseProposal(ctx, chainID, txid, signedProp, prop, res, simulationResult, ccevent, hdrExt.PayloadVisibility, hdrExt.ChaincodeId, txsim, cd)代码如下:

</>复制代码

  1. func (e *Endorser) endorseProposal(ctx context.Context, chainID string, txid string, signedProp *pb.SignedProposal, proposal *pb.Proposal, response *pb.Response, simRes []byte, event *pb.ChaincodeEvent, visibility []byte, ccid *pb.ChaincodeID, txsim ledger.TxSimulator, cd *ccprovider.ChaincodeData) (*pb.ProposalResponse, error) {
  2.     isSysCC := cd == nil
  3.     var escc string
  4.     if isSysCC {
  5.         escc = "escc"
  6.     } else {
  7.         escc = cd.Escc
  8.     }
  9.     var err error
  10.     var eventBytes []byte
  11.     if event != nil {
  12.         eventBytes, err = putils.GetBytesChaincodeEvent(event)
  13.     }
  14.     resBytes, err := putils.GetBytesResponse(response)
  15.     if isSysCC {
  16.         ccid.Version = util.GetSysCCVersion()
  17.     } else {
  18.         ccid.Version = cd.Version
  19.     }
  20.     ccidBytes, err := putils.Marshal(ccid)
  21.     args := [][]byte{[]byte(""), proposal.Header, proposal.Payload, ccidBytes, resBytes, simRes, eventBytes, visibility}
  22.     version := util.GetSysCCVersion()
  23.     ecccis := &pb.ChaincodeInvocationSpec{ChaincodeSpec: &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_GOLANG, ChaincodeId: &pb.ChaincodeID{Name: escc}, Input: &pb.ChaincodeInput{Args: args}}}
  24.     //执行escc系统链码
  25.     res, _, err := e.callChaincode(ctx, chainID, version, txid, signedProp, proposal, ecccis, &pb.ChaincodeID{Name: escc}, txsim)
  26.     prBytes := res.Payload
  27.     pResp, err := putils.GetProposalResponse(prBytes)
  28.     return pResp, nil
  29. }
  30. //代码在core/endorser/endorser.go

感谢关注兄弟连区块链教程分享!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/24368.html

相关文章

  • 区块教程Fabric1.0代码分析Peer EndorserClient(Endorser客户

    摘要:兄弟连区块链教程源代码分析客户端,年下半年,区块链行业正逐渐褪去发展之初的浮躁回归理性,表面上看相关人才需求与身价似乎正在回落。源代码笔记之客户端概述相关代码分布如下,接口及实现。代码在工具函数获取客户端代码在   兄弟连区块链教程Fabric1.0源代码分析Peer EndorserClient(Endorser客户端),2018年下半年,区块链行业正逐渐褪去发展之初的浮躁、回归理性...

    lufficc 评论0 收藏0
  • 区块教程Fabric1.0代码分析Peer peer chaincode命令及子命令实现

    摘要:兄弟连区块链教程源代码分析命令及子命令实现,年下半年,区块链行业正逐渐褪去发展之初的浮躁回归理性,表面上看相关人才需求与身价似乎正在回落。   兄弟连区块链教程Fabric1.0源代码分析Peer peer chaincode命令及子命令实现,2018年下半年,区块链行业正逐渐褪去发展之初的浮躁、回归理性,表面上看相关人才需求与身价似乎正在回落。但事实上,正是初期泡沫的渐退,让人们更多...

    gghyoo 评论0 收藏0
  • 兄弟连区块教程Fabric1.0代码分析Peer peer根命令入口及加载子命令一

    摘要:区块链教程源代码分析根命令入口及加载子命令,年下半年,区块链行业正逐渐褪去发展之初的浮躁回归理性,表面上看相关人才需求与身价似乎正在回落。代码在为命令启动。   区块链教程Fabric1.0源代码分析Peer peer根命令入口及加载子命令,2018年下半年,区块链行业正逐渐褪去发展之初的浮躁、回归理性,表面上看相关人才需求与身价似乎正在回落。但事实上,正是初期泡沫的渐退,让人们更多的...

    sean 评论0 收藏0
  • 区块教程Fabric1.0代码分析Peer peer根命令入口及加载子命令二

    摘要:兄弟连区块链教程源代码分析根命令入口及加载子命令二。此处传入为,将模块日志级别设置为,并会将初始化为。代码在目录下包括。核心代码为,目的是在或为空时设置默认值。感谢关注兄弟连区块链教程分享   兄弟连区块链教程Fabric1.0源代码分析Peer peer根命令入口及加载子命令二。flogging,即:fabric logging,为Fabric基于第三方包go-logging封装的日...

    tuantuan 评论0 收藏0
  • Hyperledger Fabric周周记:起源

    摘要:作为系列的新篇章,我选择从超级账本的开始。为什么选择超级账本作为起点我在之前的文章中曾说过会从超级账本入手开始区块链的学习和实践,同时也给出了个人的理由。检查事务提议的响应。为了降低区块链应用的开发难度,超级账本项目又引入了。 本着以教带学,Learning by Doing的想法,我于上周加入了Bob组织的HiBlock区块链技术布道群。这个群可不太好混,群规要求每个成员必需每周有输...

    hatlonely 评论0 收藏0

发表评论

0条评论

leone

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<