Fabric End-to-End流程

转载请注明出处:www.huamo.online
字节杭州 求贤若渴:

  1. https://job.toutiao.com/s/JXTdQaH
  2. https://job.toutiao.com/s/JXTMWW3
  3. https://job.toutiao.com/s/JXT1tpC
  4. https://job.toutiao.com/s/JXTdu6h

end-to-end验证提供了一个示例fabric网络,包括2个组织,每个组织包含2个peer节点,以及1个基于Kafka的排序服务。

这个验证用到了2个基础工具,用来创建一个带有数字签名验证的和访问控制的实用交易网络:

  • cryptogen - 创建x509证书,用来标识和验证网络中的各种组件。
  • configtxgen - 为orderer节点的启动和channel的创建,生成必需的配置文件(artifacts)。

每一个工具用到一个yaml配置文件,在里面我们指定了网络的拓扑结构(cryptogen需用到),以及用于各种配置操作的证书的位置(configtxgen需用到)。当这些工具都已被成功运行后,我们就可以发布这个网络了。工具的更多细节和网络的架构在下文描述。现在,让我们开始吧…

前置操作【Prerequisites

编译二进制包

  • 先生成特定平台的,cryptogenconfigtxgen二进制包

    1
    2
    $ cd $GOPATH/src/github.com/hyperledger/fabric
    $ make release

    该命令将会在fabric/release文件夹中输出特定平台的二进制包。

  • 接下来,编译Fabric镜像。这一般需要5 ~ 10分钟,所以耐心等候【国内需要更大的耐心…】:

    1
    2
    $ cd $GOPATH/src/github.com/hyperledger/fabric
    $ make docker

在终端运行命令docker images,如果这些镜像都被成功编译,你应该能够看到类似于下面的输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
REPOSITORY                     TAG                   IMAGE ID            CREATED             SIZE
hyperledger/fabric-couchdb latest e2df4dd39ca9 38 minutes ago 1.51 GB
hyperledger/fabric-couchdb x86_64-1.0.0-beta e2df4dd39ca9 38 minutes ago 1.51 GB
hyperledger/fabric-kafka latest 08af4d797266 40 minutes ago 1.3 GB
hyperledger/fabric-kafka x86_64-1.0.0-beta 08af4d797266 40 minutes ago 1.3 GB
hyperledger/fabric-zookeeper latest 444e9e695367 40 minutes ago 1.31 GB
hyperledger/fabric-zookeeper x86_64-1.0.0-beta 444e9e695367 40 minutes ago 1.31 GB
hyperledger/fabric-testenv latest 8678d3101930 41 minutes ago 1.41 GB
hyperledger/fabric-testenv x86_64-1.0.0-beta 8678d3101930 41 minutes ago 1.41 GB
hyperledger/fabric-buildenv latest 60911392c82e 41 minutes ago 1.33 GB
hyperledger/fabric-buildenv x86_64-1.0.0-beta 60911392c82e 41 minutes ago 1.33 GB
hyperledger/fabric-orderer latest 2afab937b9cc 41 minutes ago 182 MB
hyperledger/fabric-orderer x86_64-1.0.0-beta 2afab937b9cc 41 minutes ago 182 MB
hyperledger/fabric-peer latest 9560e58e8089 41 minutes ago 185 MB
hyperledger/fabric-peer x86_64-1.0.0-beta 9560e58e8089 41 minutes ago 185 MB
hyperledger/fabric-javaenv latest 881ca5219fad 42 minutes ago 1.43 GB
hyperledger/fabric-javaenv x86_64-1.0.0-beta 881ca5219fad 42 minutes ago 1.43 GB
hyperledger/fabric-ccenv latest 28af77ffe9e9 43 minutes ago 1.29 GB
hyperledger/fabric-ccenv x86_64-1.0.0-beta 28af77ffe9e9 43 minutes ago 1.29 GB
hyperledger/fabric-baseimage x86_64-0.3.0 f4751a503f02 3 months ago 1.27 GB
hyperledger/fabric-baseos x86_64-0.3.0 c3a4cf3b3350 3 months ago 161 MB

如果在编译过程中失败了,可以修复错误,然后执行make clean,最后再make docker

Cryptogen工具

