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

简介:

  区块链教程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接口定义

type EndorserServer interface {
    ProcessProposal(context.Context, *SignedProposal) (*ProposalResponse, error)
}
//代码在protos/peer/peer.pb.go

2.2、gRPC相关实现

var _Endorser_serviceDesc = grpc.ServiceDesc{
    ServiceName: "protos.Endorser",
    HandlerType: (*EndorserServer)(nil),
    Methods: []grpc.MethodDesc{
        {
            MethodName: "ProcessProposal",
            Handler:    _Endorser_ProcessProposal_Handler,
        },
    },
    Streams:  []grpc.StreamDesc{},
    Metadata: "peer/peer.proto",
}

func RegisterEndorserServer(s *grpc.Server, srv EndorserServer) {
    s.RegisterService(&_Endorser_serviceDesc, srv)
}

func _Endorser_ProcessProposal_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
    in := new(SignedProposal)
    if err := dec(in); err != nil {
        return nil, err
    }
    if interceptor == nil {
        return srv.(EndorserServer).ProcessProposal(ctx, in)
    }
    info := &grpc.UnaryServerInfo{
        Server:     srv,
        FullMethod: "/protos.Endorser/ProcessProposal",
    }
    handler := func(ctx context.Context, req interface{}) (interface{}, error) {
        return srv.(EndorserServer).ProcessProposal(ctx, req.(*SignedProposal))
    }
    return interceptor(ctx, in, info, handler)
}
//代码在protos/peer/peer.pb.go

3、EndorserServer接口实现

3.1、Endorser结构体及方法

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

涉及方法如下:

//构造Endorser
func NewEndorserServer() pb.EndorserServer
//执行提案
func (e *Endorser) ProcessProposal(ctx context.Context, signedProp *pb.SignedProposal) (*pb.ProposalResponse, error)

//检查SignedProposal是否符合通道策略,调用e.policyChecker.CheckPolicy()
func (e *Endorser) checkACL(signedProp *pb.SignedProposal, chdr *common.ChannelHeader, shdr *common.SignatureHeader, hdrext *pb.ChaincodeHeaderExtension) error
//检查Escc和Vscc,暂未实现
func (*Endorser) checkEsccAndVscc(prop *pb.Proposal) error
//获取账本的交易模拟器,调用peer.GetLedger(ledgername).NewTxSimulator()
func (*Endorser) getTxSimulator(ledgername string) (ledger.TxSimulator, error)
//获取账本历史交易查询器,调用peer.GetLedger(ledgername).NewHistoryQueryExecutor()
func (*Endorser) getHistoryQueryExecutor(ledgername string) (ledger.HistoryQueryExecutor, error)
//执行链码
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)
func (e *Endorser) disableJavaCCInst(cid *pb.ChaincodeID, cis *pb.ChaincodeInvocationSpec) error
//通过调用chaincode来模拟提案
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)
//从LSCC获取链码数据
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)
//提案背书
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)
//提交模拟交易,仅测试使用
func (e *Endorser) commitTxSimulation(proposal *pb.Proposal, chainID string, signer msp.SigningIdentity, pResp *pb.ProposalResponse, blockNumber uint64) error
//代码在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

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

validation.ValidateProposalMessage(signedProp)代码如下:

func ValidateProposalMessage(signedProp *pb.SignedProposal) (*pb.Proposal, *common.Header, *pb.ChaincodeHeaderExtension, error) {
    prop, err := utils.GetProposal(signedProp.ProposalBytes) //获取type Proposal struct
    hdr, err := utils.GetHeader(prop.Header) //获取Proposal.Header
    chdr, shdr, err := validateCommonHeader(hdr) //校验Proposal.Header
    //检查来自创建者的签名
    err = checkSignatureFromCreator(shdr.Creator, signedProp.Signature, signedProp.ProposalBytes, chdr.ChannelId)
    //校验交易TxID,TxID由Nonce和Creator构成
    err = utils.CheckProposalTxID(
        chdr.TxId, //ChannelHeader.TxId
        shdr.Nonce, //SignatureHeader.Nonce
        shdr.Creator) //SignatureHeader.Creator

    switch common.HeaderType(chdr.Type) {
    case common.HeaderType_CONFIG:
        fallthrough
    case common.HeaderType_ENDORSER_TRANSACTION:
        //校验ChaincodeHeaderExtension
        chaincodeHdrExt, err := validateChaincodeProposalMessage(prop, hdr)
        return prop, hdr, chaincodeHdrExt, err
    default:
        return nil, nil, nil, fmt.Errorf("Unsupported proposal type %d", common.HeaderType(chdr.Type))
    }
}
//代码在core/common/validation/msgvalidation.go

3.2.2、校验是否系统链码且提案不可调用,获取chainID和TxId,获取Ledger并校验txid是否已存在,非系统链码校验提案权限(是否符合通道策略)

