在Fabric中,新的链码类要重新实现Init()和Invoke()这2个方法。这里以fabone.go为例,Fabric版本为 v1.4.0,进行说明。
Fabric GitHub官网
Fabric v1.4.0源码下载
1、定义一个空类
type HelloChainCode struct {}
2、重写Init()方法
实现链码的初始化功能,这里指定为初始化 <k,v> 键值对。
func (t *HelloChainCode) Init(stub shim.ChaincodeStubInterface) peer.Response {fmt.Println("begin init...")_,args := stub.GetFunctionAndParameters()if len(args) != 2 {return shim.Error("must have two params")}//save dataerr := stub.PutState(args[0],[]byte(args[1]))if err != nil {return shim.Error("PutState() is error")}fmt.Println("init success!")return shim.Success(nil)
}
3、重写Invoke()方法
a) 实现调用链码功能,供peer节点调用,通过Invoke,将调用方法指向query()、setkey()。当然也可以指向其他方法,比如 delete()、getTxID()等等。
func (t *HelloChainCode) Invoke(stub shim.ChaincodeStubInterface) peer.Response {callStr,args := stub.GetFunctionAndParameters()if callStr == "setkey" {return t.setkey(stub)} else if callStr == "query" {return t.query(stub,args)}jsonResp := "{\"Error\":\"Nil,It has no func: "+ callStr + "\"}"return shim.Error(jsonResp)
}
b) Invoke指向的query()方法
func (t *HelloChainCode) query(stub shim.ChaincodeStubInterface, args[] string) peer.Response {if len(args) != 1 {return shim.Error("params length must equal 1")}result,err := stub.GetState(args[0])if err != nil {return shim.Error("GetState() is failed")}if result == nil {strRes := string(result[:])jsonResp := "{\"Error\":\"Nil,It has no data for:" + strRes + "\"}"return shim.Error(jsonResp)}return shim.Success(result)
}
c) Invoke指向的setkey()方法
func (t *HelloChainCode) setkey(stub shim.ChaincodeStubInterface) peer.Response {fmt.Println("begin set...")_,args := stub.GetFunctionAndParameters()if len(args) != 2 {return shim.Error("must have two params")}_,err := stub.GetState(args[0])if err != nil {return shim.Error("This key"+args[0]+" is not existed!")}//set dataerr = stub.PutState(args[0],[]byte(args[1]))if err != nil {return shim.Error("PutState() is error")}fmt.Println("set success!")return shim.Success(nil)
}
4、完整代码
a) fabone.go 完整代码
package mainimport ("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("begin init...")_,args := stub.GetFunctionAndParameters()if len(args) != 2 {return shim.Error("must have two params")}//save dataerr := stub.PutState(args[0],[]byte(args[1]))if err != nil {return shim.Error("PutState() is error")}fmt.Println("init success!")return shim.Success(nil)
}func (t *HelloChainCode) Invoke(stub shim.ChaincodeStubInterface) peer.Response {callStr,args := stub.GetFunctionAndParameters()if callStr == "setkey" {return t.setkey(stub)} else if callStr == "query" {return t.query(stub,args)}jsonResp := "{\"Error\":\"Nil,It has no func: "+ callStr + "\"}"return shim.Error(jsonResp)
}func (t *HelloChainCode) query(stub shim.ChaincodeStubInterface, args[] string) peer.Response {if len(args) != 1 {return shim.Error("params length must equal 1")}result,err := stub.GetState(args[0])if err != nil {return shim.Error("GetState() is failed")}if result == nil {strRes := string(result[:])jsonResp := "{\"Error\":\"Nil,It has no data for:" + strRes + "\"}"return shim.Error(jsonResp)}return shim.Success(result)
}func (t *HelloChainCode) setkey(stub shim.ChaincodeStubInterface) peer.Response {fmt.Println("begin set...")_,args := stub.GetFunctionAndParameters()if len(args) != 2 {return shim.Error("must have two params")}_,err := stub.GetState(args[0])if err != nil {return shim.Error("This key"+args[0]+" is not existed!")}//set dataerr = stub.PutState(args[0],[]byte(args[1]))if err != nil {return shim.Error("PutState() is error")}fmt.Println("set success!")return shim.Success(nil)
}func main() {err := shim.Start(new(HelloChainCode))if err != nil {fmt.Printf("it start failed!")}
}
b)进入fabric-samples/chaincode-docker-devmode/目录,新建一个文件夹名称为chaincode,进入chaincode目录再创建一个文件夹名称为fabone,并把fabone.go放到该目录下。
cd fabric-samples/chaincode-docker-devmode/
mkdir chaincode chaincode/fabone
cp fabone.go chaincode/fabone
5、修改配置文件
a) 在fabric-samples/chaincode-docker-devmode/目录里,
将docker-compose-simple.yaml复制一份,改名为docker-compose.yaml,同时,用"./chaincode" 替换"./…/chaincode",命令依次如下:
cd fabric-samples/chaincode-docker-devmode/
cp docker-compose-simple.yaml docker-compose.yaml
sed -i "s|./../chaincode|./chaincode|g" docker-compose.yaml
b) 在docker-compose.yaml里添加一个7052端口,并打开dev模式

