使用fabric提供的cryptogen工具生成文件模板
目前創新互聯公司已為千余家的企業提供了網站建設、域名、雅安服務器托管、網站運營、企業網站設計、平涼網站維護等服務,公司將堅持客戶導向、應用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協力一起成長,共同發展。
$ cryptogen showtemplate crypto-config.yaml
進行修改,添加一個組織,一個orderer節點.
根據crypto-config.yaml文件生成證書文件:
$ cryptogen generate --config=crypto-config.yaml
查看生成的證書文件夾結構:
需要從fabric的源碼案例中拷貝configtx.yaml文件
$ cp $GOPATH/src/github.com/hyperledger/fabric-samples/first-network/configtx.yaml ./
對configtx.yaml文件進行修改.
修改之前,創建一個文件夾,來保存即將創建的創世區塊文件
將創建區塊文件和通道的命令寫到一個腳本中! generate.sh
腳本文件和配置文件的目錄結構:
執行generate.sh文件生成創世區塊文件和通道,其實只有一個組織,也沒必要生成錨節點更新文件..
$ ./generate.sh
配置docker-compose文件:
啟動容器, 啟動后查看容器運行情況
$ docker-compose up -d
$ docker-compose ps
在這里,創建兩個腳本文件,用于docker容器的管理
clear_docker.sh 文件:
restart.sh 文件:
創建配置文件的時候,有兩個文件可以進行參考...
修改后的sdk配置文件:
創建出一個模型對象,給其賦值,并開始初始化sdk
使用 pkg/fabsdk/fabsdk.go中的New()方法進行實例化
創建請求之前,需要使用 gopackager.NewCCPackage 方法生成一個resource.CCPackage 對象,傳遞兩個參數,一個是鏈碼的路徑(相對于工程的路徑), 一個是GOPATH的路徑.
安裝鏈碼,使用pkg/client/resmgmt/resmgmt.go文件中的方法
創建請求之前,需要生成一個*cb.SignaturePolicyEnvelope類型的對象,使用 third_party/github.com/hyperledger/fabric/common/cauthdsl/cauthdsl_builder.go 文件中的方法即可,提供了好幾個方法, 使用任意一個即可.這里使用 SignedByAnyMember 方法: 需要傳入所屬組織ID
實例化鏈碼
使用 pkg/client/channel/chclient.go 中的 Execute() 方法,來進行數據寫入的操作:
rsp, err := model.Channelclient.Execute(req)
寫入之前,要創建請求:
tempArgs是要傳給鏈碼的參數,可以做下封裝,就不受參數個數的限制了
使用 pkg/client/channel/chclient.go 中的 Query() 方法,來進行數據查詢的操作: 查詢之前,同樣需要創建請求.
鏈碼在工程中的路徑應該是 工程名/chaincode文件夾
比如:
driverFabricDemo/chaincode
而不應該省略掉工程名這樣寫: chaincode
錯誤原因:cert.URIs 和 tpl.URIs 這兩個字段沒有被定義.
進入tpl對象中, /usr/local/go/src/crypto/x509/x509.go 是個結構體,并沒有發現 URIs 字段
對go版本進行升級,從1.9.3升級到1.11.3, 再次進入 /usr/local/go/src/crypto/x509/x509.go 文件中,查看結構體內容:
在執行sdk的Excute()方法時報錯.
方法不存在,一般是由于鏈碼的Invoke方法中的方法名和Excute()方法傳入的方法名不一樣.
但是可以肯定的是,鏈碼的Invoke方法中的方法名和,項目中執行Excute()方法時傳入的方法名是完全一樣的! 但是很奇怪了,為什么會出現這個錯誤呢? 使用 docker rmi 刪除掉 dev-peerx.travle.xq.com 的鏡像,再重新運行即可.
在創建實例化鏈碼請求的時候
總是提示
Cannot use str (type *cb.SignaturePolicyEnvelope) as type *common.SignaturePolicyEnvelope less... (?F1) Inspection info: Reports composite literals with incompatible types and values
明明是相同的類型,卻總是報錯,應該是IDE的問題.把vendor文件夾刪除后,就不會有提示了. 再使用vendor對工程進行init 和 add +external 就好了!!
出現這個錯誤,一般都是配置文件哪個地方寫錯了,需要細心檢查
environment:
fabric v1.4.2
在Fabric中交易的處理過程,客戶端將提案首先發送到背書節點,背書節點檢提案的合法性。如果合法的話,背書節點將通過交易所屬的鏈碼臨時執行一個交易,并執行背書節點在本地持有的狀態副本。
Chaincode應該僅僅被安裝于chaincode所有者的背書節點上,鏈碼運行在節點上的沙盒(Docker容器)中,并通過gRPC協議與相應的Peer節點進行交互,以使該chaincode邏輯對整個網絡的其他成員保密。
請務必在一條channel上每一個要運行你chaincode的背書節點上安裝你的chaincode
其他沒有chaincode的成員將無權成為chaincode影響下的交易的認證節點(endorser)。也就是說,他們不能執行chaincode。不過,他們仍可以驗證交易并提交到賬本上。
ChainCode要在區塊鏈網絡中運行,需要經過鏈碼安裝和鏈碼實例化兩個步驟。
鏈碼的安裝涉及到3個服務,分別是client,peer背書節點和LSCC容器
主要流程:
以下是在客戶端執行 "peer chaincode install ..." 的業務流程圖:
客戶端執行鏈碼安裝命令:
客戶端的整個流程切入點為 fabric/peer/main.go 的 main 函數
然后繼續找到 peer/chaincode/chaincode.go
繼續找到 peer/chaincode/install.go 的 installCmd 函數,可以看出 chaincodeInstall 為主要的入口函數
我們進去看看 InitCmdFactory 做了什么,位置在 peer/chaincode/common.go
返回了 ChaincodeCmdFactory 的結構體,定義為:
找到定義 genChaincodeDeploymentSpec
先看 getChaincodeSpec ,位于 peer/chaincode/common.go
封裝返回 ChaincodeSpec 結構體
剛才生成的 ChaincodeSpec 作為 getChaincodeDeploymentSpec 函數的輸入參數,返回 ChaincodeDeploymentSpec 結構體
CreateInstallProposalFromCDS 位于 protos/utils/proutils.go
調用 createProposalFromCDS
從結構體 ChaincodeInvocationSpec 可以看到用戶鏈碼安裝需要調用到系統鏈碼 lscc
通過 CreateProposalFromCIS=CreateChaincodeProposal=CreateChaincodeProposalWithTransient
再看 CreateChaincodeProposalWithTxIDNonceAndTransient 函數
最后返回 Proposal 結構體,定義見 protos\peer\proposal.pb.go
到這里 install 調用的 CreateInstallProposalFromCDS 完畢,返回 Proposal 結構體
關系有點復雜,給出一個類圖能看得清晰點
回到 install ,看 GetSignedProposal 對剛創建的提案結構進行簽名
函數位于 protos/utils/txutils.go
返回 SignedProposal 結構體,定義位于 protos/peer/proposal.pb.go
提案簽名完后 install 調用 ProcessProposal 發送提案到peer節點進行處理,參數帶了 SignedProposal 結構體
接下來client端就等到peer的 proposalResponse
當client調用了 ProposalResponse 消息就發送到peer背書節點,也就是走peer節點背書提案流程.
要看安裝鏈碼前做了什么,直接看 peer節點背書提案流程 就好。
我們從 core/endorser/endorser.go 的 callChaincode=Execute 函數開始講
在 core/chaincode/chaincode_support.go 找到 Execute
主要看 Invoke :
根據之前的信息,我們調用的是 lscc 來安裝鏈碼,所以在peer啟動的時候已經初始化 lscc 鏈碼容器了,所以回直接返回 handler 對象,后面的語句就不說了,在啟動鏈碼容器的章節再詳細研究。
接著我們看 execute 函數,調用 createCCMessage 創建一個 ChaincodeMessage結構體消息 . Execute 負責把消息發送出去
在 core/chaincode/handler.go 找到 Execute
這里關鍵是 h.serialSendAsync(msg) 語句,功能是把包裝好的信息以grpc協議發送出去,直接就等返回結果了。
至此 Execute 調用的 Invoke 就在等返回結果,結果返回就調用 processChaincodeExecutionResult 對鏈碼結果進行處理
peer發送的信息哪去了呢?
我們定位到 code/chaincode/shim/chaincode.go ,我們看到兩個入口函數 Start 和 StartInProc , Start 為用戶鏈碼的入口函數,而 StartInProc 是系統鏈碼的入口函數,他們同時都調用了 chatWithPeer ,因為我們調用的是lscc,就看 StartInProc
chatWithPeer就是開啟grpc的接收模式在等到節點發來信息,接收到信息后就調用 handleMessage 處理信息。
因為我們信息類型為 ChaincodeMessage_TRANSACTION ,所以我們在 core/chaincode/shim/handler.go 順著 handleMessage=handleReady 扎到 handleTransaction
其中關鍵語句 res := handler.cc.Invoke(stub) ,這語句是調用相應鏈碼的 Invoke 函數,所以我們找到 core/scc/lscc/lscc.go 下的 Invoke 函數
進去 core/scc/lscc/lscc.go 的 Invoke 函數可以看到,這里有 "INSTALL", "DEPLOY", "UPGRADE" 等操作,我們只看 INSTALL 部分。
關鍵調用函數是 executeInstall
接著看 executeInstall
HandleChaincodeInstall 為處理statedb,而 PutChaincodeToLocalStorage 是把鏈碼文件安裝到本地文件目錄
鏈碼安裝到peer的默認路徑 /var/hyperledger/production/chaincodes
到此鏈碼的安裝完畢
lscc鏈碼安裝完畢后,返回信息給peer節點,peer節點就給提案背書返回給client服務端,至此鏈碼安裝完畢。
github
參考:
5-ChainCode生命周期、分類及安裝、實例化命令解析
fabric源碼解讀【peer chaincode】:安裝鏈碼
Fabric1.4源碼解析:客戶端安裝鏈碼
跟語言無關,跟加密算法有關。你如果調用公開的算法,用同樣的算子去加密解密,那用哪種需要都一樣,關鍵就是很多算法都有你不了解的細節,有些算子是編程語言自己用了默認值,而他們彼此不同