//校验是否系统链码且提案不可调用
if syscc.IsSysCCAndNotInvokableExternal(hdrExt.ChaincodeId.Name) {
    //如果是系统链码且提案不可调用
}
//获取chainID,即ChannelId
chainID := chdr.ChannelId
//获取交易TxId
txid := chdr.TxId
if chainID != "" {
    //获取Ledger
    lgr := peer.GetLedger(chainID)
    //校验txid是否已存在
    _, err := lgr.GetTransactionByID(txid)
    //非系统链码校验提案权限(是否符合通道策略)
    if !syscc.IsSysCC(hdrExt.ChaincodeId.Name) {
        err = e.checkACL(signedProp, chdr, shdr, hdrExt)
    }
}
//代码在core/endorser/endorser.go

3.2.3、获取账本的交易模拟器和历史记录查询器,并模拟提案执行

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

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

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) {
    //获取ChaincodeInvocationSpec
    cis, err := putils.GetChaincodeInvocationSpec(prop)
    //禁用Java安装、实例化和立即升级
    err = e.disableJavaCCInst(cid, cis)
    //检查Escc和Vscc,暂未实现
    err = e.checkEsccAndVscc(prop)

    var cdLedger *ccprovider.ChaincodeData
    var version string
    if !syscc.IsSysCC(cid.Name) { //非系统链码
        //获取链码数据ChaincodeData
        cdLedger, err = e.getCDSFromLSCC(ctx, chainID, txid, signedProp, prop, cid.Name, txsim)
        //获取链码数据版本
        version = cdLedger.Version
        //检查链码实例化策略
        err = ccprovider.CheckInsantiationPolicy(cid.Name, version, cdLedger)
    } else {
        version = util.GetSysCCVersion() //获取系统链码版本
    }

    var simResult []byte
    var res *pb.Response
    var ccevent *pb.ChaincodeEvent
    //执行链码
    res, ccevent, err = e.callChaincode(ctx, chainID, version, txid, signedProp, prop, cis, cid, txsim)
    if txsim != nil {
        //获取交易模拟结果
        simResult, err = txsim.GetTxSimulationResults()
    }
    return cdLedger, res, simResult, ccevent, nil
}

//代码在core/endorser/endorser.go

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

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) {
    var err error
    var res *pb.Response
    var ccevent *pb.ChaincodeEvent
    if txsim != nil {
        //TXSimulatorKey key = "txsimulatorkey",key与对象建立关系
        ctxt = context.WithValue(ctxt, chaincode.TXSimulatorKey, txsim)
    }
    scc := syscc.IsSysCC(cid.Name) //是否系统链码
    cccid := ccprovider.NewCCContext(chainID, cid.Name, version, txid, scc, signedProp, prop)
    //执行链码
    res, ccevent, err = chaincode.ExecuteChaincode(ctxt, cccid, cis.ChaincodeSpec.Input.Args)
    //如果是生命周期管理系统链码,并且参数为实例化或升级
    if cid.Name == "lscc" && len(cis.ChaincodeSpec.Input.Args) >= 3 && (string(cis.ChaincodeSpec.Input.Args[0]) == "deploy" || string(cis.ChaincodeSpec.Input.Args[0]) == "upgrade") {
        var cds *pb.ChaincodeDeploymentSpec
        //获取ChaincodeDeploymentSpec
        cds, err = putils.GetChaincodeDeploymentSpec(cis.ChaincodeSpec.Input.Args[2])
        //待实例化或升级的链码执行实例化或升级
        cccid = ccprovider.NewCCContext(chainID, cds.ChaincodeSpec.ChaincodeId.Name, cds.ChaincodeSpec.ChaincodeId.Version, txid, false, signedProp, prop)
        _, _, err = chaincode.Execute(ctxt, cccid, cds)
    }
    return res, ccevent, err
}
//代码在core/endorser/endorser.go

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

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

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

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

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) {
    isSysCC := cd == nil
    var escc string
    if isSysCC {
        escc = "escc"
    } else {
        escc = cd.Escc
    }

    var err error
    var eventBytes []byte
    if event != nil {
        eventBytes, err = putils.GetBytesChaincodeEvent(event)
    }

    resBytes, err := putils.GetBytesResponse(response)
    if isSysCC {
        ccid.Version = util.GetSysCCVersion()
    } else {
        ccid.Version = cd.Version
    }

    ccidBytes, err := putils.Marshal(ccid)
    args := [][]byte{[]byte(""), proposal.Header, proposal.Payload, ccidBytes, resBytes, simRes, eventBytes, visibility}
    version := util.GetSysCCVersion()
    ecccis := &pb.ChaincodeInvocationSpec{ChaincodeSpec: &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_GOLANG, ChaincodeId: &pb.ChaincodeID{Name: escc}, Input: &pb.ChaincodeInput{Args: args}}}
    //执行escc系统链码
    res, _, err := e.callChaincode(ctx, chainID, version, txid, signedProp, proposal, ecccis, &pb.ChaincodeID{Name: escc}, txsim)
    prBytes := res.Payload
    pResp, err := putils.GetProposalResponse(prBytes)
    return pResp, nil
}

