fabric-Getting Start
Wei Jieyang Lv4

前言

本部分主要设计fabric环境安装,已经 fabric-sampletest-networkasset-transfer-basic 样例的运行

Fabric应用程序堆栈有五层:

织物应用堆栈
  • 必备软件:运行该软件所需的基础层,例如Docker。
  • Fabric和Fabric示例:Fabric可执行文件与示例代码一起运行Fabric网络。
  • 合约API:开发在Fabric网络上执行的智能合约。
  • 应用程序SDK:开发您的区块链应用程序。
  • 应用程序:您的区块链应用程序将利用应用程序SDK调用在Fabric网络上运行的智能合约。

fabric核心模块

模块名词功能类型
peer主节点模块,负责存储区块链数据,运行维护代码系统模块
order交易打包,排序模块系统模块
cryptogen组织和证书生成模块工具模块
configtxgen区块和交易生成模块工具模块
configtxlator区块和交易解析模块工具模块
  • 工具模块负责证书文件,区块链创始块,通道创始块等相关文件和证书的生成工作,不参与系统的运行。
  • cryptogen:模块主要用于生成组织结构和账号相关文件,任何fabric系统的开发都是从cryptogen模块开始,在系统设计完成后首要工作就是根据系统设计编写cryptogen的配置文件。
  • configtxgen

开发环境

官方文档

系统:MacOS

必备软件

Prerequisites - 先决条件

  • Homebrew:仅mac系统需要,用来管理下面所需要的软件包
  • git版本管理工具
  • cURL:curl命令是个功能强大的网络工具,支持通过http、ftp等方式下载文件、上传文件
  • Docker & Docker-compose:一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化
  • Go:Docker是基于go语言的
    • (only required if you will be writing Go chaincode or SDK applications)
  • JQ:既JQuery,一个优秀的javascript类库
    • (only required for the tutorials related to channel configuration transactions)

Homebrew

1
2
3
4
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
$ brew --version
Homebrew 3.0.4
Homebrew/homebrew-core (git revision 89d933; last commit 2020-04-01)

问题

截屏2021-03-07 下午5.22.32
  1. Error: Unknown command: cask
    • Homebrew 2.5.x 之后删掉了brew cask
    • 直接使用brew,或者brew --cask即可
截屏2021-03-07 下午5.21.56
  1. 升级后核心不可用homebrew-core is a shallow clone

    • 先按照提示执行git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core fetch --unshallow
    截屏2021-03-07 下午7.57.58
    • 如果系统不支持unshallow,则删掉核心后再update
    1
    2
    $ rm -rf /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core
    $ brew update

Git

1
2
3
$ brew install git
$ git --version
git version 2.24.3 (Apple Git-128)

cURL

1
2
3
4
5
$ brew install curl
$ curl --version
curl 7.63.0 (x86_64-apple-darwin13.4.0) libcurl/7.63.0 OpenSSL/1.1.1b zlib/1.2.11 libssh2/1.8.0
Release-Date: 2018-12-12
...

Docker

  • Since Docker Desktop is a UI application on Mac, use cask to install it.

Homebrew v2.x:

1
$ brew cask install --appdir="/Applications" docker

Homebrew v3.x:

1
$ brew install --cask --appdir="/Applications" docker
  • Docker Desktop must be launched to complete the installation so be sure to open the application after installing it:
1
$ open /Applications/Docker.app
  • Once installed, confirm the latest versions of both docker and docker-compose executables were installed.
1
2
3
4
$ docker --version
Docker version 20.10.5, build 55c4c88
$ docker-compose --version
docker-compose version 1.28.5, build c4eb3a1f

加速

  • docker镜像在国外,为了后续下载加速,配置文件将镜像换成国内的

    • /etc/docker/daemon.json文件中配置或者如下图所示在软件中配置:

    • {"registry-mirrors":["https://reg-mirror.qiniu.com/"]}

      ![截屏2021-03-07 下午9.55.31](fabric-Getting Start/截屏2021-03-07 下午9.55.31.png)

Go

1
2
3
$ brew install go
$ go version
go version go1.16 darwin/amd64
  • 可以根据喜好设置项目目录,下面为推荐目录结构
