相干试验源码已上传:https://github.com/wefantasy/...

前言

在基于truffle框架实现以太坊公开拍卖智能合约中咱们曾经实现了以太坊智能合约的编写及部署,但其工作形式注定其只能利用于无限的业务场景中。相比之下,基于超级账本的Fabric具备高可扩展性和高可定制性,可能利用在更为简单的商业场景中,但Fabric技术波及很多新的概念,源代码跟新速度快且各版本间兼容性差,对初学者很不敌对。为了使可能疾速把握Fabric,本文基于其目前最新的2.4版本搭建了一套区块链运行环境,并在此之上部署了官网示例chaincode并对其进行交互调试,最终整个环境及示例代码可能失常运行且得出预期后果。

环境搭建

网上简直所有的Fabric教程都是基于Ubuntu环境而不是Windows,其起因次要是Fabric的运行须要的Docker环境在Windows下体现不佳,此外Fabric许多官网文档也是基于Ubuntu纂写,在windows下运行可能会遇到难以预估的bug。本来为了不便前期部署至公网服务器想在CentOS上搭建环境,但因为CentOS8进行保护,且CentOS Stream应用体验颇差,于是最终抉择了Debian零碎。
本环境各零碎、软件版本如下:

零碎、软件版本
VMware Pro16.0.0
Debiandebian-11.2.0-amd64-DVD-1.iso
git2.30.2
curl7.74.0
docker20.10
golanggo1.17.8
jqjq-1.6
fabric2.4.0
fabric-ca1.5.2
fabric-samples[v2.3.0]()

本环境各Docker镜像版本如下:

镜像版本
hyperledger/fabric-tools2.4
hyperledger/fabric-peer2.4
hyperledger/fabric-orderer2.4
hyperledger/fabric-ccenv2.4
hyperledger/fabric-baseos2.4
hyperledger/fabric-ca1.5
正告:倡议Fabric所有试验过程皆在root权限下进行,否则在sudo权限切换的过程中会呈现很多环境变量的问题。

杂项装置

  1. 装置最新版本Git

    apt install git
  2. 装置最新版本cURL

    apt install curl
  3. 装置Golang
  4. 装置jq

    apt install jq

    装置Fabric

    官网脚本装置

    为了帮忙开发者疾速搭建Fabric环境,官网创立了一个Fabric环境搭建的批处理工具bootstrap.sh,能够通过该工具间接装置环境:

    wget https://raw.githubusercontent.com/hyperledger/fabric/master/scripts/bootstrap.shchmod +x bootstrap.sh./bootstrap.sh

    不出意外的话会看见脚本顺利的环境装置过程:

手动装置

当然,间接应用官网脚本不出意外的话必定会出意外(网络起因),在此咱们能够通过手动装置须要的各项环境。

  1. 装置fabric-samples
    fabric-samplesFabric的官网Demo汇合,其外部蕴含多个示例,每个示例有GolangJavaScripttypescriptJava的链码实现,并且这些链码能够间接部署到对应的Fabric上,对初学者很有帮忙。fabric-samples装置非常简单,应用git clone git@github.com:hyperledger/fabric-samples.git将我的项目源码克隆到本地即可,若始终失败也能够间接在release中下载对应版本的压缩包。
  2. 装置Fabric
    Fabric是联盟链的外围开发工具,蕴含了咱们开发、编译、部署过程中的所有命令。
  3. 下载fabric 2.4.0并解压

    wget https://github.com/hyperledger/fabric/releases/download/v2.4.0/hyperledger-fabric-linux-amd64-2.4.0.tar.gzmkdir /usr/local/fabrictar -xzvf hyperledger-fabric-linux-amd64-2.3.2.tar.gz -C /usr/local/fabric
  4. 下载fabric-ca 1.5.2并解压

    wget https://github.com/hyperledger/fabric-ca/releases/download/v1.5.2/hyperledger-fabric-ca-linux-amd64-1.5.2.tar.gztar -xzvf hyperledger-fabric-ca-linux-amd64-1.5.2.tar.gzmv bin/* /usr/local/fabric/bin
  5. 设置环境变量,在/etc/profile开端增加

    #Fabricexport FABRIC=/usr/local/fabricexport PATH=$PATH:$FABRIC/bin
  6. 更新环境变量source /etc/profile

    装置Docker

  7. 如果存在则移除旧的版本

    apt remove docker docker-engine docker.io containerd runc
  8. 更新apt索引包并容许其应用HTTPS装置

    apt updateapt install \ apt-transport-https \ ca-certificates \ curl \ gnupg \ lsb-release
  9. 增加Docker官网GPG密钥

    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
  10. 增加Docker仓库

    echo \"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \$(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
  11. 装置Docker引擎

    apt updateapt install docker-ce docker-ce-cli containerd.io
  12. 装置docker-compose

    apt install docker-compose

    装置Docker镜像依赖

    Fabric相干镜像均能够在DockerHub官网镜像网站进行下载,搜寻须要的镜像则可获取装置办法,本试验用到的所有镜像为:

    docker pull hyperledger/fabric-tools:2.4docker pull hyperledger/fabric-peer:2.4docker pull hyperledger/fabric-orderer:2.4docker pull hyperledger/fabric-ccenv:2.4docker pull hyperledger/fabric-baseos:2.4docker pull hyperledger/fabric-ca:1.5

    应用docker images命令查看装置实现后镜像:

    hyperledger/fabric-tools     2.4       625237d887db   4 weeks ago    473MBhyperledger/fabric-peer      2.4       ee643d889779   4 weeks ago    62.3MBhyperledger/fabric-orderer   2.4       df64446ac2df   4 weeks ago    37.3MBhyperledger/fabric-ccenv     2.4       da4f00cb576a   4 weeks ago    517MBhyperledger/fabric-baseos    2.4       0287ebf8aaf3   4 weeks ago    6.94MBhyperledger/fabric-ca        1.5       4ea287b75c63   6 months ago   69.8MB

    示例代码中应用的镜像标签都为latest,但如果在pull时间接抉择latest可能会报错,因而咱们在下面镜像拉取实现后手动应用以下命令为镜像打上latest标签:

    # docker tag IMAGEID(镜像id) REPOSITORY:TAG(仓库:标签)docker tag 625237d887db hyperledger/fabric-tools:latestdocker tag ee643d889779 hyperledger/fabric-peer:latestdocker tag df64446ac2df hyperledger/fabric-orderer:latestdocker tag da4f00cb576a hyperledger/fabric-ccenv:latestdocker tag 0287ebf8aaf3 hyperledger/fabric-baseos:latestdocker tag 4ea287b75c63 hyperledger/fabric-ca:latest

    最终的镜像为:

