转载请注明出处:www.huamo.online
字节杭州 求贤若渴:
end-to-end
验证提供了一个示例fabric
网络,包括2个组织,每个组织包含2个peer
节点,以及1个基于Kafka
的排序服务。
这个验证用到了2个基础工具,用来创建一个带有数字签名验证的和访问控制的实用交易网络:
每一个工具用到一个yaml
配置文件,在里面我们指定了网络的拓扑结构(cryptogen
需用到),以及用于各种配置操作的证书的位置(configtxgen
需用到)。当这些工具都已被成功运行后,我们就可以发布这个网络了。工具的更多细节和网络的架构在下文描述。现在,让我们开始吧…
前置操作【Prerequisites
】
编译二进制包
先生成特定平台的,
cryptogen
和configtxgen
二进制包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 | REPOSITORY TAG IMAGE ID CREATED SIZE |
如果在编译过程中失败了,可以修复错误,然后执行
make clean
,最后再make docker
。
Cryptogen
工具
我们将使用cryptogen
工具来为我们的各种网络实体生成加密内容(x509
证书)。证书基于PKI
标准实现,通过回溯到一个共同的信任锚点来实现验证。
它是如何工作的?
Cryptogen
使用一个文件 - crypto-config.yaml
- 包含了网络的拓扑结构,并且允许我们为组织以及组织中的各种组件,生成一系列的证书。每个组织被提供了一个唯一的根证书(ca-cert
),将指定的组件(peers
和orderers
)绑定到了该组织上。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
组织(Org1
和Org2
)每个都管理和维护2个peer
节点。这个文件也指定了一个联盟 - SampleConsortium
- 包含我们的2个Peer组织的联盟。对文件顶部的Profiles
区域中内容多留意下。你会发现我们有2个不同的顶级属性。一个是给orderer创世块用的 - TwoOrgsOrdererGenesis
- 另一个是给channel
用的 - TwoOrgsChannel
。这些顶级属性是很重要的,当我们创建配置文件时我们会把它们作为参数传入进去。这个yaml
文件还包含了2个值得注意的额外规范。首先,我们为每一个Peer
组织指定了锚peer
节点(peer0.org1.example.com
和peer0,org2.example.com
)。然后,我们为每一个成员指定了MSP
文件夹路径,这就使我们可以在orderer
创世块中按顺序的存储每个组织的根证书。这是一个很关键的概念。现在任何与排序服务通信的网络实体都能够被orderer
验证其数字签名了。
运行shell
脚本
确认你在examples/e2e_cli
目录下,这是shell
脚本所在的位置。为你的channel
起一个独特的名字,然后替换掉下方的<channel-ID>
参数。如果你不提供一个名字,那么这个脚本会运行失败。
1 | $ cd examples/e2e_cli |
这个脚本的输出有些多,因为它会生成加密库和多个文件。但是,你会在终端里看到5个截然不同的说明信息,如下所示:
1 | ########################################################## |
这些配置交易将会绑定参与成员和它们的网络组件的加密内容,并且生成1个orderer
创世块和3个channel交易文件。对于启动一个Fabric网络,以及创建一个channel来在上面做交易,这些文件都是必要的。
用Docker
运行end-to-end
测试
确保你在/e2e_cli
目录下。然后使用docker-compose
创建网络实体运行测试。注意你可以使用TIMEOUT
变量(以秒为单位),以便你的cli
容器不会在脚本结束后立马退出。你可以使用任何数值:
1 | # TIMEOUT变量是可选的 |
如果你创建了一个特定的channel名称,确保将它传入到了参数中。比如,
1 | $ CHANNEL_NAME=abc TIMEOUT=1000 docker-compose -f docker-compose-cli.yaml up -d |
等待,大概60s左右。在后台,有交易发送给peers。执行docker ps
命令来查看你激活的容器。你应该能够看到如下的输出:
1 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES |
如果你设置了一个比较大的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.com
和peer1.org1.example.com
隶属于Org1
;peer0.org2.example.com
和peer1.org2.example.com
隶属于Org2
。这些关系都定义在
crypto-config.yaml
文件中,并且MSP
路径在我们的docker-compose
文件中指定了。Org1MSP(
peer0.org1.example.com
)和Org2MSP(peer0.org2.example.com
)的锚peer
随后都会被更新,我们实现这一步是通过将Org1MSPanchors.tx
和Org2MSPanchors.tx
配置传入到orderer
服务中实现的,同时传入的还有我们的channel
名称。一个
chaincode
-chaincode_example02
- 被安装在了peer0.org1.example.com
和peer0.org2.example.com
上。这个
chaincode
随后在peer0.org2.example.com
被instantiate
。初始化操作会将这个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
的结果也会被返回。由于并没有发生写操作,所以对a
的query
依然会返回值100
。有一个
invoke
调用发送到了peer0.org1.example.com
上,该调用是”a向b转10块钱”。这个
chaincode
随后还被安装在了peer1.org2.example.com
上。有一个对
a
的query
操作发送到了peer1.org2.example.com
上。这会启动第3个chaincode
容器,名为dev-peer1.org2.example.com-mycc-1.0
。并返回值90
,这正确的反映了之前的交易,即将a
的值减10
。
这证明了什么?
证明了chaincode
必须要安装在一个peer
上,以便于它能够成功地在账本上执行读/写操作。并且,一个peer
上的chaincode
不会马上就启动容器,直到有一个init
操作或者有交易发生时才会运行 - 读/写操作 - 都是和chaincode
相关的(比如:对a
的query
操作)。交易可以使容器开始运行。另外,在一个channel
中的所有peer
都会维护一个完全相同的账本拷贝,这个账本由区块链构成,存储了不可篡改的,在区块中有序记录的数据,并且还维护了一个状态数据库,来维持当前的fabric
状态。这包含了那些没有安装chaincode
的peer
(比如:上面例子中的peer1.org1.example.com
),它们依然也有账本拷贝和状态数据库。最后,这个被安装后的合约就是可以访问的(比如:上面例子中的peer1.org2.example.com
),因为它在peer0.org2.example.com
上已经被初始化了。
我如何查看这些交易?
可以查看CLI
容器的logs
:
1 | $ docker logs -f cli |
你会看到如下输出:
1 | 2017-05-16 17:08:01.366 UTC [msp] GetLocalMSP -> DEBU 004 Returning existing local MSP |
我如何查看chaincode
的logs
可以查看每一个chaincode
容器的logs
,来检查发生在各个容器上面的每一笔交易。下面是各个容器的集合输出:
1 | $ docker logs dev-peer0.org2.example.com-mycc-1.0 |
我全都要(ALL in one)
你也可以生成配置文件和加密资料,并且使用单独的shell
脚本进行测试。crptogen
,configtxgen
,以及docker-compose
命令都集合到了脚本里。如果你不提供一个channel ID
,那么脚本就会使用默认名字mychannel
。cli
容器的超时参数是一个可选值;如果你不去设置它,那么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