1
2
3
$ export GOPATH:$Home/<user-defined-workspace>/go
$ go env GOPATH
/Users/weijieyang/go

JQ

1
2
3
$ brew install jq
$ jq --version
jq-1.6

问题

截屏2021-03-08 下午1.26.23
  1. python版本问题
    • 按照给出的指令顺序操作
    • --overwrite 表示强制
截屏2021-03-08 下午1.32.00

fabric

下载fabric

1
2
3
4
5
6
7
8
9
10
11
12
13
$ cd $GOPATH/src/github.com/hyperledger
$ git clone git@github.com:hyperledger/fabric.git

# 切换fabric版本,也可以直接使用当前版本
$ cd fabric
$ git checkout -b release-1.1 origin/release-1.1

# 生成所有工具模块的二进制可执行文件
$ make all

# 或者只单独生成所需工具模块的可执行文件
$ make configtxgen
$ make cryptogen
  • make将会在 build/bin 目录下生成二进制可执行文件

bootstrap.sh

路径fabric/script/bootstrap.sh

主要功能

截屏2021-03-28 下午1.17.26
  • SAMPLES:克隆fabric-samples

  • BINARIES:安装二进制文件

  • DOCKER:下载docker镜像

执行

docker image

镜像名称是否可选镜像说明
hyperledger/fabric-tools可选包含crytogen、configtxgen、configtxlator我第二次工具的镜像文件
hyperledger/fabric-couchdb可选CouchDB的数据库镜像文件、状态数据库选择CouchDB的时候才需要
hyperledger/fabric-kafka可选Kafka的镜像文件
hyperledger/fabric-zookeeper可选Zookeeper的镜像文件
hyperledger/fabric-peer必选Peer节点的镜像文件
hyperledger/fabric-orderer必选排序服务节点的镜像文件
hyperledger/fabric-javaenv可选java链码的基础镜像文件
hyperledger/fabric-ccenv必选Golang链码的基础镜像文件
hyperledger/fabric-ca可选fabric-ca的镜像文件,用到fabric-ca的时候才需要

fabric-sample

github源码:

1
2
3
$ mkdir -p $HOME/go/src/github.com/<your_github_userid>
$ cd $HOME/go/src/github.com/<your_github_userid>
$ curl -sSL https://bit.ly/2ysbOFE | bash -s
  • 创建go项目目录并使用curl下载sample文件
  • 上面的curl命令将会执行以下步骤:

    1. 克隆hyperledger / fabric-samples存储库。

    2. 下载最新的Hyperledger Fabric Docker映像并将其标记为 latest

    3. 将以下特定于平台编译好的的Hyperledger Fabric CLI工具二进制文件配置文件下载到fabric-samples /bin/config目录中。这些二进制文件将帮助您与测试网络进行交互。

      截屏2021-03-09 下午10.05.11

问题

报错

截屏2021-03-08 下午8.49.03
  • 此处网站 https://bit.ly/2ysbOFE 需要科学上网,在国内访问不了

(针对Ubuntu / CentOS系统)

  1. 如果无法访问上述github文件,可以考虑添加docker镜像源

    截屏2021-03-08 下午9.29.57
    • 在文件 /etc/docker/daemon.json 中添加镜像源:

      "registry-mirrors":["https://registry.docker-cn.com"]

    • 查看镜像源:

      1
      2
      3
      $ docker info|grep Mirrors -A 1
      Registry Mirrors:
      https://registry.docker-cn.com/
    • 重启网络

      1
      2
      3
      4
      5
      6
      # Ubuntu
      $ sudo /etc/init.d/networking restart
      # CentOS
      $ sudo /etc/init.d/network restart
      # Mac
      $ sudo ifconfig en0 down/up
    • 再次执行curl指令

(还是无法链接网站)

  1. 上面的网站主要是为了获得一个bootstrap.sh的脚本文件并执行
  • 我们只需要去fabric中下载bootstrap.sh源码即可

    • 需要先下载zip https://github.com/hyperledger/fabric.git (master分支)
    • 再将文件fabric/scripts/bootstrap.sh 移动到目录$HOME/go/src/github.com/<your_github_userid>
    • 或者使用github单个文件下载工具DownGit
    • 之后在此脚本目录下执行下面的指令即可
    1
    $ cat bootstrap.sh |bash -s

