Hyperledger Fabric(四)------BYFN详细剖析

  • 脚本执行
  • 分步手动执行
    • 搭建基础网络
      • 组织架构准备
      • 生成配置文件
      • 启动网络
      • 创建通道
    • 部署智能合约
  • Adding an Org to a Channel
  • Using Private Data in Fabric

这个官方样例Building Your First Network我运行了可能有5遍了,今天才真正明白是怎么回事,这里记录一下。

运行这个样例之前务必要先弄明白Docker。

另外后面有两个扩展部分Adding an Org to a ChannelUsing Private Data in Fabric,官方文档是分开讲的,由于都是用这个网络,我这里就放到一起了,认真实践之后会有很大收获。


UPDATE:20180805
一直对msp和证书相关的东西很迷,昨天仔细去看了下,又有了新的收获,发现之前理解的还是不够,在此更新一下这篇博客。

脚本执行

首先先用现成的脚本执行一次,确保环境安装正确。

./byfn.sh up

如果最后输出如下,说明运行成功。

===================== All GOOD, BYFN execution completed =====================


 _____   _   _   ____
| ____| | \ | | |  _ \
|  _|   |  \| | | | | |
| |___  | |\  | | |_| |
|_____| |_| \_| |____/

然后一定不要忘记清理运行环境。

./byfn.sh down


分步手动执行

搭建基础网络

组织架构准备

  1. 编写组织架构文件crypto-config.yaml,其中配置了排序服务节点和组织节点。

    简要说明一下

    - Name: Org2
        Domain: org2.example.com
        EnableNodeOUs: true
        Template:
          Count: 2  //表明一个Org有几个peer
        Users:
          Count: 1  //表明一个Org有几个User
  2. 使用cryptogen工具根据架构文件生成相关的证书,放到crypto-config目录下。

    ../bin/cryptogen generate --config=./crypto-config.yaml

    这里我们有必要看一下这个目录(这里只列出了子目录ordererOrganizations下的):
    Hyperledger Fabric(四)------BYFN详细剖析_第1张图片
    这里从上到下一共有三个msp文件夹:

    • 第一个msp是该成员的local msp,在config.yaml中要用来生成channel msp,把这里包含的根证书加到orderer genesis.block中,这样以后该Org的成员与order交互时数字签名可以被认证
    • 第二个和第三个是local msp,里面包含了自己的证书和私钥

    再说一下ca文件夹,这就是这个Org的CA,里面有证书和私钥。
    而tlsca文件夹,是tls通信要用的CA,里面也是证书和私钥。
    每一个order或者peer或者user都有自己的msp,如果要tls通信还要有tls,我们在docker配置文件docker-compose-cli.yaml中可以看到里面配置peer和order的时候环境变量里的msp和tls都是这两个文件夹。admin是这个组织的管理者。

生成配置文件

用到configtxgen工具,生成的配置文件都在channel-artifacts目录下,这里一共会有四个。

要告诉工具去哪里找configtx.yaml文件。

export FABRIC_CFG_PATH=$PWD

  1. 生成orderer genesis block

    ../bin/configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block

用来启动order服务

  1. 生成通道配置文件

    先指定通道名称:export CHANNEL_NAME=mychannel

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

通道建立时该文件会被广播到order

  1. 为Org定义anchor peer

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

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

指定了Org的anchor peer

启动网络

这里需要用到Docker-Compose模板文件docker-compose-cli.yaml,里面定义了需要用到的容器,去看代码发现里面其实是扩展了base目录下的另外两个模板文件,感觉就像是继承一样。

启动网络:docker-compose -f docker-compose-cli.yaml up -d

同时用先前生成的genesis.block引导启动了order服务

其中容器CLI的定义如下(截取部分):

cli:
    container_name: cli
    image: hyperledger/fabric-tools:$IMAGE_TAG
    tty: true
    stdin_open: true
    environment:  
      - GOPATH=/opt/gopath
      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
      #- CORE_LOGGING_LEVEL=DEBUG
      - CORE_LOGGING_LEVEL=INFO
      - CORE_PEER_ID=cli
      - CORE_PEER_ADDRESS=peer0.org1.example.com:7051
      - CORE_PEER_LOCALMSPID=Org1MSP
      - CORE_PEER_TLS_ENABLED=true
      - CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt
      - CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.key
      - CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
      - CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp

上面的环境变量部分指定是在peer0.org1.example.com节点操作chaincode

还要说明一下,我们是通过CLI容器对其它容器进行配置。

进入CLI容器的命令:docker exec -it cli bash

创建通道

