fabric 結構分析區塊鏈底層開發技術虛擬幣

來源:互聯網
上載者:User

區塊鏈愛好者(QQ:53016353)

先前剖析器著眼於細節分析,這樣沒有架構的概念,花了兩天時間分析整理了一下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節點會建立大量Server,這些Server後續過程我們是如何使用的


註:本人對於資料庫、Docker相關知識不是很瞭解,盡量避免關於這兩個部分的介紹以免錯誤的引導讀者。
下面會慢慢的滲透以上涉及的問題。


Server :




每個Server作用:
AdminServer:控制該節點的命運,可以刪除該節點所在的進程。(Start Stop GetStatus )
EventHubServer:Peer節點支援用戶端對指定事件進行監聽,例如Rejection等。用戶端需要先註冊自己關心的Events,當事件發生時trigger 監聽者。
OpenChainServer:對外提供ledger的提供者,涉及GetBlockchainInfo GetBlockByNumber等。
DevopsServer:負責與CLI Client對接,外部進行CC操作的入口,Deploy invoke query。
ChaincodeSupportServer:負責與shim/Chaincode通訊,ChainCode的所有調用接收發送都要與該Server資訊互動。
PeerServer:該Server是一個Engine,Engine關聯了內部訊息響應實現,同時為周圍Peer節點建立Client與之通訊。
RESTServer:該Server沒有進行分析,應該是REST介面格式相關。




一級模組分類:


Client:  之前建立伺服器與之對應的用戶端,可以理解成其他節點或者CLI client等。
Protos:  中介層,Server與Client端 API介面定義
ServerProcess:服務響應處理函數,包括各類型的HandleMessage。
Consensus:  共識模組,目前採用的是PBFT NOOPS
ChainCode Shim:代碼中shim和我理解的不一致,將ChainCodeSupport也應該算到shim,該模組的作用是串連Peer節點與ChainCode的媒介,用shim形容也可。
ChainCode:  鏈碼,應用(例如智能合約)。
DB:  資料存放區。
Library:  代碼裡有一個叫做Vendor的檔案夾,該檔案夾裡涉及的功能模組自成一體,例如grpcServer等
API:  ChainCode裡面會調用Peer節點資訊。
Crypto:  伴隨著資料加解密。 
Ledger:  賬本操作。


該代碼使用Handler觸發模式,在跟蹤代碼程式時要注意handler對象賦值位置,否則容易找錯HandleMessage,這些Handler處理函數命名基本相同,容易操作混亂。


下面分析幾個讀者應該最關心的流程:
1)Client通過CLI執行一條invoke命令
2)某節點發送給該節點ViewChange命令
3)ChainCode調用API putStatus
4)Consensus流程


一、 Client通過CLI執行一條invoke命令
1)在Peer節點初始化的時候 建立DevopsServer


serverDevops := core.NewDevopsServer(peerServer)  
pb.RegisterDevopsServer(grpcServer, serverDevops)  


2)DevopsServer設定Service規範,例如Invoke Message,調用_Devops_Invoke_Handler函數


var _Devops_serviceDesc = grpc.ServiceDesc{  
    ServiceName: "protos.Devops",  
    HandlerType: (*DevopsServer)(nil),  
    Methods: []grpc.MethodDesc{  
        {  
            MethodName: "Login",  
            Handler:    _Devops_Login_Handler,  
        },  
        {  
            MethodName: "Build",  
            Handler:    _Devops_Build_Handler,  
        },  
        {  
            MethodName: "Deploy",  
            Handler:    _Devops_Deploy_Handler,  
        },  
        {  
            MethodName: "Invoke",  
            Handler:    _Devops_Invoke_Handler,  
        },  
        {  
            MethodName: "Query",  
            Handler:    _Devops_Query_Handler,  
        },  
        {  
            MethodName: "EXP_GetApplicationTCert",  
            Handler:    _Devops_EXP_GetApplicationTCert_Handler,  
        },  
        {  
            MethodName: "EXP_PrepareForTx",  
            Handler:    _Devops_EXP_PrepareForTx_Handler,  
        },  
        {  
            MethodName: "EXP_ProduceSigma",  
            Handler:    _Devops_EXP_ProduceSigma_Handler,  
        },  
        {  
            MethodName: "EXP_ExecuteWithBinding",  
            Handler:    _Devops_EXP_ExecuteWithBinding_Handler,  
        },  
    },  
    Streams: []grpc.StreamDesc{},  
}  


3)其中_Devops_Invoke_Handler函數在Protos模組,其負責將Client接入的資訊傳遞到對應的Server模組


func _Devops_Invoke_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) {  
    in := new(ChaincodeInvocationSpec)  
    if err := dec(in); err != nil {  
        return nil, err  
    }  
    out, err := srv.(DevopsServer).Invoke(ctx, in)  
    if err != nil {  
        return nil, err  
    }  
    return out, nil  
}  


4)在函數在devops服務端代碼中處理


func (d *Devops) Invoke(ctx context.Context, chaincodeInvocationSpec *pb.ChaincodeInvocationSpec) (*pb.Response, error) {  
    return d.invokeOrQuery(ctx, chaincodeInvocationSpec, chaincodeInvocationSpec.ChaincodeSpec.Attributes, true)  
}  


5)精簡invokeOrQuery代碼,d.coord 是PeerServer對象,ExecuteTransaction 是對應Engine的實現方法


func (d *Devops) invokeOrQuery(ctx context.Context, chaincodeInvocationSpec *pb.ChaincodeInvocationSpec, attributes []string, invoke bool) (*pb.Response, error) {  
  
resp := d.coord.ExecuteTransaction(transaction)  
}  


6)本次請求被封裝成交易Struct,該處理是在PeerServer中。


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"代指PeerServer,engine是在建立PeerServer的時候指定的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 &pb.Response{Status: pb.Response_FAILURE, Msg: []byte(fmt.Sprintf("Error sending transaction to local engine: %s", err))}  
    }  
  
    var response *pb.Response  
    msg := &pb.Message{Type: pb.Message_CHAIN_TRANSACTION, Payload: data, Timestamp: util.CreateUtcTimestamp()}  
    peerLogger.Debugf("Sending message %s with timestamp %v 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.RecvMsg(msg, eng.peerEndpoint.ID)  
}  


畫圖說明上述流程:


 
該圖中沒有體現的一點是在Devops Server建立的時候將PeerServer對象作為構造參數傳入,而PeerServer建立的過程就是建立Engine的過程,也是載入Engine-handler的過程,而Engine-handler的實現在Consensus模組。圖中直接從Devops Server 跳入Consensus模組有些突兀。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.