sample测试

运行测试网络

普通网络

运行脚本 network.sh 来启动测试网络,该脚本使用本地计算机上的Docker映像站立在Fabric网络上

  • 到目录 fabric-samples/test-network 下执行命令
1
$ ./network.sh up
  • 启动网络
  • 此命令创建一个结构网络,该结构网络由两个对等节点一个订购节点组成。您在运行时不会创建任何渠道,如果命令成功完成,您将看到正在创建的节点的日志

![截屏2021-03-09 下午10.13.09](fabric-Getting Start/截屏2021-03-09 下午10.13.09.png)

1
$ ./network.sh down
  • 从以前的任何运行中删除任何容器或工件
1
2
3
4
5
6
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fcb443d2c66a hyperledger/fabric-tools:latest "/bin/bash" About a minute ago Up About a minute cli
bd07774d282d hyperledger/fabric-orderer:latest "orderer" About a minute ago Up About a minute 0.0.0.0:7050->7050/tcp, 0.0.0.0:7053->7053/tcp orderer.example.com
5257b92a5b00 hyperledger/fabric-peer:latest "peer node start" About a minute ago Up About a minute 0.0.0.0:7051->7051/tcp peer0.org1.example.com
8a8cd2ea75e4 hyperledger/fabric-peer:latest "peer node start" About a minute ago Up About a minute 7051/tcp, 0.0.0.0:9051->9051/tcp peer0.org2.example.com
  • 列出计算机上运行的所有Docker容器
    • 网络中的每个对等方都必须属于一个组织。在测试网络中,每个组织各自运营一个对等方,peer0.org1.example.compeer0.org2.example.com
    • 每个Fabric网络还包括订购服务,可以看到订购节点 orderer.example.com
1
$ ./network.sh createChannel -c channelName
  • 创建Channel,系统默认命名为 mychannel
  • channel名称限制
    • 仅包含小写ASCII字母数字,点“。”和破折号“-”
    • 少于250个字符
    • 以字母开头
1
2
3
4
5
6
$ ./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-go -ccl go
# deployCC = deploy chaincode
# -ccn set chaincode name
# -ccp set chaincode path
# -ccl set chaincode language
# -c 指定部署链码的通道名称,默认在 mychannel 上部署
  • 在channel上启动链码(此链码将在名为 mychannel 的通道上执行)
  • 可以在 fabric-sampleasset-transfer-basic 文件夹中找到资产转移的示例代码
  • 第一次部署链码的话,该脚本将安装链码依赖项

报错

  1. 第一次部署时无法下载依赖

    截屏2021-03-15 上午10.56.46
    • 只需要执行两个命令更改GO为国内代理即可,再此执行将成功

      1
      2
      $ go env -w GOPROXY=https://goproxy.io,direct
      $ go env -w GO111MODULE=on
  1. 无法下载组建 InstallChaincode

    截屏2021-03-15 上午11.15.27
    • 网络问题,重启网络,再重新创建myChannel即可

      1
      2
      3
      4
      $ ./network.sh down
      $ ./network.sh up
      $ ./network.sh createChannel
      $ ./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-go -ccl go

与网络互动,配置peer指令

  • 均在 test-network 文件夹下执行
1
2
3
4
5
6
7
8
9
10
11
# 将fabroc-sample/bin下的二进制文件添加到CLI路径中()
$ export PATH=${PWD}/../bin:$PATH
# 设置FABRIC_CFG_PATH指向fabric-sample中的core.yaml文件
$ export FABRIC_CFG_PATH=${PWD}/../config/

# Environment variables for Org1
$ 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
  • CORE_PEER_TLS_ROOTCERT_FILECORE_PEER_MSPCONFIGPATH 环境变量指向的ORG1加密材料 organizations 文件夹。
1
$ peer channel list
  • 列出网络中所有的channel
1
2
3
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":"InitLedger","Args":[]}'

# 成功的日志信息
2021-03-15 11:30:18.970 CST [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200
  • 使用资产初始化分类帐
  • 成功后就可以使用CLI来查询分类账
1
2
3
4
5
6
7
8
9
10
11
$ 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}
]
  • 获取已添加到渠道分类帐中的资产的列表
