Hyperledger Fabric 1.2 --- Chaincode Operator 解讀和測試(二)


本文接上一節是測試部分

 

搭建一個模擬測試環境

作者將fabric release1.2工程中的 example-e2e進行了改造來進行本次實驗:

1)首先我們將examples/e2e_cli/scripts/script.sh中的安裝智能合約部分注釋掉,或者從此處下載替換原有的腳本

2)然后再寫一個用於安裝signcd的腳本 script_chaincode.sh ,放在examples/e2e_cli/scripts/ 目錄下面

(3)啟動測試網絡:

  cd examples/e2e_cli/

  bash  network_setup.sh up

  ps: 注意,要保證當前docker image中fabric相關的鏡像里lastest版本是1.2.0,否則可能以其他版本的鏡像啟動,導致執行無法成功

3)執行以下命令進入cli容器

  docker exec -it cli bash


整個網絡的組織架構:

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 AdminOrg2 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 creatorown 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的證明。另外我們可以看到Org2admin並沒有對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

預期:只有符合當前安裝的chaincodeinstantiate策略的身份才可以去更新

此時我們剛執行完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
}

官方的文檔有很多隱藏的坑,所以當遇到問題時最好的方法是閱讀源碼為准。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM