环境清单

基础环境

- 操作系统 : Ubuntu 21.04 amd64
- Golang : Version 1.16.5
- Docker : Version 20.10.7
- Docker Compose : Version 1.29.2
- Hyperledger Fabric : Github - hyperledger/fabric @v2.4.0

基础环境安装参考上一篇文章:Hyperledger 学习(一):基础环境安装以及一键部署脚本

新增内容

- Hyperledger Fabric-Samples : Github - hyperledger/fabric @v2.3.0

示例下载

1、下载镜像

官方提供了镜像下载的脚本,在目录github.com/hyperledger/fabric/scripts/中,在脚本目录中执行如下命令即可
- 下载镜像


  cd $GOPATH/src/github.com/hyperledger/fabric/scripts
  ./bootstrap.sh

- 查看镜像列表

下载过程需要一些时间,完成之后查看镜像列表应该如下:


  fabric@ubuntu:~/code/go/src/github.com/hyperledger/fabric/scripts$ docker images
  ===> List out hyperledger docker images
  hyperledger/fabric-tools     2.3       a206a1593b4c   2 months ago   448MB
  hyperledger/fabric-tools     2.3.2     a206a1593b4c   2 months ago   448MB
  hyperledger/fabric-tools     latest    a206a1593b4c   2 months ago   448MB
  hyperledger/fabric-peer      2.3       85c825d4769f   2 months ago   54.2MB
  hyperledger/fabric-peer      2.3.2     85c825d4769f   2 months ago   54.2MB
  hyperledger/fabric-peer      latest    85c825d4769f   2 months ago   54.2MB
  hyperledger/fabric-orderer   2.3       7cad713cbfea   2 months ago   37.8MB
  hyperledger/fabric-orderer   2.3.2     7cad713cbfea   2 months ago   37.8MB
  hyperledger/fabric-orderer   latest    7cad713cbfea   2 months ago   37.8MB
  hyperledger/fabric-ccenv     2.3       627c556b15ca   2 months ago   514MB
  hyperledger/fabric-ccenv     2.3.2     627c556b15ca   2 months ago   514MB
  hyperledger/fabric-ccenv     latest    627c556b15ca   2 months ago   514MB
  hyperledger/fabric-baseos    2.3       e50ea411d694   2 months ago   6.86MB
  hyperledger/fabric-baseos    2.3.2     e50ea411d694   2 months ago   6.86MB
  hyperledger/fabric-baseos    latest    e50ea411d694   2 months ago   6.86MB
  hyperledger/fabric-ca        1.5       24a7c19a9fd8   3 months ago   70.8MB
  hyperledger/fabric-ca        1.5.0     24a7c19a9fd8   3 months ago   70.8MB
  hyperledger/fabric-ca        latest    24a7c19a9fd8   3 months ago   70.8MB
  fabric@ubuntu:~/code/go/src/github.com/hyperledger/fabric/scripts$

2、下载官方示例 fabric-samples

官方推荐安装到$GOPATH/src/github.com/<your_github_userid>目录,

但我自己即有github仓库,也有gitee的仓库,此处我的下载路径是 $GOPATH/src/w0x21/HyperledgerStudy



可以使用git clone或者go get再拷贝到指定目录

方式一:git clone


  mkdir -p $GOPATH/src/w0x21/HyperledgerStudy
  cd $GOPATH/src/w0x21/HyperledgerStudy
  git clone https://github.com/hyperledger/fabric-samples

方式二:go get


  mkdir -p $GOPATH/src/w0x21/HyperledgerStudy
  go get github.com/hyperledger/fabric-samples
  cp -rf $GOPATH/src/github.com/hyperledger/fabric-samples $GOPATH/src/w0x21/HyperledgerStudy/

运行示例

本文暂不阐述Fabric的详细工作原理,但在开始之前我们还是要先了解一下接下来示例中所涉及到的一些概念,更好的理解发生了什么,由浅入深进行学习。

官方文档介绍 - 隐私和保密 ,这一小段中有说明:

Hyperledger Fabric, being a permissioned platform, enables confidentiality through its channel architecture and private data feature. In channels, participants on a Fabric network establish a sub-network where every member has visibility to a particular set of transactions. Thus, only those nodes that participate in a channel have access to the smart contract (chaincode) and data transacted, preserving the privacy and confidentiality of both. Private data allows collections between members on a channel, allowing much of the same protection as channels without the maintenance overhead of creating and maintaining a separate channel.

