本文接上一节是测试部分

搭建一个模拟测试环境

作者将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

整个网络的组织架构:

  1. OrgOrderer
  2.   Org1
  3.     peer:
  4.       Peer0 : peer0.org1
  5.       Peer1 : Peer1.org1
  6.     User:
  7.       Org1Msp.admin
  8.  
  9.   Org2
  10.     peer:
  11.       Peer2: peer0.org2
  12.       Peer3: peer1.org2
  13.  
  14.   User:
  15.  
  16.       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
打包

  1. ORG_NUM= PEER_NUM= 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安装智能合约并实例化

  1. ORG_NUM= PEER_NUM= bash ./scripts/script_chaincode.sh chaincode install signedccpack.out
  2.  
  3. ORG_NUM= PEER_NUM= 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发送实例化请求

执行如下命令:

  1. ORG_NUM= PEER_NUM= 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容器

  1. docker ps
  2.  
  3. 此时我们能看到新创建了一个容器:
  4. dev-peer1.org2.example.com-mycc-1.0-26c2ef32838554aac4f7ad6f100aca865e87959c9a126e86d764c8d01f8346ab

这表示实例化成功,但是有一点peer命令比较麻烦,它只会向指定的 CORE_PEER_ADDRESS去发送命令,无法同时向多个节点发送初始化请求,所以其他节点再去实例化的时候会报错:xxxchaincode 已经存在了。

<1.2>多组织签名

setup0:
重启本地环境

  1. cd $GOPATH/github.com/hyperledger/fabric/examples/e2e_cli
  2.  
  3. bash network_setup.sh restart
  4.  
  5. docker exec -it cli bash

××cli容器中执行以下步骤

setup1
:
Org1
Admin
Org2
Admin
同时签名

  1. ORG_NUM= PEER_NUM= 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
  2.  
  3. ORG_NUM= PEER_NUM= bash ./scripts/script_chaincode.sh chaincode signpackage ccpack.out signedccpack.out
  4. ps: peer cli 中指定 -S 就会默认的用localMspchaincode进行签名。

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')"
策略。

  1. peer/chaincode/package.go
  2.  
  3. getChaincodeInstallPackage(){

  4. ip := instantiationPolicy
  5.  
  6. if ip == "" {
  7. //if an instantiation policy is not given, default
  8. //to "admin must sign chaincode instantiation proposals"
  9. mspid, err := mspmgmt.GetLocalMSP().GetIdentifier()
  10. if err != nil {
  11. return nil, err
  12. }
  13. ip = "AND('" + mspid + ".admin')"
  14. }

  15. }

2)指定实例化策略策略

预期:实例化成功

setup 0 重启测试环境

setup 1 打包智能合约并设置背书策略

  1. ORG_NUM= PEER_NUM= 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
  2.  
  3. ps: cli 中默认设置的localMspOrg1MSP

setup2: Org2 admin 去向Peer3安装智能合约并实例化

参照<1.1>setup2

结果:符合预期,测试成功。

总结: 我们这里只能测试OR策略,因为peer-cli只会读取本地的localMSP作为creator进行背书发送实例化请求,AND请求需要两个组织的admin的证明。另外我们可以看到Org2admin并没有对ccpack.out进行签名也安装成功了,是否包含ownerlist 看来并不影响实例化过程。

3)不指定实例化策略打包直接安装

预期:任何一个组织的Admin都能初始化

setup
0

重启测试环境

setup
1
:直接安装

  1. ORG_NUM= PEER_NUM= bash ./scripts/script_chaincode.sh chaincode install -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/example02/cmd
  2.  
  3. ORG_NUM= PEER_NUM= 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

  1. ORG_NUM= PEER_NUM= 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
  2.  
  3. ORG_NUM= PEER_NUM= bash ./scripts/script_chaincode.sh chaincode install ccpack.out

setup2: 更新chaincode

#使用不符合新合约策略的Org2MSP.admin去更新智能合约

  1. ORG_NUM= PEER_NUM= 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
