hyperledger-fabric1.4


byfn.sh 中执行了什么命令,如何使整个fabric网络启动。这就是这篇文章所要分析的内容。

一. 工具介绍

1. cryptogen

生成加密材料,包括x509证书和签名密钥。这些材料允许网络实体在通信和交易时进行验证和签名。
利用crypto-config.yaml文件来生成为组织和组织中的组件生成证书和密钥集。每个组织都有一个唯一的根CA,与组织中的组件相绑定。crypto-config.yaml示例文件内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
OrdererOrgs:
- Name: Orderer
Domain: example.com
EnableNodeOUs: true
Specs:
- Hostname: orderer
- Hostname: orderer2
- Hostname: orderer3
- Hostname: orderer4
- Hostname: orderer5

PeerOrgs:
- Name: Org1
Domain: org1.example.com
EnableNodeOUs: true
Template:
Count: 2
Users:
Count: 1
- Name: Org2
Domain: org2.example.com
EnableNodeOUs: true
Template:
Count: 2
Users:
Count: 1

“Specs”:

在配置中启动主机是显示定义,模板如下所示
Specs 是 Spec条目组。每个Spec条目包括两个内容:

  • Hostname: (必需) 所需主机名,不需域名.
  • CommonName: (可选) 指定CN模板或者显式覆写。默认模板如下:
                         "{{.Hostname}}.{{.Domain}}"
            包含 Spec.Hostname和 Org.Domain
    

例子如下:

1
2
3
4
5
Specs:
- Hostname: foo # 代表"foo.org1.example.com"
CommonName: foo27.org5.example.com # 覆写上面设置的主机名
- Hostname: bar
- Hostname: baz

“Template”:

允许定义利用模板来顺序创建1个或多个主机
默认情况下,从0到Count-1以”peer%d”的形式出现 .
可以修改节点数量(Count), 开始的索引(Start)和用于构建名称的模板 (Hostname).

注意: Template 和 Specs 不是互斥的。两部分可以同时定义,将会创建聚合节点。只需要留意避免名称冲突 .

例子如下:

1
2
3
4
Template:
Count: 2
Start: 5
Hostname: {{.Prefix}}{{.Index}} # 默认
1
2
3
4
5
# ---------------------------------------------------------------------------
# "Users"
# ---------------------------------------------------------------------------
# Count: 除了管理员外的用户账户
# ---------------------------------------------------------------------------

在cryptogen工具运行之后,生成的证书和密钥将会保存到crypto-config文件夹。在crypto-config.yaml文件中列出5个排序节点与排序组织相绑定,因此cryptogen会为这5个排序节点生成证书,但是除非使用了raft或者kafka排序服务,否则只有一个节点用于独立排序服务实现并用来创建系统通道和mychannel。

2. configtxgen

configtxgen工具用来生成4个配置元素:

  1. 排序节点的创世块 genesis block
  2. 通道配置交易 configuration transaction
  3. 两个锚定节点交易 anchor peer transaction

排序节点块是排序服务中的创世块,通道配置交易会在通道创建的时候广播给排序节点。而锚定节点交易即指明通道上每个组织是锚定节点。(锚定节点即负责组织与外部以及其它组织通信的节点)

与cryptogen工具类似,configtxgen也需要利用一个配置文件configtx.yaml来生成对应材料。该配置文件包含示例网络的定义。

包含三个成员: 一个排序组织(OrdererOrg)和两个节点组织(Org1 & Org2)每个组织管理和维护两个节点。

文件同时指定了一个联盟——SampleConsortium, 包含上述两个节点组织。特别注意文件最后Profiles部分,出现了几个唯一的配置:

  • TwoOrgsOrdererGenesis :为单节点排序服务生成创世区块
  • SampleMultiNodeEtcdRaft :为Raft排序服务生成创世区块。-o 选项并指定 etcdraft 时有效
  • SampleDevModeKafka :为Kafka排序服务生成创世区块。-o 选项并指定 kafka 时有效
  • TwoOrgsChannel :为通道生成创世块

注意,SampleConsortium是在系统级配置文件中定义的,然后由通道级配置文件引用。 通道存在于联盟的权限范围内,所有联盟都必须在整个网络范围内定义。

