在刚接触fabric的时候一般都是直接跟着wiki的教程一步步安装配置,执行一系列命令,最终将其运行起来,但很多人对其中的运行流程及其基础知识点可能不是很了解。基于此今天我将以$FABRIC_ROOT/examples/e2e_cli/ 经典Demo为例来分享一些我的理解,希望可以对入门者有所帮助。
生成证书
fabric是有准入门槛的联盟链,通过MSP服务来进行对其中的成员进行统一管理。既然提到了MSP,那就肯定离不开证书这一概念。证书的作用一方面是用于验证消息的签名是否有效从而验证交易是否有效,另一方面可以用于确认该证书的拥有者身份。
所以要运行起整个fabric网络首先得生成证书,生成证书的配置文件在crypto-config.yaml中,根据自己的需求定义好OrdererOrgs和PeerOrgs信息,之后在generateArtifacts.sh脚本中执行generateCerts方法即可在当前目录下生成包含证书文件的crypto-config目录。
ordererOrganizations
example.com
ca # 包含给Orderer组织颁发MSP证书的ca的公私钥
msp # 包含Orderer组织的msp相关证书(admincerts,cacerts,tlscacerts)
orderers
orderer.example.com
msp
admincerts # 管理员证书
cacerts # 给Orderer组织颁发MSP证书的ca的证书
keystore # 当前Orderer组织的私钥
signcerts # 当前Orderer组织的证书(包含公钥)
tlscacerts # 给Orderer组织颁发TLS证书的ca的证书
tls
ca.crt # 给Orderer组织颁发TLS证书的ca的证书
server.crt # 当前Orderer组织的tls证书(包含公钥)
server.key # 当前Orderer组织的tls私钥
tlsca # 包含给Orderer组织颁发TLS证书的ca的公私钥
users # 包含Orderer下普通用户和管理员用户的msp和tls证书
以上是以Orderer组织为例说明了下生成的证书目录层级结构及其对应的目录或文件的含义,Peer组织的类似。
TLS(Transport Layer Security Protocol)是Https建立在SSL 3.0之上的一个标准的安全传输层协议。负责安全通信,安全传输数据包。需要做数字签名的认证才能正常的去继续做http的握手然后再做交互。
MSP(Membership Service Provider)是负责成员是否被认证过进入我们这个网络里的安全管理
生成genesis.block
证书生成好之后接下来就可以定义Orderer的配置以生成genesis.block了。该配置在configtx.yaml中的Profiles.TwoOrgsOrdererGenesis下。
TwoOrgsOrdererGenesis:
Capabilities:
<<: *ChannelCapabilities
Orderer:
<<: *OrdererDefaults
Organizations:
- *OrdererOrg
Capabilities:
<<: *OrdererCapabilities
Consortiums:
SampleConsortium:
Organizations:
- *Org1
- *Org2
*OrdererDefaults:引用包含了Orderer的基本信息如下
- OrdererType(共识类型)是solo还是kafka。solo就是一个模拟kafka的本地的单机的文件系统实现的消息队列,缺点是在执行速度和效率上肯定不如kafka,测试环境一般就用solo,生产环境用kafka。kafka目前是通过消息队列保证所有的节点对transaction的时间有一个共识,并没有具体的像比特币之类的pow共识算法,以前的0.6版本有pbft算法,但1.0以后还没有实现。
- Addresses:Orderer服务的地址列表
- BatchTimeout:Orderer节点的出块时间
- BatchSize:区块大小包含最大交易笔数(MaxMessageCount),最大区块大小(AbsoluteMaxBytes)以及建议区块大小(PreferredMaxBytes)
- Kafka:包含brokers列表。当设置了OrdererType为kafka才生效,如果是solo则该配置不生效。
*OrdererOrg:引用包含了OrdererOrg的MSP信息
- Name:OrdererOrg
- ID:Orderer的MSPID
- MSPDir:Orderer组织的MSP目录(就是上面生成的msp目录)
*Org1 同OrdererOrg引用一样
*Org2 同OrdererOrg引用一样
综上,通过这些配置生成genesis.block之后,Orderer服务就会明确所使用的共识类型,服务地址列表,出块时间,出块大小。同时也就拥有了Orderer节点MSPID和MSP证书(包含Orderer的管理员证书,Orderer的CA证书,Orderer的TLS CA证书),以及联盟里面的所有Org(这里是Org1和Org2)的MSPID和MSP证书(包含Org的管理员证书,Org的CA证书,Org的TLS CA证书),待整个fabric网络运行起来之后Orderer服务便可以利用这些CA证书很容易的验证节点传过来的证书是否有效。
生成通道配置交易
Orderer配置好之后,同样通过configtx.yaml中的Profiles.TwoOrgsChannel配置信息来生成一个通道配置类型的交易(ConfigUpdateEnvelope)。
TwoOrgsChannel:
Consortium: SampleConsortium
Application:
<<: *ApplicationDefaults
Organizations:
- *Org1
- *Org2
Capabilities:
<<: *ApplicationCapabilities
启动网络
在e2e_cli这个Demo项目里面我们是通过Docker的方式来运行fabric网络的。正常我们的docker,比如在我们本地已经build出了很多docker image,比如我们有hyperledger/fabric-peer,如果想让docker image运行起来,一般都是通过docker run这样的命令,比如我单独去run一个peer,docker run + 这个docker image的名字,然后加一些参数就启动了一个docker container,docker container运行了这个docker image的环境。如果有多个image,我们手动的一个个去启动太麻烦了,我们想有一个配置文件,能让批量的很多很多的节点一起启动,那这个功能就引出了docker-compose。简单说,docker-compose就是把多个docker image启动的定义和配置组合在一起放在一个文件里一起启动起来。
# 启动fabric网络所需要的所有Docker Container并在后台挂起
docker-compose -f docker-compose-cli.yaml up -d
# 进入container_name为 orderer.example.com 的Docker Container
docker exec -it orderer.example.com bash
# 查看docker日志
docker logs -f containerID/containerName
docker logs -f orderer.example.com
正常情况下在docker-compose-cli.yaml里面名为“cli”的docker container在一运行起来以后就会执行脚本scripts/script.sh,该脚本中包含了创建通道、加入通道、更新锚节点、安装chaincode、实例化chaincode、query/invoke chaincode等一系列操作,为了一步步进行,因此在启动网络前需要在docker-compose-cli.yaml中做如下修改
# 将名为“cli”的docker-container原来的命令注释掉并改为如下
command: /bin/bash -c 'sleep 100000'
#command: /bin/bash -c './scripts/script.sh ${CHANNEL_NAME}; sleep $TIMEOUT'
操作网络
通过docker-compose将fabric所需要的docker container都run起来之后,就可以通过 docker exec -it cli bash 进入相应的container,从而对fabric网络进行操作。具体的操作命令在 scripts/script.sh 中都有,这里就不再赘述了。下面用一张图来描述在对网络进行一系列操作的过程中cli/sdk端、peer端、order端之间的交互过程。
说明:
- 如果在sdk/cli侧设置 $CORE_PEER_TLS_ENABLED = TRUE,则需要且仅仅在Create Channel、UpdateAnchorPeers、Instantiate Chaincode、Invoke Chaincode的时候指定OrdererCA,该配置用于设置是否开启TLS,TLS就是那个安全的SSL 3.0的时候安全的一个认证方式,相当于在数据传输之前做一个安全的认证,这里只是判断它要不要做安全认证。
- 在fabric network中,orderer侧其实也会保存有自己的区块链也就是ledger,而剩下所有的Organization中的所有的peer侧都会分别维护一个ledger和一个state db,图中为了简洁没有文字标出,这里做下解释。
- peer节点的本地账本保存位置为:/var/hyperledger/production/ledgerData/chains/chains/mychannel
- orderer里面的mychannel目录是orderer这边来存放transaction和block的位置,所有的transaction都要提交到orderer这边让orderer做一个transaction的排序,排序好之后orderer
会把block分发下去给每一个Org的主节点(leader peer)节点去同步,所以orderer本地也是存在一个block的链(账本)的,保存位置为:/var/hyperledger/production/orderer/chains/mychannel。 - 这里所说的查看peer和orderer的账本路径前提是要进入到其对应的docker container中。
实例化过程
fabric网络启动好,创建channel,加入channel,安装chaincode之后必须实例化chaincode才可以进行query/invoke操作,而instantiate chaincode这一过程也是整个过程中花时间最久的,好多新入门的伙伴在这一块也容易混淆,所以这里单独摘出来分享一下。
chaincode的instantiate过程这样的。首先peer节点需要对chaincode做编译,它会在fabric-ccenv环境里面把chaincode build,利用fabric-ccenv创建一个新的docker container并把chaincode装载进去,chaincode在这个新的docker container里面运行起来,chaincode首先会去到peer节点去注册一下,然后peer节点会允许它注册成功,peer节点做初始化,调用chaincode的init方法,之后等待别人调用。由于他们隔离在不同的container里面,之后chaincode和peer一直都会有一个keepalive的长链接(互相发送数据包)来保护他们之间的链接不被断开。
说明:
- 在一个channel中同一个chaincode只需要做一次instantiate就可以了,其它的节点只需要安装了就可以不需要再次实例化,当cli/sdk去调用到其它节点的chaincode时候,它会自动的在被调用的时候去做一次instantiate chaincode并把它装载到一个新的container里面运行起来。
- chaincode是由peer触发去build的,build好之后chaincode被装载到一个新的container运行,它的整个生命周期是由peer管理的,peer在管理chaincode的时候通过一个叫lifecycle的系统chaincode(lscc)来管理我们装载的用户chaincode,所以需要模拟去install一下chaincode,让peer知道有一个新的chaincode来了,peer知道去管理它的生命周期。
- chaincode运行阶段是一个endorsement背书模拟执行的阶段,它是在跟peer相同的机器上执行,peer创建一个新的container,然后装载chaincode来执行相应的方法。
补充知识点
1、MSP证书解释
- admincerts:管理员证书,它比普通的peer0证书有一些特殊的权限,比如对节点的修改或者配置等操作
- cacerts:里面放的是对这个peer0颁发证书的ca是谁,里面放的是ca的公钥
- keystore:是peer0这个节点msp的自己的私钥
- signcerts:里面放的是这个organization的ca(ca.org1.example.com-cert.pem)给peer0颁发的证书
- tlscacerts:里面放的是对这个peer0办法TLS证书的ca是谁,里面放的是TLS ca的公钥
- admincerts和signcerts都是签发之后的证书,只是他们的角色不同,admincerts对peer0有一些特殊的管理权限,但signcerts只是一个普通的certs
2、TLS证书解释
- ca.crt:TLS安全认证过程的时候验证证书的ca
- server.crt:节点本身的TLS证书
- server.key:节点本身的TLS私钥
3、命令行查看证书内容
openssl x509 -in peer0.org1.example.com-cert.pem -text
4、如果在当前的某个Organization中加入一个新的peer节点,则不需要更新orderer排序服务的配置,只需要给peer用所属Organization的rootca给其颁发一套证书即可;而当新加入一个新的Organization的时候我们需要更新orderer排序服务的配置。即新的Organization它的root ca是什么(msp的root ca是什么,tls的root ca是什么),然后我们拿它去验证一个成员在不在这个Organization里面
5、fabric-ca的作用是encroll注册,准入,通过name和org去获得token,以后访问就用token访问,跟msp证书是两回事。token认证既不是msp认证,又不是tls认证
6、利用configtxlator工具查看genesis.block内容,其实它就是一个common.Block(protos/common/common.pb.go)格式的结构体序列化以后生成的文件,所以反序列化的时候需要用common.Block才能把它解开,具体步骤如下
vagrant@hyperledger-devenv:523f644:/opt/gopath/src/github.com/hyperledger/fabric/release/linux-amd64/bin$ ./configtxlator start
2018-05-01 09:32:12.726 UTC [configtxlator] startServer -> INFO 001 Serving HTTP requests on 0.0.0.0:7059
configtxlator start 启动工具服务
http://127.0.0.1:7059/protolator/decode/common.Block
7、如果想要更改peer的功能,则在修改完peer部分的代码之后需要在$FABRIC_HOME下重新执行maker docker命令以生成新的fabric-peer镜像
8、fabric-baseos镜像是在peer节点在编译chaincode的时候它需要baseos作为编译环境里的一个os的基础
9、balance-transfer是一个完整的使用了fabric-node-sdk的一个client端,它能跟区块链peer,orderer做交互,它可以去配置orderer,创建channel,它可以去配置peer,让peer节点加入channel,都是可以做的。可以理解为之前通过CLI可以做的所有任务,在sdk下都可以完成,而且功能更强大,因为sdk是可编程的。
10、数字证书包含了证书原文、加密哈希算法以及ca私钥签名后的证书密文三部分内容。在验证数字证书的有效性时只需要知道该证书的颁发组织/机构(CA)的公钥即可。另外PKI体系中的公私钥非对称加密算法公钥解密的场景只有在一种情况下会发生,就是在数字证书有效性校验/数字签名验签的时候。