Hyperledger Fabric 提供了 chaincode 的开发模式,使 chaincode 在开发阶段可以进行快速开发、构建、运行、调试。
1 下载fabric-samples
git clone https://github.com/hyperledger/fabric-samples.git
完成之后,进入fabric-samples/chaincode-docker-devmode目录,里面包括以下文件。
- chaincode 链码目录
- docker-compose-simple.yaml docker编排脚本
- msp 证书文件与密钥
- myc.block 创始区块
- myc.tx channel配置文件
- orderer.block 系统通道创始区块
- script.sh cli容器的执行脚本
2 启动dev测试环境
将编写的链码放到fabric-sample/chaincode/目录下
docker-compose -f docker-compose-simple.yaml up
共启动了四个容器:
- orderer节点,映射了msp目录和orderer.block区块
- peer节点,映射了msp目录
- cli命令行客户端,执行script.sh脚本,映射了当前目录和fabric-samples/chaincode目录中的系统链码
- chaincode链码容器,用来编译执行链码
3 编译链码
进入chaincode容器,这时应该可以看到我们编写的链码hello.go
docker exec -it chaincode bash
root@950cd7608c04:/opt/gopath/src/chaincodedev/chaincode/hello#
go build
CORE_PEER_ADDRESS=peer:7052 CORE_CHAINCODE_ID_NAME=mycc:0 ./hello
4 安装与初始化
进入cli容器,安装并实例化链码,最后查询。
docker exec -it cli bash
# 以下命令按照自己的链码内容自行修改
peer chaincode install -p chaincodedev/chaincode/hello -n mycc -v 0
peer chaincode instantiate -n mycc -v 0 -c '{"Args":["init","hello","world"]}' -C myc
peer chaincode query -n mycc -c '{"Args":["query","hello"]}' -C myc
5 链码源码hello.go
package main
import (
"github.com/hyperledger/fabric/core/chaincode/shim"
"github.com/hyperledger/fabric/protos/peer"
"fmt"
)
type HelloChaincode struct {
}
func (t *HelloChaincode) Init(stub shim.ChaincodeStubInterface) peer.Response {
fmt.Println("开始实例化链码....")
_, args := stub.GetFunctionAndParameters()
if len(args) != 2 {
return shim.Error("指定了错误的参数个数")
}
fmt.Println("保存数据......")
err := stub.PutState(args[0], []byte(args[1]))
if err != nil {
return shim.Error("保存数据时发生错误...")
}
fmt.Println("实例化链码成功")
return shim.Success(nil)
}
func (t *HelloChaincode) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
fun, args := stub.GetFunctionAndParameters()
if fun == "query"{
return query(stub, args)
}
return shim.Error("非法操作, 指定功能不能实现")
}
func query(stub shim.ChaincodeStubInterface, args []string) peer.Response {
if len(args) != 1{
return shim.Error("指定的参数错误,必须且只能指定相应的Key")
}
result, err := stub.GetState(args[0])
if err != nil {
return shim.Error("根据指定的 " + args[0] + " 查询数据时发生错误")
}
if result == nil {
return shim.Error("根据指定的 " + args[0] + " 没有查询到相应的数据")
}
return shim.Success(result)
}
func main() {
err := shim.Start(new(HelloChaincode))
if err != nil {
fmt.Printf("链码启动失败: %v", err)
}
}
6 CouchDB支持
6.1 添加CounchDB容器
Hyperledger Fabric 环境中,如果需要使用 CouchDB,那么必须在docker-compose.yaml或自定义的配置文件中声明 CouchDB 容器,然后在各个 peer 容器中 environment 属性中声明相关环境内容,且在 depends_on 属性中指定声明的 CouchDB 容器的名称。
docker-compose-simple.yaml 配置文件中添加 couchdb 的容器信息:
couchdb:
container_name: couchdb
image: hyperledger/fabric-couchdb
# Populate the COUCHDB_USER and COUCHDB_PASSWORD to set an admin user and password
# for CouchDB. This will prevent CouchDB from operating in an "Admin Party" mode.
environment:
- COUCHDB_USER=
- COUCHDB_PASSWORD=
# Comment/Uncomment the port mapping if you want to hide/expose the CouchDB service,
# for example map it to utilize Fauxton User Interface in dev environments.
ports:
- "5984:5984"
6.2 peer中配置环境变量
在声明 peer 容器中的 environment 中添加如下内容:
- CORE_LEDGER_STATE_STATEDATABASE=CouchDB
- CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb:5984
- CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=
- CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD=
depends_on:
- couchdb
6.3 测试
按照上述步骤安装,实例化,执行链码,登录127.0.0.1:5984/_utils,进入到mycc目录查看执行链码设置的KV值。