该文件还包含两个值得注意的附加规范。首先,为每个对等组织指定锚点对等体(peer0.org1.example.com&peer0.org2.example.com)。其次,指向每个成员的MSP目录的位置,从而允许将每个组织的根证书存储在排序节点创始块中。

二. 命令运行

1. 生成证书及密钥

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

因为安装二进制文件的时候已经把该执行文件路径放到环境变量中了,所以可以直接使用。

1
2
3
[root@localhost first-network]# cryptogen generate --config=./crypto-config.yaml 
org1.example.com
org2.example.com

可以看到该目录下多了一个crypto-config子目录

1
2
3
4
5
[root@localhost first-network]# ls 
base ccp-template.yaml connection-org1.yaml connection-org3.yaml docker-compose-cli.yaml docker-compose-etcdraft2.yaml org3-artifacts
byfn.sh channel-artifacts connection-org2.json crypto-config docker-compose-couch-org3.yaml docker-compose-kafka.yaml README.md
ccp-generate.sh configtx.yaml connection-org2.yaml crypto-config.yaml docker-compose-couch.yaml docker-compose-org3.yaml scripts
ccp-template.json connection-org1.json connection-org3.json docker-compose-ca.yaml docker-compose-e2e-template.yaml eyfn.sh

2. 生成配置交易

2.1 创建排序创世块

首先需要配置configtx.yaml文件路径,使得工具configtxgen可以找到该文件

1
export FABRIC_CFG_PATH=$PWD

执行命令

1
configtxgen -profile TwoOrgsOrdererGenesis -channelID byfn-sys-channel -outputBlock ./channel-artifacts/genesis.block

使用配置TwoOrgsOrdererGenesis,通道ID(channelID代表系统通道的名称)设置为byfn-sys-channel,生成创世块为channel-artifacts目录下的genesis.block

1
2
3
4
5
6
7
8
[root@localhost first-network]# configtxgen -profile TwoOrgsOrdererGenesis -channelID byfn-sys-channel -outputBlock ./channel-artifacts/genesis.block
2019-10-20 15:00:32.995 CST [common.tools.configtxgen] main -> INFO 001 Loading configuration
2019-10-20 15:00:33.048 CST [common.tools.configtxgen.localconfig] completeInitialization -> INFO 002 orderer type: solo
2019-10-20 15:00:33.048 CST [common.tools.configtxgen.localconfig] Load -> INFO 003 Loaded configuration: /opt/gopath/src/github.com/hyperledger/fabric-samples/first-network/configtx.yaml
2019-10-20 15:00:33.106 CST [common.tools.configtxgen.localconfig] completeInitialization -> INFO 004 orderer type: solo
2019-10-20 15:00:33.106 CST [common.tools.configtxgen.localconfig] LoadTopLevel -> INFO 005 Loaded configuration: /opt/gopath/src/github.com/hyperledger/fabric-samples/first-network/configtx.yaml
2019-10-20 15:00:33.108 CST [common.tools.configtxgen] doOutputBlock -> INFO 006 Generating genesis block
2019-10-20 15:00:33.109 CST [common.tools.configtxgen] doOutputBlock -> INFO 007 Writing genesis block

如果需要使用Raft排序服务,则使用配置SampleMultiNodeEtcdRaft,命令如下

1
configtxgen -profile SampleMultiNodeEtcdRaft -channelID byfn-sys-channel -outputBlock ./channel-artifacts/genesis.block

如果需要使用Kafka排序服务,则使用配置SampleDevModeKafka,命令如下

1
configtxgen -profile SampleDevModeKafka -channelID byfn-sys-channel -outputBlock ./channel-artifacts/genesis.block
2.3 创建通道配置交易

设置通道名称作为环境变量同时生成配置交易

1
export CHANNEL_NAME=mychannel && configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME

使用配置TwoOrgsChannel,生成配置交易为channel-artifacts目录下的channel.tx

