Hyperledger Fabric 03 超详细图解——通过Fabric测试网络深入理解联盟链
区块链 | Hyperledger Fabric 03 超详细图解——通过Fabric测试网络深入理解联盟链 - 墨天轮
导读
超级账本,作为最火热的联盟链技术,得到了广泛地使用,也得到了很多科研人员的青睐。
今天这篇文章,我们一起来安装go环境,并通过测试网络来对联盟链Fabric有更深刻地理解。我们也针对安装过程中出现的一些问题做了详细的说明,并提供解决方案。
让我们一起走进文章,来感受Fabric并深入理解联盟链吧!

1
说在前面的话
1、预备知识
为了后续大家能够更好地学习,首先我们需要先了解一些相关的基本理论和概念。

区块链 | Hyperledger Fabric 01 超级账本介绍
后续我们也会逐步更新必备的基础概念,大家可以点击阅读原文。详细了解。
2、环境需求
在今天的内容之前,我们需要先检查一下自己的“背包”,才能让接下来的旅途走得更加悠然。
我们在测试网络文件夹打开终端:

1、Docker
首先我们先检查是否安装Docker和Docker compose,命令如下:
docker --versiondocker-compose --version

2、测试网络
然后我们检查测试网络是否存在:
./network.sh -h

上面这个命令是打印帮助文档,把测试网络所有可用的功能都打印出来。
如果这个过程出现问题,大家可以在下面这篇文章查找解决方案:

区块链 | Hyperledger Fabric 02 超详细图解——Fabric2.3.3安装及常见报错解决方案
3、安装go
前面我们没有安装go,这是因为前面我们只是安装配置fabric,go并不是必须的。
现在我们要开始运行链码,即联盟链中的智能合约,官网中给的示例是go语言开发的。如果大家有其他语言的开发经验,如Java,可以跳过这个步骤。
首先我们需要下载go的安装包:
https://studygolang.com/dl
大家也可以在我的公众号【AI与区块链技术】回复go下载。
下载好之后,我们将其解压,然后将其移动到local文件夹:
tar -zxvf go1.17.2.linux-amd64.tar.gzsudo mv go /usr/local/

接下来我们配置一下环境变量,首先我们打开环境变量文件:
sudo gedit ~/.profile
下面的提示是已经完成了更改后的警告:

然后我们在最后添加:
export GOROOT=/usr/local/goexport GOPATH=$HOME/goexport PATH=$GOPATH/bin:$GOROOT/bin:$PATH
然后点击save保存并关闭。

然后我们重新加载一下新的环境变量:
source ~/.profile
接下来我们查看我们安装的版本,检测是否安装成功:
go version

2
运行Fabric案例
1、打开测试网络
这个操作,上一篇文章我们已经讲过,执行过程中可能会出现问题,如果遇到问题,大家可以查阅上一篇文章,在这里,我们只说流程。报错及解决方案在这里就不赘述了。
首先我们先切换到我们的fabric-samples下的 test-network 文件夹,用这里的代码来测试网络。
cd fabric-samples/test-network
或者我们可以直接在test-network文件夹下打开终端,在这个文件夹下,我们能找到一个network.sh文件。我们使用如下命令运行这个文件,用以打开我们的网络:
./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 orderer.example.com ... doneCreating peer0.org1.example.com ... doneCreating peer0.org2.example.com ... doneCreating cli ... doneCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES23bf079fc362 hyperledger/fabric-tools:latest "/bin/bash" 3 seconds ago Up Less than a second cli4170f2a781a1 hyperledger/fabric-peer:latest "peer node start" 16 seconds ago Up 3 seconds 0.0.0.0:7051->7051/tcp, :::7051->7051/tcp, 0.0.0.0:17051->17051/tcp, :::17051->17051/tcp peer0.org1.example.comf1cfa1e57865 hyperledger/fabric-peer:latest "peer node start" 16 seconds ago Up 3 seconds 0.0.0.0:9051->9051/tcp, :::9051->9051/tcp, 7051/tcp, 0.0.0.0:19051->19051/tcp, :::19051->19051/tcp peer0.org2.example.com81dcce22fc01 hyperledger/fabric-orderer:latest "orderer" 16 seconds ago Up 3 seconds 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.com
下面我们详细说明一下这些内容。
2、查看容器
通过上面的结果,我们发现,一共创建了4个容器,我们可以使用如下命令去查看所有的容器:
docker ps -a

