【转载请标明出处】:https://blog.csdn.net/qq_25870633/article/details/81144847
我们接着上一篇文章 【我的区块链之路】- Hyperledger fabric的简单入门(一)接着讲fabric-samples/first-network目录中来快速启动我们的第一个fabric网络;在上篇文章中我们只是使用了 ./byfn.sh 文件来把fabric网络示例跑起来,我们也可以从日志中查看到 从启动前的准备工作、怎么启动网络及启动网络后如何去安装链码、实例化链码,调用链码等全过程。那么,今天我们来讲解下,这些详细的步骤并通过手动启动网络来实践下整个过程:
首先,我们在启动网络之前需要做一下准备工作,在前一篇文章中我们一笔带过了说在 fabric-samples/bin目录中有几个我们需要的工具 configtxgen 、configtxlator 、cryptogen ;【a】其中 cryptogen 用来生成组织的拓扑结构和相关身份证书生成的文件都放置到 crypto-config目录下(没有的话会自动创建);【b】configtxgen 用来生成 创世区块 genesis.block【创世块 为同道中所有交易的起始块】及生成通道的交易配置文件(主要用来创建通道用 xxxchannel.tx) 及各个组织的锚节点的更新配置文件(如: Org1MspAnchors.tx,生成锚节点配置文件 需要根据组织来生成 如有N个组织那个需要生成N个,包活后面的更新锚节点配置的操作也是一样,需要执根据不同的组织来执行N次);【c】configtxlator 用来解读配置信息及动态网正在运行的网络中添加 新组织;然后下面我们先来说一说 使用 fabric 网络的整个大体的流程。
进入fabric-samples/first-network目录中,执行
cryptogen generate --config=./crypto-config.yaml
或者
cryptogen generate --config=./crypto-config.yaml --output ./crypto-config
【其中 --config=./crypto-config.yaml (关于配置文件的内容我们后续再讨论)为指定使用配置文件默认会使用当前目录的 ; --output ./crypto-config 不指定的话会默认在当前文件夹生成 crypto-config 目录;里面生成了 ordererOrganizations 和 peerOrganizations】我们通过 tree 查看里面的内容为:
.
├── ordererOrganizations
│ │
│ │ ## Orderer的参考 Peer的讲解,因为他们二者差不多的
│ └── example.com
│ ├── ca
│ │ ├── 56d9c0c46acdda38a174a5ba3ffc44726a2c027e16bb22b460413acbcb9b3a90_sk
│ │ └── ca.example.com-cert.pem
│ ├── msp
│ │ ├── admincerts
│ │ │ └── [email protected]
│ │ ├── cacerts
│ │ │ └── ca.example.com-cert.pem
│ │ └── tlscacerts
│ │ └── tlsca.example.com-cert.pem
│ ├── orderers
│ │ └── orderer.example.com
│ │ ├── msp
│ │ │ ├── admincerts
│ │ │ │ └── [email protected]
│ │ │ ├── cacerts
│ │ │ │ └── ca.example.com-cert.pem
│ │ │ ├── keystore
│ │ │ │ └── 2ec1193fe048848eaa8e20666e26c527b791c4fb127d69cae65095bd31b6c80e_sk
│ │ │ ├── signcerts
│ │ │ │ └── orderer.example.com-cert.pem
│ │ │ └── tlscacerts
│ │ │ └── tlsca.example.com-cert.pem
│ │ └── tls
│ │ ├── ca.crt
│ │ ├── server.crt
│ │ └── server.key
│ ├── tlsca
│ │ ├── 2d66be83c519da67bb36b0972256a3b24357fa7f5b3a61f11405bc8b1f4d7c53_sk
│ │ └── tlsca.example.com-cert.pem
│ └── users
│ └── [email protected]
│ ├── msp
│ │ ├── admincerts
│ │ │ └── [email protected]
│ │ ├── cacerts
│ │ │ └── ca.example.com-cert.pem
│ │ ├── keystore
│ │ │ └── a3c1d7e1bc464faf2e3a205cb76ea231bd3ee7010655d3cd31dc6cb78726c4d0_sk
│ │ ├── signcerts
│ │ │ └── [email protected]
│ │ └── tlscacerts
│ │ └── tlsca.example.com-cert.pem
│ └── tls
│ ├── ca.crt
│ ├── client.crt
│ └── client.key
└── peerOrganizations
│
│ ## 组织1的
├── org1.example.com
│ ├── ca ## 存放组织Org1的 【根证书】 和 对应的私钥文件,默认采用EC算法,证书为自签名。组织内的实体将基于该根证书作为证书根。
│ │ ├── 496d6a41ae5f66bf120df3eab3a9d2dc4d268b2ab9a22af891d33d323bbdb5c8_sk
│ │ └── ca.org1.example.com-cert.pem
│ ├── msp ## 存放代表该组织的身份信息
│ │ ├── admincerts ## 组织管理员的身份验证证书,被根证书签名
│ │ │ └── [email protected]
│ │ ├── cacerts ## 组织的根证书,同ca目录下文件
│ │ │ └── ca.org1.example.com-cert.pem
│ │ ├── config.yaml
│ │ └── tlscacerts ## 用于TLS的CA证书,自签名
│ │ └── tlsca.org1.example.com-cert.pem
│ ├── peers ## 存放属于该组织的所有Peer节点
│ │ │
│ │ ├── peer0.org1.example.com ## 第一个peer的信息,包括其msp证书和tls证书两类
│ │ │ |
│ │ │ ├── msp ## msp相关证书
│ │ │ │ ├── admincerts ## 组织管理员的身份验证证书。Peer将基于这些证书来认证交易签署者是否为管理员身份
│ │ │ │ │ └── [email protected]
│ │ │ │ ├── cacerts ## 存放组织的根证书
│ │ │ │ │ └── ca.org1.example.com-cert.pem
│ │ │ │ ├── config.yaml
│ │ │ │ ├── keystore ## 本节点的身份私钥,用来签名
│ │ │ │ │ └── 0f0c2e1835086161f6a10c4bb38c2d89b2cee4e1128cee0fcda4433feb6eb6f8_sk
│ │ │ │ ├── signcerts ## 验证本节点签名的证书,被组织根证书签名
│ │ │ │ │ └── peer0.org1.example.com-cert.pem
│ │ │ │ └── tlscacerts ## TLS连接用到身份证书,即组织TLS证书
│ │ │ │ └── tlsca.org1.example.com-cert.pem
│ │ │ └── tls ## tls相关证书
│ │ │ ├── ca.crt ## 组织的根证书
│ │ │ ├── server.crt ## 验证本节点签名的证书,被组织根证书签名
│ │ │ └── server.key ## 本节点的身份私钥,用来签名
│ │ │
│ │ │
│ │ └── peer1.org1.example.com
│ │
│ │
│ │
│ ├── tlsca ## 存放tls相关的证书和私钥
│ │ ├── 3d39ea82dd5343c261b0480bc13d645a3cee13b7e7aa8c54fd2b5162f709671f_sk
│ │ └── tlsca.org1.example.com-cert.pem
│ │
│ └── users ## 存放属于该组织的用户的实体
│ │
│ ├── [email protected] ## 管理员用户的信息,其中包括msp证书和tls证书两类
│ │ │
│ │ │
│ │ ├── msp ## msp相关证书
│ │ │ |
│ │ │ ├── admincerts ## 组织根证书作为管理员身份验证证书
│ │ │ │ └── [email protected]
│ │ │ ├── cacerts ## 存放组织的根证书
│ │ │ │ └── ca.org1.example.com-cert.pem
│ │ │ ├── keystore ## 本用户的身份私钥,用来签名
│ │ │ │ └── 2b933c0740d857284be98ff218bf279261e55eff2b89d973e0a1f435f7c7d28b_sk
│ │ │ ├── signcerts ## 管理员用户的身份验证证书,被组织根证书签名。要被某个Peer认可,则必须放到该Peer的msp/admincerts目录下
│ │ │ │ └── [email protected]
│ │ │ └── tlscacerts ## TLS连接用的身份证书,即组织TLS证书
│ │ │ └── tlsca.org1.example.com-cert.pem
│ │ |
│ │ └── tls ## 存放tls相关的证书和私钥
│ │ ├── ca.crt ## 组织的根证书
│ │ ├── client.crt ## 管理员的用户身份验证证书,被组织根证书签名
│ │ └── client.key ## 管理员用户的身份私钥,被组织根证书签名
│ │
│ └── [email protected] ## 第一个用户的信息,包括msp证书和tls证书两类
│ │
│ ├── msp ## msp证书相关信息
│ │ ├── admincerts ## 组织根证书作为管理者身份验证证书
│ │ │ └── [email protected]
│ │ ├── cacerts ## 存放组织的根证书
│ │ │ └── ca.org1.example.com-cert.pem
│ │ ├── keystore ## 本用户的身份私钥,用来签名
│ │ │ └── 11ebc5afac42348f84a8882f329d18beee079efd4fd5d9b30389dc82053fc0c9_sk
│ │ ├── signcerts ## 验证本用户签名的身份证书,被组织根证书签名
│ │ │ └── [email protected]
│ │ └── tlscacerts ## TLS连接用的身份证书,被组织根证书签名
│ │ └── tlsca.org1.example.com-cert.pem
│ └── tls ## tls的根证书
│ ├── ca.crt ## 组织的根证书
│ ├── client.crt ## 验证用户签名的身份证书,被根组织证书签名
│ └── client.key ## 用户的身份私钥用来签名
└── org2.example.com
好了现在相应的组织结构及结构下的相应的身份证书都已经依照相应的目录生成存放好了。
身份的各种证书文件,一般包括:
- admincerts :管理员的身份证书文件
- cacerts :信任的根证书文件
- key store :节点的签名私钥文件
- signcerts :节点的签名身份证书文件
- tlscacerts: TLS 连接用的证书
- intermediatecerts (可选):信任的中间证书
- crls (可选):证书撤销列表
- config.yaml (可选):记录OrganizationalUnitldentifiers 信息,包括根证书位置和ID信息
这些身份文件随后可以分发到对应的Orderer 节点和Peer 节点上,并放到对应的MSP路径下,用于签名使用
【生成Orderer的创世块】
configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block
或者
## 先配置临时环境变量 FABRIC_CFG_PATH 来制定 config.yaml的路径
export FABRIC_CFG_PATH=$PWD/first-network 【因为我是在 first-network的上一级目录配置的】
configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block
或者
configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./first-network/channel-artifacts/mygenesis.block --configPath /home/gavin/fabric/fabric-samples/first-network/
【注意:--configPath 为可选项,用来指定使用的 config.yaml 文件;其中 configtxgen 默认需要用到当前目录下的 config.yaml 配置文件(关于配置文件的内容我们后续在讨论),且命令行中的 TwoOrgsOrdererGenesis 是读取了config.yaml 文件中的 Profiles 部分中定义的配置内容】,正常执行完成后我们会在命令的指定输出目录(这里是命令中指定的 channel-artifacts目录)看到genesis.block 创世块,我们可以通过 configtxgen --inspectBlock ./genesis.block 来使用json的形式把 创世块的内容打印出来
【生成通道的配置交易文件】
export CHANNEL_NAME=mychannel ## 最好是先配置个临时的环境变量方便后面引用,当然后面选择手打也是可以的
configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME
【可选项和上面生成创世块一致,貌似不指定 channelID 默认就是 mychannel ?? 】然后我们可以在指定的目录下(这里是 /home/gavin/fabric/fabric-samples/first-network/channel-artifacts 查看到 channel.tx )同样也有查看交易文件的方式:
configtxgen --inspectChannelCreateTx ./channel.tx 和查看创世块内容一样只是命令选项不一样 具体可以 --help 去查看,我们可以以json的形式打印到控制台
【生成各个组织的锚节点配置更新文件】
【注意】:生成组织的锚节点配置更新文件的时候,我们需要注意的是美哥组织都需要分别取生成对应的锚节点,详细是哪个为锚节点请查看 config.yaml 中自然清楚了;如我们的 config.yaml 中有这一段指定了每个组织的锚节点,
则,我们需要分别执行如下命令:【注意:生成组织锚节点所用的 profile选项值 和 生成 通道配置交易文件所用的一样哦~】
configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP
以及
configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org2MSP
【其中,-asOrg 所携带的值 Org1MSP 等是 上图中所示的 org的ID 的值】执行完后我们可以在 ~/fabric-samples/first-network/channel-artifacts 目录产看到两个文件 Org1MSPanchors.tx 和 Org2MSPanchors.tx 这就是我们需要的两个组织各自的锚节点配置更新文件了
OK,到目前为止我们在启动网络前的所有准备工作都已经做完了,下面我们就来把网络启动起来 【本操作是属于 单机版的演示,现实生产环境启动网络可以使 逐个去不同服务器上启动的哦~】
【注意】:我们本示例中启动网络是使用了docker-compose 来直接启动网络架构中所有的资源,这里使用的底层原理是:通过指定的 docker-compose.yaml 来对之前我们下好的Orderer、Peer等镜像及 我们生成好的组织结构及对应的身份证书、配置文件等来搭建我们的fabric网络,具体做了些什么需要查看 所指定的docker-compose.yaml 中配置了些什么。(docker-compose.yaml 我们后续再讲解),现在我们只需要用一下命令即可启动这个我们配置好的网络
docker-compose -f docker-compose-cli.yaml up -d 【注意: -d 是可选项,加了的话就不会打印详细的启动过程日志,个人建议不要加】
这只是开始的一小部分日志,往下我们还可以看到不同节点的启动过程日志,比如:
启动完之后我们可以使用 docker logs -f 容器ID/容器名称 来查看各个容器的启动控制台日志,看看是否正常启动了容器 【注意 这时候还是无法确保 当前节点是否 没有问题的哦~】
首先我们先 docker ps 查看下起了几个容器:
我们可以看到一共起了 一个Order 、4个peer、一个cli 共6个容器,我们不放心的话可以逐一的进入容器中【使用 docker logs -f 容器ID/容器名称 】查看启动日志~
有一点需要注意的是,
CLI容器将闲置1000秒。如果在需要时它消失了,可以用一个简单的命令重新启动它:
docker start cli
Peer节点启动后, 默认情况下没有加入网络中的任何应用通道, 也不会与Orderer服务建立连接.需要通过客户端对其进行操作, 让它加入网络和指定的应用通道中
我们进入cli容器来操作下面所有动作【严格来说后续的操作均是需要cli来和各个节点进行交互,主要是Peer节点】
docker exec -ti cli bash
或者
docker exec -ti cli /bin/bash 【本人更倾向这种】
为了以防万一,我们优先检查下临时环境变量是否配置了 【刚进去cli容器中是没有这个变量的】
echo $CHANNEL_NAME 没有设置的话需要设置 export CHANNEL_NAME=mychannel
进去之后直接在 cli 容器的这个目录下: /opt/gopath/src/github.com/hyperledger/fabric/peer ,然后我们可以看到
里面有三个目录 channel-artifacts 中放置的是我们准备工作中生成的 配置文件 (创世块、通道配置交易文件 等)、crypto 中放置着生成的组织结构及对应的身份证书、scripts 中是某些启动脚本;
【创建通道】:
peer channel create -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/channel.tx --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem ## --cafile 携带的是 orderer 的root cert的本地路径,允许我们去验证TLS握手
在执行完后会在当前目录下 有一个 通道名.block 的文件【本例子中为:mychannel.block】
【注意了 这个文件在 peer加入通道后,或者 cli 停止运行/重启 后 就不见了,因为他是在cli 容器里面生成的,生命伴随着 cli 容器,而 其他三个目录的内容时从外部Linux 挂载进来的,不一样~,但是我们可以使用 peer channel fetch 来从正在运行的网络中 捕获最新的 xxxchannel.block 文件】
peer channel join -b mychannel.block
【注意:当前 cli 默认就是 Org1的 peer0 请查看 docker-compose-cli.yaml 中的配置自然明白】
切换身份(其实还是在 cli 中,只不过会以 指定的组织下的身份去 操作该组织下的资源 ,因为是由 cli 来和各个peer 等做交互的,我们可以把 cli 认为是个跳板机 ),去把其他的节点也加入 通道中:
CORE_PEER_LOCALMSPID="Org2MSP" ## 指定组织
CORE_PEER_ADDRESS=peer0.org2.example.com:7051 ## 指定资源的 服务地址
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/[email protected]/msp ## 指定 资源的管理员身份信息
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt ## 指定 该组织的该资源 tls根证书
echo $CORE_PEER_LOCALMSPID ## 查看 当前的组织
echo $CORE_PEER_ADDRESS ## 查看 当前peer的服务地址
echo $CORE_PEER_MSPCONFIGPATH ## 查看 当前资源的管理员MSP 身份信息
echo $CORE_PEER_TLS_ROOTCERT_FILE ## 查看 当前资源的TLS根证书
如我们默认 docker-compose-cli.yaml 中配置了 org1的 peer0 作为 cli 容器的默认指向环境,那么我们第一次进入 cli 就依次执行上述 命令得到:
好,我们现在先切换 cli 的环境指向到 org0 的 peer1 【由于相同组织 则,组织和 管理员身份不需要切换,只有资源服务地址 和 资源的 tls根证书 需要切换】
CORE_PEER_ADDRESS=peer1.org1.example.com:7051
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt
如下: 【注意 每一次新开进入的 cli 的终端 都是默认指向 org1 的 peer0 环境的哦】
OK,我们只需要依次更换cli 指向的环境,并逐个把对应的peer 加入通道中即可
如:【注意 锚节点必须是 之前config.yaml 中所指定的哦】
peer channel update -o orderer.example.com:7050 -c ${CHANNEL_NAME} -f ./channel-artifacts/Org1MSPanchors.tx --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
到这里为止我们整个 fabric 网络结构就算搭建起来了,那么下面我们就可以使用它来跑我们的链码了。
【注意了,我们这里只是把ChainCode安装到指定的 Peer 上哦 (感觉是只需要背书节点安装即可),我没有说 所有的Peer都需要安装ChainCode】
如: 我们只在Org1 的 Peer0 上安装了链码:
peer chaincode install -n mycc -v 1.0 -p \
github.com/chaincode/chaincode_example02/go/
【注意:链码的起始 目录为 GOPATH 的src 中的 项目目录,我们这里就是 github.com 目录】
这样纸就是链码安装成功了
peer chaincode instantiate -o orderer.example.com:7050 --tls --cafile \
/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem \
-C $CHANNEL_NAME -n mycc -v 1.0 -c '{"Args":["init","a", "100", "b","200"]}' -P "OR ('Org1MSP.member','Org2MSP.member')"
【注意:我们必须在安装有链码的节点去实例化链码,不然的话会失败;其中链码是严格区分名称和版本号的,这个要和安装的时候一致;其中 -P 后面跟的是 指定调用链码时的 背书策略 其实Peer的 Endorser 节点也就是在 实例化链码时 通过背书策略 来指定的,上述背书策略表示,该链码需要Org1 或者Org2 的随意成员签名的交易均可调用该链码,如果把 member 改成peer 那么就是 随意peer 签名】
安装成功如下:
其中,在没有安装链码的节点上执行实例化而失败的结果,如:
查询:
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args": ["query","a"]}'
执行事务:
peer chaincode invoke -o orderer.example.com:7050 --tls --cafile \
/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem \
-C $CHANNEL_NAME -n mycc -c '{"Args":["invoke","a","b","10"]}'
查询:
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args": ["query","a"]}'
好了,手动执行一个简单的fabric网络及链码的调用全过程这里就结束了,今天下午我也懒得再写了,后续我们继续深入,其他的一些操作,比如: 往正在运行的网络中添加 新的组织,添加新的通道等等,Bye~