Hyperledger Fabric 是一个许可平台,通过其 通道(Channel) 架构和私有数据功能实现机密性。在 通道 中,Fabric 网络上的参与者建立一个子网络,其中每个成员都可以看到一组特定的交易。因此,只有参与 通道 的节点才能访问 智能合约(Chaincode) 和交易的数据,从而保护两者的隐私和机密性。私有数据允许在 通道 上的成员之间进行收集,从而提供与 通道 相同的保护,而无需创建和维护单独 通道 的维护开销。

这里包含两个概念:

- 智能合约(Chaincode):

Chaincode is software, running on a ledger, to encode assets and the transaction instructions (business logic) for modifying the assets.

智能合约(链码 - Chaincode) 是一个运行在账本上的软件,它可以对资产进行编码,其中的交易指令(或者叫业务逻辑)也可以用来修改资产。
- 通道(Channel):


A channel is a private blockchain overlay on a Fabric network, allowing for data isolation and confidentiality. A channel-specific ledger is shared across the peers in the channel, and transacting parties must be properly authenticated to a channel in order to interact with it. Channels are defined by a Configuration-Block.

通道(Channel) 是构建在 Fabric 网络上的私有区块链,实现了数据的隔离和保密。通道特定的账本在通道中是与所有对等节点共享的,并且交易方必须通过该通道的正确验证才能与账本进行交互。通道是由一个“配置块”来定义的。

因为Fabric项目涉及大量的概念术语,如果你并未查看过官方的项目文档,我会尽可能的在引用到相关术语的地方加粗并括号标注该词汇。如有必要,我会在文中介绍词汇所表示的含义。当然,肯定会有所疏忽,推荐参阅官方文档的词汇释义

- hyperledger-fabric 中文在线文档(词汇表)
- hyperledger-fabric 官方在线文档(词汇表)

1、示例介绍

- 1.1、示例中所运行的Docker节点:

名称 Docker 名称 角色名词 说明
排序服务 orderer.example.com Ordering Service(排序服务或共识服务) 将交易排序放入 区块(Block) 的节点的集合。
ordering service独立于 节点(Peer) 流程之外,
并以先到先得的方式为网络上所有的 通道(Channel) 作交易排序。

*ordering service支持可插拔实现,目前默认实现了SOLO和Kafka。
ordering service是整个网络的公用binding,包含与每个 成员(Member) 相关的加密材料。*
组织1的对等节点 peer0.org1.example.com Peer(节点) 组织1的网络实体
维护 账本(Ledger) 并运行 链码(Chaincode) 容器来对 账本(Ledger) 执行read-write操作。
节点(Peer)成员(Member) 拥有和维护。
组织2的对等节点 peer0.org2.example.com Peer(节点) 组织2的网络实体
维护 账本(Ledger) 并运行 链码(Chaincode) 容器来对 账本(Ledger) 执行read-write操作。
节点(Peer)成员(Member) 拥有和维护。

- 1.2、示例链码简介:

所选择运行的示例为 asset-transfer-basic

本示例为基本示例智能合约(智合约即链码 - chaincode),允许您通过将数据放入分类账并检索来创建和转移资产。

上述加粗字体为官方介绍

但是!但是!但是!

官方文档并未说明该链码的资产示例表示的什么!(也可能是我没找到!)

为了便于理解,我这里假设分类资产表示的是带颜色的水桶,尺寸表示水桶容量

链码(chaincode) 运行初始化后包含的资产清单如下:

名称 颜色 尺寸 拥有者 价值
asset1 blue 5 Tomoko 300
asset2 red 5 Brad 400
asset3 green 10 Jin Soo 500
asset4 yellow 10 Max 600
asset5 black 15 Adriana 700
asset6 white 15 Michel 800

2、运行测试网络(Docker 操作)

官方提供的实例仓库fabric-samples中有非常完善的操作脚本,我们可以直接进入对应目录执行操作进行
- 1、删除之前运行中的所有容器和组件


  cd $GOPATH/src/w0x21/HyperledgerStudy/fabric-samples/test-network
  ./network.sh down

- 2、创建Fabric网络


  ./network.sh up

