一、链码开发
1. 创建文件夹
进入 fabric-samples/chaincode/
目录下并创建一个名为 hello
的文件夹
$ cd hyfa/fabric-samples/chaincode
$ sudo mkdir hello
$ cd hello
2. 创建并编辑链码源文件
使用vim命令创建.go文件
$ sudo vim hello.go
代码示例:
//202.03.14
//北山
package main
import (
"github.com/hyperledger/fabric/core/chaincode/shim"
"github.com/hyperledger/fabric/protos/peer"
"fmt"
)
func main() {
err := shim.Start(new(HelloChaincode))
if err != nil {
fmt.Printf("链码启动失败: %v", err)
}
}
type HelloChaincode struct {
}
func (t *HelloChaincode) Init(stub shim.ChaincodeStubInterface) peer.Response {
fmt.Println("开始实例化链码....")
// 获取参数
//args := stub.GetStringArgs()
_, args := stub.GetFunctionAndParameters()
// 判断参数长度是否为2个
if len(args) != 2 {
return shim.Error("指定了错误的参数个数")
}
fmt.Println("保存数据......")
// 通过调用PutState方法将数据保存在账本中
err := stub.PutState(args[0], []byte(args[1]))
if err != nil {
return shim.Error("保存数据时发生错误...")
}
fmt.Println("实例化链码成功")
return shim.Success(nil)
}
// 对账本数据进行操作时被自动调用(query, invoke)
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 {
// 检查传递的参数个数是否为1
if len(args) != 1{
return shim.Error("指定的参数错误,必须且只能指定相应的Key")
}
// 根据指定的Key调用GetState方法查询数据
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)
}
普通用户会出现文本只读无法进行编辑,可以使用命令
$ sudo chmod 777 hello.go
修改文本属性,然后进行编辑
二、链码测试
1. 启动网络
1.1 打开终端1,进入 fabric-samples/chaincode-docker-devmode/
目录
$ cd fabric-samples/chaincode-docker-devmode
1.2 启动 chaincode-docker-devmode
$ sudo docker-compose -f docker-compose-simple.yaml up -d
不加 -d 会显示详细信息,很多很多……
上面的命令以 docker-compose-simple.yaml 启动了网络,并以开发模式启动 peer。另外还启动了两个容器:
-
一个 chaincode 容器,用于链码环境
-
一个 CLI 容器,用于与链码进行交互。
命令执行后,终端中输出如下
Creating orderer ...
Creating orderer ... done
Creating peer ...
Creating peer ... done
Creating cli ...
Creating chaincode ...
Creating chaincode
可以使用命令
$ sudo docker ps
查看正在运行的镜像,显示如下(容器ID 不同机器值不一样)
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d12166318e46 hyperledger/fabric-tools "/bin/bash -c ./scri…" 2 minutes ago Up 2 minutes cli
a823ebe43e18 hyperledger/fabric-ccenv "/bin/bash -c 'sleep…" 2 minutes ago Up 2 minutes chaincode
a76fecb0b096 hyperledger/fabric-peer "peer node start --p…" 2 minutes ago Up 1 second 0.0.0.0:7051->7051/tcp, 0.0.0.0:7053->7053/tcp peer
6612e1bcffd5 hyperledger/fabric-orderer "orderer" 2 minutes ago Up 2 minutes 0.0.0.0:7050->7050/tcp orderer
启动网络后会出现peer镜像自动关闭现象,可以使用命令
$ sudo docker-compose -f docker-compose-simple.yaml down
关闭之前已启动的网络环境,再重新启动
2. 构建并启动链码
2.1 打开新终端2,进入 chaincode 容器
$ sudo docker exec -it chaincode bash
命令提示符变为:
root@bc836e82b57c:/opt/gopath/src/chaincode#
2.2 编译链码
$ cd hello
$ go build
2.3 启动链码
$ CORE_PEER_ADDRESS=peer:7052 CORE_CHAINCODE_ID_NAME=hellocc:0 ./hello
命令执行后输出如下:
2021-03-15 03:46:53.406 UTC [shim] SetupChaincodeLogging -> INFO 001 Chaincode log level not provided; defaulting to: INFO
2021-03-15 03:46:53.407 UTC [shim] SetupChaincodeLogging -> INFO 002 Chaincode (build level: ) starting up ...
注意:文件路径要和本地一致,下同
命令含义:
- CORE_PEER_ADDRESS:用于指定peer
- CORE_CHAINCODE_ID_NAME:用于注册到peer的链码
- hellocc: 指定链码名称
- 0: 指定链码初始版本号
- ./hello: 指定链码文件
3. 执行测试
3.1 打开新终端3,进入 cli 容器
$ sudo docker exec -it cli bash
3.2 安装链码
$ peer chaincode install -p chaincodedev/chaincode/hello -n hellocc -v 0
注意:安装链码时指定的链码名称与版本号必须与在终端2中注册的链码名称及版本号相同
安装命令执行后,终端中输出如下:
2021-03-15 03:50:25.666 UTC [viperutil] getKeysRecursively -> DEBU 001 Found map[string]interface{} value for peer.BCCSP
2021-03-15 03:50:25.667 UTC [viperutil] unmarshalJSON -> DEBU 002 Unmarshal JSON: value cannot be unmarshalled: invalid character 'S' looking for beginning of value
2021-03-15 03:50:25.667 UTC [viperutil] getKeysRecursively -> DEBU 003 Found real value for peer.BCCSP.Default setting to string SW
2021-03-15 03:50:25.668 UTC [viperutil] getKeysRecursively -> DEBU 004 Found map[string]interface{} value for peer.BCCSP.SW
……
……
……
2021-03-15 03:50:26.335 UTC [golang-platform] func1 -> DEBU 048 Discarding provided package github.com/hyperledger/fabric/core/chaincode/shim
2021-03-15 03:50:26.335 UTC [golang-platform] func1 -> DEBU 049 Discarding provided package github.com/hyperledger/fabric/protos/peer
2021-03-15 03:50:26.336 UTC [golang-platform] GetDeploymentPayload -> DEBU 04a done
2021-03-15 03:50:26.336 UTC [container] WriteFileToPackage -> DEBU 04b Writing file to tarball: src/chaincodedev/chaincode/hello/helloworld.go
2021-03-15 03:50:26.340 UTC [msp/identity] Sign -> DEBU 04c Sign: plaintext: 0AC4070A5C08031A0C0882B3BB820610...D3AD7F030000FFFFBC8BAC5F000E0000
2021-03-15 03:50:26.340 UTC [msp/identity] Sign -> DEBU 04d Sign: digest: 60FD03CFA8E1B02924EF01635BD278ABDC24449A0A847A6C1155A7DE6F3DFF05
2021-03-15 03:50:26.357 UTC [chaincodeCmd] install -> INFO 04e Installed remotely response:<status:200 payload:"OK" >
3.3 实例化链码
$ peer chaincode instantiate -n hellocc -v 0 -c '{"Args":["init", "Hello","World"]}' -C myc
终端显示:
2021-03-15 03:58:59.500 UTC [viperutil] getKeysRecursively -> DEBU 001 Found map[string]interface{} value for peer.BCCSP
2021-03-15 03:58:59.500 UTC [viperutil] getKeysRecursively -> DEBU 002 Found map[string]interface{} value for peer.BCCSP.SW
2021-03-15 03:58:59.500 UTC [viperutil] getKeysRecursively -> DEBU 003 Found map[string]interface{} value for peer.BCCSP.SW.FileKeyStore
2021-03-15 03:58:59.501 UTC [viperutil] unmarshalJSON -> DEBU 004 Unmarshal JSON: value cannot be unmarshalled: unexpected end of JSON input
2021-03-15 03:58:59.501 UTC [viperutil] getKeysRecursively -> DEBU 005 Found real value for peer.BCCSP.SW.FileKeyStore.KeyStore setting to string
2021-03-15 03:58:59.501 UTC [viperutil] unmarshalJSON -> DEBU 006 Unmarshal JSON: value cannot be unmarshalled: invalid character 'S' looking for beginning of value
……
……
……
2021-03-15 03:58:59.609 UTC [chaincodeCmd] getChaincodeSpec -> DEBU 0a4 java chaincode disabled
2021-03-15 03:58:59.610 UTC [msp/identity] Sign -> DEBU 0a5 Sign: plaintext: 0AC9070A6108031A0C0883B7BB820610...6C640A000A04657363630A0476736363
2021-03-15 03:58:59.610 UTC [msp/identity] Sign -> DEBU 0a6 Sign: digest: 3B2EA8003151BD6B5403559D950A9F430384FA010A89745EC2030BDAB2A25359
2021-03-15 03:58:59.642 UTC [msp/identity] Sign -> DEBU 0a7 Sign: plaintext: 0AC9070A6108031A0C0883B7BB820610...937CFB97C375A783F0ED083D330D8DBA
2021-03-15 03:58:59.643 UTC [msp/identity] Sign -> DEBU 0a8 Sign: digest: 70C518E11400F3D5303EED40547B139CEC024FEABADCBFD793F53DE2A067502E
root@808609ef7ccc:/opt/gopath/src/chaincodedev#
参数说明:
- -o: 指定Oderer服务节点地址
- --tls: 开启 TLS 验证
- --cafile: 指定 TLS_CA 证书的所在路径
- -n: 指定要实例化的链码名称,必须与安装时指定的链码名称相同
- -v: 指定要实例化的链码的版本号,必须与安装时指定的链码版本号相同
- -C: 指定通道名称
- -c: 实例化链码时指定的参数
- -P: 指定背书策略
实例化完成后,用户即可向网络中发起交易
3.4 查询链码
$ peer chaincode query -n hellocc -c '{"Args":["query","Hello"]}' -C myc
终端输出:
2021-03-15 03:59:16.827 UTC [viperutil] getKeysRecursively -> DEBU 001 Found map[string]interface{} value for peer.BCCSP
2021-03-15 03:59:16.828 UTC [viperutil] unmarshalJSON -> DEBU 002 Unmarshal JSON: value cannot be unmarshalled: invalid character 'S' looking for beginning of value
2021-03-15 03:59:16.828 UTC [viperutil] getKeysRecursively -> DEBU 003 Found real value for peer.BCCSP.Default setting to string SW
2021-03-15 03:59:16.828 UTC [viperutil] getKeysRecursively -> DEBU 004 Found map[string]interface{} value for peer.BCCSP.SW
……
……
……
2021-03-15 03:59:16.892 UTC [msp] GetDefaultSigningIdentity -> DEBU 042 Obtaining default signing identity
2021-03-15 03:59:16.892 UTC [chaincodeCmd] getChaincodeSpec -> DEBU 043 java chaincode disabled
2021-03-15 03:59:16.893 UTC [msp/identity] Sign -> DEBU 044 Sign: plaintext: 0ACC070A6408031A0C0894B7BB820610...1A0E0A0571756572790A0548656C6C6F
2021-03-15 03:59:16.893 UTC [msp/identity] Sign -> DEBU 045 Sign: digest: B4D6D27C9E8E59142235291E853C9FD76FF1E50F7901E3E34209BC25EF9408F7
World
测试成功!!!
三、常见问题
1. Hyperledger Fabric SDK 安装
部署 fabric-sdk-go 使用命令
//获取源码
$ git clone https://github.com/hyperledger/fabric-sdk-go.git
//进入fabric-sdk-go 地址
$ cd /opt/gopath/src/github.com/hyperledger/fabric-sdk-go
//执行下载fabric-sdk-go 依赖第三方库,科学上网
/******************************************
//打开模块支持,golang 会忽略 GOPATH 和 vendor 文件夹,只根据 go.mod 下载依赖
$ go env -w GO111MODULE=on
//修改下载代理地址
$ go env -w GOPROXY=https://goproxy.io,direct
******************************************/
$ go mod download
//建立vendor 并copy相应的依赖。
$ go mod vendor
2. error trying to connect to local peer
- 查看peer镜像是否正常运行,如果没有重新启动网络
- 如果正常还是连接不上,检查port是否和peer镜像一致,修改后重新建立连接
3. 持续更新
参考链接:
1. 孔壹学院--从0到1:Hyperledger Fabric开发精要:https://www.chaindesk.cn/witbook/11/123
2. HyperLedger Fabric chaincode 开发模式 docker-devmode:https://www.jianshu.com/p/f6491609ebac?from=groupmessage
3. fabric-sdk-go v1.4 与fabric 1.4 链接指南:https://blog.csdn.net/qq_31104725/article/details/104245662
4. golang版本管理工具GO111MODULE:https://www.cnblogs.com/embedded-linux/p/11616183.html