目录结构如下:

6、初始化链码
a) 启动docker服务
cd fabric-samples/chaincode-docker-devmode
docker-compose up -d
b)打开一个新的终端2,依次输入如下命令,进入chaincode容器,编译fabone.go源文件
## 进入fabone.go所在的目录
cd fabric-samples/chaincode-docker-devmode/chaincode/fabone
sudo docker exec -it chaincode bash
go env -w GOPROXY=https://goproxy.cn,direct
go build fabone.go
c) 启动链码
CORE_PEER_ADDRESS=peer:7052 CORE_CHAINCODE_ID_NAME=fabone:1.0 ./fabone
该语句的含义是,在7052端口,启动一个fabone链码,版本为1.0。

7、安装和实例化链码
a) 再打开一个新的终端3,进入cli容器
sudo docker exec -it cli bash
b) 安装链码
将 fabone 1.0链码,安装到节点里。
peer chaincode install -v 1.0 -n fabone -p chaincodedev/chaincode/fabone
c) 实例化链码
初始化 weight = 60kg的一个<k,v>键值对,并把它保存到myc通道里。
peer chaincode instantiate -C myc -n fabone -v 1.0 -c '{"Args":["init","weight","60kg"]}'
8、调用链码
调用setkey(),把weight改成80kg,命令如下:
peer chaincode invoke -C myc -n fabone -c '{"Args":["setkey","weight","80kg"]}'
打印status=200,说明链码调用setkey()函数成功。
9、查询链码里的key-value
查询key(“weight”)对应的状态数据
peer chaincode query -C myc -n fabone -c '{"Args":["query","weight"]}'
效果如下:

10、交易查询
10.1 查看当前通道myc的区块高度
peer channel getinfo -c myc
得到通道myc的区块高度为height = 3

10.2 导出区块
a)重新打开一个新的终端4,依次输入如下命令:
cd /usr/local/gocode/src/github.com/hyperledger/fabric-samples/bin
mkdir myblock
cd ..
chmod -cR 777 myblock/sudo docker cp cli:/opt/gopath/src/chaincodedev/one.block /usr/local/gocode/src/github.com/hyperledger/fabric-samples/bin/myblock
b) 设置FABRIC_CFG_PATH环境变量
#修改/etc/profile文件
vim /etc/profile #添加FABRIC_CFG_PATH环境变量
#fabric
export FABRIC_CFG_PATH=/usr/local/gocode/src/github.com/hyperledger/fabric-samples/basic-network## 使能环境
source /etc/profile

c) 使用configtxgen工具导出区块
configtxgen -inspectBlock ./myblock/one.block > ./myblock/one.json
d) 查看one.json的txID
cat myblock/one.json |grep -A 3 "tx_id"
得到tx_id = 9573bde3b0677f29c6ab5cb7952125f95da69f2aac9f9c32a6d10b067878cef1

