Fabric网络搭建

环境搭建

Docker 安装

1
2
3
curl -fsSl <https://get.docker.com/> | sh
systemctl enable docker
service docker start

Docker-compose 安装

1
yum -y install epel-release && yum -y install python-pip && pip install docker-compose

Go安装

1
2
3
4
5
6
7
8
9
wget https://dl.google.com/go/go1.11.5.linux-amd64.tar.gz
tar -C /usr/local -zxvf go1.11.5.linux-amd64.tar.gz
echo "export GOROOT=/usr/local/go" >> /etc/profile
echo "export GOBIN=/opt/prod/go/bin" >> /etc/profile
echo "export GOPATH=/opt/prod/go" >> /etc/profile
echo "export PATH=/opt/prod/go/bin:$PATH" >> /etc/profile
echo "export PATH=/usr/local/go/bin:$PATH" >> /etc/profile
source /etc/profile
mkdir /opt/prod/go

下载Fabric组件

bootstrap.sh文件可以通过网络下载

1
2
curl -sSL https://raw.githubusercontent.com/hyperledger/fabric/master/scripts/bootstrap.sh | bash 1.4.0 -s  # 下载Fabric二进制文件    Image     以及示例文件
cp fabric-sample/bin/* $/GOPATH/bin

Fabric-sdk-go下载

github地址: https://github.com/hyperledger/fabric-sdk-go.git

sdk 编译, 最好在外网进行编译,用VPN容易超时

1
2
make pupulate
make depend

网络配置

创建目录结构

创建一个目录用来存储Fabric的所有配置文件

1
2
mkdir -p /opt/prod/Fabric/network   # 存储Fabric所有配置文件
mkdir -p /opt/prod/Fabric/network/channel-artifacts # 存放创世区块以及通道配置文件等

生成MSP

创建MSP配置信息

编辑MSP配置文件 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
# 排序节点配置
OrdererOrgs:
- Name: Orderer # 排序节点名称
Domain: myfab.com # 排序节点域名
Specs:
- Hostname: orderer # 排序节点HOST

PeerOrgs:
- Name: Org1 # 节点名称
Domain: org1.myfab.com # 节点域名
EnableNodeOUs: true #如果设置了EnableNodeOUs,就在msp下生成config.yaml文件
Template:
Count: 2 # 表示生成几个peer
Users:
Count: 3 # 表示生成几个user(admin 除外)
- Name: Org2
Domain: org2.myfab.com
EnableNodeOUs: true
Template:
Count: 2
Users:
Count: 2

Template.Count 指定了所要生成的节点数量

Users.Count 指定了需要生成的初始化用户数量。

生成MSP文件系统

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

将会生成一个名为crypto-config的目录,里面存储了order 和peer 的MSP文件系统;

使用该cryptogen工具为各种网络实体生成加密材料(x509证书和签名密钥)。这些证书代表身份,它们允许在我们的实体进行通信和交易时进行签名/验证身份验证。

Cryptogen使用文件 - crypto-config.yaml包含网络拓扑,并允许我们为组织和属于这些组织的组件生成一组证书和密钥。每个组织都配置了一个唯一的根证书(ca-cert),它将特定组件(同行和订购者)绑定到该组织。

MSP文件系统的目录结构如下:

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
.   ##  Orderer 组织配置
├── ordererOrganizations
│ │
│ └── example.com
│ │
│ ├── ca ## 存放组织根证书 及 私钥 (采用EC算法) 证书为【自签名】,组织内的实体将给予该根证书作为证书根
│ │
│ │ ├── 56d9c0c46acdda38a174a5ba3ffc44726a2c027e16bb22b460413acbcb9b3a90_sk
│ │ │
│ │ └── ca.example.com-cert.pem
│ │
│ ├── msp ## 存放该组织身份信息
│ │ │
│ │ ├── admincerts ## 组织管理员 身份验证证书,【被根证书签名】
│ │ │ │
│ │ │ └── Admin@example.com-cert.pem
│ │ │
│ │ ├── cacerts ## 组织的根证书 【和CA目录 里面一致】
│ │ │ │
│ │ │ └── ca.example.com-cert.pem
│ │ │
│ │ └── tlscacerts ## 用于TLS的CA证书, 【自签名】
│ │ │
│ │ └── tlsca.example.com-cert.pem
│ │
│ │
│ ├── orderers ## 存放所有 Orderer 的身份信息
│ │ │
│ │ └── orderer.example.com ## 第一个 Orderer 的信息 msp 及 tls
│ │ │
│ │ ├── msp
│ │ │ │
│ │ │ ├── admincerts ## 组织管理员的身份验证证书。Peer将给予这些证书来确认交易签名是否为管理员签名 【和MSP.admincerts 一致】
│ │ │ │ │
│ │ │ │ └── Admin@example.com-cert.pem
│ │ │ │
│ │ │ ├── cacerts
│ │ │ │ │
│ │ │ │ └── ca.example.com-cert.pem ## 存放组织根证书,【和CA目录 里面一致】
│ │ │ │
│ │ │ ├── keystore ## 本节点的身份私钥,用来签名
│ │ │ │ │
│ │ │ │ └── 2ec1193fe048848eaa8e20666e26c527b791c4fb127d69cae65095bd31b6c80e_sk
│ │ │ │
│ │ │ ├── signcerts ## 验证本节点签名的证书,【被根证书签名】
│ │ │ │ │
│ │ │ │ └── orderer.example.com-cert.pem
│  │  │ │
│   │   │   └── tlscacerts ## TLS连接用的身份证书, 【和msp.tlscacerts 一致】
│  │  │  │ 
│   │   │   └── tlsca.example.com-cert.pem
│  │  │ 
│   │   └── tls ## tls 的相关信息
│   │   ├── ca.crt ## 【组织的根证书】
│   │   ├── server.crt ## 验证本节点签名的证书, 【被根证书签名】
│   │   └── server.key ## 本节点的身份私钥,用来签名
│  │ 
│   ├── tlsca ## 存放tls相关的证书和私钥
│  │  │ 
│   │   ├── 2d66be83c519da67bb36b0972256a3b24357fa7f5b3a61f11405bc8b1f4d7c53_sk
│  │  │ 
│   │   └── tlsca.example.com-cert.pem
│  │ 
│   └── users ## 存放属于该组织的用户的实体
│  │ 
│   └── Admin@example.com ## 管理员用户的信息,其中包括msp证书和tls证书两类
│  │ 
│   ├── msp
│  │  │ 
│   │   ├── admincerts ## 组织根证书作为管理员身份验证证书,【和MSP.admincerts 一致】
│  │  │  │ 
│   │   │   └── Admin@example.com-cert.pem
│  │  │ 
│   │   ├── cacerts ## 存放组织的根证书,【和CA目录 里面一致】
│  │  │  │ 
│   │   │   └── ca.example.com-cert.pem
│  │  │ 
│   │   ├── keystore ## 本用户的身份私钥,用来签名
│  │  │  │ 
│   │   │   └── a3c1d7e1bc464faf2e3a205cb76ea231bd3ee7010655d3cd31dc6cb78726c4d0_sk
│  │  │ 
│   │   ├── signcerts ## 管理员用户的身份验证证书,被组织根证书签名。要被某个Orderer认可,则必须放到该 Orderer 的msp/admincerts目录下
│  │  │  │ 
│   │   │   └── Admin@example.com-cert.pem
│  │  │ 
│   │   └── tlscacerts ## TLS连接用的身份证书,即组织TLS证书,【和msp.tlscacerts 一致】
│  │  │ 
│   │   └── tlsca.example.com-cert.pem
│  │ 
│  │ 
│   └── tls ## tls 的相关信息
│   ├── ca.crt
│   ├── client.crt ## 管理员的身份验证证书,【被 组织根证书签名】
│   └── client.key ## 管理员的身份私钥,用来签名
│ 
│ 
│ 
│  ## Peer 组织配置
└── peerOrganizations
│ 
├── org1.example.com ## 第一个组织的所有身份证书
│  │ 
│   ├── ca ## 存放组织根证书及私钥 (采用EC算法) 证书为【自签名】,组织内的实体将给予该根证书作为证书根
│  │  │ 
│   │   ├── 496d6a41ae5f66bf120df3eab3a9d2dc4d268b2ab9a22af891d33d323bbdb5c8_sk
│  │  │ 
│   │   └── ca.org1.example.com-cert.pem
│  │ 
│   ├── msp ## 存放该组织身份信息
│  │  │ 
│   │   ├── admincerts ## 组织管理员 身份验证证书,【被根证书签名】
│  │  │  │ 
│   │   │   └── Admin@org1.example.com-cert.pem
│  │  │ 
│   │   ├── cacerts ## 组织的根证书 【和CA目录 里面一致】
│  │  │  │ 
│   │   │   └── ca.org1.example.com-cert.pem
│  │  │ 
│   │   ├── config.yaml ## 记录 OrganizationalUnitIdentitifiers 信息,包括 根证书位置 和 ID信息 (主要是 crypto-config.yaml 的peer配置中配了 EnableNodeOUs: true : 如果设置了EnableNodeOUs,就在msp下生成config.yaml文件)
│  │  │ 
│   │   └── tlscacerts ## 用于TLS的CA证书, 【自签名】
│  │  │ 
│   │   └── tlsca.org1.example.com-cert.pem
│  │ 
│  │ 
│   ├── peers ## 存放所有 Peer 的身份信息
│  │  │ 
│   │   ├── peer0.org1.example.com ## 第一个Peer的信息 msp 及 tls
│  │  │  │ 
│   │   │   ├── msp
│  │  │  │  │ 
│   │   │   │   ├── admincerts ## 组织管理员的身份验证证书。Peer将给予这些证书来确认交易签名是否为管理员签名 【和MSP.admincerts 一致】
│  │  │  │  │  │ 
│   │   │   │   │   └── Admin@org1.example.com-cert.pem
│  │  │  │  │ 
│   │   │   │   ├── cacerts ## 存放组织根证书,【和CA目录 里面一致】
│  │  │  │  │  │ 
│   │   │   │   │   └── ca.org1.example.com-cert.pem
│  │  │  │  │ 
│   │   │   │   ├── config.yaml
│  │  │  │  │ 
│   │   │   │   ├── keystore ## 本节点的身份私钥,用来签名
│  │  │  │  │  │ 
│   │   │   │   │   └── 0f0c2e1835086161f6a10c4bb38c2d89b2cee4e1128cee0fcda4433feb6eb6f8_sk
│  │  │  │  │ 
│  │  │  │  │ 
│   │   │   │   ├── signcerts ## 验证本节点签名的证书,【被根证书签名】
│  │  │  │  │  │ 
│   │   │   │   │   └── peer0.org1.example.com-cert.pem
│  │  │  │  │ 
│   │   │   │   └── tlscacerts ## TLS连接用的身份证书, 【和msp.tlscacerts 一致】
│  │  │  │  │ 
│   │   │   │   └── tlsca.org1.example.com-cert.pem
│  │  │  │ 
│  │  │  │ 
│   │   │   └──tls ## tls 的相关信息
│   │   │   ├── ca.crt ## 【组织的根证书】
│   │   │   ├── server.crt ## 验证本节点签名的证书, 【被根证书签名】
│   │   │   └── server.key ## 本节点的身份私钥,用来签名
│   │   │
│   │   │
│   │   └── peer1.org1.example.com
│   │
│   │
│   │
│   │  
│   ├── tlsca ## 存放tls相关的证书和私钥
│  │  │ 
│   │   ├── 3d39ea82dd5343c261b0480bc13d645a3cee13b7e7aa8c54fd2b5162f709671f_sk
│   │   └── tlsca.org1.example.com-cert.pem
│   │
│   │
│  │ 
│   └── users ## 存放属于该组织的用户的实体
│  │ 
│   ├── Admin@org1.example.com ## 管理员用户的信息,其中包括msp证书和tls证书两类
│  │  │ 
│   │   ├── msp
│  │  │  │ 
│   │   │   ├── admincerts ## 组织根证书作为管理员身份验证证书,【和MSP.admincerts 一致】
│  │  │  │  │ 
│   │   │   │   └── Admin@org1.example.com-cert.pem
│  │  │  │ 
│   │   │   ├── cacerts ## 存放组织的根证书,【和CA目录 里面一致】
│  │  │  │  │ 
│   │   │   │   └── ca.org1.example.com-cert.pem
│  │  │  │ 
│   │   │   ├── keystore ## 本用户的身份私钥,用来签名
│  │  │  │  │ 
│   │   │   │   └── 2b933c0740d857284be98ff218bf279261e55eff2b89d973e0a1f435f7c7d28b_sk
│  │  │  │ 
│   │   │   ├── signcerts ## 管理员用户的身份验证证书,被组织根证书签名。要被某个Peer认可,则必须放到该Peer的msp/admincerts目录下
│  │  │  │  │ 
│   │   │   │   └── Admin@org1.example.com-cert.pem
│  │  │  │ 
│   │   │   └── tlscacerts ## TLS连接用的身份证书,即组织TLS证书,【和msp.tlscacerts 一致】
│  │  │  │ 
│   │   │   └── tlsca.org1.example.com-cert.pem
│  │  │ 
│   │   └── tls ## tls 的相关信息
│   │   ├── ca.crt
│   │   ├── client.crt ## 管理员的身份验证证书,【被 组织根证书签名】
│   │   └── client.key ## 管理员的身份私钥,用来签名
│   │
│   │
│   └── User1@org1.example.com
│   ├── msp
│   │   ├── admincerts ## 组织根证书作为管理员身份验证证书
│   │   │   └── User1@org1.example.com-cert.pem
│   │   ├── cacerts ## 存放组织的根证书,【和CA目录 里面一致】
│   │   │   └── ca.org1.example.com-cert.pem
│   │   ├── keystore ## 【参考admin】
│   │   │   └── 11ebc5afac42348f84a8882f329d18beee079efd4fd5d9b30389dc82053fc0c9_sk
│   │   ├── signcerts ## 【参考admin】
│   │   │   └── User1@org1.example.com-cert.pem
│   │   └── tlscacerts ## 【参考admin】
│   │   └── tlsca.org1.example.com-cert.pem
│   └── tls ## 【参考admin】
│   ├── ca.crt
│   ├── client.crt
│   └── client.key

└── org2.example.com

生成Order创世区块

在 Orderer 节点上维护的有个 system chain, 这个创世区块实际上是这个 system chain 的创世区块。在 Fabric 的上下文中,chain,channel 基本上可以通用,下面有时会称 system chain 为 system channel。

创建system chain的创世区块

创建创世区块的配置文件 configtx.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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
## 一些列组织的定义,【被其他 部分引用】
##
## 【注意】:本文件中 &KEY 均为 *KEY 所引用; xx:&KEY 均为 <<: *KEY 所引用
##
Organizations:

## 定义Orderer组织 【&OrdererOrg 这类语法类似 Go的中的指针及对象地址, 此处是被Profiles 中的 - *OrdererOrg 所引用,以下均为类似做法】
- &OrdererOrg

Name: OrdererOrg ## Orderer的组织的名称

ID: OrdererMSP ## Orderer 组织的ID (ID是引用组织的关键)

MSPDir: crypto-config/ordererOrganizations/example.com/msp ## Orderer的 MSP 证书目录路径

AdminPrincipal: Role.ADMIN ## 【可选项】 组织管理员所需要的身份,可选项: Role.ADMIN 和 Role.MEMBER

## 定义Peer组织 1
- &Org1
Name: Org1MSP ## 组织名称

ID: Org1MSP ## 组织ID

MSPDir: crypto-config/peerOrganizations/org1.example.com/msp ## Peer的MSP 证书目录路径

AnchorPeers: ## 定义组织锚节点 用于跨组织 Gossip 通信
- Host: peer0.org1.example.com ## 锚节点的主机名
Port: 7051 ## 锚节点的端口号

## 定义Peer组织 2
- &Org2
Name: Org2MSP
ID: Org2MSP
MSPDir: crypto-config/peerOrganizations/org2.example.com/msp
AnchorPeers:
- Host: peer0.org2.example.com
Port: 7051

################################################################################
#
# SECTION: Capabilities 【注意】: 该部分是 V1.1.0 版本提出来的, 不可以在更早的版本中使用
#
# - 本节定义了 fabric 网络的功能. 这是v1.1.0中的一个新概念,不应在v1.0.x的peer和orderers中使用.
# Capabilities 定义了存在于结构二进制文件中的功能,以便该二进制文件安全地参与结构网络.
# 例如,如果添加了新的MSP类型,则较新的二进制文件可能会识别并验证此类型的签名,而没有此支持的旧二进制文件将无法验证这些事务.
# 这可能导致具有不同世界状态的不同版本的结构二进制文件。 相反,为通道定义功能会通知那些没有此功能的二进制文件,
# 它们必须在升级之前停止处理事务. 对于v1.0.x,如果定义了任何功能(包括关闭所有功能的配置),那么v1.0.x的peer 会主动崩溃.
#
################################################################################
Capabilities:
## 通道功能适用于orderers and the peers,并且必须得到两者的支持。 将功能的值设置为true.
Global: &ChannelCapabilities
## V1.1 的 Global是一个行为标记,已被确定为运行v1.0.x的所有orderers和peers的行为,但其修改会导致不兼容。 用户应将此标志设置为true.
V1_1: true

## Orderer功能仅适用于orderers,可以安全地操纵,而无需担心升级peers。 将功能的值设置为true
Orderer: &OrdererCapabilities
## Orderer 的V1.1是行为的一个标记,已经确定为运行v1.0.x的所有orderers 都需要,但其修改会导致不兼容。 用户应将此标志设置为true
V1_1: true

## 应用程序功能仅适用于Peer 网络,可以安全地操作,而无需担心升级或更新orderers。 将功能的值设置为true
Application: &ApplicationCapabilities
## V1.2 for Application是一个行为标记,已被确定为运行v1.0.x的所有peers所需的行为,但其修改会导致不兼容。 用户应将此标志设置为true
V1_2: true







################################################################################
#
# SECTION: Application
#
# - 应用通道相关配置,主要包括 参与应用网络的可用组织信息
#
################################################################################
Application: &ApplicationDefaults ## 自定义被引用的地址

Organizations: ## 加入通道的组织信息




################################################################################
#
# SECTION: Orderer
#
# - Orderer 系统通道相关配置,包括 Orderer 服务配置和参与Orderer 服务的可用组织
#
# Orderer 默认是 solo 的 且不包含任何组织 【主要被 Profiles 部分引用】
################################################################################
Orderer: &OrdererDefaults ## 自定义被引用的地址

OrdererType: solo ## Orderer 类型,包含 solo 和 kafka 集群

Addresses: ## 服务地址
- orderer.example.com:7050

BatchTimeout: 2s ## 区块打包的最大超时时间 (到了该时间就打包区块)

BatchSize: ## 区块打包的最大包含交易数

MaxMessageCount: 10 ## 一个区块里最大的交易数
AbsoluteMaxBytes: 99 MB ## 一个区块的最大字节数, 任何时候都不能超过
PreferredMaxBytes: 512 KB ## 一个区块的建议字节数,如果一个交易消息的大小超过了这个值, 就会被放入另外一个更大的区块中

MaxChannels: 0 ## 【可选项】 表示Orderer 允许的最大通道数, 默认 0 表示没有最大通道数

Kafka:
Brokers: ## kafka的 brokens 服务地址 允许有多个
- 127.0.0.1:9092

Organizations: ## 参与维护 Orderer 的组织,默认为空







################################################################################
#
# Profile
#
# - 一系列通道配置模板,包括Orderer 系统通道模板 和 应用通道类型模板
#
################################################################################
Profiles:

## Orderer的 系统通道模板 必须包括 Orderer、 Consortiums 两部分
TwoOrgsOrdererGenesis: ## Orderer 系统的通道及创世块配置。通道为默认配置,添加一个OrdererOrg 组织, 联盟为默认的 SampleConsortium 联盟,添加了两个组织 【该名称可以自定义 ??】
Capabilities:
<<: *ChannelCapabilities

Orderer: ## 指定Orderer系统通道自身的配置信息
<<: *OrdererDefaults ## 引用 Orderer 部分的配置 &OrdererDefaults
Organizations:
- *OrdererOrg ## 属于Orderer 的通道组织 该处引用了 【 &OrdererOrg 】位置内容
Capabilities:
<<: *OrdererCapabilities

Consortiums: ## Orderer 所服务的联盟列表
SampleConsortium: ## 创建更多应用通道时的联盟 引用 TwoOrgsChannel 所示
Organizations:
- *Org1
- *Org2

## 应用通道模板 必须包括 Application、 Consortium 两部分
TwoOrgsChannel: ## 应用通道配置。默认配置的应用通道,添加了两个组织。联盟为SampleConsortium
Consortium: SampleConsortium ## 通道所关联的联盟名称
Application: ## 指定属于某应用通道的信息,主要包括 属于通道的组织信息
<<: *ApplicationDefaults
Organizations: ## 初始 加入应用通道的组织
- *Org1
- *Org2
Capabilities:
<<: *ApplicationCapabilities

在这个文件里有两个 Profile, 一个是 OneOrgOrdererGenesis, 一个是 OneOrgChannel。

一个 Profile 代表了一组配置, 里面包含了通道相关配置,Orderer 节点相关配置,联盟成员相关配置。通道相关配置确定了系统通道的一些权限策略,Orderer 节点配置确定了 Orderer 节点的类型(是 solo 还是 kafaka),Orderer 节点的访问地址,还有出块时间,区块大小,区块内允许包含的交易数量等。联盟配置确定了联盟的名称和联盟所包含的组织,对组织来说这里最为关键的是组织的 MSP ID 和路径,这些信息都会被包含到 system chain 中。

生成创世区块

1
configtxgen -profile OneOrgOrdererGenesis -channelID order-channel -outputBlock ./channel-artifacts/genesis.block

这个命令需要指定一个 channelID,注意这里的 channelID 为系统链(system chain)的 channelID。

生成通道配置区块

现在来创建创世区块交易,通过交易将创世块上传到channel上

生成channel配置事务

通过下面的命令,可以生成这样的一个交易。

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

该命令会读取和生成 Orderer 相同的配置文件,只是使用了 “OneOrgChannel” 这个 Profile,确定了通道的权限策略,创建通道的联盟和组织信息。

只是创建了通道,而不创建锚节点的化,通道区块数据就无法跨组织传播,所以一般还要通过下面的命令创建用来更新锚节点的交易。

为每个组织生成锚节点配置事务

1
export CHANNEL_NAME=mychannel && configtxgen -profile OneOrgChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP

上面的命令生成了为每个组织生成锚节点的交易。

启动网络

接下来,就可以通过orderer命令或 docker 容器来启动网络了,orderer 启动的时候会查找一个名为 orderer.yaml 的配置文件。这个配置文件不是必须的,在找不到这个配置文件时,orderer 命令会使用默认配置。我们也可以通过环境变量或命令行参数的方式去对每个配置项进行覆盖。

配置各节点启动参数

配置 yaml_config/docker-compose.yml 文件

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#

version: '2'

volumes:
orderer.example.com:
peer0.org1.example.com:
peer1.org1.example.com:
peer0.org2.example.com:
peer1.org2.example.com:

networks:
byfn:
services:
ca0:
image: hyperledger/fabric-ca:$IMAGE_TAG
environment:
- FABRIC_CA_HOME=/etc/hyperledger/fabric-ca-server
- FABRIC_CA_SERVER_CA_NAME=ca-org1
- FABRIC_CA_SERVER_TLS_ENABLED=true
- FABRIC_CA_SERVER_TLS_CERTFILE=/etc/hyperledger/fabric-ca-server-config/ca.org1.example.com-cert.pem
- FABRIC_CA_SERVER_TLS_KEYFILE=/etc/hyperledger/fabric-ca-server-config/CA1_PRIVATE_KEY
ports:
- "7054:7054"
command: sh -c 'fabric-ca-server start --ca.certfile /etc/hyperledger/fabric-ca-server-config/ca.org1.example.com-cert.pem --ca.keyfile /etc/hyperledger/fabric-ca-server-config/CA1_PRIVATE_KEY -b admin:adminpw -d'
volumes:
- ./crypto-config/peerOrganizations/org1.example.com/ca/:/etc/hyperledger/fabric-ca-server-config
container_name: ca_peerOrg1
networks:
- byfn

ca1:
image: hyperledger/fabric-ca:$IMAGE_TAG
environment:
- FABRIC_CA_HOME=/etc/hyperledger/fabric-ca-server
- FABRIC_CA_SERVER_CA_NAME=ca-org2
- FABRIC_CA_SERVER_TLS_ENABLED=true
- FABRIC_CA_SERVER_TLS_CERTFILE=/etc/hyperledger/fabric-ca-server-config/ca.org2.example.com-cert.pem
- FABRIC_CA_SERVER_TLS_KEYFILE=/etc/hyperledger/fabric-ca-server-config/CA2_PRIVATE_KEY
ports:
- "8054:7054"
command: sh -c 'fabric-ca-server start --ca.certfile /etc/hyperledger/fabric-ca-server-config/ca.org2.example.com-cert.pem --ca.keyfile /etc/hyperledger/fabric-ca-server-config/CA2_PRIVATE_KEY -b admin:adminpw -d'
volumes:
- ./crypto-config/peerOrganizations/org2.example.com/ca/:/etc/hyperledger/fabric-ca-server-config
container_name: ca_peerOrg2
networks:
- byfn

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
networks:
- byfn

启动网络节点

1
docker-compose -f docker-compose.yml up -d ca.example.com orderer.example.com peer0.org1.example.com couchdb

注意: 如果启动ca, 之一要修改yaml文件中对应的ca私钥地址

运行Channel(示例为一个组织)

这个阶段把网络启动后,还是啥事都做不了,节点之间也没有通信。

因为还没有生成peer节点互相通信的channel,也没有将节点加入到channel中

创建channel

创建了一个channel的创世块,逻辑上就等于是创建了一个channel

1
docker exec -e "CORE_PEER_LOCALMSPID=Org1MSP" -e "CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/users/Admin@org1.example.com/msp" peer0.org1.example.com peer channel create -o orderer.example.com:7050 -c mychannel -f /etc/hyperledger/configtx/channel.tx

该命令是,通过Org1向order节点发送事务,order节点验证通过后,会生成mychannel的创世块

将组织加入到channel

将组织加入到channel

1
docker exec -e "CORE_PEER_LOCALMSPID=Org1MSP" -e "CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/users/Admin@org1.example.com/msp" peer0.org1.example.com peer channel join -b mychannel.block

更新锚节点

1
docker exec -e "CORE_PEER_LOCALMSPID=Org1MSP" -e "CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/users/Admin@org1.example.com/msp" peer0.org1.example.com peer channel update -o orderer.example.com:7050 -c mychannel -f /etc/hyperledger/configtx/Org1MSPanchors.tx

目前为止一个基本的网络就已经搭建好了。下面再介绍一些怎么更新我们的网络组织和channel成员

chain code 安装和使用

chaincode 安装

  1. 将即将安装节点配置到环境变量中

    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: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
  2. 安装chaincode

    1
    peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/chaincode_example02/go/
  3. 将chaincode实例化

    一个channel只需要实例化一次

    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')"

chaincode使用

  1. 查询

    1
    peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
  2. 调用

    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: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"]}'

创建新组织并添加到channel

生成组织的证书和密钥

创建一个目录: org3-artifacts, 用来存储生成org3最终配置和事务的配置文件和中间产物等;

该阶段操作都在org3-artifacts目录下进行

加密资料准备

  1. 生成组织的MSP文件

    创建一个新org的org3-crypto.yaml文件用来生成新组织的MSP资料

    org3-crypto.yaml文件内容

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    PeerOrgs:
    # ---------------------------------------------------------------------------
    # Org3
    # ---------------------------------------------------------------------------
    - Name: Org3
    Domain: org3.example.com
    EnableNodeOUs: true
    Template:
    Count: 2
    Users:
    Count: 1
    1
    cryptogen generate --config=./org3-crypto.yaml
  2. 导出MSP数据

    configtx.yaml文件内容

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    Organizations:
    - &Org3
    # DefaultOrg defines the organization which is used in the sampleconfig
    # of the fabric.git development environment
    Name: Org3MSP

    # ID to load the MSP definition as
    ID: Org3MSP

    MSPDir: crypto-config/peerOrganizations/org3.example.com/msp

    AnchorPeers:
    # AnchorPeers defines the location of peers which can be used
    # for cross org gossip communication. Note, this value is only
    # encoded in the genesis block in the Application section context
    - Host: peer0.org3.example.com
    Port: 11051
    1
    export FABRIC_CFG_PATH=$PWD && configtxgen -printOrg Org3MSP > ../artifacts/org3.json

    上面的命令创建一个JSON文件 - org3.json并将其输出到artifacts。此文件包含Org3的策略定义,以及以base 64格式呈现的三个重要证书:管理员用户证书(稍后将充当Org3的管理员),CA根证书和TLS根目录证书

  3. 移动order MSP数据到当前目录下

    将Orderer Org的MSP材料移植到Org3 crypto-config目录中。特别是,我们关注的是Orderer的TLS根证书,它将允许Org3实体与网络订购节点之间的安全通信。

    1
    cd ../ && cp -r crypto-config/ordererOrganizations org3-artifacts/crypto-config/

生成配置文件

  1. 进入cli应用

    1
    docker exec -it cli bash
  2. 设置环境变量

    接下来急需要使用order管理员的身份获取mychannel的区块文件

    1
    2
    export ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
    export CHANNEL_NAME=mychannel
  3. 获取channel的配置信息

    1
    peer channel fetch config config_block.pb -o orderer.example.com:7050 -c $CHANNEL_NAME --tls --cafile $ORDERER_CA
  4. 将配置转化为Json

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

    这给我们留下了一个精简的JSON对象 - config.json 它将作为我们的配置更新的基线。

获得添加组织后的配置文件

  1. 将组织的配置json文件添加到channel的应用的分组字段,并输出到modified_config.json

    1
    jq -s '.[0] * {"channel_group":{"groups":{"Application":{"groups": {"Org3MSP":.[1]}}}}}' config.json ./channel-artifacts/org3.json > modified_config.json

    现在,在CLI容器中,我们有两个感兴趣的JSON文件 - config.jsonmodified_config.json。初始文件仅包含Org1和Org2材料,而“modified”文件包含所有三个Orgs。此时,只需重新编码这两个JSON文件并计算增量即可。

  2. 将config.json翻译回到config.pb

    1
    configtxlator proto_encode --input config.json --type common.Config --output config.pb
  3. 将modified_config.json 编码成modified_config.pb:

    1
    configtxlator proto_encode --input modified_config.json --type common.Config --output modified_config.pb
  4. 计算两个pb文件的增量

    因为之前的组织MSP材料已经存在于通道的区块中,因此只需要计算和使用两个文件的增量

    1
    configtxlator compute_update --channel_id $CHANNEL_NAME --original config.pb --updated modified_config.pb --output org3_update.pb
  5. 将增量内容解码为json格式

    1
    configtxlator proto_decode --input org3_update.pb --type common.ConfigUpdate | jq . > org3_update.json
  6. 封装消息

    1
    echo '{"payload":{"header":{"channel_header":{"channel_id":"mychannel", "type":2}},"data":{"config_update":'$(cat org3_update.json)'}}}' | jq . > org3_update_in_envelope.json
  7. 将最终的json文件转化为pb格式

    1
    configtxlator proto_encode --input org3_update_in_envelope.json --type common.Envelope --output org3_update_in_envelope.pb

签名并提交配置更新

  1. 对更新做签名

    在将配置写入分类帐之前,我们需要来自必需管理员用户的签名。

    我们的渠道应用程序组的修改策略(mod_policy)设置为默认值“MAJORITY”,这意味着我们需要大多数现有组织管理员对其进行签名。

    首先,让我们将此更新原型作为Org1管理员签名。请记住,CLI容器是使用Org1 MSP材质引导的,因此我们只需要发出 命令:peer channel signconfigtx

    1
    peer channel signconfigtx -f org3_update_in_envelope.pb

    最后一步是切换CLI容器的标识以反映Org2 Admin用户。我们通过导出特定于Org2 MSP的四个环境变量来实现此目的。

    配置Org2环境变量:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # you can issue all of these commands at once

    export CORE_PEER_LOCALMSPID="Org2MSP"

    export 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

    export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp

    export CORE_PEER_ADDRESS=peer0.org2.example.com:7051

    签署

    1
    peer channel signconfigtx -f org3_update_in_envelope.pb
  2. 发送更新请求

    1
    peer channel update -f org3_update_in_envelope.pb -c $CHANNEL_NAME -o orderer.example.com:7050 --tls --cafile $ORDERER_CA

    如果您的更新已成功提交,您应该会看到类似于以下内容的消息摘要指示:

    1
    2018-02-24 18:56:33.499 UTC [msp/identity] Sign -> DEBU 00f Sign: digest: 3207B24E40DE2FAB87A2E42BC004FEAA1E6FDCA42977CB78C64F05A88E556ABA

    您还将看到我们的配置事务的提交:

    1
    2018-02-24 18:56:33.499 UTC [channelCmd] update -> INFO 010 Successfully submitted channel update

    成功的频道更新呼叫向频道上的所有对等体返回新块 - 块5。如果您还记得,块0-2是初始通道配置,而块3和4是mycc链代码的实例

将新的节点组织加入到channel

  1. 配置领导者的选举

    新的对等体不能利用gossip,因为它们无法验证其他对等体从其自己的组织转发的块,直到它们获得将该组织添加到该channel的配置事务。

    因此,新添加的对等体必须具有以下配置之一,以便它们从订购服务接收块:

    要使用静态领导模式,请将对等方配置为组织领导者:

    1
    2
    CORE_PEER_GOSSIP_USELEADERELECTION=false
    CORE_PEER_GOSSIP_ORGLEADER=true

    注意

    对于添加到通道的所有新对等方,此配置必须相同。

    要利用动态领导者选举,配置对等方使用领导者选举:

    1
    2
    CORE_PEER_GOSSIP_USELEADERELECTION=true
    CORE_PEER_GOSSIP_ORGLEADER=false

    注意

    由于新添加的组织的对等方将无法形成成员资格视图,因此该选项将类似于静态配置,因为每个对等方将开始宣称自己是领导者。但是,一旦他们更新了将组织添加到渠道的配置事务,组织中将只有一个活跃的领导者。因此,如果您最终希望组织的同行使用领导者选举,建议使用此选项

  2. 将Org3 peer加入channel

    打开org3 peer

    此时,通道配置已更新为包含我们的新组织Org3- 意味着与其关联的对等方现在可以加入mychannel

    首先,让我们为Org3对等体和Org3特定的CLI启动容器。

    打开一个新的终端并从first-network启动Org3 docker compose:

    compose文件内容:

    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
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    version: '2'

    volumes:
    peer0.org3.example.com:
    peer1.org3.example.com:

    networks:
    byfn:

    services:

    peer0.org3.example.com:
    container_name: peer0.org3.example.com
    extends:
    file: base/peer-base.yaml
    service: peer-base
    environment:
    - CORE_PEER_ID=peer0.org3.example.com
    - CORE_PEER_ADDRESS=peer0.org3.example.com:11051
    - CORE_PEER_LISTENADDRESS=0.0.0.0:11051
    - CORE_PEER_CHAINCODEADDRESS=peer0.org3.example.com:11052
    - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:11052
    - CORE_PEER_GOSSIP_BOOTSTRAP=peer1.org3.example.com:12051
    - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org3.example.com:11051
    - CORE_PEER_LOCALMSPID=Org3MSP
    volumes:
    - /var/run/:/host/var/run/
    - ./org3-artifacts/crypto-config/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/msp:/etc/hyperledger/fabric/msp
    - ./org3-artifacts/crypto-config/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls:/etc/hyperledger/fabric/tls
    - peer0.org3.example.com:/var/hyperledger/production
    ports:
    - 11051:11051
    networks:
    - byfn

    peer1.org3.example.com:
    container_name: peer1.org3.example.com
    extends:
    file: base/peer-base.yaml
    service: peer-base
    environment:
    - CORE_PEER_ID=peer1.org3.example.com
    - CORE_PEER_ADDRESS=peer1.org3.example.com:12051
    - CORE_PEER_LISTENADDRESS=0.0.0.0:12051
    - CORE_PEER_CHAINCODEADDRESS=peer1.org3.example.com:12052
    - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:12052
    - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org3.example.com:11051
    - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org3.example.com:12051
    - CORE_PEER_LOCALMSPID=Org3MSP
    volumes:
    - /var/run/:/host/var/run/
    - ./org3-artifacts/crypto-config/peerOrganizations/org3.example.com/peers/peer1.org3.example.com/msp:/etc/hyperledger/fabric/msp
    - ./org3-artifacts/crypto-config/peerOrganizations/org3.example.com/peers/peer1.org3.example.com/tls:/etc/hyperledger/fabric/tls
    - peer1.org3.example.com:/var/hyperledger/production
    ports:
    - 12051:12051
    networks:
    - byfn


    Org3cli:
    container_name: Org3cli
    image: hyperledger/fabric-tools:$IMAGE_TAG
    tty: true
    stdin_open: true
    environment:
    - GOPATH=/opt/gopath
    - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
    - FABRIC_LOGGING_SPEC=INFO
    #- FABRIC_LOGGING_SPEC=DEBUG
    - CORE_PEER_ID=Org3cli
    - CORE_PEER_ADDRESS=peer0.org3.example.com:11051
    - CORE_PEER_LOCALMSPID=Org3MSP
    - CORE_PEER_TLS_ENABLED=true
    - CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/server.crt
    - CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/server.key
    - CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt
    - CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/users/Admin@org3.example.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
    - ./org3-artifacts/crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/
    - ./crypto-config/peerOrganizations/org1.example.com:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com
    - ./crypto-config/peerOrganizations/org2.example.com:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com
    - ./scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/
    depends_on:
    - peer0.org3.example.com
    - peer1.org3.example.com
    networks:
    - byfn
    1
    docker-compose -f docker-compose-org3.yaml up -d

    此新组合文件已配置为跨越我们的初始网络,因此两个对等方和CLI容器将能够使用现有对等方和订购节点进行解析。现在运行三个新容器,执行特定于Org3的CLI容器:

    1
    docker exec -it Org3cli bash

    就像我们使用初始CLI容器一样,导出两个关键环境变量:

  3. 设置环境变量

    就像我们使用初始CLI容器一样,导出两个关键环境变量:ORDERER_CACHANNEL_NAME

    1
    export ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem && export CHANNEL_NAME=mychannel

    检查以确保已正确设置变量:

    1
    echo $ORDERER_CA && echo $CHANNEL_NAME
  4. 将节点加入到channel

    1
    peer channel join -b mychannel.block
  5. 将第二个节点加入到channel

    1
    2
    export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/peers/peer1.org3.example.com/tls/ca.crtexport CORE_PEER_ADDRESS=peer1.org3.example.com:7051
    peer channel join -b mychannel.block

升级chaincode并更改认可策略

更新chaincode的认可策略,添加org3到认可策略中

  1. 在org3 cli安装chaincode:

    1
    peer chaincode install -n mycc -v 2.0 -p github.com/chaincode/chaincode_example02/go/
  2. 在org1 和 org2 的 cli上安装新版本chaincode

    peer0.org2上安装

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

    跳到peer0.org1

    1
    2
    3
    4
    5
    6
    7
    8
    9
    export CORE_PEER_LOCALMSPID="Org1MSP"

    export 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

    export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp

    export CORE_PEER_ADDRESS=peer0.org1.example.com:7051

    peer chaincode install -n mycc -v 2.0 -p github.com/chaincode/chaincode_example02/go/
  3. 更新认可策略

    1
    peer chaincode upgrade -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -v 2.0 -c '{"Args":["init","a","90","b","210"]}' -P "OR ('Org1MSP.peer','Org2MSP.peer','Org3MSP.peer')"
刘小恺(Kyle) wechat
如有疑问可联系博主