1
2
3
4
5
6
7
[root@localhost first-network]# export CHANNEL_NAME=mychannel && configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME
2019-10-20 15:33:00.766 CST [common.tools.configtxgen] main -> INFO 001 Loading configuration
2019-10-20 15:33:00.820 CST [common.tools.configtxgen.localconfig] Load -> INFO 002 Loaded configuration: /opt/gopath/src/github.com/hyperledger/fabric-samples/first-network/configtx.yaml
2019-10-20 15:33:00.872 CST [common.tools.configtxgen.localconfig] completeInitialization -> INFO 003 orderer type: solo
2019-10-20 15:33:00.872 CST [common.tools.configtxgen.localconfig] LoadTopLevel -> INFO 004 Loaded configuration: /opt/gopath/src/github.com/hyperledger/fabric-samples/first-network/configtx.yaml
2019-10-20 15:33:00.872 CST [common.tools.configtxgen] doOutputChannelCreateTx -> INFO 005 Generating new channel configtx
2019-10-20 15:33:00.874 CST [common.tools.configtxgen] doOutputChannelCreateTx -> INFO 006 Writing new channel tx

可以注意到在该命令中并没有明确的指令指明使用的是那种排序服务(如:Kafka 或 Raft),因为TwoOrgsChannel会使用你创建创世块时所指定的排序服务配置。

2.4 创建两个锚定节点交易

创建组织1(Org1)锚节点(anchor peer)

1
configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP
1
2
3
4
5
6
7
[root@localhost first-network]# configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP
2019-10-20 16:07:11.323 CST [common.tools.configtxgen] main -> INFO 001 Loading configuration
2019-10-20 16:07:11.376 CST [common.tools.configtxgen.localconfig] Load -> INFO 002 Loaded configuration: /opt/gopath/src/github.com/hyperledger/fabric-samples/first-network/configtx.yaml
2019-10-20 16:07:11.428 CST [common.tools.configtxgen.localconfig] completeInitialization -> INFO 003 orderer type: solo
2019-10-20 16:07:11.428 CST [common.tools.configtxgen.localconfig] LoadTopLevel -> INFO 004 Loaded configuration: /opt/gopath/src/github.com/hyperledger/fabric-samples/first-network/configtx.yaml
2019-10-20 16:07:11.428 CST [common.tools.configtxgen] doOutputAnchorPeersUpdate -> INFO 005 Generating anchor peer update
2019-10-20 16:07:11.428 CST [common.tools.configtxgen] doOutputAnchorPeersUpdate -> INFO 006 Writing anchor peer update

创建同一通道上组织2(Org2)的锚节点(anchor peer)

1
configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org2MSP
1
2
3
4
5
6
7
[root@localhost first-network]# configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org2MSP
2019-10-20 16:07:50.112 CST [common.tools.configtxgen] main -> INFO 001 Loading configuration
2019-10-20 16:07:50.166 CST [common.tools.configtxgen.localconfig] Load -> INFO 002 Loaded configuration: /opt/gopath/src/github.com/hyperledger/fabric-samples/first-network/configtx.yaml
2019-10-20 16:07:50.218 CST [common.tools.configtxgen.localconfig] completeInitialization -> INFO 003 orderer type: solo
2019-10-20 16:07:50.218 CST [common.tools.configtxgen.localconfig] LoadTopLevel -> INFO 004 Loaded configuration: /opt/gopath/src/github.com/hyperledger/fabric-samples/first-network/configtx.yaml
2019-10-20 16:07:50.218 CST [common.tools.configtxgen] doOutputAnchorPeersUpdate -> INFO 005 Generating anchor peer update
2019-10-20 16:07:50.218 CST [common.tools.configtxgen] doOutputAnchorPeersUpdate -> INFO 006 Writing anchor peer update

此时查看channel-artifacts文件夹,可以看到四个所需要配置文件均生成

1
2
[root@localhost channel-artifacts]# ls
channel.tx genesis.block Org1MSPanchors.tx Org2MSPanchors.tx

3.启动网络

利用docker-compose文件启动网络,使用上面步骤生成的 genesis.block 文件来启动排序服务

