Fabric链码入门案例(go语言版本)

article/2025/10/3 4:46:10

    在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模式

图(1) 在Fabric v1.4.0里,启用7052端口

    目录结构如下:

图(2) fabric-samples/chaincode-docker-devmode/chaincode目录结构

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。

图(3) 启动链码监听的端口为7052

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"]}'

    效果如下:

图(4) 查到weight = 80kg

10、交易查询

10.1 查看当前通道myc的区块高度

peer channel getinfo -c myc

    得到通道myc的区块高度为height = 3

图(4) 查看当前通道myc的区块高度

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
图(5) 添加FABBRIC_CFG_PATH到/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

图(6) 查看tx_id

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 链码字段

图(7) RWset字段
图(8) 链码的入参字段(函数名称、参数1、参数2)

11.3 RWset和证书解码

    fabric里的RWset、证书采用base64编码,所以需要进行base64解码才能显示正常的结果。
    a) RWset 原文与解码

"writes": [{"is_delete": false,"key": "weight","value": "ODBrZw=="}
]

    对value进行解码

echo $(echo ODBrZw== | base64 -d)
图(9) 对vaule进行base64解码

    即解码后 {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

    得到如下:

图(10) 对id_bytes进行base64解码,得到证书mycert.pem
表示由ca.org1.example.com发给 peer0.org1.example.com的COP类型的证书,其CA=FALSE。

12、关闭fabric-dev网络

exit
docker-compose down

http://chatgpt.dhexx.cn/article/d1TCXEZx.shtml

相关文章

fabric链码安装失败

chaincode install failed with status: 500 - error in simulation: failed to execute transaction 233fe94f75fc7a6614e08de88b9d262de4f65a73b8f66f7de48b4b698e48e6b6: error sending: timeout expired while executing transaction 链码安装失败&#xff0c;状态&#x…

Fabric 2.2.0 链码交互

根据fabric 官方文档记录https://hyperledger-fabric.readthedocs.io/en/release-2.2/write_first_app.html https://hyperledger-fabric.readthedocs.io/en/release-2.2/test_network.html 1.在test-network目录进行操作 将二进制文件(fabric-samples/bin/目录下)添加到CLI路…

freeman链码

参考链接&#xff1a;https://baike.baidu.com/item/%E9%93%BE%E7%A0%81/4272744?fraladdin 链码&#xff08;又称为freeman码&#xff09;是用曲线起始点的坐标和边界点方向代码来描述曲线或边界的方法&#xff0c;常被用来在图像处理、计算机图形学、模式识别等领域中表示曲…

使用go语言开发部署链码

使用go语言开发部署链码 需要提前部署好测试网络&#xff0c;以下安装操作是基于测试网络的安装&#xff0c;fabric版本为2.4.1 注ps&#xff1a;链码在go版本1.13环境下会出问题&#xff0c;本文是在1.18环境下执行的&#xff0c;可以自行升级版本 第一步编写go链码 packag…

【fabric】部署链码

链码开发好后 参考文章&#xff1a;https://blog.csdn.net/taifei/article/details/85234632 1:启动网络后&#xff0c;查看容器 docker ps -a 部署链码是在cli容器里面。第一步我们可以先查看一下cli有没有成功启动&#xff0c;他的ID是什么。后续可以通过ID或者名字进入容器…

fabric2.0 概念,链码和私有数据

1.智能合约和链码 管理员将相关智能合约组织起来用于部署–链码。 智能合约中存储各方交易的业务模型&#xff0c;定义了术语、处理流程等。利用区块链可以将智能合约转换为可执行程序。应用通过调用智能合约来产生交易与在账本进行记录。使用智能合约可以实现自动化&#xf…

matlab计算图片链码,MATLAB--数字图像处理 计算图像链码及其相似多边形

题目 计算下面图像 边界阶数为20的形状数及其相应的近似多边形 在这里插入图片描述 概念 形状数&#xff1a;链码的最小一阶差分码 简单说来求形状数就是&#xff1a;先求出图像的链码 &#xff0c;再求其一阶差分码&#xff0c;最后找一阶差分码的最小值 在这里插入图片描述 在…

链码的打包与升级

目录 1、链码的打包与签名 ​编辑 对链码的签名 1、安装已经添加签名的链码 2、安装成功之后进行链码的实例化操作&#xff0c;同时指定其背书策略 测试 1、查询链码 2、调用链码 3、查询链码 链码的升级 1、安装链码 2、升级链码 3、测试 1、查询 2、调用 3、…

fabric链码的编写-入门

链码的编写 前言:fabric链码的编写较简单&#xff0c;在熟悉了基本结构和相关API之后就可上手编写&#xff0c;但是要多多练习&#xff0c;提高编写链码的速度和正确度。 学习步骤&#xff1a; 1.熟悉链码的基本结构 2.熟练链码相关API 3.练习&#xff0c;练习&#xff0c…

Hyperledger Fabric 链码

懂哪写哪&#xff0c;随时补充 链码结构 链码API 链码在开发过程中需要实现链码接口&#xff0c;交易的类型决定了哪个接口函数将会被调用&#xff0c;链码的接口定义如下&#xff1a; type Chaincode interface {Init(stub ChaincodeStubInterface) pb.ResponseInvoke(stu…

fabric2.3链码对比1.4链码小记

最近实验室的项目要部署到fabric2.0以上版本&#xff0c;之前写的都是1.4的链码&#xff0c;现在看2.0版本的链码还是有些不一样的&#xff0c;主要是链码api改了&#xff1a; 前提&#xff1a;如果想在fabric2.0以上环境中还是想用shim和peerAPI的话&#xff1a;也就是&#…

Hyperledger Fabric 链码生命周期

目录 一、什么是链码 二、部署链码 2.1 安装和定义链码 2.1.1 打包智能合约 2.1.2 peer节点安装链码 2.1.3 组织批准链码 2.1.4 将链码提交到通道 2.2 升级链码 总结 一、什么是链码 ChainCode&#xff08;链码&#xff09;是一个程序&#xff0c;用Go、Node.js或Java编…

matlab freeman链码,对Freeman链码分析的角点检测算法

图像中的角点是图像的重要特征, 具有旋转不变性, 决定了图像形状, 可以降低图像信息的存储效率, 在目标跟踪, 目标检测, 图像匹配, 图像轮廓拟合等领域都有重要的应用价值. 近几十年来, 国内外学者提出的图像角点检测算法[, 各有各的优缺点, 大致可分为三大类: 基于灰度强度的角…

Fabric链码升级

一、修改链码&#xff0c;上传 二、打包链码 1、设置组织1环境变量 export PATH${PWD}/../bin:$PATH export FABRIC_CFG_PATH$PWD/../config/ # Environment variables for Org1 export CORE_PEER_TLS_ENABLEDtrue export CORE_PEER_LOCALMSPID"Org1MSP" export C…

图像特征-链码(Freeman code)

目录 引言链码编程实现轮廓提取链码计算 总结 引言 本文介绍了图像的形状特征–链码&#xff0c;以及通过python和opencv实现的链码提取方法。所有opencv的版本为3.4.2&#xff0c;已经移除了直接返回链码的选项。 链码 链码用于描述图像的形状特征&#xff0c;首先需要获得图像…

Java知识扫盲——向上转型(类向上转型、接口向上转型)以及向上转型的优势、灵活运用

目录 普通类示例 抽象类的向上转型&#xff0c; 接口向上转型&#xff1a; 作用&#xff1a;使用向上转型可以&#xff0c;提高代码的简洁性、灵活性、适用性。 普通类示例 父类&#xff1a; package 普通类向上转型;public class Father {public int age 48;public void…

java 向上转换_java的向上转型总结

在《think of java》中对向上转型有着如下的描述 看完之后很蒙圈&#xff0c;所以自己在网上找了一些描述&#xff0c;并自己做了简单的总结 简单的例子 class A{ public void A1(){ System.out.println("父类方法1"); } public void A2(){ System.out.println("…

JAVA中多态以及向上转型向下转型、重写的讲解

重写 重写(override)&#xff1a;也称为覆盖。重写是子类对父类非静态、非private修饰&#xff0c;非final修饰&#xff0c;非构造方法等的实现过程 进行重新编写, 注意&#xff01;&#xff01;&#xff01;返回值和形参都不能改变。 重写的好处在于子类可以根据需要&#x…

JAVA中的向上转型和向下转型

一、向上转型和向下转型 向上转型和向下转型是在JAVA继承操作中用到的东西&#xff0c;在讲到转型之前我们需要认识到继承过程中的对象类型转换&#xff0c;这种转换有两个特点&#xff1a; 1.这是继承过程中发生的操作 2.新类是现有类的一种类型。这种说法主要是因为现有类的方…

java转型 内存_Java向上转型及内存分析

学习设计模式的时候&#xff0c;发现很多模式都用到了向上转型(eg. 工厂方法)。而我对向上转型(upcasting)的机制并不十分熟悉。这篇文章将深入分析向上转型的机制、内存分析。 概念 先从几个基本概念开始&#xff1a; 1. Java中的引用类型(reference type) Java中的数据类型分…