分步详解 Fabric 区块链网络的部署 部署一个示例的 Fabric 区块链网络

## 分步详解 Fabric 区块链网络的部署 部署一个示例的 Fabric 区块链网络

前言
区块链(Blockchain)技术正在迅速发展,在银行、保险、物流、新闻出版、食品安全等很多领域都开始了实际应用。可以预见,将来会有越来越多的行业会应用它。

Hyperledger Fabric 是其中一个非常重要的区块链技术平台。它是一个开源的、企业级的、有许可的分布式账本技术平台,它是为用于企业环境而设计的,与一些其他流行的分布式账本技术或区块链平台相比,它提供了一些非常关键的差异化的能力。

本系列文章从 Fabric 实践入手,对之进行学习与研究,进而进行基于 Fabric 的区块链应用开发,再深入研究它的数据结构、源代码与安全机制。期望能通过此系列文章,使读者能快速了解它的全貌。

本文是此系列文章的第一篇。主要内容是分步骤讲解如何部署一个示例的 Fabric 区块链网络,并初步了解 Fabric 中的一些基础内容。本文以 Fabric 1.3 为基础。

系统环境
Fabric 可以被部署在 Linux,Unix,Windows,MacOS 等系统上,本文以 Ubuntu 16.04 为基础进行讲解,读者如需了解其他系统上的使用情况,请参考 Fabric 原始文档 。

我们需要先行安装这些软件:curl,docker,docker-compose,Go lang,Python,Node.js。

有些软件如果在系统中已经存在,且版本合适,则请略过相关步骤。

如无特殊说明,下文中所有命令都以 root 用户执行。如果为非 root 用户,可能有些命令需要加 sudo。

确认 Ubuntu 版本
cat / etc / issue

安装 curl
apt install curl

安装 docker 17.06.2-ce 或更高版本
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu
$(lsb_release -cs) stable"
apt update
apt install docker-ce
usermod -aG docker $(whoami)
docker --version

显示更多
安装 docker-compose 1.14.0 或更高版本
curl -L "https://github.com/docker/compose/releases/download/1.23.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
docker-compose --version

显示更多
安装 Go 语言 1.11.x 版本
curl -O https://dl.google.com/go/go1.11.2.linux-amd64.tar.gz
tar -C /usr/local -xzf go1.11.2.linux-amd64.tar.gz

显示更多
设置 Go 语言环境变量
vi ~/.bashrc

在.bashrc 文件中增加以下内容

export PATH=$PATH:/usr/local/go/bin

执行 .bashrc 文件,使之生效

source ~/. bashrc

安装 Node.js 8.9.x 或更高版本
请注意 Fabric 目前不支持 Node.js 9.x 版本。

curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -

apt install nodejs

安装 Node.js 后,npm 应该被同时自动安装,执行以下命令确认。

npm install npm -g

安装 Python 2.7
apt install python

下载 fabric 可执行文件、示例与 docker 镜像

cd ~

mkdir fabric

cd fabric

curl -sSL http://bit.ly/2ysbOFE | bash -s 1.3.0

如果提示错误,请尝试使用 https:

curl -sSL https://bit.ly/2ysbOFE | bash -s 1.3.0

下载、安装成功后,当前目录下会增加一个 fabric-samples 目录。 并在 docker repository 中会增加一些 docker 镜像。可以通过 docker images 命令查看。

docker images

应该显示类似如下内容。

