HyperLeger Fabric开发(八)——HyperLeger Fabric链码开发测试

HyperLeger Fabric开发(八)——HyperLeger Fabric链码开发测试

一、链码实例

SACC项目链码实例如下:

package main

import (
   "fmt"

   "github.com/hyperledger/fabric/core/chaincode/shim"
   "github.com/hyperledger/fabric/protos/peer"
)

// SimpleAsset implements a simple chaincode to manage an asset
type SimpleAsset struct {
}

// Init方法在链码实例化或链码升级期间调用
func (t *SimpleAsset) Init(stub shim.ChaincodeStubInterface) peer.Response {
   // 从交易提案获取参数
   args := stub.GetStringArgs()
   if len(args) != 2 {
      return shim.Error("Incorrect arguments. Expecting a key and a value")
   }

   // 存储资产到账本
   err := stub.PutState(args[0], []byte(args[1]))
   if err != nil {
      return shim.Error(fmt.Sprintf("Failed to create asset: %s", args[0]))
   }
   return shim.Success(nil)
}

// Invoke方法在链码上执行每次交易时被调用
func (t *SimpleAsset) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
   // 从交易提案提取参数
   fn, args := stub.GetFunctionAndParameters()

   var result string
   var err error
   if fn == "set" {
      result, err = set(stub, args)
   } else { // assume ‘get‘ even if fn is nil
      result, err = get(stub, args)
   }
   if err != nil {
      return shim.Error(err.Error())
   }

   // Return the result as success payload
   return shim.Success([]byte(result))
}

// 在账本上使用key-value设置资产,如果key存在,使用新的值更新
func set(stub shim.ChaincodeStubInterface, args []string) (string, error) {
   if len(args) != 2 {
      return "", fmt.Errorf("Incorrect arguments. Expecting a key and a value")
   }

   err := stub.PutState(args[0], []byte(args[1]))
   if err != nil {
      return "", fmt.Errorf("Failed to set asset: %s", args[0])
   }
   return args[1], nil
}

// 获取指定资产key的值
func get(stub shim.ChaincodeStubInterface, args []string) (string, error) {
   if len(args) != 1 {
      return "", fmt.Errorf("Incorrect arguments. Expecting a key")
   }

   value, err := stub.GetState(args[0])
   if err != nil {
      return "", fmt.Errorf("Failed to get asset: %s with error: %s", args[0], err)
   }
   if value == nil {
      return "", fmt.Errorf("Asset not found: %s", args[0])
   }
   return string(value), nil
}

// 实例化期间在容器启动链码
func main() {
   if err := shim.Start(new(SimpleAsset)); err != nil {
      fmt.Printf("Error starting SimpleAsset chaincode: %s", err)
   }
}

二、链码的单元测试

1、链码的单元测试简介

链码开发完毕后,并不需要在区块链环境中部署链码才能进行调试,可以利用shim.MockStub来编写单元测试代码,直接在Go语言开发环境(无Fabric区块链网络的环境)中调试。

2、链码测试代码编写

进入sacc目录,新建一个编写测试代码的sacc_test.go文件

package main

import (
   "testing"
   "github.com/hyperledger/fabric/core/chaincode/shim"
   "fmt"
)

func TestSet(t *testing.T) {
   //模拟链码部署
   scc := new(SimpleAsset)
   stub := shim.NewMockStub("SimpleAsset", scc)
   mockInit(t, stub, [][]byte{[]byte("user1"), []byte("0")})
   //调用链码的交易方法
   invokeSet(t, stub, []string{"user1", "10000"})
   invokeSet(t, stub, []string{"user1", "1000"})
}

func mockInit(t *testing.T, stub *shim.MockStub, args [][]byte) {
   res := stub.MockInit("1", args)
   if res.Status != shim.OK {
      fmt.Println("Init failed", string(res.Message))
      t.FailNow()
   }
}

func invokeSet(t *testing.T, stub *shim.MockStub, args []string) {
   // invoke调用
   res := stub.MockInvoke("1", [][]byte{[]byte("set"), []byte(args[0]),[]byte(args[1])})
   fmt.Println("set(" + args[0]+","+ args[1]+")")
   if res.Status != shim.OK {
      fmt.Println("invoke set failed:", args[0], string(res.Message))
      t.FailNow()
   }
}

func TestGet(t *testing.T) {
   //模拟链码部署
   scc := new(SimpleAsset)
   stub := shim.NewMockStub("SimpleAsset", scc)
   mockInit(t, stub, [][]byte{[]byte("user1"), []byte("10000")})
   //调用链码
   invokeGet(t, stub, []string{"user1"})
}

