• 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
    }

    官方的文档有很多隐藏的坑,所以当遇到问题时最好的方法是阅读源码为准。

  • 相关阅读:
    select入门学习
    tomcat入门及相关学习
    Tomcat&Servlet
    CPU排行榜
    CPU后字母代表的含义
    刷 BIOS
    Java的三个体系
    XML入门及案例
    BootStrap笔记
    第三节 DOM及案例 表格全选、表单验证
  • 原文地址:https://www.cnblogs.com/cnblogs-wangzhipeng/p/9531733.html
Copyright © 2020-2023  润新知