//代码在core/endorser/endorser.go
相关文章
|
2月前
|
存储 供应链 监控
区块链技术在供应链管理中的应用与前景分析
随着信息化时代的到来,供应链管理面临着越来越多的挑战和机遇。本文主要探讨了区块链技术在供应链管理中的应用,以及未来的发展前景。通过对区块链技术的特点和优势进行分析,结合实际案例和趋势展望,展示了区块链技术在提升供应链透明度、效率和安全性方面的潜力,以及未来发展的可能方向。
|
4天前
|
存储 安全 区块链
元宇宙与区块链技术的关系可以从多个角度进行阐述。以下是对这两者之间关系的详细分析
**元宇宙:虚拟世界融合现实元素,强调交互与沉浸;区块链:去中心化、安全的分布式账本。两者结合,区块链确保元宇宙中虚拟资产安全、支付高效、身份验证私密、治理透明,支撑其经济体系与用户信任,驱动未来发展。**
|
2月前
|
存储 供应链 安全
基于区块链技术的智能合约安全性分析
【5月更文挑战第31天】本文深入探讨了区块链技术中智能合约的安全性问题,通过分析现有智能合约的安全漏洞和攻击手段,提出了一系列增强智能合约安全性的策略。文章首先介绍了区块链和智能合约的基本概念,随后详细讨论了智能合约面临的安全挑战,包括代码漏洞、重入攻击等问题,并对比分析了不同平台下智能合约的安全性差异。最后,文章提出了一系列提高智能合约安全性的建议,旨在为区块链应用的健康发展提供参考。
|
11天前
|
区块链
近期区块链市场趋势分析
**区块链市场趋势摘要:** - 跨链技术成熟,提升互操作性,助力区块链网络融合。 - DeFi持续繁荣,智能合约与AMM创新活跃,市场竞争驱动市场壮大。 - NFT市场多样化,拓展至游戏、音乐等领域,实用性增强。 - 区块链寻求绿色转型,通过PoS共识与绿色能源减少能耗。 - 技术模块化、可组合性提升,降低成本,增强系统灵活性。 这些趋势展现区块链潜力,带来机遇与挑战,促进行业创新。
|
2月前
|
存储 算法 安全
区块链系统开发技术规则分析
区块链核心技术包括:1) 哈希算法,利用单向函数将任意数据转化为固定长度代码,确保安全验证;2) 非对称加密,使用公钥和私钥一对进行加密解密,保证信息安全;3) 共识机制,如PoW、PoS、DPoS等,实现快速交易验证和确认;4) 智能合约,自动执行的可信代码,一旦编写即不可更改,用于自动化交易;5) 分布式存储,将数据分散存储在网络各处,涵盖结构化、非结构化和半结构化数据。
|
2月前
|
供应链 区块链 数据安全/隐私保护
探索区块链技术在金融领域的应用与前景分析
本文将深入探讨区块链技术在金融领域的具体应用场景,分析其优势与挑战,并展望未来发展趋势。通过案例分析和技术解析,揭示区块链技术在金融行业中的革新意义及前景。
252 15
|
12月前
Minecraft Fabric 教程 #8 添加附魔书
这就创建了一个FireBoom附魔书 onTargetDamaged //当目标被攻击 在mc FireballEntity类有一个 方法就是当火球碰撞了就创建一个火焰爆炸的效果
51 0
|
12月前
Minecraft Fabric 教程 #4 添加分组
在 ItemGroup 显示 使用 FabricItemGroupBuilder
44 0
|
10月前
|
区块链
区块链的发币流程技术分析
区块链现在是发展的如火如荼,很多人都想趁着这个风口,投入区块链创业的浪潮中。 那么我们该怎么做才能抓住这个机会呢? 进行区块链发币要求是很多的,主要有以下几个步骤。
|
10月前
|
安全 算法 区块链
区块链交易所开发技术说明:智能合约设计与实现步骤实现分析
智能合约是区块链技术的核心应用,其能够自动执行、验证和执行合同,并以可验证的方式进行操作。在区块链交易所中,智能合约扮演着重要的角色,它们保证了交易的透明性、效率和安全性。作为一名专业的交易所开发团队一员,在交易所开发这块拥有相对成熟的开发技术,目前已经有成熟的区块链交易所开发案例。本文将介绍如何设计和实现可靠的智能合约来支持区块链交易所。

热门文章

最新文章