本文接上一節是測試部分html
搭建一個模擬測試環境
做者將
fabric release1.2
工程中的
example-e2e
進行了改造來進行本次實驗:
git
(
1
)首先咱們將examples/e2e_cli/
scripts/script.sh
中的安裝智能合約部分註釋掉,或者從此處下載替換原有的腳本
github
(
2
)而後再寫一個用於安裝
signcd
的腳本 script_chaincode.sh ,放在
dockerexamples/e2e_cli/
scripts/
目錄下面
(3)啓動測試網絡:bash
cd examples/e2e_cli/
網絡
bash network_setup.sh up
架構
ps: 注意,要保證當前docker image中fabric相關的鏡像裏lastest版本是1.2.0,不然可能以其餘版本的鏡像啓動,致使執行沒法成功
ide
(
3
)執行如下命令進入
cli
容器
測試
docker exec -it cli bash
lua
整個網絡的組織架構:
OrgOrderer Org1 peer: Peer0 : peer0.org1 Peer1 : Peer1.org1 User: Org1Msp.admin Org2 peer: Peer2: peer0.org2 Peer3: peer1.org2 User: Org2Msp.admin
若是以上四步都沒有報錯說明環境正常。
測試場景
(
1
)缺省策略測試,即不指定
實例化
策略
預期結果:任意一個
Org Admin
都能實例化。
<1.1>
無簽名
setup0:
啓動本地測試環境
cd $GOPATH/github.com/hyperledger/fabric/examples/e2e_cli
bash network_setup.sh restart
#
等服務徹底啓動後再進入
cli
容器內
docker exec -it cli bash
ps:
若是服務已經啓動過了就無需再啓動了
ps1
:如下幾步都是在
cli
容器內執行的
setup1:
由
Org1 admin
對
chaincode
打包
ORG_NUM=1 PEER_NUM=0 bash ./scripts/script_chaincode.sh chaincode package -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/example02/cmd -s ccpack.out
ps:
咱們此時沒有調用
-i
指令去指定背書策略,
-S
沒有指定因此沒有
owner
簽名。
setup2:
由
Org2 admin
去向
Peer3
安裝智能合約並實例化
ORG_NUM=2 PEER_NUM=3 bash ./scripts/script_chaincode.sh chaincode install signedccpack.out ORG_NUM=2 PEER_NUM=3 bash ./scripts/script_chaincode.sh chaincode instantiate -C mychannel -n mycc -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P "OR('Org1MSP.peer','Org2MSP.peer')"
此時會拋出如下錯誤:
Error: could not assemble transaction, err Proposal response was not successful, error code 500, msg instantiation policy violation: signature set did not satisfy policy
而這不符合咱們的預期
;
setup3:
由
Org1 admin
去向
Peer3
發送實例化請求
執行以下命令:
ORG_NUM=1 PEER_NUM=3 bash ./scripts/script_chaincode.sh chaincode instantiate -C mychannel -n mycc -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P "OR('Org1MSP.peer','Org2MSP.peer')"
查看本地
docker
容器
docker ps 此時咱們能看到新建立了一個容器: dev-peer1.org2.example.com-mycc-1.0-26c2ef32838554aac4f7ad6f100aca865e87959c9a126e86d764c8d01f8346ab
這表示實例化成功,可是有一點
peer
命令比較麻煩,它只會向指定的
CORE_PEER_ADDRESS
去發送命令,沒法同時向多個節點發送初始化請求,因此其餘節點再去實例化的時候會報錯:
xxxchaincode
已經存在了。
<1.2>
多組織簽名
setup0:
重啓本地環境
cd $GOPATH/github.com/hyperledger/fabric/examples/e2e_cli
bash network_setup.sh restart
docker exec -it cli bash
××
在
cli
容器中執行如下步驟
setup1 :
由
Org1 Admin
和
Org2 Admin
同時簽名
ORG_NUM=1 PEER_NUM=0 bash ./scripts/script_chaincode.sh chaincode package -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/example02/cmd -s -S ccpack.out ORG_NUM=2 PEER_NUM=2 bash ./scripts/script_chaincode.sh chaincode signpackage ccpack.out signedccpack.out ps: peer cli 中指定 -S 就會默認的用localMsp對chaincode進行簽名。
setup2:
由
Org2 admin
去向
Peer3
安裝智能合約並實例化
重複
<1.1>
中的
setup2
步驟
仍然會拋出不符合實例化策略的錯誤。
setup3:
由
Org1 admin
去向
Peer3
發送實例化請求
重複
<1.1>
中的
setup3
步驟
執行成功
總結:
目前來看不符合預期的結果!
從以上兩種狀況來看,即使是
instantiation proposal
的
creator
在
own list
中(對
chaincode
進行了簽名),若是不符合策略仍然不會成功。
另外,咱們發現是不管是否對
CDS
進行簽名,
Policy
都會生效,校驗
Creator
的時候用
packge
時的
LocalMsp admin
發起實例化都會成功。
分析源碼找到了緣由:
Peercli
在打包時不指定
policy
的狀況下,默認會添進去的
"AND('" + mspid + ".admin')"
策略。
peer/chaincode/package.go getChaincodeInstallPackage(){ … … ip := instantiationPolicy if ip == "" { //if an instantiation policy is not given, default //to "admin must sign chaincode instantiation proposals" mspid, err := mspmgmt.GetLocalMSP().GetIdentifier() if err != nil { return nil, err } ip = "AND('" + mspid + ".admin')" } … … }
(
2
)指定實例化策略策略
預期:實例化成功
setup 0
重啓測試環境
略
setup 1
打包智能合約並設置背書策略
ORG_NUM=1 PEER_NUM=3 bash ./scripts/script_chaincode.sh chaincode package -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/example02/cmd -s -i "OR('Org1MSP.admin','Org2MSP.admin')" ccpack.out ps: cli 中默認設置的localMsp是Org1MSP
setup2:
由
Org2 admin
去向
Peer3
安裝智能合約並實例化
參照
<1.1>
中
setup2
結果:符合預期,測試成功。
總結
:
咱們這裏只能測試
OR
策略,由於
peer-cli
只會讀取本地的
localMSP
做爲
creator
進行背書發送實例化請求,
AND
請求須要兩個組織的
admin
的證實。另外咱們能夠看到
Org2
的
admin
並無對
ccpack.out
進行簽名也安裝成功了,是否包含
ownerlist
看來並不影響實例化過程。
(
3
)不指定實例化策略打包直接安裝
預期:任何一個組織的
Admin
都能初始化
setup 0
: 重啓測試環境
略
setup 1
:直接安裝
ORG_NUM=2 PEER_NUM=3 bash ./scripts/script_chaincode.sh chaincode install -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/example02/cmd ORG_NUM=1 PEER_NUM=3 bash ./scripts/script_chaincode.sh chaincode instantiate -C mychannel -n mycc -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P "OR('Org1MSP.peer','Org2MSP.peer')"
結果執行成功:與預期相互符合。
(
4
)升級
chaincode
<4.1>
已安裝的
chaincode
未指定
instantiate policy
預期:任意一個
OrgAdmin
能夠更新,由於在官方文檔中說法是按照當前已經存在的chaincode的實例化策略進行判別,目前狀態下的chaincode是沒有指定策略,也就是任意一個org.admin身份均可以。
setup1:
安裝新版本鏈碼並指定
instantiate policy
策略,版本設置爲
1.1
#
指定實例化策略爲只有
Org1MSP.admin
ORG_NUM=1 PEER_NUM=3 bash ./scripts/script_chaincode.sh chaincode package -n mycc -v 1.1 -p github.com/hyperledger/fabric/examples/chaincode/go/example02/cmd -s -i "AND('Org1MSP.admin')" ccpack.out ORG_NUM=2 PEER_NUM=3 bash ./scripts/script_chaincode.sh chaincode install ccpack.out
setup2:
更新
chaincode
#
使用不符合新合約策略的
Org2MSP.admin
去更新智能合約
ORG_NUM=2 PEER_NUM=3 bash ./scripts/script_chaincode.sh chaincode upgrade -C mychannel -n mycc -v 1.1 -c '{"Args":["init","a","100","b","200"]}' -P "OR('Org1MSP.peer','Org2MSP.peer')"
執行失敗
setup3:
#
使用
Org1MSP.admin
去更新智能合約
ORG_NUM=1 PEER_NUM=3 bash ./scripts/script_chaincode.sh chaincode upgrade -o orderer.example.com:7050 -n mycc -v 1.1 -c '{"Args":["init","a","100","b","200"]}' -P "OR('Org1MSP.peer','Org2MSP.peer')" -C mychannel
執行成功
結果
:
不符合預期
<4.2>
已安裝的
chaincode
指定
instantiate policy
預期:只有符合當前安裝的
chaincode
的
instantiate
策略的身份才能夠去更新
此時咱們剛執行完
4.2
測試,因此正好符合測試場景
setup1:
安裝新版本鏈碼並指定
instantiate policy
策略,版本設置爲
1.2
#
指定實例化策略爲只有
Org1MSP.admin
ORG_NUM=2 PEER_NUM=3 bash ./scripts/script_chaincode.sh package -n mycc -v 1.2 -p github.com/hyperledger/fabric/examples/chaincode/go/example02/cmd -s -i "AND('Org2MSP.admin')" ccpack.out ORG_NUM=2 PEER_NUM=3 ./scripts/script_chaincode.sh chaincode install ccpack.out
setup2:
更新
chaincode
#
使用不符合新合約策略的
Org2MSP.admin
去更新智能合約
ORG_NUM=2 PEER_NUM=3 ./scripts/script_chaincode.sh chaincode upgrade -C mychannel -n mycc -v 1.2 -c '{"Args":["init","a","100","b","200"]}' -P "OR('Org1MSP.peer','Org2MSP.peer')"
不能實例化成功:
msg instantiation policy violation: signature set did not satisfy policy
符合預期
Setup3:
ORG_NUM=1 PEER_NUM=3 bash ./scripts/script_chaincode.sh chaincode upgrade -o orderer.example.com:7050 -n mycc -v 1.2 -c '{"Args":["init","a","100","b","200"]}' -P "OR('Org1MSP.peer','Org2MSP.peer')" -C mychannel
不能實例化成功:
msg instantiation policy violation: signature set did not satisfy policy
執行失敗
結果: 不符合預期
總結:根據咱們對源碼的研究,更新智能合約的時候不單單會校驗當前已經實例化合約的
instantiate_policy
還會去校驗新安裝合約的
instantiate_policy
,必須兩者所有符合才能生效!
// executeUpgrade implements the "upgrade" Invoke transaction. func (lscc *lifeCycleSysCC) executeUpgrade(stub shim.ChaincodeStubInterface, chainName string, cds *pb.ChaincodeDeploymentSpec, policy []byte, escc []byte, vscc []byte, cdfs *ccprovider.ChaincodeData, ccpackfs ccprovider.CCPackage, collectionConfigBytes []byte) (*ccprovider.ChaincodeData, error) { //獲取當前版本的chaincode cds //we need the cd to compare the version cdLedger, err := lscc.getChaincodeData(chaincodeName, cdbytes) if err != nil { return nil, err } //do not upgrade if same version if cdLedger.Version == cds.ChaincodeSpec.ChaincodeId.Version { return nil, IdenticalVersionErr(chaincodeName) } //do not upgrade if instantiation policy is violated if cdLedger.InstantiationPolicy == nil { return nil, InstantiationPolicyMissing("") } // get the signed instantiation proposal //校驗是否符合當前版本的InstantiationPolicy signedProp, err := stub.GetSignedProposal() if err != nil { return nil, err } err = lscc.support.CheckInstantiationPolicy(signedProp, chainName, cdLedger.InstantiationPolicy) if err != nil { return nil, err } //校驗是否符合請求中實例化的chaincode所指定的 Instantiation Policy //retain chaincode specific data and fill channel specific ones cdfs.Escc = string(escc) //用於背書的系統級智能合約名稱 默認爲escc cdfs.Vscc = string(vscc) //用於校驗的系統級智能合約名稱 默認爲cscc cdfs.Policy = policy //從client端傳入 // retrieve and evaluate new instantiation policy cdfs.InstantiationPolicy, err = lscc.support.GetInstantiationPolicy(chainName, ccpackfs) if err != nil { return nil, err } err = lscc.support.CheckInstantiationPolicy(signedProp, chainName, cdfs.InstantiationPolicy) if err != nil { return nil, err } …… …… return cdfs, nil }
官方的文檔有不少隱藏的坑,因此當遇到問題時最好的方法是閱讀源碼爲準。