|
1.编写你的链码
可参考fabric-samples中提供的链码进行修改。
2.配置链码依赖
把要部署的链码文件夹放在fabric-samples下。如我的链码所在路径为
echo ${PWD}
/home/yellow/go/src/github.com/hyperledger/fabric/scripts/fabric-samples/task-transfer-basic/chaincode-go/chaincode
从参考示例中复制go.mod和go.sum文件,编辑go.mod中的依赖以适应你的需要。go.mod的内容如下所示
module github.com/hyperledger/fabric-samples/task-transfer-basic/chaincode-go
go 1.14
require (
github.com/golang/protobuf v1.3.2
github.com/hyperledger/fabric-chaincode-go v0.0.0-20200424173110-d7076418f212
github.com/hyperledger/fabric-contract-api-go v1.1.0
github.com/hyperledger/fabric-protos-go v0.0.0-20200424173316-dd554ba3746e
github.com/stretchr/testify v1.5.1
)进入go.mod所在路径(/go/src/http://github.com/hyperledger/fabric/scripts/fabric-samples/task-transfer-basic/chaincode-go),输入下面的代码将会生成一个vendor文件夹,里面有链码所需的包
GO111MODULE=on go mod vendor3.配置CouchDB
修改位于fabric-samples下的config文件夹中的core.yaml文件,修改616行中stateDatabase字段的值为CouchDB
4.配置couchDB索引
编辑META-INF/statedb/couchdb/indexes路径下的json格式的索引文件,文件格式如下
{"index":{"fields":["username"]},"ddoc":"indexUsernameDoc", "name":"indexUsername","type":"json"}其中,ddoc为可选项,但仍建议加上此项,因为后续查询时可指定此次查询选用的索引且可用于判断少量数据下查询使用索引与否。fields为查询涉及到的字段,type字段仅支持json格式。
关于索引的查找效率:
- 若实际查询字段包含且多于索引中列出的字段,则会在索引的基础上查询整个表的额外字段,这会降低查询效率;
- 若实际查询字段少于索引中列出的字段,则无法使用此索引进行查询。
关于索引的增加删除:
- 可使用fauxton(即couchDB提供的图形界面),登录用户名和密码分别为admin、adminpw(可在test-network/docker/docker-compose-couch.yaml文件中查看和修改)
- 可使用curl命令(详情请查看参考资料部分)
5.启动测试网络
# 进入测试网络路径
cd ../../test-network
# 确保上次测试网络已关闭
./network.sh down
# 启动网络、创建频道mychannel并设置状态数据库为couchDB
./network.sh up createChannel -s couchdb6.设置Logspout(可选)
Logspout能将来自不同docker容器的输出流汇总到一个窗口下,对调试错误很有帮助。fabric-samples中的commercial-paper样例中就包含有安装并配置logspout的脚本,你可以通过files图形化界面或者执行下面的代码将它从fabric-samples/commercial-paper/organization/digibank/configuration/cli/路径下复制到test-network下。
# 执行前确保你当前在test-network路径下
cp ../commercial-paper/organization/digibank/configuration/cli/monitordocker.sh .
# 运行脚本以启动logspout
./monitordocker.sh net_test7.打包链码、安装链码并实例化链码
export PATH=${PWD}/../bin:$PATH
export FABRIC_CFG_PATH=$PWD/../config/
# 检查peer版本(可选)
peer version
# 打包链码,会在test-network下生成一个tar.gz文件
peer lifecycle chaincode package basic.tar.gz --path ../task-transfer-basic/chaincode-go/ --lang golang --label basic_1.0
# 设置环境变量以使用组织1管理员的身份
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
# 在组织1的peer节点上安装链码
peer lifecycle chaincode install basic.tar.gz
# 设置环境变量以使用组织2管理员的身份
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:9051
# 在组织2的peer节点上安装链码
peer lifecycle chaincode install basic.tar.gz
# 查询频道上已安装的链码
peer lifecycle chaincode queryinstalled
# 将查询得到的PACKAGE_ID设置会环境变量以方便后续使用(注意:你的PACKAGE_ID可能与此处不同)
export CC_PACKAGE_ID=basic_1.0:a33a85fa1e534d64415582d6d82ab122249f1e92a142f2017c6365be0e3f9f68
# 组织2批准链码定义(当前身份仍为组织2的管理员)
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name basic --version 1.0 --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
# 设置环境变量以使用组织1管理员的身份
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_ADDRESS=localhost:7051
# 组织1批准链码定义
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name basic --version 1.0 --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
# 查询链码定义是否已批准(--output json表示以json格式输出)
peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name basic --version 1.0 --sequence 1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --output json
# 通过链码
peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name basic --version 1.0 --sequence 1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
# 查询链码是否通过
peer lifecycle chaincode querycommitted --channelID mychannel --name basic --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
# 检查couchDB的索引是否部署
docker logs peer0.org1.example.com 2>&1 | grep "CouchDB index"8.调用链码
请按照你自己编写的链码,参考教程文档的命令格式或附件中的taskchaincode.sh中的内容进行。
9.可能遇到的问题
9.1无法关闭测试网络
在配置logspout工具收集docker输出信息后关闭网络时可能会遇到网络无法关闭的问题,报错信息如下
$ ./network.sh down
Stopping network
Removing network net_test
ERROR: error while removing network: network net_test id 5b49638dcf4952cf4a74ecd4a16f616c156e39851417935520912c3bf5c70bbd has active endpoints
Removing network net_test
ERROR: error while removing network: network net_test id 5b49638dcf4952cf4a74ecd4a16f616c156e39851417935520912c3bf5c70bbd has active endpoints解决方案为
# 检查测试网络中net_test中仍处于活动状态的端点名称(可选,检查不检查都是logspout在搞鬼,这里是为了帮我们定位出错原因)
docker network inspect net_test
# 断开logspout与测试网络net_test的连接
docker network disconnect -f net_test logspout9.2执行taskchaincode.sh时出现query错误
执行invoke和query命令仍有问题,但你可以注释掉此脚本的InitTask调用链码的后半部分,以实现快速安装和实例化链码(注意package_ID)。出现错误的真正原因我还没想明白,欢迎讨论。
10.参考资料
Deploying a smart contract to a channel
Using CouchDB
CouchDB Configuration
Unable to remove network "has active endpoints" #17217
11.附件
压缩包中包含链码文件夹和taskchaincode.sh,其中task-transfer-basic应放在fabric-samples下,此文件夹中的taskchaincode.sh可放在test-network下方便使用。
# bring down the latest network
./network.sh down
# bring up the testwork and create mychannel with couchDB
./network.sh up createChannel -s couchdb
export PATH=${PWD}/../bin:$PATH
export FABRIC_CFG_PATH=$PWD/../config/
# check peer version
peer version
# package the chaincode as basic.tar.gz
peer lifecycle chaincode package basic.tar.gz --path ../task-transfer-basic/chaincode-go/ --lang golang --label basic_1.0
# use org1' admin certificate
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
# install chaincode on org1's peer
peer lifecycle chaincode install basic.tar.gz
# use org2' admin certificate
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:9051
# install chaincode on org2's peer
peer lifecycle chaincode install basic.tar.gz
# query chaincodes installed on the channel
peer lifecycle chaincode queryinstalled
# set package_ID enviroment variables for subsequent use
export CC_PACKAGE_ID=basic_1.0:a33a85fa1e534d64415582d6d82ab122249f1e92a142f2017c6365be0e3f9f68
# Approve for org2
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name basic --version 1.0 --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
# use org1' admin certificate
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_ADDRESS=localhost:7051
# Approve for org1
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name basic --version 1.0 --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
# check if the chaincode is aprroved
peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name basic --version 1.0 --sequence 1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --output json
# commit the chaincode
peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name basic --version 1.0 --sequence 1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
# check if the chaincode is committed
peer lifecycle chaincode querycommitted --channelID mychannel --name basic --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
# verify index was deployed
docker logs peer0.org1.example.com 2>&1 | grep "CouchDB index"
# init the ledger to create some tasks
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"initLedger","Args":[]}'
# query all tasks in mychannel
peer chaincode query -C mychannel -n basic -c '{"Args":["getAllTasks"]}'
# query tasks owned by task_poster6
peer chaincode query -C mychannel -n basic -c '{"Args":["QueryTasksByUsername", "task_poster6"]}'
# query task1's info
peer chaincode query -C mychannel -n basic -c '{"Args":["ReadTask", "task1"]}'
# invoke to transfer task1 to task_poster6
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"TransferTask","Args":["task1", "task_poster6"]}'
# re-query task1's info to check if task's owner has changed
peer chaincode query -C mychannel -n basic -c '{"Args":["ReadTask", "task1"]}'
# re-query tasks owned by task_poster6
peer chaincode query -C mychannel -n basic -c '{"Args":["QueryTasksByUsername", "task_poster6"]}'
# querry the history of task1
peer chaincode query -C mychannel -n basic -c '{"Args":["GetTaskHistory", "task1"]}'
# check if QueryTasks function working well
peer chaincode query -C mychannel -n basic -c '{"Args":["QueryTasks", "{\"selector\":{\"username\":\"task_poster6\"}, \"use_index\":[\"_design/indexUsernameDoc\", \"indexUsername\"]}"]}'
# invoke to create another 6 tasks for task_poster6 for later QueryTasksWithPagination
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"CreateTask","Args":["task7", "task_poster6","poster","EMNIST_NN","a test sample of the combination of federated learning and blockchain","EMNIST","NN","10","5","15","true"]}'
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"CreateTask","Args":["task8", "task_poster6","poster","EMNIST_NN","a test sample of the combination of federated learning and blockchain","EMNIST","NN","10","5","15","true"]}'
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"CreateTask","Args":["task9", "task_poster6","poster","EMNIST_NN","a test sample of the combination of federated learning and blockchain","EMNIST","NN","10","5","15","true"]}'
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"CreateTask","Args":["task10", "task_poster6","poster","EMNIST_NN","a test sample of the combination of federated learning and blockchain","EMNIST","NN","10","5","15","true"]}'
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"CreateTask","Args":["task11", "task_poster6","poster","EMNIST_NN","a test sample of the combination of federated learning and blockchain","EMNIST","NN","10","5","15","true"]}'
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"CreateTask","Args":["task12", "task_poster6","poster","EMNIST_NN","a test sample of the combination of federated learning and blockchain","EMNIST","NN","10","5","15","true"]}'
# re-query tasks owned by task_poster6
peer chaincode query -C mychannel -n basic -c '{"Args":["QueryTasksByUsername", "task_poster6"]}'
# Rich Query with index name explicitly specified and a page size of 3:
# return task1, task10, task11
peer chaincode query -C mychannel -n basic -c '{"Args":["QueryTasksWithPagination", "{\"selector\":{\"username\":\"task_poster6\"}, \"use_index\":[\"_design/indexUsernameDoc\", \"indexUsername\"]}","3",""]}'
# use the bookmark the last querry returned this time
# return task12, task6, task7
peer chaincode query -C mychannel -n basic -c '{"Args":["QueryTasksWithPagination", "{\"selector\":{\"username\":\"task_poster6\"}, \"use_index\":[\"_design/indexUsernameDoc\", \"indexUsername\"]}","3","g1AAAABIeJzLYWBgYMpgSmHgKy5JLCrJTq2MT8lPzkzJBYqzlSQWZxsagmQ5YLI5QHFGkCQPSDK-IL-4JLXILCsLAMeaFJg"]}'
# return task8, task9
peer chaincode query -C mychannel -n basic -c '{"Args":["QueryTasksWithPagination", "{\"selector\":{\"username\":\"task_poster6\"}, \"use_index\":[\"_design/indexUsernameDoc\", \"indexUsername\"]}","3","g1AAAABHeJzLYWBgYMpgSmHgKy5JLCrJTq2MT8lPzkzJBYqzliQWZ5uDJDlgkjlAYUaQHA9ILr4gv7gktcgsKwsAt5IUbA"]}'
# return null
peer chaincode query -C mychannel -n basic -c '{"Args":["QueryTasksWithPagination", "{\"selector\":{\"username\":\"task_poster6\"}, \"use_index\":[\"_design/indexUsernameDoc\", \"indexUsername\"]}","3","g1AAAABHeJzLYWBgYMpgSmHgKy5JLCrJTq2MT8lPzkzJBYqzliQWZ1uCJDlgkjlAYUaQHA9ILr4gv7gktcgsKwsAt94Ubg"]}'
# disconnect logspout(if you did setup logspout, this command will disconnect the connection between logspout and net_test network to get ready for the network to bring down)
# docker network disconnect -f net_test logspout
# bring down the network
# ./network.sh downtask-transfer-basic.zip上传失败,以后再放。 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|