筆者在詳細分析程式前有以下疑問:
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後續過程我們是如何使用的
下面會慢慢的滲透以上涉及的問題。
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與之通訊。
一級模組分類:
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,
, ,
, ,
, ,
, ,
},
streams: grpc.streamdesc{},
} 3)其中_devops_invoke_handler函式在protos模組,其負責將client接入的資訊傳遞到對應的server模組
func _devops_invoke_handler(srv inte***ce{}, ctx context.context, dec func(inte***ce{}) error) (inte***ce{}, error)
out, err := srv.(devopsserver).invoke(ctx, in)
if err != nil
return out, nil
} 4)在函式在devops服務端**中處理
func (d *devops) invoke(ctx context.context, chaincodeinvocationspec *pb.chaincodeinvocationspec) (*pb.response, error)
5)精簡invokeorquery**,d.coord 是peerserver物件,executetransaction 是對應engine的實現方法
func (d *devops) invokeorquery(ctx context.context, chaincodeinvocationspec *pb.chaincodeinvocationspec, attributes string, invoke bool) (*pb.response, error)
6)本次請求被封裝成交易struct,該處理是在peerserver中。
func (p *impl) executetransaction(transaction *pb.transaction) (response *pb.response) else
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
} var response *pb.response
msg := &pb.message
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)
畫圖說明上述流程:
該圖中沒有體現的一點是在devops server建立的時候將peerserver物件作為構造引數傳入,而peerserver建立的過程就是建立engine的過程,也是載入engine-handler的過程,而engine-handler的實現在consensus模組。圖中直接從devops server 跳入consensus模組有些突兀。
區塊鏈的底層架構
區塊鏈基礎架構分為6層,包括資料層 網路層 共識層 激勵層 合約層 應用層。每層分別完成一項核心功能,各層之間互相配合,實現乙個去中心化的信任機制。資料層主要描述區塊鏈技術的物理形式。區塊鏈系統設計的技術人員們首先建立的乙個起始節點是 創世區塊 之後在同樣規則下建立的規格相同的區塊通過乙個鏈式的結構...
區塊鏈 Fabric基礎架構原理(二)
fabric 的網路節點本質上是互相複製的狀態機,節點之間需要保持相同的賬本狀態。為了實現這個目的,各個節點需要通過共識 consensus 過程,對賬本狀態的變化達成一致性的認同。fabric 的共識過程包括 3 個階段 背書 排序和校驗。在背書 endorsement 階段中,背書節點對客戶端發...
區塊鏈技術公司區塊鏈的特點分析
今天想巨集觀得聊一下,自己對區塊鏈主流技術的基本認知和特點分析。說到區塊鏈技術,它們競爭的核心都是演算法,而這些演算法裡面,社群討論的最多是共識演算法。現在主流公鏈上的共識演算法使用的最多應該還是pow。pow的演算法,能非常好得解決隨機性的問題,所以基於它建立的區塊鏈系統,具有簡單高效可靠性好這些...