1
docker-compose -f docker-compose-cli.yaml up -d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@localhost first-network]# docker-compose -f docker-compose-cli.yaml up -d
Creating network "net_byfn" with the default driver
Creating volume "net_peer0.org2.example.com" with default driver
Creating volume "net_peer1.org2.example.com" with default driver
Creating volume "net_peer1.org1.example.com" with default driver
Creating volume "net_peer0.org1.example.com" with default driver
Creating volume "net_orderer.example.com" with default driver
Creating peer0.org2.example.com ... done
Creating orderer.example.com ... done
Creating peer1.org1.example.com ... done
Creating peer1.org2.example.com ... done
Creating peer0.org1.example.com ... done
Creating cli ... done
[root@localhost first-network]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3797ff79a60f hyperledger/fabric-tools:latest "/bin/bash" 47 seconds ago Up 46 seconds cli
1cd801dfe6a9 hyperledger/fabric-peer:latest "peer node start" 49 seconds ago Up 46 seconds 0.0.0.0:9051->9051/tcp peer0.org2.example.com
87bdc5b7f31e hyperledger/fabric-peer:latest "peer node start" 49 seconds ago Up 47 seconds 0.0.0.0:10051->10051/tcp peer1.org2.example.com
35067e605249 hyperledger/fabric-peer:latest "peer node start" 49 seconds ago Up 46 seconds 0.0.0.0:8051->8051/tcp peer1.org1.example.com
349a8be2cfa9 hyperledger/fabric-orderer:latest "orderer" 49 seconds ago Up 46 seconds 0.0.0.0:7050->7050/tcp orderer.example.com
1c458fb55bd8 hyperledger/fabric-peer:latest "peer node start" 49 seconds ago Up 46 seconds 0.0.0.0:7051->7051/tcp peer0.org1.example.com

可以看到已经启动两个组织的4个节点,一个排序节点,和一个cli容器

4. 创建并加入通道

上面已经创建通道配置交易,如果想要创建额外的通道,可以重复上述通道配置创建过程使用configtx.yaml中相同或者不同的配置。
首先,进入cli容器

1
docker exec -it cli bash

进入cli容器结果:

1
2
[root@localhost first-network]# docker exec -it cli bash
root@3797ff79a60f:/opt/gopath/src/github.com/hyperledger/fabric/peer#

因为cli容器中的默认环境变量是 peer0.org1.example.com 对应的环境变量,因此调用 peer0.org1.example.com 时可以不做变量设置,直接调用即可。但是如果需要调用其它节点,则需要在调用命令执行之前设置对应节点的环境变量。peer0.org1的环境变量如下:

1
2
3
4
5
6
# Environment variables for PEER0

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

peer0.org2的环境变量如下:

1
2
3
4
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:9051
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
4.1 创建通道

将生成的通道配置交易channel.tx传给orderer,作为通道创建需求的一部分,注意通道名称不能出现大写字母。

1
2
export CHANNEL_NAME=mychannel
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根证书的本地路径,可以用来验证TLS握手。
命令会返回一个创世区块 -<CHANNEL_NAME.block>,包含channel.tx中指定的配置信息。本次示例返回mychannel.block,在加入通道时需要使用到。

1
2
3
4
5
2019-10-20 09:21:41.951 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2019-10-20 09:21:41.998 UTC [cli.common] readBlock -> INFO 002 Received block: 0

root@3797ff79a60f:/opt/gopath/src/github.com/hyperledger/fabric/peer# ls
channel-artifacts crypto mychannel.block scripts
4.2 加入通道

将peer0.org1.example.com加入通道

1
peer channel join -b mychannel.block
1
2
2019-10-20 09:25:43.238 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2019-10-20 09:25:43.279 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel

将peer0.org2.example.com加入通道,需要先设置环境变量为peer0.org2.example.com对应的环境变量再执行命令

1
2
3
4
5
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:9051
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
1
2
2019-10-20 09:30:00.602 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2019-10-20 09:30:00.639 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel
4.3 更新锚节点

更新锚节点会传播到通道的定义。从本质上来讲,是在通道的创世区块上添加配置信息。但这不是修改创世区块,而是添加锚节点的定义到链中。

更新通道定义将Org1的锚节点定义为 peer0.org1.example.com。将生成的锚节点交易Org1MSPanchors.tx传给orderer