运行测试

启动fabric网络

  1. 进入fabric-sample的test-network目录

    cd fabric-samples/test-network
  2. 运行./network.sh up 启动网络

    Creating network "fabric_test" with the default driverCreating volume "docker_orderer.example.com" with default driverCreating volume "docker_peer0.org1.example.com" with default driverCreating volume "docker_peer0.org2.example.com" with default driverCreating peer0.org1.example.com ... doneCreating orderer.example.com    ... doneCreating peer0.org2.example.com ... doneCreating cli                    ... doneCONTAINER ID   IMAGE                               COMMAND             CREATED                  STATUSPORTS         NAMES7738c1e84751   hyperledger/fabric-tools:latest     "/bin/bash"         Less than a second ago   Up Less than a second                   cli1f24de2c6cd5   hyperledger/fabric-peer:latest      "peer node start"   2 seconds ago            Up Less than a second   0.0.0.0:9051->9051/tcp, :::9051->9051/tcp, 0.0.0.0:19051->19051/tcp, :::19051->19051/tcp                peer0.org2.example.combfc48b20360c   hyperledger/fabric-orderer:latest   "orderer"           2 seconds ago            Up Less than a second   0.0.0.0:7050->7050/tcp, :::7050->7050/tcp, 0.0.0.0:7053->7053/tcp, :::7053->7053/tcp, 0.0.0.0:17050->17050/tcp, :::17050->17050/tcp   orderer.example.comb9a61fdaf47a   hyperledger/fabric-peer:latest      "peer node start"   2 seconds ago            Up Less than a second   0.0.0.0:7051->7051/tcp, :::7051->7051/tcp, 0.0.0.0:17051->17051/tcp, :::17051->17051/tcp                peer0.org1.example.com

最终呈现以上输入日志则示意网络启动胜利,每个退出Fabric网络的Node和User都须要隶属于某个组织,以上网络中蕴含了两个平行组织————peer0.org1.example.compeer0.org2.example.com,它还包含一个作为ordering service保护网络的orderer.example.com

创立channel

上节曾经在机器上运行了peer节点和orderer节点,当初能够应用network.sh为Org1和Org2之间创立channel。channel是特定网络成员之间的公有通道,只能被属于该通道的组织应用,并且对网络的其余成员是不可见的。每个channel都有一个独自的区块链账本,属于该通道的组织能够让其下peer退出该通道,以让peer可能存储channel上的帐本并验证账本上的交易。
应用以下命令创立自定义通道testchannel:

./network.sh createChannel -c testchannel

部署chaincode

倡议部署操作全副在root账户下进行,否则可能产生未知谬误,以下流程为笔者在非root用户下所遇问题,最终重建虚拟机全副指令在root账户下才实现部署。

创立通道后,您能够开始应用智能合约与通道账本交互。智能合约蕴含治理区块链账本上资产的业务逻辑,由成员运行的应用程序网络能够在账本上调用智能合约创立,更改和转让这些资产。能够通过./network.sh deployCC命令部署智能合约,但本过程可能会呈现很多问题。
应用以下命令部署chaincode:

./network.sh deployCC -c testchannel -ccn basic -ccp ../asset-transfer-basic/chaincode-go -ccl go