11、查看区块个数
11.1 区块数据
//one.json 区块数据
{"data": {"data": [{"payload": {"data": {"actions": [{"header": {"creator": {"id_bytes": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNOakNDQWQyZ0F3SUJBZ0lSQU1uZjkvZG1WOVJ2Q0NWdzlwWlFVZlV3Q2dZSUtvWkl6ajBFQXdJd2dZRXgKQ3pBSkJnTlZCQVlUQWxWVE1STXdFUVlEVlFRSUV3cERZV3hwWm05eWJtbGhNUll3RkFZRFZRUUhFdzFUWVc0ZwpSbkpoYm1OcGMyTnZNUmt3RndZRFZRUUtFeEJ2Y21jeExtVjRZVzF3YkdVdVkyOXRNUXd3Q2dZRFZRUUxFd05EClQxQXhIREFhQmdOVkJBTVRFMk5oTG05eVp6RXVaWGhoYlhCc1pTNWpiMjB3SGhjTk1UY3hNVEV5TVRNME1URXgKV2hjTk1qY3hNVEV3TVRNME1URXhXakJwTVFzd0NRWURWUVFHRXdKVlV6RVRNQkVHQTFVRUNCTUtRMkZzYVdadgpjbTVwWVRFV01CUUdBMVVFQnhNTlUyRnVJRVp5WVc1amFYTmpiekVNTUFvR0ExVUVDeE1EUTA5UU1SOHdIUVlEClZRUURFeFp3WldWeU1DNXZjbWN4TG1WNFlXMXdiR1V1WTI5dE1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMEQKQVFjRFFnQUVaOFM0VjcxT0JKcHlNSVZaZHdZZEZYQWNrSXRycHZTckNmMEhRZzQwV1c5WFNvT09PNzZJK1VtZgpFa21UbElKWFA3L0F5UlJTUlUzOG9JOEl2dHU0TTZOTk1Fc3dEZ1lEVlIwUEFRSC9CQVFEQWdlQU1Bd0dBMVVkCkV3RUIvd1FDTUFBd0t3WURWUjBqQkNRd0lvQWdpbk9SSWhuUEVGWlVoWG02ZVdCa203SzdaYzhSNC96N0xXNEgKb3NzRGxDc3dDZ1lJS29aSXpqMEVBd0lEUndBd1JBSWdWaWtJVVp6Z2Z1RnNHTFFIV0pVVkpDVTdwRGFFVGthegpQekZnc0NpTHhVQUNJQ2d6SllsVzdudlp4UDdiNnRiZXUzdDhtcmhNWFFzOTU2bUQ0K0JvS3VOSQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==","mspid": "DEFAULT"},"nonce": "/n5TtJl5QryN4z5T7qa8SL0M14otTlu0"},"payload": {"action": {"endorsements": [{"endorser": "CgdERUZBVUxUEroGLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNOakNDQWQyZ0F3SUJBZ0lSQU1uZjkvZG1WOVJ2Q0NWdzlwWlFVZlV3Q2dZSUtvWkl6ajBFQXdJd2dZRXgKQ3pBSkJnTlZCQVlUQWxWVE1STXdFUVlEVlFRSUV3cERZV3hwWm05eWJtbGhNUll3RkFZRFZRUUhFdzFUWVc0ZwpSbkpoYm1OcGMyTnZNUmt3RndZRFZRUUtFeEJ2Y21jeExtVjRZVzF3YkdVdVkyOXRNUXd3Q2dZRFZRUUxFd05EClQxQXhIREFhQmdOVkJBTVRFMk5oTG05eVp6RXVaWGhoYlhCc1pTNWpiMjB3SGhjTk1UY3hNVEV5TVRNME1URXgKV2hjTk1qY3hNVEV3TVRNME1URXhXakJwTVFzd0NRWURWUVFHRXdKVlV6RVRNQkVHQTFVRUNCTUtRMkZzYVdadgpjbTVwWVRFV01CUUdBMVVFQnhNTlUyRnVJRVp5WVc1amFYTmpiekVNTUFvR0ExVUVDeE1EUTA5UU1SOHdIUVlEClZRUURFeFp3WldWeU1DNXZjbWN4TG1WNFlXMXdiR1V1WTI5dE1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMEQKQVFjRFFnQUVaOFM0VjcxT0JKcHlNSVZaZHdZZEZYQWNrSXRycHZTckNmMEhRZzQwV1c5WFNvT09PNzZJK1VtZgpFa21UbElKWFA3L0F5UlJTUlUzOG9JOEl2dHU0TTZOTk1Fc3dEZ1lEVlIwUEFRSC9CQVFEQWdlQU1Bd0dBMVVkCkV3RUIvd1FDTUFBd0t3WURWUjBqQkNRd0lvQWdpbk9SSWhuUEVGWlVoWG02ZVdCa203SzdaYzhSNC96N0xXNEgKb3NzRGxDc3dDZ1lJS29aSXpqMEVBd0lEUndBd1JBSWdWaWtJVVp6Z2Z1RnNHTFFIV0pVVkpDVTdwRGFFVGthegpQekZnc0NpTHhVQUNJQ2d6SllsVzdudlp4UDdiNnRiZXUzdDhtcmhNWFFzOTU2bUQ0K0JvS3VOSQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==","signature": "MEUCIQCQzgUxtNyYVwhYan6IMSQl0z61ModWm16l+l1pkf/XggIgP8N+pKigKTzubun8o/wZx02R7Mj/f1IOGgVw1MqK/zE="}],"proposal_response_payload": {"extension": {"chaincode_id": {"name": "fabone","path": "","version": "1.0"},"events": null,"response": {"message": "","payload": null,"status": 200},"results": {"data_model": "KV","ns_rwset": [{"collection_hashed_rwset": [],"namespace": "fabone","rwset": {"metadata_writes": [],"range_queries_info": [],"reads": [{"key": "weight","version": {"block_num": "1","tx_num": "0"}}],"writes": [{"is_delete": false,"key": "weight","value": "ODBrZw=="}]}},{"collection_hashed_rwset": [],"namespace": "lscc","rwset": {"metadata_writes": [],"range_queries_info": [],"reads": [{"key": "fabone","version": {"block_num": "1","tx_num": "0"}}],"writes": []}}]},"token_expectation": null},"proposal_hash": "cwzYy2afp1nVfaDFuFfJYUGC/HSOTHj9TdNBMvGlc9I="}},"chaincode_proposal_payload": {"TransientMap": {},"input": {"chaincode_spec": {"chaincode_id": {"name": "fabone","path": "","version": ""},"input": {"args": ["c2V0a2V5","d2VpZ2h0","ODBrZw=="],"decorations": {}},"timeout": 0,"type": "GOLANG"}}}}}]},"header": {"channel_header": {"channel_id": "myc","epoch": "0","extension": "EggSBmZhYm9uZQ==","timestamp": "2021-07-30T00:38:53.450469289Z","tls_cert_hash": null,"tx_id": "9573bde3b0677f29c6ab5cb7952125f95da69f2aac9f9c32a6d10b067878cef1","type": 3,"version": 0},"signature_header": {"creator": {"id_bytes": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNOakNDQWQyZ0F3SUJBZ0lSQU1uZjkvZG1WOVJ2Q0NWdzlwWlFVZlV3Q2dZSUtvWkl6ajBFQXdJd2dZRXgKQ3pBSkJnTlZCQVlUQWxWVE1STXdFUVlEVlFRSUV3cERZV3hwWm05eWJtbGhNUll3RkFZRFZRUUhFdzFUWVc0ZwpSbkpoYm1OcGMyTnZNUmt3RndZRFZRUUtFeEJ2Y21jeExtVjRZVzF3YkdVdVkyOXRNUXd3Q2dZRFZRUUxFd05EClQxQXhIREFhQmdOVkJBTVRFMk5oTG05eVp6RXVaWGhoYlhCc1pTNWpiMjB3SGhjTk1UY3hNVEV5TVRNME1URXgKV2hjTk1qY3hNVEV3TVRNME1URXhXakJwTVFzd0NRWURWUVFHRXdKVlV6RVRNQkVHQTFVRUNCTUtRMkZzYVdadgpjbTVwWVRFV01CUUdBMVVFQnhNTlUyRnVJRVp5WVc1amFYTmpiekVNTUFvR0ExVUVDeE1EUTA5UU1SOHdIUVlEClZRUURFeFp3WldWeU1DNXZjbWN4TG1WNFlXMXdiR1V1WTI5dE1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMEQKQVFjRFFnQUVaOFM0VjcxT0JKcHlNSVZaZHdZZEZYQWNrSXRycHZTckNmMEhRZzQwV1c5WFNvT09PNzZJK1VtZgpFa21UbElKWFA3L0F5UlJTUlUzOG9JOEl2dHU0TTZOTk1Fc3dEZ1lEVlIwUEFRSC9CQVFEQWdlQU1Bd0dBMVVkCkV3RUIvd1FDTUFBd0t3WURWUjBqQkNRd0lvQWdpbk9SSWhuUEVGWlVoWG02ZVdCa203SzdaYzhSNC96N0xXNEgKb3NzRGxDc3dDZ1lJS29aSXpqMEVBd0lEUndBd1JBSWdWaWtJVVp6Z2Z1RnNHTFFIV0pVVkpDVTdwRGFFVGthegpQekZnc0NpTHhVQUNJQ2d6SllsVzdudlp4UDdiNnRiZXUzdDhtcmhNWFFzOTU2bUQ0K0JvS3VOSQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==","mspid": "DEFAULT"},"nonce": "/n5TtJl5QryN4z5T7qa8SL0M14otTlu0"}}},"signature": "MEQCIG17Wq1iZsDcnKqgxaccsz2O26jJP1J+eIC4/fq9TBIsAiBj4RV/gDmYDDD5s7iy0l+y/i+dA+sVT8dF1oy1B8HzzA=="}]},"header": {"data_hash": "U5Fms2VccR9eDTHkwbE2usd8KRpcSLcK1XKtyOScHbg=","number": "2","previous_hash": "QIs/gsEKWtVr1q9sLKcXLmgLtRw+le2h9DA1lwjdBVA="},"metadata": {"metadata": ["Eq4HCuMGCsYGCgdERUZBVUxUEroGLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNOakNDQWQyZ0F3SUJBZ0lSQU1uZjkvZG1WOVJ2Q0NWdzlwWlFVZlV3Q2dZSUtvWkl6ajBFQXdJd2dZRXgKQ3pBSkJnTlZCQVlUQWxWVE1STXdFUVlEVlFRSUV3cERZV3hwWm05eWJtbGhNUll3RkFZRFZRUUhFdzFUWVc0ZwpSbkpoYm1OcGMyTnZNUmt3RndZRFZRUUtFeEJ2Y21jeExtVjRZVzF3YkdVdVkyOXRNUXd3Q2dZRFZRUUxFd05EClQxQXhIREFhQmdOVkJBTVRFMk5oTG05eVp6RXVaWGhoYlhCc1pTNWpiMjB3SGhjTk1UY3hNVEV5TVRNME1URXgKV2hjTk1qY3hNVEV3TVRNME1URXhXakJwTVFzd0NRWURWUVFHRXdKVlV6RVRNQkVHQTFVRUNCTUtRMkZzYVdadgpjbTVwWVRFV01CUUdBMVVFQnhNTlUyRnVJRVp5WVc1amFYTmpiekVNTUFvR0ExVUVDeE1EUTA5UU1SOHdIUVlEClZRUURFeFp3WldWeU1DNXZjbWN4TG1WNFlXMXdiR1V1WTI5dE1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMEQKQVFjRFFnQUVaOFM0VjcxT0JKcHlNSVZaZHdZZEZYQWNrSXRycHZTckNmMEhRZzQwV1c5WFNvT09PNzZJK1VtZgpFa21UbElKWFA3L0F5UlJTUlUzOG9JOEl2dHU0TTZOTk1Fc3dEZ1lEVlIwUEFRSC9CQVFEQWdlQU1Bd0dBMVVkCkV3RUIvd1FDTUFBd0t3WURWUjBqQkNRd0lvQWdpbk9SSWhuUEVGWlVoWG02ZVdCa203SzdaYzhSNC96N0xXNEgKb3NzRGxDc3dDZ1lJS29aSXpqMEVBd0lEUndBd1JBSWdWaWtJVVp6Z2Z1RnNHTFFIV0pVVkpDVTdwRGFFVGthegpQekZnc0NpTHhVQUNJQ2d6SllsVzdudlp4UDdiNnRiZXUzdDhtcmhNWFFzOTU2bUQ0K0JvS3VOSQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tChIYup0Fwdp1zJIWos86CzfFeuRKODN6zPq2EkYwRAIgURFQpq8gFlVFPldkzeCCEZRb404jsJtZoziJ3nWmz30CIER1x+Ab6/zW1RF2VdUDbf87kbwbAioQS0olnikdFaBr","Eq8HCuMGCsYGCgdERUZBVUxUEroGLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNOakNDQWQyZ0F3SUJBZ0lSQU1uZjkvZG1WOVJ2Q0NWdzlwWlFVZlV3Q2dZSUtvWkl6ajBFQXdJd2dZRXgKQ3pBSkJnTlZCQVlUQWxWVE1STXdFUVlEVlFRSUV3cERZV3hwWm05eWJtbGhNUll3RkFZRFZRUUhFdzFUWVc0ZwpSbkpoYm1OcGMyTnZNUmt3RndZRFZRUUtFeEJ2Y21jeExtVjRZVzF3YkdVdVkyOXRNUXd3Q2dZRFZRUUxFd05EClQxQXhIREFhQmdOVkJBTVRFMk5oTG05eVp6RXVaWGhoYlhCc1pTNWpiMjB3SGhjTk1UY3hNVEV5TVRNME1URXgKV2hjTk1qY3hNVEV3TVRNME1URXhXakJwTVFzd0NRWURWUVFHRXdKVlV6RVRNQkVHQTFVRUNCTUtRMkZzYVdadgpjbTVwWVRFV01CUUdBMVVFQnhNTlUyRnVJRVp5WVc1amFYTmpiekVNTUFvR0ExVUVDeE1EUTA5UU1SOHdIUVlEClZRUURFeFp3WldWeU1DNXZjbWN4TG1WNFlXMXdiR1V1WTI5dE1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMEQKQVFjRFFnQUVaOFM0VjcxT0JKcHlNSVZaZHdZZEZYQWNrSXRycHZTckNmMEhRZzQwV1c5WFNvT09PNzZJK1VtZgpFa21UbElKWFA3L0F5UlJTUlUzOG9JOEl2dHU0TTZOTk1Fc3dEZ1lEVlIwUEFRSC9CQVFEQWdlQU1Bd0dBMVVkCkV3RUIvd1FDTUFBd0t3WURWUjBqQkNRd0lvQWdpbk9SSWhuUEVGWlVoWG02ZVdCa203SzdaYzhSNC96N0xXNEgKb3NzRGxDc3dDZ1lJS29aSXpqMEVBd0lEUndBd1JBSWdWaWtJVVp6Z2Z1RnNHTFFIV0pVVkpDVTdwRGFFVGthegpQekZnc0NpTHhVQUNJQ2d6SllsVzdudlp4UDdiNnRiZXUzdDhtcmhNWFFzOTU2bUQ0K0JvS3VOSQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tChIY5PG6lm822S+1oY4mcW0nMOc63lxK+/CrEkcwRQIhAPOZZITCLnyuIY/XZLAJsqmoBB22l+75GUbxOWojpqwpAiBICXRvbDIBu9qv6I6/XfqpXVXfRdaMHwkTIT9FNE2Zkg==","AA==",""]}
}
11.2 链码字段


11.3 RWset和证书解码
fabric里的RWset、证书采用base64编码,所以需要进行base64解码才能显示正常的结果。
a) RWset 原文与解码
"writes": [{"is_delete": false,"key": "weight","value": "ODBrZw=="}
]
对value进行解码
echo $(echo ODBrZw== | base64 -d)

即解码后 {value: 0DBrzw== } == {value: 80kg }
b)证书原文与解码
"signature_header": {"creator": {"id_bytes": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNOakNDQWQyZ0F3SUJBZ0lSQU1uZjkvZG1WOVJ2Q0NWdzlwWlFVZlV3Q2dZSUtvWkl6ajBFQXdJd2dZRXgKQ3pBSkJnTlZCQVlUQWxWVE1STXdFUVlEVlFRSUV3cERZV3hwWm05eWJtbGhNUll3RkFZRFZRUUhFdzFUWVc0ZwpSbkpoYm1OcGMyTnZNUmt3RndZRFZRUUtFeEJ2Y21jeExtVjRZVzF3YkdVdVkyOXRNUXd3Q2dZRFZRUUxFd05EClQxQXhIREFhQmdOVkJBTVRFMk5oTG05eVp6RXVaWGhoYlhCc1pTNWpiMjB3SGhjTk1UY3hNVEV5TVRNME1URXgKV2hjTk1qY3hNVEV3TVRNME1URXhXakJwTVFzd0NRWURWUVFHRXdKVlV6RVRNQkVHQTFVRUNCTUtRMkZzYVdadgpjbTVwWVRFV01CUUdBMVVFQnhNTlUyRnVJRVp5WVc1amFYTmpiekVNTUFvR0ExVUVDeE1EUTA5UU1SOHdIUVlEClZRUURFeFp3WldWeU1DNXZjbWN4TG1WNFlXMXdiR1V1WTI5dE1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMEQKQVFjRFFnQUVaOFM0VjcxT0JKcHlNSVZaZHdZZEZYQWNrSXRycHZTckNmMEhRZzQwV1c5WFNvT09PNzZJK1VtZgpFa21UbElKWFA3L0F5UlJTUlUzOG9JOEl2dHU0TTZOTk1Fc3dEZ1lEVlIwUEFRSC9CQVFEQWdlQU1Bd0dBMVVkCkV3RUIvd1FDTUFBd0t3WURWUjBqQkNRd0lvQWdpbk9SSWhuUEVGWlVoWG02ZVdCa203SzdaYzhSNC96N0xXNEgKb3NzRGxDc3dDZ1lJS29aSXpqMEVBd0lEUndBd1JBSWdWaWtJVVp6Z2Z1RnNHTFFIV0pVVkpDVTdwRGFFVGthegpQekZnc0NpTHhVQUNJQ2d6SllsVzdudlp4UDdiNnRiZXUzdDhtcmhNWFFzOTU2bUQ0K0JvS3VOSQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==","mspid": "DEFAULT"},"nonce": "/n5TtJl5QryN4z5T7qa8SL0M14otTlu0"
}
对id_bytes进行解码
## 保存证书信息到mycert.pem
echo LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNOakNDQWQyZ0F3SUJBZ0lSQU1uZjkvZG1WOVJ2Q0NWdzlwWlFVZlV3Q2dZSUtvWkl6ajBFQXdJd2dZRXgKQ3pBSkJnTlZCQVlUQWxWVE1STXdFUVlEVlFRSUV3cERZV3hwWm05eWJtbGhNUll3RkFZRFZRUUhFdzFUWVc0ZwpSbkpoYm1OcGMyTnZNUmt3RndZRFZRUUtFeEJ2Y21jeExtVjRZVzF3YkdVdVkyOXRNUXd3Q2dZRFZRUUxFd05EClQxQXhIREFhQmdOVkJBTVRFMk5oTG05eVp6RXVaWGhoYlhCc1pTNWpiMjB3SGhjTk1UY3hNVEV5TVRNME1URXgKV2hjTk1qY3hNVEV3TVRNME1URXhXakJwTVFzd0NRWURWUVFHRXdKVlV6RVRNQkVHQTFVRUNCTUtRMkZzYVdadgpjbTVwWVRFV01CUUdBMVVFQnhNTlUyRnVJRVp5WVc1amFYTmpiekVNTUFvR0ExVUVDeE1EUTA5UU1SOHdIUVlEClZRUURFeFp3WldWeU1DNXZjbWN4TG1WNFlXMXdiR1V1WTI5dE1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMEQKQVFjRFFnQUVaOFM0VjcxT0JKcHlNSVZaZHdZZEZYQWNrSXRycHZTckNmMEhRZzQwV1c5WFNvT09PNzZJK1VtZgpFa21UbElKWFA3L0F5UlJTUlUzOG9JOEl2dHU0TTZOTk1Fc3dEZ1lEVlIwUEFRSC9CQVFEQWdlQU1Bd0dBMVVkCkV3RUIvd1FDTUFBd0t3WURWUjBqQkNRd0lvQWdpbk9SSWhuUEVGWlVoWG02ZVdCa203SzdaYzhSNC96N0xXNEgKb3NzRGxDc3dDZ1lJS29aSXpqMEVBd0lEUndBd1JBSWdWaWtJVVp6Z2Z1RnNHTFFIV0pVVkpDVTdwRGFFVGthegpQekZnc0NpTHhVQUNJQ2d6SllsVzdudlp4UDdiNnRiZXUzdDhtcmhNWFFzOTU2bUQ0K0JvS3VOSQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== | base64 -d > mycert.pem## 查看mycert.pem文件
openssl x509 -text -noout -in mycert.pem
得到如下:

12、关闭fabric-dev网络
exit
docker-compose down