- 3、查看运行中的节点


  fabric@ubuntu:~/code/go/src/w0x21/HyperledgerStudy/fabric-samples/test-network$ docker ps -a
  CONTAINER ID   IMAGE                               COMMAND             CREATED         STATUS         PORTS                                                                                                                                 NAMES
  6e8f97041f76   hyperledger/fabric-tools:latest     "/bin/bash"         8 minutes ago   Up 8 minutes                                                                                                                                         cli
  48b5469b1de8   hyperledger/fabric-peer:latest      "peer node start"   8 minutes ago   Up 8 minutes   0.0.0.0:7051->7051/tcp, :::7051->7051/tcp, 0.0.0.0:17051->17051/tcp, :::17051->17051/tcp                                              peer0.org1.example.com
  17a4597187b3   hyperledger/fabric-orderer:latest   "orderer"           8 minutes ago   Up 8 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
  f1671d011063   hyperledger/fabric-peer:latest      "peer node start"   8 minutes ago   Up 8 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.com
  fabric@ubuntu:~/code/go/src/w0x21/HyperledgerStudy/fabric-samples/test-network$

如果查看运行节点和我的一样,则表示Fabric网络运行成功了,接下来可以运行 智能合约(链码 - Chaincode)

3、运行智能合约(链码 - Chaincode)

- 1、初始化环境变量


  cd ~/code/go/src/w0x21/HyperledgerStudy/fabric-samples/test-network
  export PATH=${PWD}/../bin:$PATH
  export FABRIC_CFG_PATH=$PWD/../config/

- 2、创建通道


  ./network.sh createChannel -c mychannel

- 3、启动链码(部署链码)


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

4、调用智能合约

以下所有操作均在目录~/code/go/src/w0x21/HyperledgerStudy/fabric-samples/test-network中运行
- 1、初始化成员(Member)身份为组织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

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

- 3、查询已添加到通道分类账的资产列表


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

如果成功,看到的结果应该如下:


  [
      {"ID": "asset1", "color": "blue", "size": 5, "owner": "Tomoko", "appraisedValue": 300},
      {"ID": "asset2", "color": "red", "size": 5, "owner": "Brad", "appraisedValue": 400},
      {"ID": "asset3", "color": "green", "size": 10, "owner": "Jin Soo", "appraisedValue": 500},
      {"ID": "asset4", "color": "yellow", "size": 10, "owner": "Max", "appraisedValue": 600},
      {"ID": "asset5", "color": "black", "size": 15, "owner": "Adriana", "appraisedValue": 700},
      {"ID": "asset6", "color": "white", "size": 15, "owner": "Michel", "appraisedValue": 800}
  ]

- 4、添加资产(增)


  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":"CreateAsset","Args":["asset7","Blue","6","w0x0021","1021"]}'

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

- 6、变更资产(改)


  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":"UpdateAsset","Args":["asset7","Blue","6","w0x0021","1033"]}'

- 7、转移资产(改)


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

- 8、查询资产(查)


  peer chaincode query -C mychannel -n basic -c '{"Args":["ReadAsset","asset6"]}'

5、切换身份

上一小节的操作演示是使用 组织1(Org1) 的身份来验证了链码的增删改查功能,切换身份到 组织2(Org2) 验证功能,只需要变更 4.1 中的环境变量即可,bash中种执行下面的代码:


  export PATH=${PWD}/../bin:$PATH
  export CORE_PEER_TLS_ENABLED=true
  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_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
  export CORE_PEER_ADDRESS=localhost:9051

具体操作此处不做复述,可以尝试打开两个bash窗口,初始化为不同的身份,一个窗口做资产变更操作,另一个窗口做资产查询操作来进行区块链的同步效果测试。

总结

本篇文章只是简单的对官方示例进行了一些拓展记录,并未深入研究链码的运行。但如果操作完整篇流程,应该不难发现, Fabric 框架在调用链码过程其实是一种 RPC 远程调用的方式,并且框架内包含了身份验证。但:

- 具体的区块存储是怎么样存储?

- 身份验证中的证书如何生成又如何验证?

- 证书包含哪一些?

- 创建初始区块需要作哪一些准备?

- ……?

都可以通过这一个简单的示例展开,这个简单的示例给我带来了太多问题。至此,Fabric 真的包含了太多知识点,深入学习这套框架的所带来的提升一定会非常巨大,接下来还是由浅入深,继续研究链码调用。