[Fabric/源碼分析] Proposal 消息處理流程(v1.0)

Fabric1.0的架構(gòu)中引入了client -> endorser -> order ->commiter的概念??蛻舳耸紫葘⒔灰装l(fā)送到背書節(jié)點(diǎn)進(jìn)行模擬執(zhí)行,然后收集一定數(shù)量的背書結(jié)果構(gòu)造交易發(fā)送到排序節(jié)點(diǎn)進(jìn)行排序,最后排序節(jié)點(diǎn)對(duì)收到的交易進(jìn)行排序并打包發(fā)送給commiter節(jié)點(diǎn)進(jìn)行驗(yàn)證和計(jì)入賬本。本文將針對(duì)交易執(zhí)行的第一個(gè)階段client -> endorser的相關(guān)流程結(jié)合源碼進(jìn)行分析。

一、Proposal交互流程

1.客戶端向endorser 發(fā)送proposal, proposal 定義如下:

message SignedProposal {
    // Proposal 消息序列化bytes
    bytes proposal_bytes = 1;
    //針對(duì)proposal_bytes的簽名
    bytes signature = 2;
}
//Proposal消息的實(shí)際定義
message Proposal {

    // The header of the proposal. It is the bytes of the Header
    bytes header = 1;

    // 具體的Proposal消息體的序列化內(nèi)容,消息體類型由header類型確定
    bytes payload = 2;

    // 擴(kuò)展字段對(duì)于 CHAINCODE類型, 其可能使
    bytes extension = 3;
}
  1. endorserproposal 執(zhí)行結(jié)果返回給客戶端,propose response的定義如下:
message ProposalResponse {

    // Version indicates message protocol version
    int32 version = 1;
    google.protobuf.Timestamp timestamp = 2;
    //表示執(zhí)行是否成功
    Response response = 4;

    // 返回結(jié)果ProposalResponsePayload的序列化bytes
    bytes payload = 5;

    // The endorsement of the proposal, basically
    // the endorser's signature over the payload
    Endorsement endorsement = 6;
}

message Response {

    // A status code that should follow the HTTP status codes.
    int32 status = 1;

    // A message associated with the response code.
    string message = 2;

    // A payload that can be used to include metadata with this response.
    bytes payload = 3;
}

message ProposalResponsePayload {
    bytes proposal_hash = 1; 
    bytes extension = 2;
}

message Endorsement {
    bytes endorser = 1; // endorser id
    bytes signature = 2;// endorser  的簽名
}
  1. 客戶端收集背書組裝成一個(gè)交易transaction

一個(gè)完整的transaction包含一個(gè)或者多個(gè)proposal以及其對(duì)應(yīng)的返回response。交易將會(huì)被發(fā)送到共識(shí)節(jié)點(diǎn)orders, 經(jīng)過排序之后batch形式的交易會(huì)被廣播到peer節(jié)點(diǎn)進(jìn)行驗(yàn)證以及寫入賬本。

二、Endorser節(jié)點(diǎn)的處理流程

源文件fabric/core/endorser.go中ProcessProposal函數(shù)負(fù)責(zé)具體的Proposel的處理。

  1. 檢查message是否有效,消息體個(gè)個(gè)字段的完整性以及chaincode id以及調(diào)用類型的檢查,例如proposal的消息不能調(diào)用system chaincode;
  2. 檢查proposal是否滿足channel的policy, tx的重復(fù)性判斷;
  3. 模擬執(zhí)行proposal中的chaincode調(diào)用,其實(shí)也就是實(shí)際執(zhí)行,這里需要兩個(gè)關(guān)鍵組件:
var txsim ledger.TxSimulator
var historyQueryExecutor ledger.HistoryQueryExecutor
    ...
    //1 -- simulate
cd, res, simulationResult, ccevent, err := e.simulateProposal(ctx, chainID, txid, signedProp, prop, hdrExt.ChaincodeId, txsim)

4.生成endorsement結(jié)果返回

pResp, err = e.endorseProposal(ctx, chainID, txid, signedProp, prop, res, simulationResult, ccevent, hdrExt.PayloadVisibility, hdrExt.ChaincodeId, txsim, cd)
    

2.1 simulate proposal 詳細(xì)流程

以上便是ProcessProposal的整體流程,這里關(guān)鍵的是simulateProposal這一步,接下來對(duì)該函數(shù)進(jìn)行展開分析。

  1. 解析chaincode調(diào)用參數(shù):cis, err := putils.GetChaincodeInvocationSpec(prop)

  2. 為chancode檢查ESCC和VSCC, 該函數(shù)暫時(shí)未實(shí)現(xiàn)

    if err = e.checkEsccAndVscc(prop); err != nil {
        return nil, nil, nil, nil, err
    }
  1. 獲取chaincode的相關(guān)數(shù)據(jù)ChancodeData
cdLedger, err = e.getCDSFromLSCC(ctx, chainID, txid, signedProp, prop, cid.Name, txsim)
  1. 執(zhí)行chaincode并獲取結(jié)果
var simResult *ledger.TxSimulationResults
    var pubSimResBytes []byte
    var res *pb.Response
    var ccevent *pb.ChaincodeEvent
    res, ccevent, err = e.callChaincode(ctx, chainID, version, txid, signedProp, prop, cis, cid, txsim)
    if err != nil {
        endorserLogger.Errorf("failed to invoke chaincode %s on transaction %s, error: %s", cid, txid, err)
        return nil, nil, nil, nil, err
    }

    if txsim != nil {
        if simResult, err = txsim.GetTxSimulationResults(); err != nil {
            return nil, nil, nil, nil, err
        }

        if pubSimResBytes, err = simResult.GetPubSimulationBytes(); err != nil {
            return nil, nil, nil, nil, err
        }
    }
    return cdLedger, res, pubSimResBytes, ccevent, nil
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容