表 1. docker images 命令查看显示
REPOSITORY	TAG	IMAGE ID	CREATED	SIZE
hyperledger/fabric-javaenv	1.3.0	2476cefaf833	5 weeks ago	1.7GB
hyperledger/fabric-javaenv	latest	2476cefaf833	5 weeks ago	1.7GB
hyperledger/fabric-ca	1.3.0	5c6b20ba944f	5 weeks ago	244MB
hyperledger/fabric-ca	latest	5c6b20ba944f	5 weeks ago	244MB
hyperledger/fabric-tools	1.3.0	c056cd9890e7	5 weeks ago	1.5GB
hyperledger/fabric-tools	latest	c056cd9890e7	5 weeks ago	1.5GB
hyperledger/fabric-ccenv	1.3.0	953124d80237	5 weeks ago	1.38GB
hyperledger/fabric-ccenv	latest	953124d80237	5 weeks ago	1.38GB
hyperledger/fabric-orderer	1.3.0	f430f581b46b	5 weeks ago	145MB
hyperledger/fabric-orderer	latest	f430f581b46b	5 weeks ago	145MB
hyperledger/fabric-peer	1.3.0	f3ea63abddaa	5 weeks ago	151MB
hyperledger/fabric-peer	latest	f3ea63abddaa	5 weeks ago	151MB
hyperledger/fabric-zookeeper	0.4.13	e62e0af39193	5 weeks ago	1.39GB
hyperledger/fabric-zookeeper	latest	e62e0af39193	5 weeks ago	1.39GB
hyperledger/fabric-kafka	0.4.13	4121ea662c47	5 weeks ago	1.4GB
hyperledger/fabric-kafka	latest	4121ea662c47	5 weeks ago	1.4GB
hyperledger/fabric-couchdb	0.4.13	1d3266e01e64	5 weeks ago	1.45GB
hyperledger/fabric-couchdb	latest	1d3266e01e64	5 weeks ago	1.45GB
hyperledger/fabric-baseos	amd64-0.4.13	f0fe49196c40	5 weeks ago	124MB
将 Fabric 可执行文件目录加入系统路径
vi ~/.bashrc

在. bashrc 文件中增加以下内容:

export PATH=$PATH:~/fabric/fabric-samples/bin

执行. bashrc 文件,使之生效。

source ~/.bashrc

现在,Fabric 必需的系统环境与软件就全部准备好了,我们就要开始下载、部署第一个 Fabric 区块链网络了。

区块链网络示例 byfn(Building Your First Network.)
安装的 sample 中有一个示例区块链网络 first-network,位于目录 fabric/fabric-samples/first-network,它提供了 byfn.sh 脚本以启动示例网络,但本文会跳过这个过程,而按详细步骤分解执行这个示例网络启动过程,以讲解 Fabric 中的基础文件、运行过程。

读者如果对 byfn.sh 有兴趣,可以前往 Fabric 官方文档 查看详细内容。

byfn 启动过程详解
下面,我们开始按步骤详细解释这个示例的初始化与启动过程。这些详细步骤正是以 byfn.sh 为基础的。

准备
为保证一个干净的运行环境,我们需要先清理之间测试遗留下来的 docker 环境。

注意:本文假定当前系统完全为 Fabric 测试部署,没有其他 docker 容器、镜像存在或运行。如果系统中有其他容器、镜像,请不要执行以下命令,并选择执行适当的命令,以避免不当删除。

进入 first-network
cd fabric/fabric-samples/first-network

清理临时文件、docker 容器、镜像及网络
./byfn.sh down

设置环境变量
清单 1. 环境变量
export PATH=${PWD}/../bin:${PWD}:$PATH
export FABRIC_CFG_PATH=${PWD}
export CLI_TIMEOUT=10
export CLI_DELAY=3
export CHANNEL_NAME="mychannel"
export COMPOSE_FILE=docker-compose-cli.yaml
export COMPOSE_FILE_COUCH=docker-compose-couch.yaml
export COMPOSE_FILE_ORG3=docker-compose-org3.yaml
export LANGUAGE=golang
export IMAGETAG="latest"
export VERBOSE=true

显示更多
CHANNEL_NAME 是将要建立的 Blockchain Channel 的名字,默认值是 “mychannel”,也可以设置为你所期望的其他值,我们在以后的步骤中,一般会直接引用 $CHANNEL_NAME。

证书
我们利用 cryptogen 命令,生成这个区块链网络所需要的一系列证书及相关文件。证书是基于 PKI 体系的 x509 格式证书,内容包括:自签名 CA 根证书、节点 (Orderer、Peer) 证书、管理员证书、证书对应的私钥、TLS 证书等。

这个操作需要一个配置文件 crypto-config.yaml,示例中已经存在。crypto-config.yaml 中主要定义了:

1 个 Orderer 节点:orderer.example.com,
4 个 Peer 节点:peer0.org1.example.com, peer1.org1.example.com, peer0.org2.example.com, peer1.org2.example.com。
在此请注意 2 点:

执行前请先确认当前目录下没有 crypto-config 目录,如果已经存在,请先删除。
cryptogen 仅用作测试目的,可以方便快速的生成网络所需要的所有节点的证书。但一般情况下,cryptogen 不应被用于生产环境。(我们会在以后讲解如何添加节点,加入 Channel,并处理相关证书问题。)
生成证书
cryptogen generate --config=./crypto-config.yaml

