Hyperledger Fabric2中文文档-创建通道(channel)

翻译:https://hyperledger-fabric.readthedocs.io/en/latest/create_channel/create_channel.html

为了在Hyperledger Fabric网络中创建和交易价值,组织需要加入到通道中。通道是特定组织之间的私有通信层。每个通道由独立的账本组成,账本只能被通道内的成员读写,通道成员是将peer加入到通道中接收来自order的新的区块和交易的组织。peer,节点,证书授权机构这些物理结构组成网络,通道负责组织之间沟通和交流。通道对于通道外其它成员不可见。

本文档介绍如何使用configtxgen CLI 工具来创建通道,使用peer channel命令来将peer加入到通道中。虽然本教程使用测试网络来创建通道,但是这些步骤同样可以适用与生产网络。

创建channel的过程,本文通过以下步骤和概念来介绍。

  • 安装configtxgen工具
  • 使用configtx.yaml文件
  • orderer系统通道
  • 创建一个应用通道
  • 将peer加入通道中
  • 设置锚节点

安装configtxgen工具

通道创建是通过通道创建事务来创建,并将事务提交到排序service。通道创建事务指定通道的初始配置并由order service写入通道生成区块。虽然可以手动建立通道创建事务,使用configtxgen工具更容易。这个工具通过读取configtx.yaml来工作,此文件定义了通道的设置,然后将相关信息写入通道创建事务。在讨论configtx.yaml文件之前,我们先下载并安装configtxgen工具。

你可以下载安装configtxgen 按照 install the samples, binaries and Docker images的步骤。configtxgen会和其它命令一起被下载并安装到fabric-samples下的bin目录中。

本文的目的是在test-network中操作

cd fabric-samples/test-network

接下来将命令加入到CLI路径中

export PATH=${PWD}/../bin:$PATH

要使用configtxgen前,需要设置FABRIC_CFG_PATH指向包含configtx.yaml的目录中。在本文中我们会查到configtx.yaml被安装在test network的configtx文件夹中

export FABRIC_CFG_PATH=${PWD}/configtx

此时可以使用工具了

configtxgen --help

configtx.yaml

configtx.yaml文件指定了创建新通道的配置。构建通道的信息在配置文件中,包含了读写内容。configtxgen 工具使用文件中profile部分创建通道配置并且将其写入到 protobuf format(可以被Fabric读取)。

可以在test-network的configtx文件夹中找到configtx.yaml.文件包含了创建通道需要的以下信息:

  • Organizations:可以成为通道成员的组织。每个组织有加密素材用来构建通道的MSP
  • Ordering service: 哪些order节点可以构成网络的排序service,他们之间使用什么共识协议来为交易达成一致。该文件还包含了哪些组织可以成为排序管理员。
  • Channel policies:文件中不同的部分共同定义了如何管理组织和通道之间的交互,哪些组织需要审议通道升级。本文中,我们使用默认策略。
  • Channel profiles:每个通道的配置可以引用文件中其它部分的配置。配置文件用来创建order系统的创始区块,这些通道也会被peer组织使用。为了区分于系统通道,peer组织使用的通道被成为应用通道。

configtxgen 会使用配置文件创建完整的系统通道的创始区块。因此,系统通道配置文件需要指定完整的系统通道配置,用于创建通道创建事务的通道配置文件只需要包含创建应用程序所需的附加配置信息。

开启网络

我们会使用test network来创建新的通道。为了本次教程,我们从一个已知的初始化状态开始。下面命令会kill所有活跃的容器并且删除之前运行产生的数据。确保目录在test-network下

./network.sh down

可以使用如下命令来启动test network

./network.sh up

会创建两个组织和一个order组织,每个组织会有一个peer,排序服务的管理员操作一个order节点。当运行成功后,会输出节点被创建的log:

Creating network "net_test" with the default driver
Creating volume "net_orderer.example.com" with default driver
Creating volume "net_peer0.org1.example.com" with default driver
Creating volume "net_peer0.org2.example.com" with default driver
Creating orderer.example.com    ... done
Creating peer0.org2.example.com ... done
Creating peer0.org1.example.com ... done
CONTAINER ID        IMAGE                               COMMAND             CREATED             STATUS                  PORTS                              NAMES
8d0c74b9d6af        hyperledger/fabric-orderer:latest   "orderer"           4 seconds ago       Up Less than a second   0.0.0.0:7050->7050/tcp             orderer.example.com
ea1cf82b5b99        hyperledger/fabric-peer:latest      "peer node start"   4 seconds ago       Up Less than a second   0.0.0.0:7051->7051/tcp             peer0.org1.example.com
cd8d9b23cb56        hyperledger/fabric-peer:latest      "peer node start"   4 seconds ago       Up 1 second             7051/tcp, 0.0.0.0:9051->9051/tcp   peer0.org2.example.com

此时网络已经部署但没有创建应用通道。但是已经创建了系统通道。脚本其实是用configtxgen工具和configtx.yaml文件来创建的系统创始区块。因为系统通道被用来创建其它通道,所以在创建应用通道之前我们需要花时间来理解orderer的系统通道。

orderer系统通道

Fabric网络创建的第一个通道是系统通道。系统通道定义了order节点和作为order service管理员的组织。

系统通道也包含了联盟链的组织成员。联盟是一些属于系统通道的对等组织,但不是ordering service的管理员。联盟成员有能力去创建新通道并且包括其它组织成为通道成员。

系统通道的初始块被用来部署新的排序service,test network脚本已经创建了系统通道创始区块当你执行了./network.sh up命令。创始区块用来部署单独的排序节点,排序节点用这个区块来创建系统通道并组建排序service。如果你查看./network.sh脚本,你会发现创建创始区块的命令:

configtxgen -profile TwoOrgsOrdererGenesis -channelID system-channel -outputBlock ./system-genesis-block/genesis.block

configtxgen工具使用TwoOrgsOrdererGenesis通道配置来生成创始区块并储存到system-genesis-block,你可以看到TwoOrgsOrdererGenesis 的配置如下

TwoOrgsOrdererGenesis:
    <<: *ChannelDefaults
    Orderer:
        <<: *OrdererDefaults
        Organizations:
            - *OrdererOrg
        Capabilities:
            <<: *OrdererCapabilities
    Consortiums:
        SampleConsortium:
            Organizations:
                - *Org1
                - *Org2

Orderer:配置部分创建单独节点的Raft排序服务,OrdererOrg 作为一个排序服务的管理员。Consortiums 部分配置创建一个组织的联盟叫做SampleConsortium:。Org1和Org2是一个联盟成员。所以我们要将两个组织都包含到新创建的通道中。如果我们想要将一个组织加入到通道中,但并不将组织添加到联盟,我们首先需要创建通道Org1和Org2,并且增加组织通过updating the channel configuration.

创建一个应用通道

现在我们通过network.sh脚本已经部署了网络的节点并且创建了orderer系统通道,接下来可以为peer组织创建一个新的通道。我们已经为使用configtxgen工具设置了环境变量。运行下面命令来为通道channel1创建一个通道创建事务

configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel1.tx -channelID channel1

-channelID设置的是未来通道的名称。通道名称必须全部小写,少于250个字符并且匹配了正则表达[a-z][a-z0-9.-]*。这个命令使用-profile指向TwoOrgsChannel:配置,这个是用来创建应用通道的。

TwoOrgsChannel:
    Consortium: SampleConsortium
    <<: *ChannelDefaults
    Application:
        <<: *ApplicationDefaults
        Organizations:
            - *Org1
            - *Org2
        Capabilities:
            <<: *ApplicationCapabilities