去更新智能合约

  1. ORG_NUM= PEER_NUM= bash ./scripts/script_chaincode.sh chaincode upgrade -o orderer.example.com: -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

  1. ORG_NUM= PEER_NUM= 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
  2.  
  3. ORG_NUM= PEER_NUM= ./scripts/script_chaincode.sh chaincode install ccpack.out

setup2: 更新chaincode

#使用不符合新合约策略的Org2MSP.admin去更新智能合约

  1. ORG_NUM= PEER_NUM= ./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:

  1. ORG_NUM= PEER_NUM= bash ./scripts/script_chaincode.sh chaincode upgrade -o orderer.example.com: -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,必须二者全部符合才能生效!

  1.  
  1. // executeUpgrade implements the "upgrade" Invoke transaction.
  2. 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) {
  3.  
  4. //获取当前版本的chaincode cds
  5. //we need the cd to compare the version
  6. cdLedger, err := lscc.getChaincodeData(chaincodeName, cdbytes)
  7. if err != nil {
  8. return nil, err
  9. }
  10. //do not upgrade if same version
  11. if cdLedger.Version == cds.ChaincodeSpec.ChaincodeId.Version {
  12. return nil, IdenticalVersionErr(chaincodeName)
  13. }
  14. //do not upgrade if instantiation policy is violated
  15. if cdLedger.InstantiationPolicy == nil {
  16. return nil, InstantiationPolicyMissing("")
  17. }
  18. // get the signed instantiation proposal
  19.  
  20. //校验是否符合当前版本的InstantiationPolicy
  21. signedProp, err := stub.GetSignedProposal()
  22. if err != nil {
  23. return nil, err
  24. }
  25.  
  26. err = lscc.support.CheckInstantiationPolicy(signedProp, chainName, cdLedger.InstantiationPolicy)
  27. if err != nil {
  28. return nil, err
  29. }
  30.  
  31. //校验是否符合请求中实例化的chaincode所指定的 Instantiation Policy
  32. //retain chaincode specific data and fill channel specific ones
  33. cdfs.Escc = string(escc) //用于背书的系统级智能合约名称 默认为escc
  34. cdfs.Vscc = string(vscc) //用于校验的系统级智能合约名称 默认为cscc
  35. cdfs.Policy = policy //从client端传入
  36. // retrieve and evaluate new instantiation policy
  37. cdfs.InstantiationPolicy, err = lscc.support.GetInstantiationPolicy(chainName, ccpackfs)
  38. if err != nil {
  39. return nil, err
  40. }
  41. err = lscc.support.CheckInstantiationPolicy(signedProp, chainName, cdfs.InstantiationPolicy)
  42. if err != nil {
  43. return nil, err
  44. }
  45. …… ……
  46. return cdfs, nil
  47. }

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