证书目录结构
执行成功后,会在当前目录下增加一个新目录 crypto-config,包含有这个网络节点的证书、私钥等加密、签名相关元素。其基本结构如下:

图 1. 证书目录结构
证书目录结构

在这个示例网络中,有一个 CA(Certificate Authority),即证书颁发机构,名字是 example.com。它给自己颁发了一个自签名根证书 ca.example.com-cert.pem,在生成的多个目录中都包含了这个 CA 根证书,而其他节点证书(除了 TLS 证书)都由此 CA 颁发。

我们查看其中的一个目录 crypto-config/ordererOrganizations/example.com/ca,有两个文件:

图 2. CA 自签名根证书与私钥
CA 自签名根证书与私钥

其中,ca.example.com-cert.pem 是 CA 自签名根证书。4a7d8de29b3597d425494254605833721a6f121d4941b1ca7611c1364c1436ff_sk 是根证书对应的私钥。

证书中的私钥文件名是随机产生,每次执行 cryptogen 都会产生不一样的文件名,在后续引用中请注意将之改成实际测试中产生的文件名

CA 根证书
显示证书内容

openssl x509 -in ca.example.com-cert.pem -text -noout

显示证书内容如下:

清单 2. CA 根证书内容
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            81:0a:27:99:0a:db:06:c0:34:0f:d1:c3:9a:d5:9f:ed
    Signature Algorithm: ecdsa-with-SHA256
        Issuer: C=US, ST=California, L=San Francisco, O=example.com, CN=ca.example.com
        Validity
            Not Before: Oct  7 13:15:00 2018 GMT
            Not After : Oct  4 13:15:00 2028 GMT
        Subject: C=US, ST=California, L=San Francisco, O=example.com, CN=ca.example.com
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:49:52:eb:47:10:b5:ce:cb:8a:9e:d1:96:6e:92:
                    77:6d:f5:1f:53:a6:66:a0:98:be:a9:18:f5:53:e8:
                    fc:dd:1d:fc:58:88:0c:84:2d:40:2f:b6:93:94:54:
                    62:8b:26:df:d6:0f:ac:17:58:70:47:66:5a:14:de:
                    8d:f0:85:c2:11
                ASN1 OID: prime256v1
                NIST CURVE: P-256
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment, Certificate Sign, CRL Sign
            X509v3 Extended Key Usage:
                Any Extended Key Usage
            X509v3 Basic Constraints: critical
                CA:TRUE
            X509v3 Subject Key Identifier:
                4A:7D:8D:E2:9B:35:97:D4:25:49:42:54:60:58:33:72:1A:6F:12:1D:49:41:B1:CA:76:11:C1:36:4C:14:36:FF
    Signature Algorithm: ecdsa-with-SHA256
         30:44:02:20:08:e5:a2:bb:54:bf:37:01:b4:60:c8:38:1f:4f:
         7c:0e:1a:21:45:31:a2:45:1f:35:03:3e:70:c4:6a:75:a0:2e:
         02:20:14:5a:e3:36:33:82:20:88:33:d0:e7:b3:33:e3:8e:07:
         a3:b7:eb:55:83:7c:ce:22:73:5c:c8:84:4b:94:7c:bd

显示较少
其中第六行:Signature Algorithm: ecdsa-with-SHA256。ECDSA 的全名是 Elliptic Curve DSA,即椭圆曲线 DSA。它是 Digital Signature Algorithm (DSA) 应用了椭圆曲线加密算法的变种。ecdsa-with-SHA256 使用 SHA256 算法对内容先计算摘要,再应用签名算法对摘要进行签名。

查看 Issuer 与 Subject,可以看到这是一个自签名证书。

PKI 相关内容是区块链技术中的一个重要环节,建议读者对 PKI 并结合 openssl 进行更详细的学习。这里顺便列举一些常用的 openssl 操作,以进一步理解证书体系。

从证书中提取公钥:

openssl x509 -pubkey -in ca.example.com-cert.pem -noout > pubkey.pem cat pubkey.pem

输出内容如下:

—– BEGIN PUBLIC KEY-----

MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAESVLrRxC1zsuKntGWbpJ3bfUfU6Zm