1
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
1
2
2019-10-20 11:28:10.858 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2019-10-20 11:28:10.877 UTC [channelCmd] update -> INFO 002 Successfully submitted channel update

更新通道定义将Org2的锚节点定义为 peer0.org2.example.com:

1
2
3
4
5
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:9051
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
1
2
2019-10-20 11:29:46.293 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2019-10-20 11:29:46.320 UTC [channelCmd] update -> INFO 002 Successfully submitted channel update
4.4 安装链码

本示例中,使用简单已经存在的链码。应用通过链码与区块链账本进行交互。因此在每个需要执行和背书的节点上都需要安装链码,然后在对应通道中将链码实例化。

首先安装链码,该命令将链码放置到对应节点的文件系统中。每个链码名称和版本只能对应一个链码源代码。

1
peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/chaincode_example02/go/
  • -n 链码名称
  • -v 链码版本
  • -p 链码路径
  • -l 链码语言(默认golang)
    1
    2
    3
    2019-10-20 11:52:41.045 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
    2019-10-20 11:52:41.045 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
    2019-10-20 11:52:41.613 UTC [chaincodeCmd] install -> INFO 003 Installed remotely response:<status:200 payload:"OK" >
    Node.js版本
    1
    peer chaincode install -n mycc -v 1.0 -l node -p /opt/gopath/src/github.com/chaincode/chaincode_example02/node/
    Java版本
    1
    peer chaincode install -n mycc -v 1.0 -l java -p /opt/gopath/src/github.com/chaincode/chaincode_example02/java/
    将链码安装在Org2的peer0上,修改环境变量
    1
    2
    3
    4
    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:9051
    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
    安装链码:
    1
    peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/chaincode_example02/go/
    1
    2
    3
    2019-10-20 11:57:55.352 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
    2019-10-20 11:57:55.352 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
    2019-10-20 11:57:55.585 UTC [chaincodeCmd] install -> INFO 003 Installed remotely response:<status:200 payload:"OK" >
4.5 实例化链码

实例化链码即初始化通道上的链码并为链码设置背书策略,然后为目标节点启动链码容器。其中-P参数对应的是指定的背书策略,指定对应交易验证所需要的条件。

在示例中使用 -P "AND ('Org1MSP.peer','Org2MSP.peer')",表示需要来自Org1和Org2的背书交易才能验证通过,缺一不可。如果将其中的AND改成OR,则只需要两者之一即可。

实例化链码:

1
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')"
1
2
2019-10-20 12:10:25.198 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2019-10-20 12:10:25.198 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc

如果需要其它节点参加到账本的交互中来的话,只需要将同样名称、版本和语言的链码源码安装到对应的节点上。当节点想要与特定链码交互的时候,对应的链码容器将会被启动。

实例化完成后可以看到启动了一个链码容器:

1
2
3
4
5
6
7
8
9
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fba2e8af5e59 dev-peer0.org2.example.com-mycc-1.0-15b571b3ce849066b7ec74497da3b27e54e0df1345daff3951b94245ce09c42b "chaincode -peer.add…" 2 minutes ago Up 2 minutes dev-peer0.org2.example.com-mycc-1.0
3797ff79a60f hyperledger/fabric-tools:latest "/bin/bash" 4 hours ago Up 4 hours cli
1cd801dfe6a9 hyperledger/fabric-peer:latest "peer node start" 4 hours ago Up 4 hours 0.0.0.0:9051->9051/tcp peer0.org2.example.com
87bdc5b7f31e hyperledger/fabric-peer:latest "peer node start" 4 hours ago Up 4 hours 0.0.0.0:10051->10051/tcp peer1.org2.example.com
35067e605249 hyperledger/fabric-peer:latest "peer node start" 4 hours ago Up 4 hours 0.0.0.0:8051->8051/tcp peer1.org1.example.com
349a8be2cfa9 hyperledger/fabric-orderer:latest "orderer" 4 hours ago Up 4 hours 0.0.0.0:7050->7050/tcp orderer.example.com
1c458fb55bd8 hyperledger/fabric-peer:latest "peer node start" 4 hours ago Up 4 hours 0.0.0.0:7051->7051/tcp peer0.org1.example.com