我们将使用cryptogen工具来为我们的各种网络实体生成加密内容(x509证书)。证书基于PKI标准实现,通过回溯到一个共同的信任锚点来实现验证。

它是如何工作的?

Cryptogen使用一个文件 - crypto-config.yaml - 包含了网络的拓扑结构,并且允许我们为组织以及组织中的各种组件,生成一系列的证书。每个组织被提供了一个唯一的根证书(ca-cert),将指定的组件(peersorderers)绑定到了该组织上。Fabric中的交易和通讯都由一个实体的私钥(keystore)进行签名,然后由相应的公钥(signcerts)进行验证。在这个yaml文件中你会看到一个count变量。我们使用这个值指定了每个组织的peer数量;这里我们指定了2个peer。这个模板的其它部分都是非常浅显易懂的。

在我们运行了工具之后,证书会被放在crypto-config目录下。

Configtxgen工具

configtxgen工具用来生成4种文件:orderer节点的启动块(bootstrap block),fabric channel的配置交易(channel configuration transaction),以及2个锚peer交易(anchor peer transactions)– 一个Peer组织一个。

orderer block是排序服务的创世块,channel交易文件会在channel创建时广播给orderer节点。而锚peer节点交易,就像名字表示的那样,在这个channel上为每个组织指定一个锚peer节点。

它是如何工作的?

Configtxgen读取一个文件 - configtx.yaml - 文件中包含了样例网络的定义。有3个成员 - 一个Orderer组织(OrdererOrg),和2个Peer组织(Org1Org2)每个都管理和维护2个peer节点。这个文件也指定了一个联盟 - SampleConsortium - 包含我们的2个Peer组织的联盟。对文件顶部的Profiles区域中内容多留意下。你会发现我们有2个不同的顶级属性。一个是给orderer创世块用的 - TwoOrgsOrdererGenesis - 另一个是给channel用的 - TwoOrgsChannel。这些顶级属性是很重要的,当我们创建配置文件时我们会把它们作为参数传入进去。这个yaml文件还包含了2个值得注意的额外规范。首先,我们为每一个Peer组织指定了锚peer节点(peer0.org1.example.compeer0,org2.example.com)。然后,我们为每一个成员指定了MSP文件夹路径,这就使我们可以在orderer创世块中按顺序的存储每个组织的根证书。这是一个很关键的概念。现在任何与排序服务通信的网络实体都能够被orderer验证其数字签名了。

运行shell脚本

确认你在examples/e2e_cli目录下,这是shell脚本所在的位置。为你的channel起一个独特的名字,然后替换掉下方的<channel-ID>参数。如果你不提供一个名字,那么这个脚本会运行失败。

1
2
$ cd examples/e2e_cli
$ ./generateArtifacts.sh <channel-ID>

这个脚本的输出有些多,因为它会生成加密库和多个文件。但是,你会在终端里看到5个截然不同的说明信息,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
##########################################################
##### Generate certificates using cryptogen tool #########
##########################################################

##########################################################
######### Generating Orderer Genesis block ##############
##########################################################

#################################################################
### Generating channel configuration transaction 'channel.tx' ###
#################################################################

#################################################################
####### Generating anchor peer update for Org0MSP ##########
#################################################################

#################################################################
####### Generating anchor peer update for Org1MSP ##########
#################################################################

这些配置交易将会绑定参与成员和它们的网络组件的加密内容,并且生成1个orderer创世块和3个channel交易文件。对于启动一个Fabric网络,以及创建一个channel来在上面做交易,这些文件都是必要的。

Docker运行end-to-end测试

确保你在/e2e_cli目录下。然后使用docker-compose创建网络实体运行测试。注意你可以使用TIMEOUT变量(以秒为单位),以便你的cli容器不会在脚本结束后立马退出。你可以使用任何数值:

1
2
# TIMEOUT变量是可选的
$ CHANNEL_NAME=<channel-id> TIMEOUT=<value> docker-compose -f docker-compose-cli.yaml up -d

如果你创建了一个特定的channel名称,确保将它传入到了参数中。比如,

1
$ CHANNEL_NAME=abc TIMEOUT=1000 docker-compose -f docker-compose-cli.yaml up -d