func invokeGet(t *testing.T, stub *shim.MockStub, args []string) {
   // invoke调用
   res := stub.MockInvoke("1", [][]byte{[]byte("get"), []byte(args[0])})
   fmt.Println("get(" + args[0]+ ")" + "->" + string(res.Payload))
   if res.Status != shim.OK {
      fmt.Println("invoke get failed:", args[0], string(res.Message))
      t.FailNow()
   }
}

// output:
//=== RUN   TestSet
//set(user1,10000)
//set(user1,1000)
//--- PASS: TestSet (0.00s)
//=== RUN   TestGet
//get(user1)->10000
//--- PASS: TestGet (0.00s)
//PASS

3、进行单元测试

在链码目录sacc下执行单元测试
go test -v sacc_test.go sacc.go

三、链码的开发环境测试

1、启动链码开发调试环境

打开终端T1,进入chaincode-docker-devmode目录,启动Fabric网络:
docker-compose -f docker-compose-simple.yaml up

2、编译并启动链码

打开终端T2,进入chaincode容器
docker exec -it chaincode bash
进入SACC(简单资产链码)项目目录:
cd sacc
编译链码:
go build -o sacc
启动链码:
CORE_PEER_ADDRESS=peer:7052 CORE_CHAINCODE_ID_NAME=sacc:0 ./sacc

3、操作链码

打开终端T3,进入客户端cli容器:
docker exec -it cli bash
安装链码:
peer chaincode install -p chaincodedev/chaincode/sacc -n sacc -v 0
安装成功打印信息:Installed remotely response:<status:200 payload:"OK"
实例化链码:
peer chaincode instantiate -n sacc -v 0 -c ‘{"Args":["user1","100"]}‘ -C myc
通道名称必须是myc(创世区块和配置交易的文件名称为myc),否则将报错信息:
Error: error getting channel (testchannel) orderer endpoint: error bad proposal response 500: access denied for [GetConfigBlock][testchannel]: Failed to get policy manager for channel [testchannel]
调用链码,设置用户user1的账户余额:
peer chaincode invoke -n sacc -c ‘{"Args":["set", "user1", "1000"]}‘ -C myc
查询用户user1的余额:
peer chaincode query -n sacc -c ‘{"Args":["get","user1"]}‘ -C myc

4、打包链码

通过将链码相关数据进行封装, 可以实现对其进行打包和签名操作。
打包链码:
peer chaincode package -n sacc -p chaincodedev/chaincode/sacc -v 0 -s -S -i "AND(‘OrgA.admin‘)" ccpack.out
-s: 创建角色支持的CC部署规范包, 而不是原始的CC部署规范
-S: 如果创建CC部署规范方案角色支持,也与本地MSP签名
-i: 指定实例化策略
打包后的文件, 可以直接用于install操作:
peer chaincode install ccpack.out
对一个打包文件进行签名操作(添加当前MSP签名到签名列表中)
peer chaincode signpackage ccpack.out signedccpack.out

5、升级链码

退出cli容器,停止chaincode容器。
在终端T2中重新进入chaincode容器:
docker exec -it chaincode bash
进入SACC项目:
cd sacc
编译链码:
go build -o sacc
启动链码:
CORE_PEER_ADDRESS=peer:7052 CORE_CHAINCODE_ID_NAME=sacc:1 ./sacc
将链码sacc从版本0升级为版本1
打开终端T3,进入cli容器:
docker exec -it cli bash
安装链码:
peer chaincode install -p chaincodedev/chaincode/sacc -n sacc -v 1
升级链码:
peer chaincode upgrade -n sacc -v 1 -c ‘{"Args":["user1", "10000"]}‘ -C myc
在对某链码代码升级前,推荐先将所有该链码的容器停止,并从Peer上备份并移除旧链码部署文件,然后先在个别Peer节点上部署新链码,对原有数据进行测试,成功后再在其它节点上进行升级操作
查询用户user1的账户余额:
peer chaincode query -n sacc -c ‘{"Args":["get","user1"]}‘ -C myc

6、关闭Fabric网络

删除所有在运行的容器:
docker rm -f $(docker ps -aq)
清理Faric网络缓存:
docker network prune

原文地址:http://blog.51cto.com/9291927/2318364

时间: 2024-11-06 20:38:21

HyperLeger Fabric开发(八)——HyperLeger Fabric链码开发测试的相关文章

HyperLeger Fabric开发(七)——HyperLeger Fabric链码开发