oJi+qRj1U+j83R38WIgMhC1AL7aTlFRiiybf1g+sF1hwR2ZaFN6N8IXCEQ==

—– END PUBLIC KEY—–

为方便使用,将私钥文件复制一个文件名比较短的:

cp 4a7d8de29b3597d425494254605833721a6f121d4941b1ca7611c1364c1436ff_sk key.pem

从私钥中输出公钥部分:

openssl ec -in key.pem -pubout

输出内容如下:

read EC key

writing EC key

-----BEGIN PUBLIC KEY-----

MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAESVLrRxC1zsuKntGWbpJ3bfUfU6Zm

oJi+qRj1U+j83R38WIgMhC1AL7aTlFRiiybf1g+sF1hwR2ZaFN6N8IXCEQ==

-----END PUBLIC KEY-----

可以看到,这里的内容与之前从证书中提取的公钥内容相同。

使用私钥对测试文件 origcont 进行签名 :

echo TheContent > origcont

openssl dgst -sha256 -hex -c -sign key.pem origcont

输出内容如下:

EC-SHA256(origcont)= 30:44:02:20:15:71:15:71:63:d2:0f:15:83:09:86:67:bb:5d:b6:a9:14:8c:ef:02:c1:6e:52:0e:29:ea:f6:5f:d8:66:4f:62:02:20:17:31:ce:d7:ea:c3:f5:d6:11:37:eb:ed:cd:1d:64:4d:34:ed:da:7c:91:0a:bb:a0:89:da:f1:50:3c:8c:1f:d2

因为有随机数影响,当重复执行命令时,我们可以看到每次输出结果都是不同的。

使用私钥对文件 origcont 进行签名:

openssl pkeyutl -sign -in origcont -inkey key.pem -out origcont.sig

使用公钥验证签名:

openssl pkeyutl -verify -in origcont -sigfile origcont.sig -inkey pubkey.pem -pubin

Orderer 节点管理员证书位于 crypto-config/ordererOrganizations/example.com/msp/admincerts。由 CA 颁发给 Admin@example.com。

查看 Admin@example.com 证书:

openssl x509 -in Admin@example.com-cert.pem -text -noout

显示证书内容如下:

清单 3. 管理员证书内容
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            5e:ca:17:c3:99:28:45:2a:65:eb:07:1e:f7:e7:ea:d7
    Signature Algorithm: ecdsa-with-SHA256
        Issuer: C=US, ST=California, L=San Francisco, O=example.com, CN=ca.example.com
        Validity
            Not Before: Oct  7 13:15:00 2018 GMT
            Not After : Oct  4 13:15:00 2028 GMT
        Subject: C=US, ST=California, L=San Francisco, CN=Admin@example.com
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:0a:60:ba:17:9b:54:de:42:7b:82:7e:d5:0b:66:
                    6f:61:8e:de:8d:ab:d2:bc:3c:3f:2c:bb:49:f4:7a:
                    ef:4b:59:e4:74:15:c3:4a:39:db:6c:04:f8:98:64:
                    ef:dd:17:b7:68:9e:a1:f9:4d:a3:6b:66:5f:dc:44:
                    a7:18:db:34:e9
                ASN1 OID: prime256v1
                NIST CURVE: P-256
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Authority Key Identifier:
                keyid:4A:7D:8D:E2:9B:35:97:D4:25:49:42:54:60:58:33:72:1A:6F:12:1D:49:41:B1:CA:76:11:C1:36:4C:14:36:FF
    Signature Algorithm: ecdsa-with-SHA256
         30:45:02:21:00:d6:de:4b:37:30:e6:be:b1:3f:b1:4b:11:0d:
         50:21:dd:d8:b4:59:4c:e8:09:a7:65:f4:eb:1c:e6:66:d8:5f:
         d9:02:20:42:1e:18:f0:cf:b6:79:9b:07:9a:3c:77:55:84:8f:
         b2:c4:2e:8a:dd:c9:7e:e2:2d:0d:ea:89:71:eb:b4:81:3f

显示较少
用根证书验证 A dmin@example.com 证书:

openssl verify -CAfile ../../ca/ca.example.com-cert.pem Admin@example.com-cert.pem

TLS 证书
TLS 证书是自签名证书,与之前的 CA 证书没有关系。位于 crypto-config/ordererOrganizations/example.com/msp/tlscacerts。 查看 TLS 证书:

openssl x509 -in tlsca.example.com-cert.pem -text

清单 4. TLS 证书内容
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            26:46:ff:f7:80:6a:97:8c:77:b4:0d:e3:8e:b7:de:8f
    Signature Algorithm: ecdsa-with-SHA256
        Issuer: C=US, ST=California, L=San Francisco, O=example.com, CN=tlsca.example.com
        Validity
            Not Before: Oct  7 13:15:00 2018 GMT
            Not After : Oct  4 13:15:00 2028 GMT
        Subject: C=US, ST=California, L=San Francisco, O=example.com, CN=tlsca.example.com

显示更多
TLS 客户端证书
TLS 客户端证书是由 TLS CA 颁发给 Admin@example.com 的用于 TLS 连接的证书。位于 crypto-config/ordererOrganizations/example.com/users/Admin@example.com/tls。 查看 TLS 客户端证书:

openssl x509 -in client.crt -text -noout

显示内容如下(部分内容略):

清单 5. TLS 客户端证书内容
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            91:e8:d1:66:9e:1a:73:d8:32:0e:b4:84:3c:1f:eb:7a
    Signature Algorithm: ecdsa-with-SHA256
        Issuer: C=US, ST=California, L=San Francisco, O=example.com, CN=tlsca.example.com
        Validity
            Not Before: Oct  7 13:15:00 2018 GMT
            Not After : Oct  4 13:15:00 2028 GMT
        Subject: C=US, ST=California, L=San Francisco, CN=Admin@example.com

显示更多
证书间的关系
如前文所述,cryptogen 命令一般情况下仅用作测试用途,在生产环境中应通过正式合法 CA 颁发证书。但 cryptogen 命令产生的示例证书及其间的关系仍然值得学习与研究。

下面试着通过图表的方式将 ordererOrganizations 目录下的证书及其部分关系展示出来。

颜色相同的线条表示文件内容相同。
红色箭头表示 CA 颁发证书给某个组织或个人。
图 3. 证书间关系
证书间关系

对于 peerOrganizations 目录下证书间的关系这里不再详述,读者可以自行按类似方法进行分析与理解。

Channel 文件
配置文件
以下操作将使用配置文件 configtx.yaml,其中定义了 TwoOrgsOrdererGenesis profile 与 TwoOrgsChannel profile。读者可以先行查看此文件内容,也可以留待生成 channel 文件后再对比分析。其中部分内容如下:

清单 6. configtx.yaml
Profiles:
    TwoOrgsOrdererGenesis:
        <<: *ChannelDefaults
        Orderer:
            <<: *OrdererDefaults
            Organizations:
                - *OrdererOrg
            Capabilities:
                <<: *OrdererCapabilities
        Consortiums:
            SampleConsortium:
                Organizations:
                    - *Org1
                    - *Org2
    TwoOrgsChannel:
        Consortium: SampleConsortium
        Application:
            <<: *ApplicationDefaults
            Organizations:
                - *Org1
                - *Org2
            Capabilities:
                <<: *ApplicationCapabilities

显示较少
生成创世区块 Genesis Block
configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block

显示更多
生成的文件位于目录 channel-artifacts 下,可以通过以下命令将 Block 详细内容导入到 json 文件方便查看:

configtxgen -inspectBlock channel-artifacts/genesis.block > genesis.block.json

其结构大概如下:

图 4. genesis.block.json
genesis.block.json

在 genesis.block 中也包含了相关的证书内容,如下面这段内容:

"values":
       { "MSP": {
                 "mod_policy": "Admins",
                 "value": {
                         "config": {
                                  "admins": [
                                             "LS0tLS1CRUdJTi<此处省略>RJRklDQVRFLS0tLS0K"
                                           ],

显示较少
“admins” 对应的字符串即为经过 base64 编码的 Admin@org1.example.com 证书。我们可以通过以下命令查看它:

echo LS0tLS1CRUdJTi<此处省略>RJRklDQVRFLS0tLS0K| base64 -d > test.pem
openssl x509 -in test.pem -text -noout

显示更多
生成其他 Channel 文件
生成 Channel 配置 Transaction:

configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME

生成锚节点配置 Transaction for Org1:

configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP

生成锚节点配置 Transaction for Org2:

configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org2MSP

可以通过以下命令将 transaction 导出到 JSON 文件进行查看:

configtxgen -inspectChannelCreateTx channel.tx > channel.tx.json
configtxgen -inspectChannelCreateTx Org1MSPanchors.tx > Org1MSPanchors.tx.json
configtxgen -inspectChannelCreateTx Org2MSPanchors.tx > Org2MSPanchors.tx.json

显示较少
这三个文件的结构类似,但与 genesis.block 的结构很大不同。前者是交易,而后者是 block。

部署示例区块链网络
启动网络将使用三个配置文件,且它们有继承、扩展关系如下:

COMPOSE_FILE = docker-compose-cli.yaml
               base/docker-compose-base.yaml
               base/peer-base.yaml

显示较少
peer-base.yaml

这个配置文件中定义了将要启动的 container 所使用的镜像 image,并且定义了 container 启动后自动执行的命令。

docker-compose-base.yaml

这个配置文件里定义了 5 个 container:orderer.example.com,peer0.org1.example.com,peer1.org1.example.com,peer0.org2.example.com,peer1.org2.example.com。其中,4 个 peer node 的配置继承自 peer-base.yaml, 如:

peer0.org1.example.com:
            container_name: peer0.org1.example.com
            extends:
              file: peer-base.yaml
              service: peer-base

显示较少
而 orderer.example.com 则是单独的定义,并会执行不同的命令 command: orderer。

docker-compose-cli

这个配置文件扩展了 docker-compose-base.yaml 中的内容,并指定了 docker container 所加入的网络 networks: – byfn。而且又启动了一个 container cli, 这是一个 fabric 工具集 docker container。后续中,我们会经常登录这个 container 以与 fabric 进行交互、操作。

启动区块链网络
docker-compose -f $COMPOSE_FILE up -d 2>&1

启动后,执行 docker ps 可以看到 6 个 docker container。

docker ps --format "{{.ID}}\t{{.Command}}\t {{.Image}}\t{{.Names}}"

显示结果类似:

109b538211e2 "/bin/bash"       hyperledger/fabric-tools:latest   cli
d6ca0ef10248 "peer node start" hyperledger/fabric-peer:latest    peer0.org2.example.com
b5143e44f87d "orderer"         hyperledger/fabric-orderer:latest orderer.example.com
4618ecb778cf "peer node start" hyperledger/fabric-peer:latest    peer1.org1.example.com
563244de0109 "peer node start" hyperledger/fabric-peer:latest    peer0.org1.example.com
23dc569f214e "peer node start" hyperledger/fabric-peer:latest    peer1.org2.example.com

显示更多
登录 cli Container
docker exec -it cli bash

登录成功后进入 cli container, 请注意之后的操作如无特别说明, 均 为于 container 内执行命令。

如果退出 container, 再 次登入时,下面的”准备环境变量 ” 操作必须再执行一次。

清单 7. 准备环境变量
export CHANNEL_NAME="mychannel"
export LANGUAGE=golang

export ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

export PEER0_ORG1_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export PEER0_ORG2_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export ORG1_MSP=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export ORG2_MSP=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp

export CC_SRC_PATH="github.com/chaincode/chaincode_example02/go/"

export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=$PEER0_ORG1_CA
export CORE_PEER_MSPCONFIGPATH=$ORG1_MSP
export CORE_PEER_ADDRESS=peer0.org1.example.com:7051

显示较少
这些环境变量将在执行 peer 命令时被使用,这些值也可以以参数的形式直接传递给 peer command。具体请查看 Fabric Commands 文档。

创建 Channel
peer channel create -o orderer.example.com:7050 -c $CHANNEL_NAME -f
./channel-artifacts/channel.tx --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA

显示较少
执行成功后后,会在当前目录增加文件 mychannel.block,即<$CHANNEL_NAME>.block,可以通过以下命令查看 block 文件内容:

configtxgen -inspectBlock mychannel.block

加入 Channel
将之前在配置文件中定义的 4 个节点加入 channel。

清单 8. 将节点加入 channel
# joinChannelWithRetry 0 1
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=$PEER0_ORG1_CA
export CORE_PEER_MSPCONFIGPATH=$ORG1_MSP
export CORE_PEER_ADDRESS=peer0.org1.example.com:7051
peer channel join -b $CHANNEL_NAME.block

# joinChannelWithRetry 1 1
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=$PEER0_ORG1_CA
export CORE_PEER_MSPCONFIGPATH=$ORG1_MSP
export CORE_PEER_ADDRESS=peer1.org1.example.com:7051
peer channel join -b $CHANNEL_NAME.block

# joinChannelWithRetry 0 2
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=$PEER0_ORG2_CA
export CORE_PEER_MSPCONFIGPATH=$ORG2_MSP
export CORE_PEER_ADDRESS=peer0.org2.example.com:7051
peer channel join -b $CHANNEL_NAME.block

# joinChannelWithRetry 1 2
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=$PEER0_ORG2_CA
export CORE_PEER_MSPCONFIGPATH=$ORG2_MSP
export CORE_PEER_ADDRESS=peer1.org2.example.com:7051
peer channel join -b $CHANNEL_NAME.block

显示较少
更新 Anchor Peer
清单 9. 更新 Anchor Peer
# updateAnchorPeers 0 1
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=$PEER0_ORG1_CA
export CORE_PEER_MSPCONFIGPATH=$ORG1_MSP
export CORE_PEER_ADDRESS=peer0.org1.example.com:7051
peer channel update -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/${CORE_PEER_LOCALMSPID}anchors.tx --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA

# updateAnchorPeers 0 2
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=$PEER0_ORG2_CA
export CORE_PEER_MSPCONFIGPATH=$ORG2_MSP
export CORE_PEER_ADDRESS=peer0.org2.example.com:7051
peer channel update -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/${CORE_PEER_LOCALMSPID}anchors.tx --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA

显示较少
安装 Chaincode
如果要通过某个 peer node 访问 chaincode,那么,这个节点必须事先安装这个 chaincode。

我们将要安装的 chaincode 位于 container 中的目录 /opt/gopath/src/github.com/chaincode/chaincode_example02/go (环境变量${CC_SRC_PATH})。 在主机中的位置是 fabric/fabric-samples/chaincode/chaincode_example02/go。我们可以打开文件 chaincode_example02.go 查看代码。

它主要实现了 Init 与 Invoke 接口,并通过 Invoke 接口实现了三种操作:invode, delete, query:

清单 10. chaincode_example02.go
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
    ...
}
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
    ...
}
// Transaction makes payment of X units from A to B
func (t *SimpleChaincode) invoke(stub shim.ChaincodeStubInterface, args []string) pb.Response {
    ...
}
// Deletes an entity from state
func (t *SimpleChaincode) delete(stub shim.ChaincodeStubInterface, args []string) pb.Response {
    ...
}
// query callback representing the query of a chaincode
func (t *SimpleChaincode) query(stub shim.ChaincodeStubInterface, args []string) pb.Response {
    ...
}

显示更多
在 cli container 中安装 chaincode:

清单 11. 在 cli container 中安装 chaincode
# installChaincode in peer 0 1
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=$PEER0_ORG1_CA
export CORE_PEER_MSPCONFIGPATH=$ORG1_MSP
export CORE_PEER_ADDRESS=peer0.org1.example.com:7051
export VERSION="1.0"
peer chaincode install -n mycc -v ${VERSION} -l ${LANGUAGE} -p ${CC_SRC_PATH}

# installChaincode in peer 0 2
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=$PEER0_ORG2_CA
export CORE_PEER_MSPCONFIGPATH=$ORG2_MSP
export CORE_PEER_ADDRESS=peer0.org2.example.com:7051
export VERSION="1.0"
peer chaincode install -n mycc -v ${VERSION} -l ${LANGUAGE} -p ${CC_SRC_PATH}

显示较少
实例化 Chaincode
Chaincode 安装后需要实例化才能使用,在 channel 中,一个 chaincode 只需要进行一次 instantiate 操作即可。这个步骤需要比较长的时间(在当前测试环境里需要 10 秒左右)。

export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=$PEER0_ORG2_CA
export CORE_PEER_MSPCONFIGPATH=$ORG2_MSP
export CORE_PEER_ADDRESS=peer0.org2.example.com:7051
export VERSION="1.0"
peer chaincode instantiate -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED
--cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -l ${LANGUAGE} -v ${VERSION} -c
'{"Args":["init","a","100","b","200"]}' -P "AND ('Org1MSP.peer','Org2MSP.peer')"

显示更多
Chaincode –Query
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'

得到结果为 100,即为这个 channel ledger 中 “a” 所对应的初始的值。

peer chaincode query 命令会获得经背书的 chaincode 执行结果。但它不会产生 transaction。

Chaincode –Invoke
export PEER_CONN_PARMS="--peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles
/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:7051 --tlsRootCertFiles
/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt"
peer chaincode invoke -o orderer.example.com:7050 --tls
$CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc
$PEER_CONN_PARMS -c '{"Args":["invoke","a","b","10"]}'

显示较少
通过这个命令会产生一个 transaction,将 a 对应的值减 10,同时将 b 的值加 10。

再次查询:

peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'

返回结果为 90。

Chaincode – Query(2)
尝试连接 peer1.org1.example.com 进行查询:

export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=$PEER0_ORG1_CA
export CORE_PEER_MSPCONFIGPATH=$ORG1_MSP
export CORE_PEER_ADDRESS=peer1.org1.example.com:7051
export VERSION="1.0"
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'

显示较少
返回错误结果如下:

Error: endorsement failure during query. response: status:500 message:"cannot retrieve package for chaincode mycc/1.0, error open /var/hyperledger/production/chaincodes/mycc.1.0: no such file or directory"

因为我们之前并没有在 peer1.org1.example.com 节点上安装 chaincode。我们尝试安装:

peer chaincode install -n mycc -v ${VERSION} -l ${LANGUAGE} -p ${CC_SRC_PATH}

再次进行查询:

peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'

Chaincode Container
在节点的 Chaincode 第一次被实例化或使用激活时,会启动一个 container 以运行 chaincode。再次执行 docker ps 可以看到增加了 3 个 container:

d1a150be4270 dev-peer1.org1.example.com-mycc-1.0-cd123150154e6bf2df7ce682e0b1bcbea...
9506d7970113 dev-peer0.org1.example.com-mycc-1.0-384f11f484b9302df90b453200cfb2517...
3d710c8dc821 dev-peer0.org2.example.com-mycc-1.0-15b571b3ce849066b7ec74497da3b27e5...

显示较少
其他 Channel、Chaincode 操作
仍然在 cli Container 中执行以下操作。

列出当前节点所有加入 的 C hannel:

peer channel list

列出当前节点所 有已经安装的 Chaincode :

peer chaincode list --installed

获取特 定 C hanne l 的 区块链信息:

peer channel getinfo -c $CHANNEL_NAME

可得到返回结果类似如下:

Blockchain info: {"height":7,"currentBlockHash":"OV8dnCVwKhfJlLUsIg+orqpdMnn6cEjWDxq+1njNBZM=","previousBlockHash":"6VjT1rtVhY6jSCz+e5pWQzw7eMOkOewcfT7JkRXkw0c="}

其中,block height 的值是 7。

我们可以进一步获取特定的 Block 的详细内容:

peer channel fetch 6 mychannel_6.block -o orderer.example.com:7050 -c $CHANNEL_NAME --tls
--cafile $ORDERER_CA
configtxgen --inspectBlock mychannel_6.block > mychannel_6.json

显示较少
结束语
我们准备了 Fabric 1.3 所需要的系统环境,下载了 Fabric 示例镜像、文件,部署了第一个 Fabric 区块链示例网络 first-network,并一步一步地分解执行了 byfn.sh 中的内容。在此过程中,对每一步骤的作用进行了讲解,也分析了所用的资源文件,与产生的结果。

希望通过这个初始的比较简单的示例,我们可以对 Fabric 建立起直观印象,了解到它的一些概念、结构与运行方式。

为方便读者,本文中”byfn 启动过程详解”中用到的命令被集中于文件 stepbystep.txt 中,可以下载并分步执行。

在本系列的下一篇文章中,我们将一起学习开发、部署 Chaincode,并学习如何与数据库结合,使用 Private data 等 Fabric 特性,并探讨如何将一个新的节点加入区块链。

参考资源
参考 IBM Blockchain Dev Center ,查看 IBM 在区块链领域的最新信息。
参考 Hyperledger Projects ,了解开源项目 Hyperledger 的主要内容。
参考 Hyperledger Fabric Documentation ,了解开源项目 Fabric 的主要内容。
参考 PKI ,了解 PKI 相关内容。
参考 openssl ,了解证书上、签名、加密的相关操作。
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值