Node.js版本

1
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 -l node -v 1.0 -c '{"Args":["init","a", "100", "b","200"]}' -P "AND ('Org1MSP.peer','Org2MSP.peer')"

Java版本

1
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 -l java -v 1.0 -c '{"Args":["init","a", "100", "b","200"]}' -P "AND ('Org1MSP.peer','Org2MSP.peer')"
4.6 链码查询
1
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
1
2
root@3797ff79a60f:/opt/gopath/src/github.com/hyperledger/fabric/peer# peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
100
4.7 链码调用
1
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:9051 --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"]}'
1
2019-10-20 12:29:16.689 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200 

再次查询

1
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
1
2
root@3797ff79a60f:/opt/gopath/src/github.com/hyperledger/fabric/peer# peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
90

此时可以看到存在两个链码镜像,因为链码调用的时候peer0.org1需要与账本交互,此前已经安装了对应链码,因此会自动启动对应的链码容器。

1
2
3
4
5
6
7
8
9
10
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3a32eea0e068 dev-peer0.org1.example.com-mycc-1.0-384f11f484b9302df90b453200cfb25174305fce8f53f4e94d45ee3b6cab0ce9 "chaincode -peer.add…" 2 seconds ago Up 2 seconds dev-peer0.org1.example.com-mycc-1.0
fba2e8af5e59 dev-peer0.org2.example.com-mycc-1.0-15b571b3ce849066b7ec74497da3b27e54e0df1345daff3951b94245ce09c42b "chaincode -peer.add…" 15 minutes ago Up 15 minutes dev-peer0.org2.example.com-mycc-1.0
3797ff79a60f hyperledger/fabric-tools:latest "/bin/bash" 4 hours ago Up 4 hours cli
1cd801dfe6a9 hyperledger/fabric-peer:latest "peer node start" 4 hours ago Up 4 hours 0.0.0.0:9051->9051/tcp peer0.org2.example.com
87bdc5b7f31e hyperledger/fabric-peer:latest "peer node start" 4 hours ago Up 4 hours 0.0.0.0:10051->10051/tcp peer1.org2.example.com
35067e605249 hyperledger/fabric-peer:latest "peer node start" 4 hours ago Up 4 hours 0.0.0.0:8051->8051/tcp peer1.org1.example.com
349a8be2cfa9 hyperledger/fabric-orderer:latest "orderer" 4 hours ago Up 4 hours 0.0.0.0:7050->7050/tcp orderer.example.com
1c458fb55bd8 hyperledger/fabric-peer:latest "peer node start" 4 hours ago Up 4 hours 0.0.0.0:7051->7051/tcp peer0.org1.example.com
4.8 在第三个节点上安装链码

本次将链码安装在Org2的peer1上。同样,首先修改环境变量:

1
2
3
4
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=peer1.org2.example.com:10051
CORE_PEER_LOCALMSPID="Org2MSP"
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt

安装链码:

1
peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/chaincode_example02/go/
1
2
3
2019-10-20 12:40:01.588 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2019-10-20 12:40:01.588 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
2019-10-20 12:40:01.809 UTC [chaincodeCmd] install -> INFO 003 Installed remotely response:<status:200 payload:"OK" >

因为在上述链码中,变量a被初始化为100,接着在调用的时候被转走10,因此对a的查询最后应该返回90。为了确认我们可以在Org2的peer1上进行查询,首先应该先加入通道

1
2
3
4
5
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=peer1.org2.example.com:10051
CORE_PEER_LOCALMSPID="Org2MSP"
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt
peer channel join -b mychannel.block
1
2
2019-10-20 12:45:00.417 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2019-10-20 12:45:00.439 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel

加入通道后即可进行查询:

1
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
1
2
root@3797ff79a60f:/opt/gopath/src/github.com/hyperledger/fabric/peer# peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
90

返回结果无误,而且在查询过程中,需要等待一段时间才会有响应,是因为在Org2的peer1节点上也不存在着已经启动的链码容器,因为这是该节点第一次与账本交互,因此会启动对应的链码容器,花费一定时间。