此命令执行后可能会呈现谬误:scripts/deployCC.sh: line 114: log.txt: Permission denied,很显著这是权限有余所致,加上sudo试试:

./network.sh deployCC -c testchannel -ccn basic -ccp ../asset-transfer-basic/chaincode-go -ccl go

加上sudo后呈现新的谬误:deployCC.sh: line 59: go: command not found。查看本用户go命令可用,查看root用户go命令可用,单单sudo后不能用。查阅材料后发现这是因为linux零碎为了平安,限度在应用sudo时会清空自定义的环境变量,最简略的解决办法是在/etc/sudoers文件中间接将该限度正文1

加上正文后从新执行上条命令,又呈现了新的谬误:

go: github.com/golang/protobuf@v1.3.2: Get "https://proxy.golang.org/github.com/golang/protobuf/@v/v1.3.2.mod": dial tcp 172.217.160.81:443: i/o timeout

很显著这是因为本地网络无法访问proxy.golang.org所致,在命令行输出go env -w GO111MODULE=on && go env -w GOPROXY=https://goproxy.cn,direct命令配置国内代理2后再次执行。令人意外的是谬误不变,设置的代理没有失效?手动应用go get github.com/golang/protobuf手动下载安装后再次运行谬误还是不变,此时查看本地GOPATH目录下已有github.com/golang/protobuf包,为什么没有辨认到?此时眉头一皱;计上心来,应用go env查看GOPATH环境变量,发现与本地用户不统一,原来sudo命令会应用rootgo环境变量,而之前设置的代理、下载的包都只能在本地用户下失效,因而这个问题最终的解决方案是间接切换到root用户下重新配置go代理并运行。胜利运行后可看见如下后果:

2021-08-15 00:45:54.064 PDT [chaincodeCmd] ClientWait -> INFO 001 txid [ebeb8df6904f45b81fb30714f7eecb30b4bbfd32f4acc809f34f7c660e396eb8] committed with status (VALID) at localhost:70512021-08-15 00:45:54.144 PDT [chaincodeCmd] ClientWait -> INFO 002 txid [ebeb8df6904f45b81fb30714f7eecb30b4bbfd32f4acc809f34f7c660e396eb8] committed with status (VALID) at localhost:9051Chaincode definition committed on channel 'testchannel'Using organization 1Querying chaincode definition on peer0.org1 on channel 'testchannel'...Attempting to Query committed status on peer0.org1, Retry after 3 seconds.+ peer lifecycle chaincode querycommitted --channelID testchannel --name basic+ res=0Committed chaincode definition for chaincode 'basic' on channel 'testchannel':Version: 1.0, Sequence: 1, Endorsement Plugin: escc, Validation Plugin: vscc, Approvals: [Org1MSP: true, Org2MSP: true]Query chaincode definition successful on peer0.org1 on channel 'testchannel'Using organization 2Querying chaincode definition on peer0.org2 on channel 'testchannel'...Attempting to Query committed status on peer0.org2, Retry after 3 seconds.+ peer lifecycle chaincode querycommitted --channelID testchannel --name basic+ res=0Committed chaincode definition for chaincode 'basic' on channel 'testchannel':Version: 1.0, Sequence: 1, Endorsement Plugin: escc, Validation Plugin: vscc, Approvals: [Org1MSP: true, Org2MSP: true]Query chaincode definition successful on peer0.org2 on channel 'testchannel'Chaincode initialization is not required

合约交互

在装置fabric中咱们曾经设置了fabric可执行文件的环境变量,需保障能够胜利在test-network目录下应用peer命令。

  1. 设置FABRIC_CFG_PATH变量,其下需蕴含core.yaml文件

    export FABRIC_CFG_PATH=$PWD/../config/# export FABRIC_CFG_PATH=/usr/local/fabric/config/
  2. 设置其它Org1组织的变量依赖

    # Environment variables for Org1# CORE_PEER_TLS_ROOTCERT_FILE和CORE_PEER_MSPCONFIGPATH环境变量指向Org1的organizations文件夹中的身份证书。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
  3. 初始化chaincode

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

  4. 查问账本资产列表

    peer chaincode query -C testchannel -n basic -c '{"Args":["GetAllAssets"]}'

  5. 批改账本资产

    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 testchannel -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":"TransferAsset","Args":["asset6","Christopher"]}'

  6. 敞开网络

    ./network.sh down

    该命令将进行并删除节点和链码容器、组织加密资料、删除之前运行的通道我的项目和docker卷,并从Docker Registry移除链码镜像。

因为asset-transfer (basic)链码的背书策略须要交易同时被Org1Org2签名,所以链码调用指令须要应用--peerAddresses标签来指向peer0.org1.example.compeer0.org2.example.com;因为网络的TLS被开启,指令也须要用--tlsRootCertFiles标签指向每个peer节点的TLS证书。

参考


  1. qq_JWang_03215367. 解决command not found 报错. 慕课. [2018-07-31] ↩
  2. 沐沐子枫. failed to normalize chaincode path: 'go list' failed with: go. 博客园. [2020-11-27] ↩