Hyperledger Fabric 1.2 --- Chaincode Operator 解读和测试(二)的更多相关文章

  1. Hyperledger Fabric 1.2 --- Chaincode Operator 解读和测试(一)

    前言 本文主要目的是用于整理Hyperledger  Fabric中关于chaincode 管理和操作的内容,作者以release-1.2为范本进行讲解. 主要参考链接: https://hyperl ...

  2. hyperledger fabric 中java chaincode 支持离线打包

    联盟链由于其本身的特性,目前应用在一些大型国有企业银行比较多.出于安全考虑,这些企业一般会隔离外网环境.所以在实际生产需求中可能存在需要在一个离线的环境中打包安装chaincode的情况. 本文基于这 ...

  3. Hyperledger Fabric Chaincode for Operators——实操智能合约

    什么是Chaincode(智能合约)? chaincode是一个程序,它是使用Go语言编写的,最终在Java等其他编程语言中实现了指定的接口.chaincode运行在一个被背书peer进程独立出来的安 ...

  4. Hyperledger Fabric(5)ChainCode的编写步骤

    链码(chaincode) 会对 Fabric应用程序  发送的交易做出响应,执行代码逻辑,与 账本 进行交互. 再复习下他们之间的逻辑关系: Hyperledger Fabric 中,Chainco ...

  5. Hyperledger Fabric CouchDB as the State Database

    使用CouchDB作为状态数据库 状态数据库选项 状态数据库包括LevelDB和CouchDB.LevelDB是嵌入在peer进程中的默认键/值状态数据库,CouchDB是一个可选的外部状态数据库.与 ...

  6. Hyperledger Fabric CouchDB as the State Database——使用CouchDB

    使用CouchDB作为状态数据库 状态数据库选项 状态数据库包括LevelDB和CouchDB.LevelDB是嵌入在peer进程中的默认键/值状态数据库,CouchDB是一个可选的外部状态数据库.与 ...

  7. Hyperledger Fabric 第一次安装

    第一次安装fabric有很多坑.记录一下,主要跟版本问题. 参考的是http://www.cnblogs.com/aberic/p/7532114.html 这篇博客. 我用的阿里云centOs 7. ...

  8. Hyperledger Fabric 踩坑汇总

    搭建基础环境 阿里云安装出现的一些问题解决 1. [signal SIGSEGV: segmentation violation code=0x1 addr=xxx pc=xxx] 类似的错误:原始错 ...

  9. 搭建基于hyperledger fabric的联盟社区(四) --chaincode开发

    前几章已经分别把三台虚拟机环境和配置文件准备好了,在启动fabric网络之前我们要准备好写好的chaincode.chaincode的开发一般是使用GO或者JAVA,而我选择的是GO语言.先分析一下官 ...

随机推荐

  1. Sequelize-nodejs-2-basic usage

    Basic usage基本使用 To get the ball rollin' you first have to create an instance of Sequelize. Use it th ...

  2. Windows7下配置JMeter安装环境

    JMeter配置安装 1.安装JDK环境  下载地址:http://www.Oracle.com/technetwork/Java/javase/downloads/jdk8-downloads-21 ...

  3. node.js学习之post文件上传 (multer中间件)

    express为了性能考虑,采用按需加载的方式,引入各种中间件来完成需求, 平时解析post上传的数据时,是用body-parser. 但这个中间件有缺点,只能解析post的文本内容,(applica ...

  4. 1554: SG Value (巧妙的模拟题,也属于思维题)

    1554: SG Value Submit Page    Summary    Time Limit: 5 Sec     Memory Limit: 256 Mb     Submitted: 4 ...

  5. traefik-Ingress边缘路由器落地到微服务

    1.理解Ingress 简单的说,ingress就是从kubernetes集群外访问集群的入口,将用户的URL请求转发到不同的service上.Ingress相当于nginx.apache等负载均衡方 ...

  6. Hdu4952 - Number Transformation - 数论(2014 Multi-University Training Contest 8)

    寻找1~k内i的倍数.则这个数能够看成i*x,则下一个数为(i+1)*y,(i+1)*y>=i*x,那么能够推出.y=x-x/(i+1); 那么当x<i+1时,y==x.之后的循环也不会改 ...

  7. Linux下如何查看分区文件系统类型

    1,fdisk -l fdisk -l 只能列出硬盘的分区表.容量大小以及分区类型,但看不到文件系统类型. 2,df -h df 命令是用来查看文件系统磁盘空间使用量的.但df 命令只会列出已挂载的文 ...

  8. php生成带自定义logo和带二维码跳转自定义地址的二维码

    index.php<?phpheader('Content-type:text/html;charset=UTF-8');// 指定允许其他域名访问header('Access-Control- ...

  9. FIFO队列 ADT接口 数组实现

    FIFO.h (接口) #include "Item.h" #include <stdlib.h> typedef struct STACKnode *link; st ...

  10. PI接口开发之调java WS接口(转)

    java提供的WSDL:http://XXX.XXX.XXX.XX/XXXXXXXcrm/ws/financialStatementsService?wsdl 登陆PI,下载Enterprise Se ...