1
2
3
4
5
6
7
8
9
10
11
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b25b1a4c1ea3 dev-peer1.org2.example.com-mycc-1.0-26c2ef32838554aac4f7ad6f100aca865e87959c9a126e86d764c8d01f8346ab "chaincode -peer.add…" 2 minutes ago Up 2 minutes dev-peer1.org2.example.com-mycc-1.0
3a32eea0e068 dev-peer0.org1.example.com-mycc-1.0-384f11f484b9302df90b453200cfb25174305fce8f53f4e94d45ee3b6cab0ce9 "chaincode -peer.add…" 23 minutes ago Up 23 minutes dev-peer0.org1.example.com-mycc-1.0
fba2e8af5e59 dev-peer0.org2.example.com-mycc-1.0-15b571b3ce849066b7ec74497da3b27e54e0df1345daff3951b94245ce09c42b "chaincode -peer.add…" 38 minutes ago Up 38 minutes dev-peer0.org2.example.com-mycc-1.0
3797ff79a60f hyperledger/fabric-tools:latest "/bin/bash" 4 hours ago Up 4 hours cli
1cd801dfe6a9 hyperledger/fabric-peer:latest "peer node start" 4 hours ago Up 4 hours 0.0.0.0:9051->9051/tcp peer0.org2.example.com
87bdc5b7f31e hyperledger/fabric-peer:latest "peer node start" 4 hours ago Up 4 hours 0.0.0.0:10051->10051/tcp peer1.org2.example.com
35067e605249 hyperledger/fabric-peer:latest "peer node start" 4 hours ago Up 4 hours 0.0.0.0:8051->8051/tcp peer1.org1.example.com
349a8be2cfa9 hyperledger/fabric-orderer:latest "orderer" 4 hours ago Up 4 hours 0.0.0.0:7050->7050/tcp orderer.example.com
1c458fb55bd8 hyperledger/fabric-peer:latest "peer node start" 4 hours ago Up 4 hours 0.0.0.0:7051->7051/tcp peer0.org1.example.com

注:

  • 如果需要对账本成功执行读/写操作,必需要在对应节点上安装链码。链码容器会在初始化或者传统读写交易的触发下才会开始启动。
  • 通道中的所有节点都会维护一个精确的账本副本,将不可篡改和顺序的区块数据组成区块链,来维护当前状态。这些节点也包括了没有安装链码但已经加入该通道的节点。
  • 如果要访问链码,只需要在对应节点上安装上链码源码即可,因为链码已经被实例化过了。
4.9 查看交易
1
docker logs -f cli
4.10 查看链码日志
1
2
3
docker logs dev-peer0.org2.example.com-mycc-1.0
docker logs dev-peer0.org1.example.com-mycc-1.0
docker logs dev-peer1.org2.example.com-mycc-1.0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[root@localhost ~]# docker logs dev-peer0.org2.example.com-mycc-1.0
ex02 Init
Aval = 100, Bval = 200
ex02 Invoke
Query Response:{"Name":"a","Amount":"100"}
ex02 Invoke
Aval = 90, Bval = 210

[root@localhost ~]# docker logs dev-peer0.org1.example.com-mycc-1.0
ex02 Invoke
Query Response:{"Name":"a","Amount":"100"}
ex02 Invoke
Aval = 90, Bval = 210
ex02 Invoke
Query Response:{"Name":"a","Amount":"90"}
ex02 Invoke
Query Response:{"Name":"a","Amount":"90"}
ex02 Invoke
Query Response:{"Name":"a","Amount":"90"}
ex02 Invoke
Query Response:{"Name":"a","Amount":"90"}

[root@localhost ~]# docker logs dev-peer1.org2.example.com-mycc-1.0
ex02 Invoke
Query Response:{"Name":"a","Amount":"90"}
ex02 Invoke
Query Response:{"Name":"a","Amount":"90"}

最后更新: 2020年09月21日 17:31

原始链接: https://silence-linhl.github.io/blog/2019/10/22/byfn2/

× 请我吃糖~
打赏二维码