Fabric框架的学习-3-手动组建Fabric网络(重点!含自动化部署脚本一键操作)
四、 Fabric核心模块
在搭建自己的网络之前还需要了解下核心模块
对于模块的说明:
模块名称 | 说明 |
---|---|
peer | / |
orderer | / |
cryptogen | 编写配置文件,根据配置文件生成证书 |
cryfigtxgen | 生成创世块文件(不是创世快)、生成通道文件 |
configtxlator | 对区块文件修改,可以将二进制的区块文件变为JSON的可读模式。以及动态的添加组织 |
操作这些模块,就主要使用这些模块给我们提供的shell命令,这些shell命令都在bin目录下
并且之前已经将这些命令加入到
/usr/local/bin`全局变量下了
命令手册:
http://cw.hubwiz.com/card/c/fabric-command-manual/1/1/1/
五、手动组建Fabric网络
5.1 生成Fabric证书-yaml 命令:cryptogen
cryptogen --help
cryptogen showtemplate # 会输出配置文件的模板
Fabric V1.2.0中的版本cryptogen:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VYnJyFAR-1602896946058)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201008115438319.png)]
对于每一子命令可以查看:
cryptogen generate --help
获取配置文件模板
cryptogen showtemplate
# 会直接输出到终端
# 重定向到一个新yaml文件
cryptogen showtemplate > a.yaml
vim a.yaml # 这样就可以直接使用了
模板文档解释(一些注释做了删减):
# ---------------------------------------------------------------------------
# "OrdererOrgs" - Definition of organizations managing orderer nodes
# ---------------------------------------------------------------------------
# 排序节点组织信息
OrdererOrgs:
# ---------------------------------------------------------------------------
# Orderer
# ---------------------------------------------------------------------------
- Name: Orderer # 排序节点组织名
Domain: example.com # 根域名,排序节点组织的根域名,在实际开发环境中需要使用真实已经备案的域名,测试环境下自己随便起就可以
EnableNodeOUs: false # 链码是否支持nodejs
# ---------------------------------------------------------------------------
# "Specs" - See PeerOrgs below for complete description
# ---------------------------------------------------------------------------
Specs:
- Hostname: orderer # 子域名,因为一个域名只能绑定一个ip,而orderer是多个的,所以要多个子域名,这里就只有这一个orderer一个即可
# 访问这台orderer对应的域名就是orderer.example.com
# ---------------------------------------------------------------------------
# "PeerOrgs" - Definition of organizations managing peer nodes
# ---------------------------------------------------------------------------
# peer节点组织
PeerOrgs:
# ---------------------------------------------------------------------------
# Org1
# ---------------------------------------------------------------------------
# 组织还可以进行细分,分为Org1、Org2等等,在下方添加即可
- Name: Org1 # 组织名字可以自己制定
Domain: org1.example.com # 访问第一个组织用到的根域名
EnableNodeOUs: false # 链码是否支持nodejs
Template: # 模板, 根据默认的规则生成2个peer数据存储节点
Count: 2 # 第一个节点域名: peer0.org1.example.com 第二个节点域名: peer1.org1.example.com
Users: # 创建普通用户的个数
Count: 1
# ---------------------------------------------------------------------------
# Org2: See "Org1" for full specification
# ---------------------------------------------------------------------------
# 组织2同理
- Name: Org2
Domain: org2.example.com
EnableNodeOUs: false
Template:
Count: 1
Users:
Count: 1
注意事项:
-
Domain: example.com 根域名,排序节点组织的根域名,在实际开发环境中需要使用真实已经备案的域名,测试环境下自己随便起就可以
-
使用Specs或者Template指定节点的子域名两者都可以,区别就在于用Specs可以自己规划子域名,而Template则是例如pee0、peer1这样的默认设置
两个还可以一起用,最终节点数是两者之和
例:
Template: Count: 2 # 两个默认域名 Specs: - Hostname: orderer # 一个指定域名 # 这样是指定三个节点
小练习:
要求:
mkdir fabric-test01 #创建一个空目录作为环境
cd fabric-test01/
cryptogen showtemplate > crypto-config.yaml # 创建空模板文件
vim crypto-config.yaml
# 修改模板
2 # ---------------------------------------------------------------------------
3 # "OrdererOrgs" - Definition of organizations managing orderer nodes
4 # ---------------------------------------------------------------------------
5 OrdererOrgs:
6 # ---------------------------------------------------------------------------
7 # Orderer
8 # ---------------------------------------------------------------------------
9 - Name: Orderer
10 Domain: xwj.com
11 EnableNodeOUs: false
12
13 # ---------------------------------------------------------------------------
14 # "Specs" - See PeerOrgs below for complete description
15 # ---------------------------------------------------------------------------
16 Specs:
17 - Hostname: orderer
18
19 # ---------------------------------------------------------------------------
20 # "PeerOrgs" - Definition of organizations managing peer nodes
21 # ---------------------------------------------------------------------------
22 PeerOrgs:
23 # ---------------------------------------------------------------------------
24 # Org1
25 # ---------------------------------------------------------------------------
26 - Name: OrgGo
27 Domain: orggo.xwj.com
28 EnableNodeOUs: true
29 Template:
30 Count: 2
31 Users:
32 Count: 3
33
34 # ---------------------------------------------------------------------------
35 # Org2: See "Org1" for full specification
36 # ---------------------------------------------------------------------------
37 - Name: OrgCpp
38 Domain: orgcpp.xwj.com
39 EnableNodeOUs: true
40 Template:
41 Count: 2
42 Users:
43 Count: 3
使用–config命令去执行配置文件,如果不指定配置文件,则会按照模板文件来执行
cryptogen generate --config=crypto-config.yaml # 出现自己写的组织名称则说明成功了
# 随后生成crypto-config文件
检查peer和user创建的个数,符合要求即成功
5.2 创世块文件和通道文件的生成命令:configtxgen
5.2.1 命令介绍:
参数如下:
configtxgen --help
# 没有子命令
Usage of configtxgen:
-asOrg string #所属组织,也就是为某个特定组织生成配置
-channelID string #channel名称,如果不指定默认是"testchainid"
-inspectBlock string #打印指定区块文件中配置内容
-inspectChannelCreateTx string #打印指定创建通道交易的配置文件
-outputAnchorPeersUpdate string #生成一个更新锚点的更新channel配置信息
-outputBlock string #输出区块文件路径
-outputCreateChannelTx string #指定一个路径,来生成channel配置文件
-profile string #配置文件中的节点,用于生成相关配置文件,默认是 "SampleInsecureSolo")
-version #显示版本信息
执行这个命令,必须要指定固定名字的一个配置文件 configtx.yaml
cp /home/xwj/fabric-1.2/fabric-samples/first-network/configtx.yaml /home/xwj/fabric-1.2/test01/
# 这个没有模板,所以在之前的first-network文件夹中复制一个到自己的目录中修改即可
6 ---
15 Organizations: # 固定的
19 - &OrdererOrg # 排序节点组织的名字,这里的组织名可以随便取 *OrdererOrg代表这整个块
22 Name: OrdererOrg # 组织名
23
25 ID: OrdererMSP # 排序节点组织的ID
26
28 MSPDir: crypto-config/ordererOrganizations/example.com/msp # 这里是创建证书时MSP的地址,这里是相对地址
29
30 - &Org1 # 第一个组织,名字自己起
33 Name: Org1MSP # 第一个组织的名字
34
36 ID: Org1MSP # 组织ID
37
38 MSPDir: crypto-config/peerOrganizations/org1.example.com/msp
39
40 AnchorPeers: # 锚节点
44 - Host: peer0.org1.example.com # 指定该组织中任一个节点peer节点的域名,其就作为该组织的锚节点。一个组织只有一个锚节点
45 Port: 7051 # 固定端口
46
47 - &Org2
50 Name: Org2MSP
51
53 ID: Org2MSP
54
55 MSPDir: crypto-config/peerOrganizations/org2.example.com/msp
56
57 AnchorPeers:
61 - Host: peer0.org2.example.com
62 Port: 7051
63 ### 如果有多个组织,基础添加即可
83 Capabilities: # 能力 V1.1之后出现的,设置时全部设置为True(为了向上兼容)
86 Global: &ChannelCapabilities
91 V1_1: true
96 Orderer: &OrdererCapabilities
101 V1_1: true
102
106 Application: &ApplicationCapabilities
111 V1_2: true
112
121 Application: &ApplicationDefaults #一般就用默认配置
122
125 Organizations:
126
135 Orderer: &OrdererDefaults # 对orderer节点组织设置一些更加细的命令
136
137 # Orderer Type: The orderer implementation to start
138 # Available types are "solo" and "kafka"
# 共识机制 == 排序算法 ,Fabric V1.2 提供的共识机制有两种solo和kafka,测试环境一般用solo。真实环境用kafka(适用于高并发)
# solo就是指orderer节点就只有一个不需要共识算法
139 OrdererType: solo # 共识算法
140
141 Addresses: # orderer节点的地址
142 - orderer.example.com:7050 # 端口一般不修改
143
145 BatchTimeout: 2s # 多长时间产生一个区块
146
##### BatchTimeout、MaxMessageCount、AbsoluteMaxBytes这三者有一个超过了就产生区块
148 BatchSize:
149
150 # Max Message Count: The maximum number of messages to permit in a batch
151 MaxMessageCount: 10 # 交易的最大数量,,建议100
152
153 # Absolute Max Bytes: The absolute maximum number of bytes allowed for
154 # the serialized messages in a batch.
155 AbsoluteMaxBytes: 99 MB # 数据大小最大值,数据量达到99M也会产生区块,一般32M/64M
156
160 PreferredMaxBytes: 512 KB # 建议的最大数量
161
162 Kafka:
165 Brokers: # 代理人
166 - 127.0.0.1:9092 #kafka的服务器
167
170 Organizations:
171
174 # Profile 上面分散的设置的总结
180 Profiles: # 固定的不能修改
181 # *是引用上面&的数据
182 TwoOrgsOrdererGenesis: # 区块名字 可以改
183 Capabilities: # 能力,即上面设置的
184 <<: *ChannelCapabilities # 通道的能力
185 Orderer:
186 <<: *OrdererDefaults # orderer组织的细节配置
187 Organizations:
188 - *OrdererOrg # orderer组织的配置
189 Capabilities:
190 <<: *OrdererCapabilities # orderer的能力
191 Consortiums: # 联盟
192 SampleConsortium: # 实例联盟 可以自定义
193 Organizations: # 两个peer节点组织
194 - *Org1
195 - *Org2
196 TwoOrgsChannel: # 通道名字可以自定义
197 Consortium: SampleConsortium # 对应上面的联盟名字,要保持一致
198 Application:
199 <<: *ApplicationDefaults
200 Organizations: # 事先声明组织在改通道中,后续其中的节点就可以选择加入该通道
201 - *Org1
202 - *Org2
203 Capabilities:
204 <<: *ApplicationCapabilities
锚节点
5.2.2 修改配置文件
事先需要做的事:
-
找出orderer的msp的位置:
/home/xwj/fabric_1.2/fabric-test01/crypto-config/ordererOrganizations/xwj.com/msp
-
找出两个peer组织的msp的位置
go组织:
/home/xwj/fabric_1.2/fabric-test01/crypto-config/peerOrganizations/orggo.xwj.com/msp
cpp组织同样的方法。。。不再赘述
/home/xwj/fabric_1.2/fabric-test01/crypto-config/peerOrganizations/orgcpp.xwj.com/msp
configtx.yaml 配置文件如下
---
Organizations:
- &OrdererOrg
Name: OrdererOrg
ID: OrdererMSP
MSPDir: crypto-config/ordererOrganizations/xwj.com/msp
- &org_go
Name: OrgGoMSP
ID: OrgGoMSP
MSPDir: crypto-config/peerOrganizations/orggo.xwj.com/msp
AnchorPeers:
- Host: peer0.orggo.xwj.com
Port: 7051
- &org_cpp
Name: OrgCppMSP
ID: OrgCppMSP
MSPDir: crypto-config/peerOrganizations/orgcpp.xwj.com/msp
AnchorPeers:
- Host: peer0.orgcpp.xwj.com
Port: 7051
Capabilities:
Global: &ChannelCapabilities
V1_1: true
Orderer: &OrdererCapabilities
V1_1: true
Application: &ApplicationCapabilities
V1_2: true
Application: &ApplicationDefaults
Organizations:
Orderer: &OrdererDefaults
OrdererType: solo
Addresses:
- orderer.xwj.com:7050
BatchTimeout: 2s
BatchSize:
MaxMessageCount: 100
AbsoluteMaxBytes: 32 MB
PreferredMaxBytes: 512 KB
Kafka:
Brokers:
- 127.0.0.1:9092
Organizations:
Profiles:
XwjOrdererGenesis:
Capabilities:
<<: *ChannelCapabilities
Orderer:
<<: *OrdererDefaults
Organizations:
- *OrdererOrg
Capabilities:
<<: *OrdererCapabilities
Consortiums:
SampleConsortium:
Organizations:
- *org_go
- *org_cpp
XwjOrgsChannel:
Consortium: SampleConsortium
Application:
<<: *ApplicationDefaults
Organizations:
- *org_go
- *org_cpp
Capabilities:
<<: *ApplicationCapabilities
5.2.3 命令执行配置文件
-
创建创世块
configtxgen -profile XwjOrdererGenesis -outputBlock ./genesis.block
注意参数不是configtx.yaml的文件名,而是其中Profiles创世块的这个名字(因为是创建创世块的命令需要这些配置信息):
没有报错信息,并且看到genesis.block文件生成则说明成功了。
为了适应后面的配置文件的默认目录,一般会将genesis.block文件放到channel-artifacts文件夹下:
mkdir channel-artifacts mv genesis.block channel-artifacts/
-
生成通道文件
configtxgen -profile XwjOrgsChannel -outputCreateChannelTx channel-artifacts/channel.tx -channelID xwjChannel # outputCreateChannelTx 参数后接 保存的文件名,一般tx后缀 # channelID 是自己指定的通道的id,这个与configtx.yaml中的配置名字无关
注意后接通道配置名:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rvmpSSYg-1602896946088)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201011102458781.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BlPdd144-1602896946091)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201011102829381.png)]
-
生成锚节点更新文件
这个操作是可选的,可以做可以不做
这个锚节点更新文件是为了当你选定的锚节点失效的时候,更新整个组织的锚节点(重新指定一个锚节点)的作用
configtxgen -profile XwjOrgsChannel -outputAnchorPeersUpdate channel-artifacts/GoMSPanchors.tx -channelID xwjChannel -asOrg OrgGoMSP # profile 还是指定通道配置名 # outputAnchorPeersUpdate 指定输出文件名 # channelID 之前设置的通道id # asOrg 指明锚节点属于哪个组织 configtxgen -profile XwjOrgsChannel -outputAnchorPeersUpdate channel-artifacts/CPPMSPanchors.tx -channelID xwjChannel -asOrg OrgCppMSP
对应生成两个更新文件
每个组织都生成一个对应的锚节点更新文件
5.3 docker-compose文件的编写
5.3.1 文件关系介绍
一个网络中有非常多的各类节点,每个节点都是在docker容器中运行的,需要编写docker-compose文件去管理这些docker
-
docker-compose-cli.yaml
官方实例first-network中的docker-compose-cli.yaml解析
version: '2' # docker-compose的版本号 volumes: # 官方实例有五个节点,所以分别对应五个数据卷的映射 映射本地主机地址一般在/var/lib/docker/volumes # 这里的映射只写了一半,在docker-compose-base中写了完整的映射关系 orderer.example.com: peer0.org1.example.com: peer1.org1.example.com: peer0.org2.example.com: peer1.org2.example.com: networks: # 节点所属的网络 byfn: services: # 服务 orderer.example.com: # 服务名 可以自己指定 extends: # 继承下方文件中的服务 file: base/docker-compose-base.yaml service: orderer.example.com # 具体继承文件中哪项服务 container_name: orderer.example.com # 指定容器的名字 networks: # 节点所在网络 - byfn peer0.org1.example.com: container_name: peer0.org1.example.com extends: file: base/docker-compose-base.yaml service: peer0.org1.example.com networks: - byfn peer1.org1.example.com: container_name: peer1.org1.example.com extends: file: base/docker-compose-base.yaml service: peer1.org1.example.com networks: - byfn peer0.org2.example.com: container_name: peer0.org2.example.com extends: file: base/docker-compose-base.yaml service: peer0.org2.example.com networks: - byfn peer1.org2.example.com: container_name: peer1.org2.example.com extends: file: base/docker-compose-base.yaml service: peer1.org2.example.com cli: # 客户端的终端 可以用linux也可以用nodejs、java编写 这里是linux 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/aaa@qq.com/msp working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer # 进入镜像时其工作目录 command: /bin/bash # 命令 volumes: # 数据卷的挂载 - /var/run/:/host/var/run/ - ./../chaincode/:/opt/gopath/src/github.com/chaincode - ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ - ./scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/ - ./channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts # 上面生成的那些文件 depends_on: # 启动顺序 - orderer.example.com - peer0.org1.example.com - peer1.org1.example.com - peer0.org2.example.com - peer1.org2.example.com networks: # 客户端所在网络 - byfn
以上配置文件会启动6个容器(包含客户端cli)
-
base目录下的docker-compose-base.yaml
version: '2' services: orderer.example.com: # 被上面那个文件所继承的服务 container_name: orderer.example.com # 容器名 image: hyperledger/fabric-orderer:$IMAGE_TAG # $IMAGE_TAG环境变量指定运行镜像的版本tag environment: # orderer镜像运行需要使用的环境变量 - ORDERER_GENERAL_LOGLEVEL=INFO - ORDERER_GENERAL_LISTENADDRESS=0.0.0.0 - ORDERER_GENERAL_GENESISMETHOD=file - ORDERER_GENERAL_GENESISFILE=/var/hyperledger/orderer/orderer.genesis.block - ORDERER_GENERAL_LOCALMSPID=OrdererMSP - ORDERER_GENERAL_LOCALMSPDIR=/var/hyperledger/orderer/msp # enabled TLS - ORDERER_GENERAL_TLS_ENABLED=true - ORDERER_GENERAL_TLS_PRIVATEKEY=/var/hyperledger/orderer/tls/server.key - ORDERER_GENERAL_TLS_CERTIFICATE=/var/hyperledger/orderer/tls/server.crt - ORDERER_GENERAL_TLS_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt] working_dir: /opt/gopath/src/github.com/hyperledger/fabric # 启动后的工作目录 command: orderer # 启动order服务 volumes: # 数据卷映射 - ../channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block # 创世块映射 # order节点的身份证书msp - ../crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/msp:/var/hyperledger/orderer/msp # tls证书 - ../crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/:/var/hyperledger/orderer/tls # 完整的映射关系 # 把/var/lib/docker/volumes/order.xwj.com 映射到/var/hyperledger/production/orderer - orderer.example.com:/var/hyperledger/production/orderer ports: - 7050:7050 # 端口映射 orderer一个端口用于通信,而peer有两个端口 peer0.org1.example.com: container_name: peer0.org1.example.com extends: # 又继承了一个文件peer-base.yaml中的peer-base服务,peer-base是peer节点的一个通用配置,所以单独提出来了 file: peer-base.yaml service: peer-base environment: - CORE_PEER_ID=peer0.org1.example.com - CORE_PEER_ADDRESS=peer0.org1.example.com:7051 - CORE_PEER_GOSSIP_BOOTSTRAP=peer1.org1.example.com:7051 - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org1.example.com:7051 - CORE_PEER_LOCALMSPID=Org1MSP volumes: - /var/run/:/host/var/run/ - ../crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp:/etc/hyperledger/fabric/msp - ../crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls:/etc/hyperledger/fabric/tls - peer0.org1.example.com:/var/hyperledger/production ports: - 7051:7051 # 一般情况 ~51端口用于通信 - 7053:7053 # ~53端口用于事件传播 peer1.org1.example.com: container_name: peer1.org1.example.com extends: file: peer-base.yaml service: peer-base environment: - CORE_PEER_ID=peer1.org1.example.com - CORE_PEER_ADDRESS=peer1.org1.example.com:7051 - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org1.example.com:7051 - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org1.example.com:7051 - CORE_PEER_LOCALMSPID=Org1MSP volumes: - /var/run/:/host/var/run/ - ../crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/msp:/etc/hyperledger/fabric/msp - ../crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls:/etc/hyperledger/fabric/tls - peer1.org1.example.com:/var/hyperledger/production ports: - 8051:7051 - 8053:7053 peer0.org2.example.com: container_name: peer0.org2.example.com extends: file: peer-base.yaml service: peer-base environment: - CORE_PEER_ID=peer0.org2.example.com - CORE_PEER_ADDRESS=peer0.org2.example.com:7051 - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org2.example.com:7051 - CORE_PEER_GOSSIP_BOOTSTRAP=peer1.org2.example.com:7051 - CORE_PEER_LOCALMSPID=Org2MSP volumes: - /var/run/:/host/var/run/ - ../crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/msp:/etc/hyperledger/fabric/msp - ../crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls:/etc/hyperledger/fabric/tls - peer0.org2.example.com:/var/hyperledger/production ports: - 9051:7051 - 9053:7053 peer1.org2.example.com: container_name: peer1.org2.example.com extends: file: peer-base.yaml service: peer-base environment: - CORE_PEER_ID=peer1.org2.example.com - CORE_PEER_ADDRESS=peer1.org2.example.com:7051 - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org2.example.com:7051 - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org2.example.com:7051 - CORE_PEER_LOCALMSPID=Org2MSP volumes: - /var/run/:/host/var/run/ - ../crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/msp:/etc/hyperledger/fabric/msp - ../crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls:/etc/hyperledger/fabric/tls - peer1.org2.example.com:/var/hyperledger/production ports: - 10051:7051 - 10053:7053
peer-base.yaml文件:
version: '2' services: peer-base: image: hyperledger/fabric-peer:$IMAGE_TAG environment: - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock # the following setting starts chaincode containers on the same # bridge network as the peers # https://docs.docker.com/compose/networking/ - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=${COMPOSE_PROJECT_NAME}_byfn - CORE_LOGGING_LEVEL=INFO #- CORE_LOGGING_LEVEL=DEBUG - CORE_PEER_TLS_ENABLED=true - CORE_PEER_GOSSIP_USELEADERELECTION=true - CORE_PEER_GOSSIP_ORGLEADER=false - CORE_PEER_PROFILE_ENABLED=true - CORE_PEER_TLS_CERT_FILE=/etc/hyperledger/fabric/tls/server.crt - CORE_PEER_TLS_KEY_FILE=/etc/hyperledger/fabric/tls/server.key - CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer # 工作目录 command: peer node start # 启动peer
5.3.2 客户端角色需要使用的环境变量
# 客户端docker容器启动之后,go的工作目录
- GOPATH=/opt/gopath # 一般不变
# docker启动之后的本地套接字,一般不变
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
# 日志级别: critical 严重错误 | error | warning | notice | info | debug
- CORE_LOGGING_LEVEL=INFO
# 当前客户端节点的id,自己指定
- CORE_PEER_ID=cli
# 客户端需要连接的peer节点地址(同一个组织下),客户端必须要连接一个peer节点才能通信,端口一般不该
- CORE_PEER_ADDRESS=peer0.org1.example.com:7051
# 客户端、peer节点所属的组织
- CORE_PEER_LOCALMSPID=Org1MSP
# 通信是否使用tls加密,true对应下方的一系列设置
- CORE_PEER_TLS_ENABLED=true
# 证书文件 这些文件对应的是客户端要连接peer节点的证书目录
-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/aaa@qq.com/msp
修改客户端的配置:
cli:
container_name: cli
image: hyperledger/fabric-tools:latest
tty: true
stdin_open: true
environment:
- GOPATH=/opt/gopath
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
- CORE_LOGGING_LEVEL=INFO
- CORE_PEER_ID=cli
- CORE_PEER_ADDRESS=peer0.orggo.xwj.com:7051
- CORE_PEER_LOCALMSPID=OrgGoMSP
- CORE_PEER_TLS_ENABLED=true
- CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orggo.xwj.com/peers/peer0.orggo.xwj.com/tls/server.crt
- CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orggo.xwj.com/peers/peer0.orggo.xwj.com/tls/server.key
- CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orggo.xwj.com/peers/peer0.orggo.xwj.com/tls/ca.crt
- CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orggo.xwj.com/users/aaa@qq.com/msp
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
command: /bin/bash
volumes:
- /var/run/:/host/var/run/
- ./chaincode/:/opt/gopath/src/github.com/chaincode
- ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/
- ./channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts
depends_on:
- orderer.xwj.com
- peer0.orggo.xwj.com
- peer1.orggo.xwj.com
- peer0.orgcpp.xwj.com
- peer1.orgcpp.xwj.com
networks:
- byfn
5.3.3 orderer节点需要使用的环境变量
环境配置解析:
environment: # orderer镜像运行需要使用的环境变量
- ORDERER_GENERAL_LOGLEVEL=INFO # 日志级别
- ORDERER_GENERAL_LISTENADDRESS=0.0.0.0 # orderer监听的ip地址
- ORDERER_GENERAL_GENESISMETHOD=file # 创世块的来源,指定file来源就是文件
# 创世快对应的文件,这个目录被挂载,不需要改
# - ../channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block
- ORDERER_GENERAL_GENESISFILE=/var/hyperledger/orderer/orderer.genesis.block
- ORDERER_GENERAL_LOCALMSPID=OrdererMSP # orderer的所属组id
- ORDERER_GENERAL_LOCALMSPDIR=/var/hyperledger/orderer/msp # 当前节点的msp账号
# enabled TLS
- ORDERER_GENERAL_TLS_ENABLED=true # 是否使用tls加密
- ORDERER_GENERAL_TLS_PRIVATEKEY=/var/hyperledger/orderer/tls/server.key # 私钥
- ORDERER_GENERAL_TLS_CERTIFICATE=/var/hyperledger/orderer/tls/server.crt # 证书
- ORDERER_GENERAL_TLS_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt] # 根证书
修改环境配置:
5.3.4 peer节点需要使用的环境变量
peer节点需要配置的环境变量解析:
extends: # 又继承了一个文件peer-base.yaml中的peer-base服务,peer-base是peer节点的一个通用配置,所以单独提出来了
file: peer-base.yaml
service: peer-base
environment:
- CORE_PEER_ID=peer0.org1.example.com # 当前peer节点的名字
- CORE_PEER_ADDRESS=peer0.org1.example.com:7051 # peer节点的ip地址信息
# 启动后向哪些节点发起gossip连接,以加入网络
# gossip流言协议,每个节点只向没有收到流言的节点传播
# 一般配置就写自己的ip+端口就可以了(不知道写谁的话)
- CORE_PEER_GOSSIP_BOOTSTRAP=peer1.org1.example.com:7051
# 为了被其他节点感知到。设置自己的地址和端口,不设置别的节点就不知道
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org1.example.com:7051
# peer节点所属组的组id
- CORE_PEER_LOCALMSPID=Org1MSP
# peer-base.yaml 中环境配置
environment:
# 本地套接字地址 一般不需要改
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
# the following setting starts chaincode containers on the same
# bridge network as the peers
# https://docs.docker.com/compose/networking/
# 当前节点属于哪个网络
- CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=${COMPOSE_PROJECT_NAME}_byfn
- CORE_LOGGING_LEVEL=INFO # 日志级别
#- CORE_LOGGING_LEVEL=DEBUG
- CORE_PEER_TLS_ENABLED=true # 是否加密
- CORE_PEER_GOSSIP_USELEADERELECTION=true # 下方单独解释
- CORE_PEER_GOSSIP_ORGLEADER=false # 下方单独解释
- CORE_PEER_PROFILE_ENABLED=true # 在peer节点中有一个profile服务,在此指定是否开启
- CORE_PEER_TLS_CERT_FILE=/etc/hyperledger/fabric/tls/server.crt
- CORE_PEER_TLS_KEY_FILE=/etc/hyperledger/fabric/tls/server.key
- CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt
- CORE_PEER_GOSSIP_USELEADERELECTION=true 是否使用自动选举
- CORE_PEER_GOSSIP_ORGLEADER=false 当前节点是否为leader节点
一个组织中的leader节点可以手动设置,也可以让网络自动指定。但是手动设置的节点一旦故障那么网络不会自动替代,所以一般采用网络自动选举的机制CORE_PEER_GOSSIP_USELEADERELECTION环境变量就是设置是否由网络指定
CORE_PEER_GOSSIP_ORGLEADER=false 表明当前节点是否为leader节点,如果设置了网络自动选举,那么这一项就设置为false
修改docker-compose-cli.yaml docker-compose-base.yaml peer-base.yaml
# docker-compose-cli文件中的peer部分
peer0.orggo.xwj.com:
container_name: peer0.orggo.xwj.com
extends:
file: base/docker-compose-base.yaml
service: peer0.orggo.xwj.com
networks:
- byfn
peer1.orggo.xwj.com:
container_name: peer1.orggo.xwj.com
extends:
file: base/docker-compose-base.yaml
service: peer1.orggo.xwj.com
networks:
- byfn
peer0.orgcpp.xwj.com:
container_name: peer0.orgcpp.xwj.com
extends:
file: base/docker-compose-base.yaml
service: peer0.orgcpp.xwj.com
networks:
- byfn
peer1.orgcpp.xwj.com:
container_name: peer1.orgcpp.xwj.com
extends:
file: base/docker-compose-base.yaml
service: peer1.orgcpp.xwj.com
networks:
- byfn
# docker-compose-base.yaml文件中的peer部分
peer0.orggo.xwj.com:
container_name: peer0.orggo.xwj.com
extends:
file: peer-base.yaml
service: peer-base
environment:
- CORE_PEER_ID=peer0.orggo.xwj.com
- CORE_PEER_ADDRESS=peer0.orggo.xwj.com:7051
- CORE_PEER_GOSSIP_BOOTSTRAP=peer1.orggo.xwj.com:7051
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.orggo.xwj.com:7051
- CORE_PEER_LOCALMSPID=OrgGoMSP
volumes:
- /var/run/:/host/var/run/
- ../crypto-config/peerOrganizations/orggo.xwj.com/peers/peer0.orggo.xwj.com/msp:/etc/hyperledger/fabric/msp
- ../crypto-config/peerOrganizations/orggo.xwj.com/peers/peer0.orggo.xwj.com/tls:/etc/hyperledger/fabric/tls
- peer0.orggo.xwj.com:/var/hyperledger/production
ports:
- 7051:7051
- 7053:7053
peer1.orggo.xwj.com:
container_name: peer1.orggo.xwj.com
extends:
file: peer-base.yaml
service: peer-base
environment:
- CORE_PEER_ID=peer1.orggo.xwj.com
- CORE_PEER_ADDRESS=peer1.orggo.xwj.com:7051
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.orggo.xwj.com:7051
- CORE_PEER_GOSSIP_BOOTSTRAP=peer0.orggo.xwj.com:7051
- CORE_PEER_LOCALMSPID=OrgGoMSP
volumes:
- /var/run/:/host/var/run/
- ../crypto-config/peerOrganizations/orggo.xwj.com/peers/peer1.orggo.xwj.com/msp:/etc/hyperledger/fabric/msp
- ../crypto-config/peerOrganizations/orggo.xwj.com/peers/peer1.orggo.xwj.com/tls:/etc/hyperledger/fabric/tls
- peer1.orggo.xwj.com:/var/hyperledger/production
ports:
- 8051:7051
- 8053:7053
peer0.orgcpp.xwj.com:
container_name: peer0.orgcpp.xwj.com
extends:
file: peer-base.yaml
service: peer-base
environment:
- CORE_PEER_ID=peer0.orgcpp.xwj.com
- CORE_PEER_ADDRESS=peer0.orgcpp.xwj.com:7051
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.orgcpp.xwj.com:7051
- CORE_PEER_GOSSIP_BOOTSTRAP=peer1.orgcpp.xwj.com:7051
- CORE_PEER_LOCALMSPID=OrgCppMSP
volumes:
- /var/run/:/host/var/run/
- ../crypto-config/peerOrganizations/orgcpp.xwj.com/peers/peer0.orgcpp.xwj.com/msp:/etc/hyperledger/fabric/msp
- ../crypto-config/peerOrganizations/orgcpp.xwj.com/peers/peer0.orgcpp.xwj.com/tls:/etc/hyperledger/fabric/tls
- peer0.orgcpp.xwj.com:/var/hyperledger/production
ports:
- 9051:7051
- 9053:7053
peer1.orgcpp.xwj.com:
container_name: peer1.orgcpp.xwj.com
extends:
file: peer-base.yaml
service: peer-base
environment:
- CORE_PEER_ID=peer1.orgcpp.xwj.com
- CORE_PEER_ADDRESS=peer1.orgcpp.xwj.com:7051
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.orgcpp.xwj.com:7051
- CORE_PEER_GOSSIP_BOOTSTRAP=peer0.orgcpp.xwj.com:7051
- CORE_PEER_LOCALMSPID=OrgCppMSP
volumes:
- /var/run/:/host/var/run/
- ../crypto-config/peerOrganizations/orgcpp.xwj.com/peers/peer1.orgcpp.xwj.com/msp:/etc/hyperledger/fabric/msp
- ../crypto-config/peerOrganizations/orgcpp.xwj.com/peers/peer1.orgcpp.xwj.com/tls:/etc/hyperledger/fabric/tls
- peer1.orgcpp.xwj.com:/var/hyperledger/production
ports:
- 10051:7051
- 10053:7053
# peer-base.yaml
version: '2'
services:
peer-base:
image: hyperledger/fabric-peer:latest
environment:
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
# the following setting starts chaincode containers on the same
# bridge network as the peers
# https://docs.docker.com/compose/networking/
- CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=${COMPOSE_PROJECT_NAME}_byfn
- CORE_LOGGING_LEVEL=INFO
#- CORE_LOGGING_LEVEL=DEBUG
- CORE_PEER_TLS_ENABLED=true
- CORE_PEER_GOSSIP_USELEADERELECTION=true
- CORE_PEER_GOSSIP_ORGLEADER=false
- CORE_PEER_PROFILE_ENABLED=true
- CORE_PEER_TLS_CERT_FILE=/etc/hyperledger/fabric/tls/server.crt
- CORE_PEER_TLS_KEY_FILE=/etc/hyperledger/fabric/tls/server.key
- CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
command: peer node start
5.3.5 配置文件结构目录
5.3.6 docker-compose 启动配置文件中的镜像
现在first-network中测试:
cd first-network
sudo ./byfn.sh down # 先关闭以防止之前开启过
sudo ./byfn.sh generate # 创建证书,因为配置文件中需要使用
docker-compose -f docker-compose-cli.yaml up -d # 使用配置文件运行各个镜像
docker-compose -f docker-compose-cli.yaml ps # 查看,全部为绿色up状态才表示镜像开启成功
注意: 这里的done并不代表着就启动成功了,必须还要去查看
查看,全部为绿色up状态才表示镜像开启成功
启动自己的构建的网络配置文件:
将docker-compose-cli文件更名为docker-compose,为了方便使用docker-compose命令,不用在敲-f 文件名
创建文件夹,把 docker-compose-base.yaml peer-base.yaml两个文件放到base文件夹下(适应配置文件中的数据卷映射)
# 先关闭之前所有已运行的镜像
docker stop $(docker ps -qa)
# 或者
docker-compose down -v
# 检查是否还有相关镜像运行
docker ps
# 没有后开始运行配置文件
# 在包含docker-compose.yaml文件的目录下运行,会自动找docker-compose.yaml文件执行
docker-compose up -d
# 检查运行状态
docker-compose ps
运行成功则出现:
COMPOSE_PROJECT_NAME是在peer-base.yaml中设置的
test01_byfn => network网络名字是 [当前目录_配置文件中的名字]
所以,我们可以设置环境变量:
vim ~/.bashrc
# 加入这一行
export COMPOSE_PROJECT_NAME=xwj_fabric_12 # 自己取名 不要用特殊的符号,小写的字母加数字其实就可以了
# 保存
source ~/.bashrc
# 重新运行
docker-compose up -d
大功告成!
5.4 客户端操作peer节点 命令:peer
5.4.0 客户端对peer节点的总体操作流程
-
创建通道,通过客户端节点来完成
- 进入到客户端节点来完成
-
将每个组织中的每个节点都加入到通道中,也是通过客户端完成
-
以客户端同时只能连接一个peer节点
所以需要改变客户端的配置属性连接到不同的客户端,实现一个一个的加入到通道中
-
-
给每个peer节点安装链码(智能合约) -> 链代码程序:go nodejs java
-
对智能合约进行初始化,对应智能合约中的init函数
- 智能合约只需要初始化一次,在任意节点均可,数据会自动同步到各个组织的各个节点中
-
对数据进行查询(读),对数据进行交易(写)
5.4.1 创建channel通道
这个动作需要在cli容器中运行,也就是上面配置好的文件,docker-compose启动后的运行容器cli中
# 进入cli容器
docker exec -it cli bash
# 创建通道
peer channel create -o ubuntu.itcast.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/channel.tx --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA
# 参数说明
-o 后面接连接的orederer的地址,hostname:port
-$CHANNEL_NAME: 创建通道文件的时候写的IDchannel的id,没指定默认为mychannel,通道创建成功后会在磁盘生成一个文件:$CHANNEL_NAME.block
-$CORE_PEER_TLS_ENABLED: 和docker通信时是否启用tls
-$ORDERER_CA: 使用tls时,所使用的orderer节点的pem格式证书文件
peer channel create -o orderer.xwj.com:7050 -c xwjchannel -f ./channel-artifacts/channel.tx --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/xwj.com/orderers/orderer.xwj.com/msp/tlscacerts/tlsca.xwj.com-cert.pem
orderer证书的绝对路径目录($ORDERER_CA),可按同样的方式去以下目录查找:(此目录是在镜像中的目录,与本机目录无关)
/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/xwj.com/orderers/orderer.xwj.com/msp/tlscacerts/tlsca.xwj.com-cert.pem
注意:必须先进入cli容器中再执行创建通道的命令
注意:如果提示路径错误请检查!存放证书的文件夹我们之前命名为crypto-config,映射到cli镜像中则变成了crypto,所以命令中需要注意。
注意:$CHANNEL_NAME不能为出现大写字母,不然会报错!(只能是小写或者数字或者破折号)
重新创建通道文件(命令可见上方),命名规范要注意,然后再次执行即可:
显示0 block(创世区块)则说明创建成功!
5.4.2 加入通道
$ peer channel join[flags],常用参数为:
-b, --blockpath: 通过peer channel create命令生成的通道文件
# example
$ peer channel join -b 生成的通道block文件
peer channel join -b xwjchannel.block
注意,加入到channel只有当前一个peer节点成功了,并不是所有的peer,还需要加入其他节点
加入其它的节点,通道无需重新创建,只需要修改当前客户端的环境变量,使其连接其他的peer节点就可以了
具体改变只有一下内容:
例:go组织的二个节点,在cli容器中输入以下命令:
export CORE_PEER_ADDRESS=peer0.orggo.xwj.com:7051
export CORE_PEER_LOCALMSPID=OrgGoMSP
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orggo.xwj.com/peers/peer0.orggo.xwj.com/tls/server.crt
export CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orggo.xwj.com/peers/peer0.orggo.xwj.com/tls/server.key
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orggo.xwj.com/peers/peer0.orggo.xwj.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orggo.xwj.com/users/aaa@qq.com/msp
export CORE_PEER_ADDRESS=peer1.orggo.xwj.com:7051
export CORE_PEER_LOCALMSPID=OrgGoMSP
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orggo.xwj.com/peers/peer1.orggo.xwj.com/tls/server.crt
export CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orggo.xwj.com/peers/peer1.orggo.xwj.com/tls/server.key
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orggo.xwj.com/peers/peer1.orggo.xwj.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orggo.xwj.com/users/aaa@qq.com/msp
cpp组织的两个节点:
export CORE_PEER_ADDRESS=peer0.orgcpp.xwj.com:7051
export CORE_PEER_LOCALMSPID=OrgCppMSP
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orgcpp.xwj.com/peers/peer0.orgcpp.xwj.com/tls/server.crt
export CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orgcpp.xwj.com/peers/peer0.orgcpp.xwj.com/tls/server.key
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orgcpp.xwj.com/peers/peer0.orgcpp.xwj.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orgcpp.xwj.com/users/aaa@qq.com/msp
export CORE_PEER_ADDRESS=peer1.orgcpp.xwj.com:7051
export CORE_PEER_LOCALMSPID=OrgCppMSP
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orgcpp.xwj.com/peers/peer1.orgcpp.xwj.com/tls/server.crt
export CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orgcpp.xwj.com/peers/peer1.orgcpp.xwj.com/tls/server.key
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orgcpp.xwj.com/peers/peer1.orgcpp.xwj.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orgcpp.xwj.com/users/aaa@qq.com/msp
显示成功,则此节点完成。
一个一个节点这样操作即可
5.4.3 更新锚节点
锚节点的指定在docker-compose.yaml中就指定好了,要更换才需要操作,非必需操作
锚节点的更新文件路径:
5.4.4 安装链码
准备工作:
# 复制first-network中的一个链码到项目目录
cp ~/fabric-1.2/fabric-samples/chaincode/chaincode_example02/go/chaincode_example02.go chaincode/
# 重命名
cd chaincode/
mv chaincode_example02.go test.go
# 进入客户端cli
docker exec -it cli bash
# 查看映射文件是否已经存在
ls /opt/gopath/src/github.com/chaincode/
# 发现重命名的文件存在则说明已经成功
# 安装链码
peer chaincode install [flags], 常用参数为:
-c, --ctor: Json格式的构造函数,默认是“{}”
-l, --lang: 编写链码的编程语言,默认是golang
-n, --name: 链码的名字
-p, --path: 链码源代码的目录,从$GOPATH/src 路径后开始写
-v, --version: 当前操作的链码的版本,适用于这些命令:install/instantiate/upgrade
# example
peer chaincode install -n 链码的名字 -v 链码的版本 -l 链码的语言 -p 链码的位置
- 链码名字自定义
- 链码的版本,自己根据实际情况去指定
- 这里的路径不是写完全的绝对路径,而是从$GOPATH/src 路径后开始写
peer chaincode install -n testcc -v 1.0 -l golang -p github.com/chaincode/
# 安装完之后的检查
peer chaincode list --installed
返回响应为200, OK则代表成功
注意,每个peer节点都需要安装链码!初始化只需要初始化一个就可以,和上面加入通道同样的操作(修改配置,一个一个安装)
5.4.5 链码初始化
注意链码的初始化只需要在一个节点上即可,其后会自动进行同步
peer chaincode instantiate [flags], 常用参数为:
-C, --channelID: 当前命令运行的通道,默认值是“testchainid”
-c, --ctor: JSON格式的构造参数,默认值是“{}”
-l, --lang: 编写链码的编程语言,默认是golang
-n, --name: 链码的名字
-P, --policy: 当前Chaincode的背书策略
-v, --version: 当前操作的链码的版本,适用于这些命令:install/instantiate/upgrade
--tls: 通信时是否使用tls加密
--cafile: 当前orderer节点pem格式的tls证书文件,要使用绝对路径
# example
# -c '{"Args":["init","a","100","b","200"]}' # 给构造函数传参数
# -P "AND ('OrgGoMASP.member', 'OrgCppMSP.member')"
# AND表示这两个组织中的成员都需要参与,member表示组织中任一节点均可。如果是“OR”则表示任何一个组织成员都可以
peer chaincode instantiate -o orderer节点地址:端口 --tls true --cafile orderer节点pem格式的证书文件 -C 通道名称 -n 链码名称 -l 链码语言 -v 链码语言 -v 链码版本 -c 链码函数调用 -P 背书策略
背书策略:交易的规则,哪些人参与这笔交易,确定后进行模拟交易(测试)
注意这里的背书策略目前是初始化的指定作用,真正使用还需要到交易产生的时候
peer chaincode instantiate -o orderer.xwj.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/xwj.com/orderers/orderer.xwj.com/msp/tlscacerts/tlsca.xwj.com-cert.pem -C xwjchannel -n testcc -l golang -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P "AND ('OrgGoMSP.member', 'OrgCppMSP.member')"
此处错误集合:
-
err Proposal response was not successful, error code 500, msg cannot get package for chaincode (testcc:1.0)
解决办法:
检查链码是否布置安装存在
peer chaincode list --installed
不存在的话先安装。退出cli容器要从创建channel通道开始重头再来
-
API error (404): network xwj_fabric_1.2_byfn not found
peer-base.yaml文件中的网络设置环境变量与启动网络的配置不一致,我之前
export COMPOSE_PROJECT_NAME=xwj_fabric_1.2
这个“.”导致了问题,所以自己取名不要用“点”符号重新启动网络,重新操作
5.4.6 查询
# 查询账户A余额
peer chaincode query -C xwjchannel -c '{"Args":["query","a"]}' -n testcc
# 查询账户B的余额
peer chaincode query -C xwjchannel -c '{"Args":["query","b"]}' -n testcc
5.4.7 交易
peer chaincode invoke -o orderer.xwj.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/xwj.com/orderers/orderer.xwj.com/msp/tlscacerts/tlsca.xwj.com-cert.pem -C xwjchannel -n testcc --peerAddresses peer0.orggo.xwj.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orggo.xwj.com/peers/peer0.orggo.xwj.com/tls/ca.crt --peerAddresses peer1.orgcpp.xwj.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orgcpp.xwj.com/peers/peer1.orgcpp.xwj.com/tls/ca.crt -c '{"Args": ["invoke", "a", "b", "10"]}'
5.4.8 自动化shell脚本
先进入客户端
deploy.sh
# 将各个组织的所有节点加入到一个通道中,对每个节点部署链码,并对其中一个初始化链码
# 变量
CHANNEL_ID=xwjchannel # 通道id
CHANNEL_FIEL=./channel-artifacts/channel.tx # 通道文件
ORDER_CAFILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/xwj.com/orderers/orderer.xwj.com/msp/tlscacerts/tlsca.xwj.com-cert.pem # order的tls证书
# 组织
ORG01_NAME=orggo.xwj.com
ORG01_MSPID=OrgGoMSP
ORG02_NAME=orgcpp.xwj.com
ORG02_MSPID=OrgCppMSP
# 节点配置
ORDERER=orderer.xwj.com
ORDERER_PORT=7050
ORG01_PEERS=(peer0.$ORG01_NAME peer1.$ORG01_NAME)
ORG02_PEERS=(peer0.$ORG02_NAME peer1.$ORG02_NAME)
PEERS_PORT=7051
# 链码配置
CHAINCODE_NAME=testcc
CHAINCODE_VERSION=1.0
CHAINCODE_LANG=golang
CHAINCODE_PATH=github.com/chaincode/
# 背书策略
ENDORSE_POLICY="AND('$ORG01_MSPID.member','$ORG02_MSPID.member')"
# 初始化链码函数调用
INIT_FUNC='{"Args":["init","a","100","b","200"]}'
# 创建通道
peer channel create -o $ORDERER:$ORDERER_PORT -c $CHANNEL_ID -f $CHANNEL_FIEL --tls true --cafile $ORDER_CAFILE
if [ -f $CHANNEL_ID.block ];then
echo -e "\033[32m create channel: $CHANNEL_ID path: $CHANNEL_FIEL ==> OK! \033[0m"
else
echo -e "\033[31m create channel: $CHANNEL_ID ==> ERR! \033[0m"
fi
# 遍历各个组织 给每个节点加入通道和安装链码
# 对于第一个组织Org1
for PEER in ${ORG01_PEERS[@]};do
# 切换配置(换节点)
export CORE_PEER_ADDRESS=$PEER:$PEERS_PORT
export CORE_PEER_LOCALMSPID=$ORG01_MSPID
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/$ORG01_NAME/peers/$PEER/tls/server.crt
export CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/$ORG01_NAME/peers/$PEER/tls/server.key
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/$ORG01_NAME/peers/$PEER/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/$ORG01_NAME/users/aaa@qq.com$ORG01_NAME/msp
# 加入通道并且安装链码
echo -e "\033[32m $CORE_PEER_ADDRESS Configuring...... \033[0m"
peer channel join -b $CHANNEL_ID.block
peer chaincode install -n $CHAINCODE_NAME -v $CHAINCODE_VERSION -l $CHAINCODE_LANG -p $CHAINCODE_PATH
echo -e "\033[32m $PEER Add channel: $CHANNEL_ID ==> OK! \033[0m"
echo -e "\033[32m $PEER Install chaincode: $CHAINCODE_NAME ==> OK! \033[0m"
done
# 对于第二个组织
for PEER in ${ORG02_PEERS[@]};do
# 切换配置(换节点)
export CORE_PEER_ADDRESS=$PEER:$PEERS_PORT
export CORE_PEER_LOCALMSPID=$ORG02_MSPID
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/$ORG02_NAME/peers/$PEER/tls/server.crt
export CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/$ORG02_NAME/peers/$PEER/tls/server.key
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/$ORG02_NAME/peers/$PEER/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/$ORG02_NAME/users/aaa@qq.com$ORG02_NAME/msp
# 加入通道并且安装链码
echo -e "\033[32m $CORE_PEER_ADDRESS Configuring...... \033[0m"
peer channel join -b $CHANNEL_ID.block
peer chaincode install -n $CHAINCODE_NAME -v $CHAINCODE_VERSION -l $CHAINCODE_LANG -p $CHAINCODE_PATH
echo -e "\033[32m $PEER Add channel: $CHANNEL_ID ==> OK! \033[0m"
echo -e "\033[32m $PEER Install chaincode: $CHAINCODE_NAME ==> OK! \033[0m"
done
# 对其中一个节点初始化链码
peer chaincode instantiate -o $ORDERER:$ORDERER_PORT --tls true --cafile $ORDER_CAFILE -C $CHANNEL_ID -n $CHAINCODE_NAME -l $CHAINCODE_LANG -v $CHAINCODE_VERSION -c $INIT_FUNC -P $ENDORSE_POLICY
echo -e "\033[32m $CORE_PEER_ADDRESS Instantiate chaincode: $CHAINCODE_NAME ==> OK! \033[0m"
爽的一p
Tips
1. 从Linux的vim中复制内容到系统的剪贴板
# 下载第三方插件
sudo apt-get install vim-gnome
# 再使用yy命令即可
注意,通过远程访问的无法复制到远程访问主机的剪贴板
2. 重复创建通道出错
error validating ReadSet: readset expected key [Group] /Channel/Application at version 0, but got version 1
原因:旧的通道还没删除,新的通道重复创建
解决办法,重新部署:
$ docker-compose down -v
$ docker volume prune
$ docker-compose up -d
上一篇: 软件测试作业2
下一篇: 松茸可以生吃吗?吃松茸的禁忌有什么?