声明通道名:export CHANNEL_NAME=mychannel

  1. 创建通道

    channel.tx发送至order节点

    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

    -o 指定排序节点,-c指定通道名字,-f指定通道配置文件,–tls允许tls通信,–cafile指定排序节点根证书目录(也就是上图中的第一个msp目录)以允许tls握手

    这一步会生成mychannel.block,里面包含了channel.tx中的通道配置信息,直接在当前命令行输入ls就可看到,后面加入peer节点是需要用到。

  2. 将peer加入通道

    加入peer0.org1.example.com节点

    peer channel join -b mychannel.block

    加入peer0.org2.example.com节点,这里要先声明环境变量

    CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
    CORE_PEER_ADDRESS=peer0.org2.example.com:7051
    CORE_PEER_LOCALMSPID="Org2MSP"
    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

    加入通道:peer channel join -b mychannel.block

  3. 更新anchor peer

    将对应的文件发给order节点。
    本质上是更新通道配置信息,并没有修改genesis.block,而是添加到后面。

    更新Org1的anchor peerpeer0.org1.example.com

    CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
    CORE_PEER_ADDRESS=peer0.org1.example.com:7051
    CORE_PEER_LOCALMSPID="Org1MSP"
    CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt

    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

    更新Org2的anchor peerpeer0.org2.example.com

    先设置环境变量

    CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
    CORE_PEER_ADDRESS=peer0.org2.example.com:7051
    CORE_PEER_LOCALMSPID="Org2MSP"
    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

    更新:peer channel update -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/Org2MSPanchors.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

注意这里每次设置时都需要重新设置环境变量


部署智能合约

这里我们用的是chaincode/chaincode_example02/go/目录下现成的智能合约,当然也可以自己写。
可以在docker-compose-cli.yaml中peer0的volumes配置部分看到./../chaincode/:/opt/gopath/src/github.com/chaincode,这里就是把上面说的那个目录映射到peer0中的目录下。不过这里映射的目录有一点疑惑,下面install的时候的路径也很迷,既不是相对当前目录的路径,也不是绝对路径,而是相对/opt/gopath/src/的路径=_=

  1. 安装智能合约

    peer0.org1.example.com上安装

    CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
    CORE_PEER_ADDRESS=peer0.org1.example.com:7051
    CORE_PEER_LOCALMSPID="Org1MSP"
    CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt

    peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/chaincode_example02/go/

    peer0.org2.example.com上安装

    当然还是要设置环境变量

     CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
    CORE_PEER_ADDRESS=peer0.org2.example.com:7051
    CORE_PEER_LOCALMSPID="Org2MSP"
    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

    安装:peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/chaincode_example02/go/

    注意这里如果不在peer0.org2.example.com上安装智能合约,后面转账(invoke)时会报错

  2. 实例化智能合约

    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 "AND ('Org1MSP.peer','Org2MSP.peer')"

    -o指定排序节点,–tls允许tls通信,–cafile指定排序节点根证书目录,-C指定通道名字,-n指定智能合约名字,-v指定智能合约版本,-c为调用智能合约传递参数

  3. 查询和转账

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

    转账:peer chaincode invoke -o orderer.example.com:7050 --tls true --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 --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 -c '{"Args":["invoke","a","b","10"]}'

    可以看到这里转账用到的证书是第一个msp下tlscacerts文件夹下的pem格式的证书,以及后面两个peer目录下tls文件夹下的ca.crt证书。应该就是tls通信需要。

    这里如果转账之后立即查询,可能会发现账本未更新,结果与预期不符,等一下再去查询结果又对了,应该是查询只需要在本地peer上进行比较快,而转账需要其它节点参与以及共识机制,要慢。

  4. 查看交易日志

    打开一个新的终端:docker logs dev-peer0.org2.example.com-mycc-1.0

    看这里也可以发现只有和自己有关的交易日志才会记录下来,比如说peer0.org1的查询只在docker logs dev-peer0.org1.example.com-mycc-1.0中可以看到,而转账在两个中都可以看到。

可以用CouchDB替换默认的goleveldb数据库,支持丰富的查询。


Adding an Org to a Channel

如果上面的部分都已经理解透彻了,强烈建议看一下这部分内容,虽然比较麻烦,不过看完了相信会有很大收获。
官方文档
这里说一下大概步骤:
1. 先生成Org3需要的证书
2. 计算出需要更新的网络,这一步比较繁琐,需要pb文件和json文件来回转换
3. 更新网络
4. 将Org3相关的加入网络
5. 安装智能合约
6. 更新智能合约
7. 就可以查询转账了


Using Private Data in Fabric

官方文档

collection vs. private channel:

  • 当交易的全部信息只能被某些Orgs看到时,用channel。
  • 当只有交易的部分信息能被某些Orgs看到而对其他Org保密时,或者交易信息需要对Order保密时,用collection。

智能合约的不同之处在于要对数据分别处理,而且实例化智能合约的时候要用--collections-config参数执行collection definiton的目录。

另外collection definiton中有个blockToLive参数,用来指定私有数据的存活时间,以Block为单位,过期会被销毁。


你可能感兴趣的:(区块链)