等待,大概60s左右。在后台,有交易发送给peers。执行docker ps命令来查看你激活的容器。你应该能够看到如下的输出:

1
2
3
4
5
6
7
8
9
CONTAINER ID        IMAGE                                 COMMAND                  CREATED             STATUS              PORTS                                              NAMES
b568de3fe931 dev-peer1.org2.example.com-mycc-1.0 "chaincode -peer.a..." 4 minutes ago Up 4 minutes dev-peer1.org2.example.com-mycc-1.0
17c1c82087e7 dev-peer0.org1.example.com-mycc-1.0 "chaincode -peer.a..." 4 minutes ago Up 4 minutes dev-peer0.org1.example.com-mycc-1.0
0e1c5034c47b dev-peer0.org2.example.com-mycc-1.0 "chaincode -peer.a..." 4 minutes ago Up 4 minutes dev-peer0.org2.example.com-mycc-1.0
71339e7e1d38 hyperledger/fabric-peer "peer node start -..." 5 minutes ago Up 5 minutes 0.0.0.0:8051->7051/tcp, 0.0.0.0:8053->7053/tcp peer1.org1.example.com
add6113ffdcf hyperledger/fabric-peer "peer node start -..." 5 minutes ago Up 5 minutes 0.0.0.0:10051->7051/tcp, 0.0.0.0:10053->7053/tcp peer1.org2.example.com
689396c0e520 hyperledger/fabric-peer "peer node start -..." 5 minutes ago Up 5 minutes 0.0.0.0:7051->7051/tcp, 0.0.0.0:7053->7053/tcp peer0.org1.example.com
65424407a653 hyperledger/fabric-orderer "orderer" 5 minutes ago Up 5 minutes 0.0.0.0:7050->7050/tcp orderer.example.com
ce14853db660 hyperledger/fabric-peer "peer node start -..." 5 minutes ago Up 5 minutes 0.0.0.0:9051->7051/tcp, 0.0.0.0:9053->7053/tcp peer0.org2.example.com

如果你设置了一个比较大的TIMEOUT值,你还可以看到你的cli容器。

后台究竟发生了什么?

  • 一个脚本 - script.sh - 被放在了cli容器中。这个脚本会使用提供的channel名字,以及用于channel设置的channel.tx文件,执行createChannel命令。

  • createChannel的输出是一个创世块 - <your_channel_name>.block - 会存在peers的文件系统中,并且包含了由channel.tx指定的channel配置。

  • joinChannel命令用于所有4个peer节点,用上一步产生的创世块作为输入。该命令指示这些peer节点加入<your_channel_name>,并且创建一个以<your_channel_name>.block开始的链。

  • 现在我们有了一个包含4个peer节点,和2个组织的链。这就是我们TwoOrgsChannel描述的样子。

  • peer0.org1.example.compeer1.org1.example.com隶属于Org1peer0.org2.example.compeer1.org2.example.com隶属于Org2

  • 这些关系都定义在crypto-config.yaml文件中,并且MSP路径在我们的docker-compose文件中指定了。

  • Org1MSP(peer0.org1.example.com)和Org2MSP(peer0.org2.example.com)的锚peer随后都会被更新,我们实现这一步是通过将Org1MSPanchors.txOrg2MSPanchors.tx配置传入到orderer服务中实现的,同时传入的还有我们的channel名称。

  • 一个chaincode - chaincode_example02 - 被安装在了peer0.org1.example.compeer0.org2.example.com上。

  • 这个chaincode随后在peer0.org2.example.cominstantiate。初始化操作会将这个chaincode添加到channel中,针对目标peer启动docker容器,并且用和chaincode相关的key-value对进行初始化。在这个例子中初始化值为["a","100","b","200"]。初始化结束后,以dev-peer0.org2.example.com-mycc-1.0为名字的容器开始运行。

  • a键的query发送到了peer0.org1.example.com上。相关的chaincode前面已经安装在了peer0.org1.example.com上,所以这将会为Org1 peer0运行一个名为dev-peer0.org1.example.com-mycc-1.0的容器。query的结果也会被返回。由于并没有发生写操作,所以对aquery依然会返回值100

  • 有一个invoke调用发送到了peer0.org1.example.com上,该调用是”a向b转10块钱”。

  • 这个chaincode随后还被安装在了peer1.org2.example.com上。

  • 有一个对aquery操作发送到了peer1.org2.example.com上。这会启动第3个chaincode容器,名为dev-peer1.org2.example.com-mycc-1.0。并返回值90,这正确的反映了之前的交易,即将a的值减10