我们将其复制下来,会发现和我们上面的是对应的:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES23bf079fc362 hyperledger/fabric-tools:latest "/bin/bash" 4 minutes ago Up 4 minutes cli4170f2a781a1 hyperledger/fabric-peer:latest "peer node start" 4 minutes ago Up 4 minutes 0.0.0.0:7051->7051/tcp, :::7051->7051/tcp, 0.0.0.0:17051->17051/tcp, :::17051->17051/tcp peer0.org1.example.comf1cfa1e57865 hyperledger/fabric-peer:latest "peer node start" 4 minutes ago Up 4 minutes 0.0.0.0:9051->9051/tcp, :::9051->9051/tcp, 7051/tcp, 0.0.0.0:19051->19051/tcp, :::19051->19051/tcp peer0.org2.example.com81dcce22fc01 hyperledger/fabric-orderer:latest "orderer" 4 minutes ago Up 4 minutes 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.com
这四个容器分别存储不同的节点:
1、其中第一个是客户端节点(cli),客户端节点本质上也是一个对等节点。
2、中间两个是peer节点(对等节点) 用于存储区块链账本并在进行交易之前对其进行验证,同行运行包含业务用于管理区块链账本的智能合约上的业务逻辑;两个对等节点如下:
Org1 (peer0.org1.example.com)Org2 (peer0.org2.example.com)
3、最后一个是排序节点(orderer.example.com),用于维护网络排序服务。
每个节点和用户都必须属于一个网络成员的组织。 在测试网络中,每个组织都只产生一个节点,这一个节点会独立表示一个组织,后面的讲解中,对于概念和理论的讲解我们会使用组织,对代码的说明我们使用节点。Fabric网络成员的所有组织通常称为联盟(consortium)。
与传统公链不同,联盟链Fabric网络需要一个排序服务。对等组织只负责验证交易并将交易块添加到区块链账本,他们不决定交易顺序或包含他们进入新的区块。在分布式网络上,对等组织中的节点经常分布很远且可能具有很大的差异,并且对何时创建事务难以达成共识。也就是说,在交易顺序上达成共识是一个代价高昂的过程,这会为其他对等节点增加开销。排序服务允许对等组织中的节点专注于验证交易并将它们提交到账本。排序节点从客户那里收到认可的交易后,他们就交易顺序达成共识,然后添加区块。这样会极大地提高效率。这些区块之后被分配给添加这些区块到账本的对等节点。
排序组织还可以操作定义Fabric网络的功能的系统通道,例如如何制作块以及节点可以使用的Fabric版本。系统通道定义了哪个组织是该联盟的成员。
在上面的测试网络中使用一个排序节点(orderer.example.com)运行Raft排序服务,该服务由排序组织运行。但是在一个真实的网络将有多个排序节点,不同的排序节点将使用Raft共识算法达成跨交易顺序的共识网络。
3、创建通道
接下来我们需要创建用于对等节点之间进行交易的Fabric通道。
通道是特定网络成员之间的专用通信层。通道只能由被邀请加入通道的组织使用,并且对网络的其他成员不可见。每个通道都有一个单独的区块链账本。被邀请的组织“加入”他们的对等节点来存储其通道账本并验证交易。
首先就是默认创建方式:
./network.sh createChannel
这种方式会创建名为mychannel的通道:

这个命令执行会有特别长的输出,并且会自动将两个peer节点添加到通道中:



如果我们想自己自定义通道名称,我们可以使用如下命令,其中channel1是通道名称:
./network.sh createChannel -c channel1

这两个通道除了名称不同,其他都是相通的,包括通道中的节点(因为我们目前只有两个peer节点)。也就是说,是允许多个节点或者多个组织之间存在多个通道的。
接下来我们继续创建一个通道:
./network.sh createChannel -c channel2

最后我们可以在文件夹下发现新建了一个channel-artifacts文件夹,里面有三个通道文件:

我们也可以在开启网络的时候,就直接同步创建通道:
./network.sh up createChannel
4、链码测试
做完了上面的,我们就可以来测试一下链码啦!
注意,默认情况下,脚本安装Go版本的 asset-transfer (basic) 链码。但是大家可以使用语言便签 -l
,用于安装 Java 或 javascript 版本的链码。我们可以在 fabric-samples 目录的 asset-transfer-basic 文件夹中找到 asset-transfer (basic) 链码。此目录包含作为案例和用来突显 Fabric 特征的样本链码。
我们执行如下命令:
./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-go -ccl go
但是会有如下报错:

首先我们先检查自己是否成功安装go,如果成功安装,那就需要检查我们的网络是否连接了。
最简单的方法就是在看右上角的的网络连接,或者系统中打开网页,如果无法成功打开,则说明网络有问题,我们在主机中Win+R 打开services.msc。

然后找到虚拟机网络服务,让他们重新运行。

接下来大家可以再次尝试,如果不行,那就需要更换代理,我们输入如下两条命令:
go env -w GOPROXY=https://goproxy.io,directgo env -w GO111MODULE=on
然后再执行。
如果产生如下错误:

Error: chaincode install failed with status: 500 - failed to invoke backing implementation of 'InstallChaincode': chaincode already successfully installedChaincode installation on peer0.org1 has failedDeploying chaincode failed
我们首先关掉这个测试网络:
./network.sh down
然后我们再重新开启并创建通道:
./network.sh up createChannel
也就是把前面的所有流程重新来一遍。
然后我们就可以执行了:

5、与网络交互
完成上面的操作后,我们就可以使用客户端节点来和网络交互啦!我们可以通过客户端节点调用已部署的智能合约,更新通道,或安装和部署新的智能合约。
1、基本配置
首先我们需要做一些基本配置,我们把peer的二进制文件添加到客户端节点路径中:
export PATH=${PWD}/../bin:$PATH
然后我们将fabric-samples代码库中的FABRIC_CFG_PATH设置为指向其中的core.yaml文件:
export FABRIC_CFG_PATH=$PWD/../config/
执行结果如下:

2、组织1配置
然后我们需要配置组织1的环境,全部命令如下:
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、组织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 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":[]}'
为了方便大家观看,我们整理一下格式:
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":[]}'
我们会得到如下输出:
2021-10-26 23:12:37.939 CST [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200

接下来我们用客户端工具来查询账本。运行以下指令来获取添加到通道账本的资产列表:
peer chaincode query -C mychannel -n basic -c '{"Args":["GetAllAssets"]}'
我们会得到如下输出:
[{"AppraisedValue":300,"Color":"blue","ID":"asset1","Owner":"Tomoko","Size":5},{"AppraisedValue":400,"Color":"red","ID":"asset2","Owner":"Brad","Size":5},{"AppraisedValue":500,"Color":"green","ID":"asset3","Owner":"Jin Soo","Size":10},{"AppraisedValue":600,"Color":"yellow","ID":"asset4","Owner":"Max","Size":10},{"AppraisedValue":700,"Color":"black","ID":"asset5","Owner":"Adriana","Size":15},{"AppraisedValue":800,"Color":"white","ID":"asset6","Owner":"Michel","Size":15}]

当一个网络成员希望在账本上转账或者改变资产时,我们需要调用 asset-transfer (basic) 链码改变账本上的资产所有者,因为 asset-transfer (basic) 链码的背书策略需要交易同时被 Org1 和 Org2 签名,链码调用指令需要使用 --peerAddresses 标签来指向如下两个地址:
peer0.org1.example.compeer0.org2.example.com
命令如下:
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":"TransferAsset","Args":["asset6","Christopher"]}'
和前面类似,我们会得到下面的结果:

4、组织2配置
调用链码之后,我们可以使用另一个查询来查看调用如何改变了区块链账本的资产。因为我们已经查询了 Org1 的 peer,我们可以把这个查询链码的机会通过 Org2 的 peer 来运行。设置以下的环境变量来操作 Org2:
export CORE_PEER_TLS_ENABLED=trueexport 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:9051
执行结果如下:

5、结果查询
我们可以查询运行在 peer0.org2.example.com asset-transfer (basic) 链码:
peer chaincode query -C mychannel -n basic -c '{"Args":["ReadAsset","asset6"]}'
执行结果如下:

6、关闭网络
到这里,我们测试网络的基本操作就完成啦,通过这个测试网络,我们就能大致了解联盟链的工作流程和参与的实体。最后我们将我们测试的网络关闭即可:
./network.sh down

3
说在后面的话
到这里,我们就了解了联盟链的基本概念,了解了Hyperledger Fabric的基本原理,安装与配置以及执行细节。在未来,我们会更加深入学习相关的知识。
一起加油啦!