HyperLeger Fabric开发(七)--HyperLeger Fabric链码开发 一.链码开发模式 1.链码开发模式简介 Fabric的链码开发调试比较繁琐.在不使用链码开发模式的情况下,链码不能在本地测试,必须部署到docker,install和instantiate后,Peer节点会在新的容器中启动链码.但只能通过docker logs查看链码日志,通过打印日志的方式进行链码调试.如果对链码进行了修改,需要重新开始上述流程.为了简化Fabric链码开发的调试过程,Fabric引入了

Fabric1.4:Go 链码开发与编写

1 链码结构 1.1 链码接口 链码启动必须通过调用 shim 包中的 Start 函数,传递一个类型为 Chaincode 的参数,该参数是一个接口类型,有两个重要的函数 Init 与 Invoke . type Chaincode interface{ Init(stub ChaincodeStubInterface) peer.Response Invoke(stub ChaincodeStubInterface) peer.Response } Init:在链码实例化或升级时被调用, 完

深入探索spring技术内幕(八): Spring +JDBC组合开发和事务控制

一. 配置数据源 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="org.gjt.mm.mysql.Driver"/> <property name="

《nodejs+gulp+webpack基础实战篇》课程笔记(八)--模板化开发演练:分离公共头文件

还是先来安装本课需要的插件: npm install raw-loader --save-dev //示例:var header = require("xxx.html");就会把html的内容读取出来 这是一个webpack加载器,可以把文件原样返回为字符串. 这里补充下使用加载器的两种方法: 1.在我们的webpack配置文件中写上 {test:/\.html$/,loader:"加载器名称"} //这代表所有html后缀均会使用这个加载器来处理 2.在requ

谭八爷下单平台开发公司

谭八爷下单平台开发公司找(何 188.264.66502 微/电),谭八爷下单平台开发.谭八爷微商下单平台开发--对任何一个企业和品牌来说,抓住某一个窗口流量成本很低的封闭期是非常重要的. 无印良品创始人愿意为了做一个好产品坚持3年,磨砺三年.事实上,15年1月份--8月份,他们的产品都不太稳定,所以在这8个月,他们愿意停下来放弃一切销售,一心调整供应链,打磨产品.所以说,成功不是没有原因的. 谭八爷下单平台开发公司,谭八爷微商平台模式开发找-- 一.谭八爷下单平台开发公司有哪些优势点? 1.模

.Net开发八年,坐标杭州,上个月换工作感觉现在.Net岗位很少,希望和同在杭州的同行们交流一下

.Net开发八年,坐标杭州,中间做过2年Java, 目前新入职一家做防伪溯源的中型公司,200人左右, 之前在一家500人规模的软件公司工作过4年,后面2年工作过3家互联网创业公司, 上个月换工作感觉现在.Net岗位很少, 希望和同在杭州的同行们交流一下, 有时间大家可以约个饭,爬个山,或者找地方聚一下聊聊天... 微信号:hoperboy 原文地址:https://www.cnblogs.com/hoperboy/p/9838113.html

[问八系列] Windows 8 开发 (6) - 使用 Windows 8 模拟器测试应用程序

今天因缘际会间,得知了 Visual Studio "11" 可以使用模拟器来测试应用程序,马上就试用了,不但简单,速度也很令人满意.而且只要一个简单的步骤,就能采用模拟器来启动自己的 Metro-style application. 在 Windows 8 中使用 Visual Studio "11" 开发 Metro-style application,最常用的测试方式应该会是直接按 F5 启动,然后用本机来测试应用程序,这是笔者之前所做的开发与测试方式,但老实

Hyperledger Fabric 实战(十二): Fabric 源码本地调试

借助开发网络调试 fabric 源码本地调试 准备工作 IDE Goland Go 1.9.7 fabric-samples 模块 chaincode-docker-devmode fabric 源码 步骤 添加本地域名 127.0.0.1 peer 127.0.0.1 orderer 用 ide 打开 $GOPATH 下的fabric源码目录 在源码目录下添加 dev-network 把 sampleconfig 下的所有文件复制到 dev-network 修改 core.yaml 中 fil

Java微信开发-崔用志-微信开发-java版本

  今天看到一些关于微信开发的知识蛮好的博客,分享给大家,希望对大家有帮助. 微信开发准备(一)--Maven仓库管理新建WEB项目 微信开发准备(二)--springmvc+mybatis项目结构的搭建 微信开发准备(三)--框架以及工具的基本使用 Mybatis工具Generator 微信开发准备(四)--nat123内网地址公网映射实现 Java微信公众平台开发(一)--接入微信公众平台 Java微信公众平台开发(二)--微信服务器post消息体的接收 Java微信公众平台开发(三)--接