一、前置环境安装
1 安装pip,curl,git工具包
2 安装docker
3 安装docker-compose
4 GO语言依赖
二、Fabric2.2 开发环境
1 创建文件夹并拉取 fabric 源码
2 下载实验所需样例及 docker 镜像
3 网络环境测试
4 问题
三、测试自己的链码
1 启动 Fabric 网络
2 部署链码
3 调用结果
WIN10 Ubuntu20.04 Fabric 2.0安装部署
虚拟机配置:
一、前置环境安装
1 安装pip,curl,git工具包
在安装相关工具包前更新所需软件,否则安装时部分包会安装失败。
更新指令:sudoapt-getupdate 和 sudoapt-getupgradesudo apt install gitsudo apt install curlsudo apt install python-pippip install --upgrade pip
2 安装docker
安装 docker前为确保docker版本先卸载原有 docker 版本 ,重新安装
卸载指令:sudo apt-get remove docker docker-engine docker.io安装 docker 指令:sudo apt install docker.io
查看 docker 版本: docker -v
重启服务
sudo systemctl daemon-reloadsudo systemctl restart docker
3 安装docker-compose
安装指令:sudo apt install docker-compose查看指令:docker-compose -v
允许其他用户执行 compose 相关命令
执行指令:sudo chmod +x /usr/share/doc/docker-compose
4 GO语言依赖
安装依赖包:sudo apt install libtool libltdl-dev
下载GO语言安装包并解压安装,指令下载的是go1.14.6
安装指令:wget https://studygolang.com/dl/golang/go1.14.6.linux-amd64.tar.gz解压指令:sudo tar -xzvf go1.14.6.linux-amd64.tar.gz -C /usr/local/
配置环境变量 ,加在文件末尾
配置指令:sudo vim/etc/profile export PATH= $PATH:/usr/local/go/binexport GOROOT= /usr/local/goexport GOPATH= $HOME/goexport PATH= $PATH:$GOPATH/bin:$GOPATH/bin
错误:vim:command not found
缺少 vim 工具,安装指令:sudo apt-get install vim-gtk,类似错误同样处理。
生效指令:source /etc/profile检查是否安装成功:go version
重启虚拟机,检查环境
GO 语言:go1.14.6linux/amd64
Docker-compose:docker-composeversion1.25.0
Docker:dockerversion19.03.8
二、Fabric2.2 开发环境
1 创建文件夹并拉取 fabric 源码
mkdir -p go/src/github.com/hyperledger/cd go/src/github.com/hyperledger/安装指令:git clone "https://github.com/hyperledger/fabric.git"cd fabric/cd scripts/
2 下载实验所需样例及 docker 镜像
可以直接运行sudo./bootstrap.sh下载官方样例和所需docker镜像,但是运行特别慢,失败可以重新运行,或者修改 bootstrap.sh 脚本运行:
vim ~/ go/src/github.com/hyperledger/fabric/scripts/bootstrap.sh
图片左边改成右边,:wq!保存退出
回到原来的文件夹运行指令:sudo./bootstrap.sh
修改后的脚本下载时只会进行镜像拉取,因此需要手动下载 fabric-samples 及二进制文件。
cd ~/ go/src/github.com/hyperledger/fabric/scriptsgit clone https://github.com/hyperledger/fabric-samples.git
这里很容易因为网络问题下载不全镜像,之后的运行会出问题,如果出问题,多运行几次,下全缺失的镜像
下好 fabric-samples 文件后下载二进制文件并解压。
wget https://github.com/hyperledger/fabric/releases/download/v2.2.1/hyperledger-fabric-lin ux-amd64-2.2.1.tar.gzsudo tar -xzvf hyperledger-fabric-lin ux-amd64-2.2.1.tar.gz
3 网络环境测试
进入管理员权限,不会频繁出环境变量的错误
启动 fabric 网络:sudo ./network.sh up
在网络上建立通道:sudo ./network.sh createChannel
在通道上启动链码:sudo ./network.sh deployCC
启动链码后在 test-network 目录上进行环境变量设置并使之生效。
source /etc/profile
执行查询指令:peer chaincode query -C mychannel -n fabcar -c '{ "Args":["queryAllCars"]}'
查询出现错误后进入 fabcar 文件执行./startFabric.sh,重新启动网络再查询
cd /opt/gopath/src/github.com/hyperledger/fabric/scripts/famples-samples/fabcarsudo ./startFabric.sh
关闭网络:./network.sh down
4 问题
解决办法:对 go 换源,之后重新启动链码。
执行指令:go env -w GO111MODULE=on go env -w GOPROXY=https://goproxy.cn,direct
三、测试自己的链码
例子:资产交易平台:
链接里的代码是基于1.4的,需要把开头这个部分替换掉"github.com/hyperledger/fabric-chaincode-go/shim""github.com/hyperledger/fabric-protos-go/peer"
把这里的链码复制到fabcar.go文件里替换保存
1 启动 Fabric 网络
删除运行中的 docker,以免之前实验的遗留部分有所影响,关闭网络。
执行指令:./network.sh down
建立新的测试网络:./network.sh up 和 ./network.sh createChannel。
执行后可创建一个通道 mychannel 和两个组织 Org1,Org2.每个 组织有一个 peer 且已经加入通道中。
2 部署链码
部署链码主要分为四部分:打包链码、安装打包的链码、各组织对链码内容和定义达成一致、向 channel 中提交链码。
1 打包链码
先对链码打包,进入 fabric-samples/chaincode/fabcar/go 文件,使用 go module,查看 go.mod 文件并安装链码依赖包。
链码依赖包安装完成后,回到 test-network 目录。
root权限下cd /home/用户名/go/src/github.com/hyperledger/fabric/scripts/fabric-samples/chaincode/fabcar/gocat go.modGO111MODULE=on go mod vendorcd /home/用户名/go/src/github.com/hyperledger/fabric/scripts/fabric-samples/test-network
使用 peerCLI 来打包链码,添加 Peer 到 CLI 命令路径中,并设置相关路径, 设置完成后查看 peer 版本来确认是否安装成功。
export PATH=${ PWD}/../bin:$PATHexport FABRIC_CFG_PATH=$PWD/../config/peer version
打包链码:peer lifecycle chaincode package fabcar.tar.gz --path../chaincode/fabcar/go/ --langgolang --labelfabcar_1
2 安装打包的链码
首先在 Org1 的 peer 上安装,可以通过设置环境变量来指定 peer 操作的是 Org1。
export CORE_PEER_TLS_ENABLED=trueexport CORE_PEER_LOCALMSPID="Org1MSP"export CORE_PEER_TLS_ROOTCERT_FILE=${ PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crtexport CORE_PEER_MSPCONFIGPATH=${ PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/mspexport CORE_PEER_ADDRESS=localhost:7051
peer lifecycle chaincode install fabcar.tar.gz
同样,在 Org2 的 peer 上安装链码:
export CORE_PEER_LOCALMSPID="Org2MSP"export CORE_PEER_TLS_ROOTCERT_FILE=${ PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crtexport CORE_PEER_MSPCONFIGPATH=${ PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/mspexport CORE_PEER_ADDRESS=localhost:9051peer lifecycle chaincode install fabcar.tar.gz
输出的结果是一样的
3 审议链码定义
查找 peer 上的 packageID 并将其保存到环境变量中。
peer lifecycle chaincode queryinstalledexport CC_PACKAGE_ID=______________________________//这里是刚查出来的id
用 Org1 和 Org2 分别审议链码,这里环境变量还在Org2下
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name fabcar --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
再审议Org1
//回到org1的环境export CORE_PEER_LOCALMSPID="Org1MSP"export CORE_PEER_MSPCONFIGPATH=${ PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/mspexport CORE_PEER_TLS_ROOTCERT_FILE=${ PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crtexport CORE_PEER_ADDRESS=localhost:7051peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name fabcar --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
4 向 Channel 中提交链码定义
检查一下哪些成员同意了链码定义
peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name fabcar --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
通道内所有组织都同意了链码定义之后,链码定义就可以提交到 channel 中。
peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name fabcar --version 1.0 --sequence 1 --tls true --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.examp le.com/tls/ca.crt//确认是否提交到通道上peer lifecycle chaincode querycommitted
3 调用结果
之前用的root权限,所以每次注册的操作都要对相关的安全证书定义,注册的代码比较长,查询的不需要
//用户1注册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 fabcar --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 '{ "Args":["userRegister", "user1", "user1"]}'//资产1登记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 fabcar --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 '{ "Args":["assetEnroll", "asset1", "asset1", "metadata", "user1"]}'//用户2注册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 fabcar --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 '{ "Args":["userRegister", "user2", "user2"]}'//1资产转让2peer 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 fabcar --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 '{ "Args":["assetExchange", "user1", "asset1", "user2"]}'//用户1注销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 fabcar --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 '{ "Args":["userDestroy", "user1"]}'//用户1查询sudo peer chaincode query -C mychannel -n token -c '{ "Args":["queryUser", "user1"]}'//资产1查询sudo peer chaincode query -C mychannel -n token -c '{ "Args":["queryAsset", "asset1"]}'//用户2查询sudo peer chaincode query -C mychannel -n token -c '{ "Args":["queryUser", "user2"]}'//资产交易记录查询sudo peer chaincode query -C mychannel -n token -c '{ "Args":["queryAssetHistory", "asset1"]}'sudo peer chaincode query -C mychannel -n token -c '{ "Args":["queryAssetHistory", "asset1", "all"]}'