这证明了什么?

证明了chaincode必须要安装在一个peer上,以便于它能够成功地在账本上执行读/写操作。并且,一个peer上的chaincode不会马上就启动容器,直到有一个init操作或者有交易发生时才会运行 - 读/写操作 - 都是和chaincode相关的(比如:对aquery操作)。交易可以使容器开始运行。另外,在一个channel中的所有peer都会维护一个完全相同的账本拷贝,这个账本由区块链构成,存储了不可篡改的,在区块中有序记录的数据,并且还维护了一个状态数据库,来维持当前的fabric状态。这包含了那些没有安装chaincodepeer(比如:上面例子中的peer1.org1.example.com),它们依然也有账本拷贝和状态数据库。最后,这个被安装后的合约就是可以访问的(比如:上面例子中的peer1.org2.example.com),因为它在peer0.org2.example.com上已经被初始化了。

我如何查看这些交易?

可以查看CLI容器的logs:

1
$ docker logs -f cli

你会看到如下输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2017-05-16 17:08:01.366 UTC [msp] GetLocalMSP -> DEBU 004 Returning existing local MSP
2017-05-16 17:08:01.366 UTC [msp] GetDefaultSigningIdentity -> DEBU 005 Obtaining default signing identity
2017-05-16 17:08:01.366 UTC [msp/identity] Sign -> DEBU 006 Sign: plaintext: 0AB1070A6708031A0C08F1E3ECC80510...6D7963631A0A0A0571756572790A0161
2017-05-16 17:08:01.367 UTC [msp/identity] Sign -> DEBU 007 Sign: digest: E61DB37F4E8B0D32C9FE10E3936BA9B8CD278FAA1F3320B08712164248285C54
Query Result: 90
2017-05-16 17:08:15.158 UTC [main] main -> INFO 008 Exiting.....
===================== Query on PEER3 on channel 'mychannel' is successful =====================

===================== All GOOD, End-2-End execution completed =====================


_____ _ _ ____ _____ ____ _____
| ____| | \ | | | _ \ | ____| |___ \ | ____|
| _| | \| | | | | | _____ | _| __) | | _|
| |___ | |\ | | |_| | |_____| | |___ / __/ | |___
|_____| |_| \_| |____/ |_____| |_____| |_____|

我如何查看chaincodelogs

可以查看每一个chaincode容器的logs,来检查发生在各个容器上面的每一笔交易。下面是各个容器的集合输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ docker logs dev-peer0.org2.example.com-mycc-1.0
04:30:45.947 [BCCSP_FACTORY] DEBU : Initialize BCCSP [SW]
ex02 Init
Aval = 100, Bval = 200

$ docker logs dev-peer0.org1.example.com-mycc-1.0
04:31:10.569 [BCCSP_FACTORY] DEBU : Initialize BCCSP [SW]
ex02 Invoke
Query Response:{"Name":"a","Amount":"100"}
ex02 Invoke
Aval = 90, Bval = 210

$ docker logs dev-peer1.org2.example.com-mycc-1.0
04:31:30.420 [BCCSP_FACTORY] DEBU : Initialize BCCSP [SW]
ex02 Invoke
Query Response:{"Name":"a","Amount":"90"}

我全都要(ALL in one)

你也可以生成配置文件和加密资料,并且使用单独的shell脚本进行测试。crptogenconfigtxgen,以及docker-compose命令都集合到了脚本里。如果你不提供一个channel ID,那么脚本就会使用默认名字mychannelcli容器的超时参数是一个可选值;如果你不去设置它,那么cli容器将在脚本结束时退出。

1
$ ./network_setup.sh up

或者

1
$ ./network_setup.sh up <channel-ID> <timeout-value>

全部清理可以用以下命令:

1
$ ./network_setup.sh down <channel-ID>

参考文章

转载请注明出处:www.huamo.online