1
2
3
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":"InitLedger","Args":[]}'

# 成功的日志信息
2021-03-15 11:36:04.958 CST [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200
  • 当网络成员要转移或更改分类帐上的资产时,将调用链码。
  • 此命令通过调用 asset-transfer-basic 链码来更改分类帐上资产的所有者

调用链代码后,我们可以使用另一个查询来查看该调用如何更改了区块链分类账上的资产。由于我们已经查询过Org1对等体,因此我们可以借此机会查询Org2对等体上运行的链码。

1
2
3
4
5
6
# Environment variables for Org2
$ 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
  • 设置环境变量以作为Org2进行操作
1
$ peer chaincode query -C mychannel -n basic -c '{"Args":["ReadAsset","asset6"]}'
  • 查询运行在 mychannel 上的 asset-transfer-basic 链码 peer0.org2.example.com

  • 结果显示 "asset6" 已转移到Christopher:

    截屏2021-03-15 上午11.39.59

与证书颁发机构建立网络

1
$ ./network.sh up -ca
1
2
3
4
# tree命令并不是默认安装的,如果没有该命令,先安装
$ brew install tree
# 在 fabric-sample/test-network 下执行
$ tree organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/
  • 显示MSP文件夹的结构和配置文件:

    截屏2021-03-14 下午1.15.18

运行结构应用程序

资产转移

asset-transfer-basic 样本演示了如何使用资产初始化分类帐,查询那些资产,创建新资产,基于资产ID查询单个资产,更新现有资产以及将资产转移给新所有者。它涉及以下两个组件:

  1. 示例应用程序:调用区块链网络,调用以链码(智能合约)实现的交易。该应用程序位于以下fabric-samples目录中:

    1
    asset-transfer-basic/application-javascript
  1. 智能合约本身,实现涉及与分类账交互的交易。智能合约(链码)位于以下fabric-samples目录中:

    1
    asset-transfer-basic/chaincode-(javascript, java, go, typescript)

请注意,在本教程中,术语链码和智能合约可互换使用。在此示例中,我们将使用javascript链码。

主要步骤:

  1. 建立开发环境。我们的应用程序需要与之交互的网络,因此我们将为我们的智能合约和应用程序部署一个基本的网络。AppConceptsOverview

  2. 探索样本智能合约。 我们将检查示例assetTransfer(javascript)智能合约,以了解其中的交易以及应用程序如何使用它们查询和更新分类账。

  3. 通过示例应用程序与智能合约进行交互。我们的应用程序将使用assetTransfer智能合约在分类账上创建,查询和更新资产。我们将深入研究应用程序及其创建的交易的代码,包括使用资产初始化分类账,查询资产,查询一系列资产,创建新资产以及将资产转让给新所有者。

启动网络

  • 根据运行测试网络的步骤
1
2
3
4
5
$ open /Applications/Docker.app  # mac上启动docker desktop的方式
$ cd fabric-samples/test-network
$ ./network.sh down
$ ./network.sh up createChannel -c mychannel -ca
$ ./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-javascript/ -ccl javascript

申请样本

1
2
$ export PATH=${PWD}/../bin:$PATH
$ export FABRIC_CFG_PATH=$PWD/../config/
  • 设置peer指令环境变量
1
$ cd fabric-sample/asset-transfer-basic/application-javascript
  • 打开一个新的终端,进入到示例代码文件中,
  • 该目录包含使用Fabric SDK for Node.js开发的示例程序。
1
2
$ npm install
$ node app.js
  • 运行 npm 命令以安装应用程序依赖项。最多可能需要一分钟才能完成。

  • 此过程将安装在的应用程序中定义的关键应用程序依赖项 package.json。其中最重要的是 fabric-network Node.js模块;它使应用程序能够使用身份,钱包和网关来连接到渠道,提交交易并等待通知

  • 运行完成后将得到以下文件

    截屏2021-03-16 上午11.23.37

代码解析

fabric-sample/asset-transfer-basic/application-javascript/app.js

  • 仅调用方法
    • 方法定义在 fabric-sample/test-application/javascript/CAUtil.jsAppUtil.js
app.js:

当我们启动Fabric测试网络时,创建了一个管理员用户(字面上称为admin)作为证书颁发机构(CA)的注册商

截屏2021-03-16 下午3.01.28
  1. 调用函数 enrollAdmin() 生成 admin 的私钥,公钥和X.509证书。
    • 此过程使用证书签名请求(CSR)-专用密钥和公用密钥首先在本地生成,然后将公用密钥发送到CA,CA返回编码的证书供应用程序使用。
    • 这些凭证然后存储在 application-javascript/wallet 中,使我们能够充当CA的管理员。
    • 可以在wallet/admin.id 文件中找到管理员的证书和私钥

注意

如果您决定通过断开网络并重新启动来重新开始,则必须wallet在重新运行javascript应用程序之前删除该文件夹及其标识,否则会出现错误。发生这种情况的原因是,在关闭测试网络时,关闭了证书颁发机构及其数据库,但是原始钱包仍保留在application-javascript目录中,因此必须将其删除。当您重新运行示例javascript应用程序时,将生成一个新的钱包和凭据。

  1. 调用 registerAndEnrollUser() 来注册并加入一个应用程序用户 appUser,该用户将用于与区块链网络进行交互
    • 与管理员注册类似,此功能使用CSR来注册,注册 appUser 和存储其凭据以及admin钱包中的凭据。
    • 现在,我们拥有两个独立用户的身份,admin并且appUser该身份可以由我们的应用程序使用
截屏2021-03-16 下午3.20.50
  1. 应用程序正在通过网关 gateway 使用 chaincodeNamechannelName 名称来引用合约

    • (本例是在 mychannel 中使用 asset-transfer-basic 合约)

    • 当链码包包含多个智能合约时,可以在getContract()API上指定链码包的名称和要定位的特定智能合约。

      1
      const contract = await network.getContract('chaincodeName', 'smartContractName');
    • asLocalhost set true 告知它以localhost连接。在不将客户端与其他结构节点在同一网络上运行的部署中,该 asLocalhost 选项将设置为 false

截屏2021-03-16 下午3.20.58
  1. SubmitTransaction() 函数用于调用chaincode的 InitLedger 函数,以使用一些样本数据填充分类帐。
    • 在幕后,submitTransaction() 函数将使用服务发现来为链码找到一组所需的认可对等体,在所需数目的对等体上调用链码,从这些对等体收集链码认可的结果,最后将事务提交给订购服务。
    • 对等体在assets中指定,然后使用 ctx.stub.putState(...) 来验证(chaincode-javascript中)
截屏2021-03-16 下午3.45.11 截屏2021-03-16 下午3.35.33

require(‘fabric-network’); 模块中,定义在文件 fabric-network/lib/transaction.js 中

evaluateTransaction()

  • 代表了区块链网络中与智能合约最简单的交互之一。只是查询账本内容而已
  • 它只是选择一个在连接配置文件中定义的对等体,然后将请求发送到该对等体,并在此对其进行评估。智能合约查询对等方账本副本上的资产,并将结果返回给应用程序。
  • 这种交互不会导致分类账的更新。

submitTransaction()

  • evaluateTransaction() 复杂得多,是一个完整的共识流程(提交-背书-检验)
  • SDK不会与单个peer进行交互,而是根据chaincode的背书政策,向区块链网络中每个需要的组织对等方发送 proposal。这些对等方中的每一个都将使用该 proposal 执行所请求的智能合约,以生成交易响应,该交易响应将对其背书(签署)并返回到SDK。SDK将所有已背书的交易响应收集到一个交易中,然后将其提交给oderer。oderer将来自各种应用程序客户端的交易收集并排序为一个交易块。这些块被分发到网络中的每个对等点,在此对每个事务进行验证和提交。最后,通过事件通知SDK,使其可以将控制权返回给应用程序。
CAUtil.js

enrollAdmin

registerAndEnrollUser

常见错误

https://www.jianshu.com/p/248530bf31b8

  • Post title:fabric-Getting Start
  • Post author:Wei Jieyang
  • Create time:2021-03-14 12:08:44
  • Post link:https://jieyang-wei.github.io/2021/03/14/fabric-Getting Start/
  • Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.