配置文件中引用系统通道的名称SampleConsortium ,包含了联盟中所有peer组织的通道成员。因为系统通道被用作模板来创建应用通道,在系统中定义的order节点成为新通道的默认成员(consenter set),且排序节点的管理员也会成为通道的排序节点的管理员。排序节点和排序组织也可以增加和删除。

如果命令成功了,你会看到如下输出

2020-03-11 16:37:12.695 EDT [common.tools.configtxgen] main -> INFO 001 Loading configuration
2020-03-11 16:37:12.738 EDT [common.tools.configtxgen.localconfig] Load -> INFO 002 Loaded configuration: /Usrs/fabric-samples/test-network/configtx/configtx.yaml
2020-03-11 16:37:12.740 EDT [common.tools.configtxgen] doOutputChannelCreateTx -> INFO 003 Generating new channel configtx
2020-03-11 16:37:12.789 EDT [common.tools.configtxgen] doOutputChannelCreateTx -> INFO 004 Writing new channel tx

我们可以通过使用peer的CLI来提交通道创建事务到ordering service。要使用peer,首先使用FABRIC_CFG_PATH 指向到core.yaml目录,在文件夹fabric-samples/config下。

export FABRIC_CFG_PATH=$PWD/../config/

在ordering service创建通道之前,ordering service会检查提交者的身份权限。默认的,只有属于系统通道联盟成员的组织管理员才能创建新的通道。以Org1的管理员身份运行

export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051

可以使用如下命令创建通道

peer channel create -o localhost:7050  --ordererTLSHostnameOverride orderer.example.com -c channel1 -f ./channel-artifacts/channel1.tx --outputBlock ./channel-artifacts/channel1.block --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

上述命令中使用-f指定通道创建事务文件,-c指定通道名称。-o用来选择order节点(创建通道的节点)。--cafile是指向order节点TLS证书的路径,返回输出结果如下

2020-03-06 17:33:49.322 EST [channelCmd] InitCmdFactory -> INFO 00b Endorser and orderer connections initialized
2020-03-06 17:33:49.550 EST [cli.common] readBlock -> INFO 00c Received block: 0

因为我们使用Raft排序服务,你可能会收到一些状态不可用的消息,你可以安全的忽略这些消息。

命令会生成一个创始块,路径由--outputBlock指定。

将Peer加入到通道

通道创建后,就可以将peer加入到通道中。通道内的成员从ordering service 中使用peer channel fetch来获取创始区块。组织可以使用 peer channel join 命令,利用创始区块加入通道。一旦peer加入到通道中,peer会通过从ordering service上检索并获取通道上的其它区块,来构建区块链账本。

既然我们当前以Org1管理员的身份来操作peer CLI,接下来让我们将Org1的peer加入到通道中。如果Org1已经提交了通道的创建事务,我们已经有了通道的创始块,加入通道的命令如下

peer channel join -b ./channel-artifacts/channel1.block

CORE_PEER_ADDRESS 环境变量已经被指向了peer0.org1.example.com。运行成功会返回:

2020-03-06 17:49:09.903 EST [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2020-03-06 17:49:10.060 EST [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel

使用 peer channel getinfo来验证是否已经加入通道

peer channel getinfo -c channel1

命令会列出区块的高度和最新的块的哈希值。因为创始区块是通道内唯一的区块,区块高度因此为1.

2020-03-13 10:50:06.978 EDT [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
Blockchain info: {"height":1,"currentBlockHash":"kvtQYYEL2tz0kDCNttPFNC4e6HVUFOGMTIDxZ+DeNQM="}

将Org2的peer加入到通道中,设置环境变量

export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:9051

系统中已经存在了通道的创始区块,在更现实的情况下,Org2应该从ordering service获取区块。作为一个例子,我们也使用fetch命令来为Org2获取区块。

peer channel fetch 0 ./channel-artifacts/channel_org2.block -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com -c channel1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

命令中使用0来指定它需要获取创始区块用来加入通道。成功后输出:

2020-03-13 11:32:06.309 EDT [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2020-03-13 11:32:06.336 EDT [cli.common] readBlock -> INFO 002 Received block: 0

命令会返回通道的创始区块并命名为channel_org2.block来区分它从org1中拉取的区块。可以使用这个区块来将Org2的peer加入通道

peer channel join -b ./channel-artifacts/channel_org2.block

设置锚节点

一个组织已经将peer加入到通道中,至少要选择一个peer成为锚节点。为了利用私有数据和服务发现,需要锚节点。每个组织需要设置多个锚节点以备冗余。更多关于gossip和锚节点,查看 Gossip data dissemination protocol

组织的锚节点的终端信息都包含在通道的配置中。每个通道成员可以通过升级通道来指定自己的锚节点。可以使用configtxlator 工具来升级通道配置,并且选择Org1和Org2的锚节点。设置锚节点的过程与其它通道更新所需步骤类似,并介绍如何使用configtxlator更新通道配置。需要安装 jq tool 。

我们先为Org1选择锚节点。第一步使用peer channel fetch拉取最新的通道配置区块。设置接下来的环境变量作为Org1的管理员来操作peer CLI

export FABRIC_CFG_PATH=$PWD/../config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051

接下来使用下面命令来下载通道配置

peer channel fetch config channel-artifacts/config_block.pb -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com -c channel1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

因为最新的通道配置区块是通道创始区块,你会看到通道中返回block 0

2020-04-15 20:41:56.595 EDT [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2020-04-15 20:41:56.603 EDT [cli.common] readBlock -> INFO 002 Received block: 0
2020-04-15 20:41:56.603 EDT [channelCmd] fetch -> INFO 003 Retrieving last config block: 0
2020-04-15 20:41:56.608 EDT [cli.common] readBlock -> INFO 004 Received block: 0

通道配置区块存储在channel-artifacts目录中来保证独立存放。

cd channel-artifacts

当我们开始使用configtxlator工具来操作通道配置时,第一步是将区块从protobuf 转译到JSON,这样就可读可编辑。我们这里去除掉不能理解的区块数据,只留下通道配置

configtxlator proto_decode --input config_block.pb --type common.Block --output config_block.json
jq .data.data[0].payload.data.config config_block.json > config.json

以上命令会将配置区块转译为config.json。我们不想直接编辑这个文件,先复制一份。

cp config.json config_copy.json

现在可以使用jq工具来将Org1锚节点加入到通道配置文件。

jq '.channel_group.groups.Application.groups.Org1MSP.values += {"AnchorPeers":{"mod_policy": "Admins","value":{"anchor_peers": [{"host": "peer0.org1.example.com","port": 7051}]},"version": "0"}}' config_copy.json > modified_config.json

我们已经升级了json格式的通道配置文件modified_config.json,我们可以转换原来的和修改过的配置文件到protobuf格式,并核算它们之间的不同。

configtxlator proto_encode --input config.json --type common.Config --output config.pb
configtxlator proto_encode --input modified_config.json --type common.Config --output modified_config.pb
configtxlator compute_update --channel_id channel1 --original config.pb --updated modified_config.pb --output config_update.pb

新的protobuf叫channel_update.pb且包含了升级了锚节点的配置。我们将配置更改封装在事务中并创建通道升级事务。

configtxlator proto_decode --input config_update.pb --type common.ConfigUpdate --output config_update.json
echo '{"payload":{"header":{"channel_header":{"channel_id":"channel1", "type":2}},"data":{"config_update":'$(cat config_update.json)'}}}' | jq . > config_update_in_envelope.json
configtxlator proto_encode --input config_update_in_envelope.json --type common.Envelope --output config_update_in_envelope.pb

现在可以使用config_update_in_envelope.pb来升级通道,切换目录

cd ..

我们更新用通道的新配置(peer channel update命令)来增加锚节点。因为我们修改该的通道部分只影响了Org1,另一个通道成员不需要赞同这次通道升级。

peer channel update -f channel-artifacts/config_update_in_envelope.pb -c channel1 -o localhost:7050  --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

执行成功后,返回如下

2020-01-09 21:30:45.791 UTC [channelCmd] update -> INFO 002 Successfully submitted channel update

我们也要设置Org2的锚节点。因为这是第二次经历,所以我们这次快一点。

export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:9051

拉取最新的通道配置区块,这是通道的第二个区块。

peer channel fetch config channel-artifacts/config_block.pb -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com -c channel1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
cd channel-artifacts
configtxlator proto_decode --input config_block.pb --type common.Block --output config_block.json
jq .data.data[0].payload.data.config config_block.json > config.json
cp config.json config_copy.json
jq '.channel_group.groups.Application.groups.Org2MSP.values += {"AnchorPeers":{"mod_policy": "Admins","value":{"anchor_peers": [{"host": "peer0.org2.example.com","port": 9051}]},"version": "0"}}' config_copy.json > modified_config.json
configtxlator proto_encode --input config.json --type common.Config --output config.pb
configtxlator proto_encode --input modified_config.json --type common.Config --output modified_config.pb
configtxlator compute_update --channel_id channel1 --original config.pb --updated modified_config.pb --output config_update.pb
configtxlator proto_decode --input config_update.pb --type common.ConfigUpdate --output config_update.json
echo '{"payload":{"header":{"channel_header":{"channel_id":"channel1", "type":2}},"data":{"config_update":'$(cat config_update.json)'}}}' | jq . > config_update_in_envelope.json
configtxlator proto_encode --input config_update_in_envelope.json --type common.Envelope --output config_update_in_envelope.pb
cd ..
peer channel update -f channel-artifacts/config_update_in_envelope.pb -c channel1 -o localhost:7050  --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

确认是否已经升级可以运行如下命令

peer channel getinfo -c channel1

返回

Blockchain info: {"height":3,"currentBlockHash":"eBpwWKTNUgnXGpaY2ojF4xeP3bWdjlPHuxiPCTIMxTk=","previousBlockHash":"DpJ8Yvkg79XHXNfdgneDb0jjQlXLb/wxuNypbfHMjas="}

在通道上部署链码

我们可以确实通道上已经部署了链码。我们可以在使用network.sh脚本在任意test network上部署链码。部署链码使用如下命令

./network.sh deployCC -c channel1

运行后,会看到部署的日志。链码被调用,增加数据,查询数据。

[{"Key":"CAR0","Record":{"make":"Toyota","model":"Prius","colour":"blue","owner":"Tomoko"}},
{"Key":"CAR1","Record":{"make":"Ford","model":"Mustang","colour":"red","owner":"Brad"}},
{"Key":"CAR2","Record":{"make":"Hyundai","model":"Tucson","colour":"green","owner":"Jin Soo"}},
{"Key":"CAR3","Record":{"make":"Volkswagen","model":"Passat","colour":"yellow","owner":"Max"}},
{"Key":"CAR4","Record":{"make":"Tesla","model":"S","colour":"black","owner":"Adriana"}},
{"Key":"CAR5","Record":{"make":"Peugeot","model":"205","colour":"purple","owner":"Michel"}},
{"Key":"CAR6","Record":{"make":"Chery","model":"S22L","colour":"white","owner":"Aarav"}},
{"Key":"CAR7","Record":{"make":"Fiat","model":"Punto","colour":"violet","owner":"Pari"}},
{"Key":"CAR8","Record":{"make":"Tata","model":"Nano","colour":"indigo","owner":"Valeria"}},
{"Key":"CAR9","Record":{"make":"Holden","model":"Barina","colour":"brown","owner":"Shotaro"}}]
===================== Query successful on peer0.org1 on channel 'channel1' =====================

 

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值