├── Fabirc-Explorer搭建文档.md ├── Fabric-CA的介绍及使用.md ├── Fabric1.4.2的搭建文档.md ├── Fabric中动态加入组织.md ├── Fabric中动态加入节点.md ├── README.md ├── fabricCA 批处理 ├── ca_crypto-config.sh └── ca_start.sh ├── images ├── crypto-config.png ├── fabric-ca.png ├── raft1.png └── raftOSN.png ├── 使用Chaincode开发模式调试链码.md ├── 在Fabric1.4.2中使用并分析Raft共识.md └── 手动启动Fabric1.4.2并解析全过程.md /Fabirc-Explorer搭建文档.md: -------------------------------------------------------------------------------- 1 | # 基于Fabric 1.4.2 搭建 BlockChain-Explorer(cii-badge分支) 2 | 3 | ## 1.环境依赖说明 4 | 5 | - [nodejs](https://nodejs.org/dist/) 8.11.x (对于版本9.x还不支持) 6 | - [PostgreSQL]([https://www.postgresql.org](https://www.postgresql.org/)) 9.5 以上 7 | - [JQ](https://stedolan.github.io/jq/),jq 是一个轻量级且灵活的命令行JSON处理器 8 | - Git 9 | - gcc-c++ 10 | 11 | 已经验证的Docker环境支持版本 12 | 13 | - [Docker CE 18.09.2 or later](https://hub.docker.com/search/?type=edition&offering=community&operating_system=linux) 14 | - [Docker Compose 1.14.0](https://docs.docker.com/compose) 15 | 16 | > **注**:测试环境为`CentOS Linux release 7.4.1708 (Core)` 17 | 18 | ## 2. Git 等依赖软件安装 19 | 20 | - 安装 21 | 22 | ```bash 23 | yum install -y git 24 | yum install -y gcc-c++ 25 | ``` 26 | 27 | - 测试 28 | 29 | ```bash 30 | git --version 31 | gcc --version 32 | g++ --version 33 | ``` 34 | 35 | ## 3. Node.js 环境安装 36 | 37 | - 下载解压 38 | 39 | ```bash 40 | wget https://nodejs.org/dist/v8.11.4/node-v8.11.4-linux-x64.tar.xz 41 | tar -xvf node-v8.11.4-linux-x64.tar.xz 42 | ``` 43 | 44 | - 建立软链接 45 | 46 | ```bash 47 | ln -s /root/node-v8.11.4-linux-x64/bin/node /usr/local/bin/node 48 | ln -s /root/node-v8.11.4-linux-x64/bin/npm /usr/local/bin/npm 49 | ``` 50 | 51 | - 测试 52 | 53 | ```bash 54 | node -v # v8.11.4 55 | npm -v # 5.6.0 56 | ``` 57 | 58 | - npm 设置淘宝源 59 | 60 | ```bash 61 | npm config set registry https://registry.npm.taobao.org --global 62 | npm config set disturl https://npm.taobao.org/dist --global 63 | ``` 64 | 65 | > **注**:如果用`nvm`安装,在执行初始化数据库步骤时可能会出现问题 66 | 67 | ## 4.PostgreSQL 安装(*号步骤可以不用操作) 68 | 69 | - 添加 RPM 70 | 71 | ```bash 72 | yum install https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm 73 | ``` 74 | 75 | > **注**:如果无效,建议去[官方下载地址](https://www.postgresql.org/download/linux/)查看 76 | 77 | - 安装PostgreSQL 9.5 78 | 79 | ```bash 80 | yum install postgresql95-server postgresql95-contrib -y 81 | ``` 82 | 83 | - 初始化数据库 84 | 85 | ```bash 86 | /usr/pgsql-9.5/bin/postgresql95-setup initdb 87 | ``` 88 | 89 | - 设置开机自启并启动服务 90 | 91 | ```bash 92 | systemctl enable postgresql-9.5.service # 设置开机自启 93 | systemctl start postgresql-9.5.service # 启动服务 94 | ``` 95 | 96 | > **注**:PostgreSQL 安装完成后,会建立一下`postgres`用户,用于执行PostgreSQL,数据库中也会建立一个`postgres`用户,默认密码为自动生成,需要在系统中改一下。 97 | 98 | - 修改用户密码 99 | 100 | ```bash 101 | su - postgres # 切换用户,执行后提示符会变为 '-bash-4.2$' 102 | psql -U postgres # 登录数据库,执行后提示符变为 'postgres=#' 103 | ALTER USER postgres WITH PASSWORD 'postgres'; #设置postgres用户密码(!!!这个密码要注意下不能包含@符号) 104 | \q #退出数据库 105 | exit # 退出 postgres 用户 106 | ``` 107 | 108 | - (*)开启远程访问 109 | 110 | ```bash 111 | vi /var/lib/pgsql/9.5/data/postgresql.conf 112 | # 修改 #listen_addresses = 'localhost' 为 listen_addresses='*',表示任何人都可以访问 113 | # 当然,此处‘*’也可以改为任何你想开放的服务器IP 114 | ``` 115 | 116 | - (*)信任远程连接 117 | 118 | ```bash 119 | vi /var/lib/pgsql/9.5/data/pg_hba.conf 120 | # 修改如下内容,信任指定服务器连接 121 | # IPv4 local connections: 122 | host all all 127.0.0.1/32 md5 123 | # 增加一行 124 | host all all 0.0.0.0/0 md5 125 | ``` 126 | 127 | - (*)重启PostgreSQL服务 128 | 129 | ```bash 130 | systemctl restart postgresql-9.5.service 131 | ``` 132 | 133 | **如果不想在主机上安装 PostgreSQL,可以通过 Docker 容器安装 PostgreSQL**,具体步骤如下: 134 | 135 | - 拉取`Docker`镜像: 136 | 137 | ```bash 138 | docker pull postgres:9.5 139 | ``` 140 | 141 | - 启动容器,并挂载`db`目录到容器的`home/db`目录下,注意,先执行下载`Hyperledger Explorer`后再来执行这一步: 142 | 143 | ```bash 144 | docker run -p 5432:5432 \ 145 | --restart=always \ 146 | --name postgres \ 147 | -e POSTGRES_PASSWORD=postgres \ 148 | -v /opt/gopath/src/github.com/hyperledger/blockchain-explorer/app/persistence/fabric/postgreSQL/db:/home/db \ 149 | -d postgres:9.5 150 | ``` 151 | 152 | - 进入容器,进行修改密码和运行`sql`文件的操作: 153 | 154 | ```bash 155 | # 进入容器 156 | docker exec -it postgres bash 157 | 158 | # 修改密码操作 159 | psql -U postgres # 登录数据库,执行后提示符变为 'postgres=#' 160 | ALTER USER postgres WITH PASSWORD 'postgres'; 161 | \q #退出数据库 162 | 163 | # 进入到 home/db 目录 164 | cd /home/db 165 | 166 | # 执行运行 sql 文件的操作 167 | psql -v dbname=fabricexplorer -v user=postgres -v passwd=postgres -f ./explorerpg.sql; 168 | psql -v dbname=fabricexplorer -v user=postgres -v passwd=postgres -f ./updatepg.sql; 169 | 170 | # 运行结束后,退出容器 171 | exit 172 | ``` 173 | 174 | ## 5. 安装 JQ 175 | 176 | - 安装 JQ 需要的 epel 源 177 | 178 | ```bash 179 | wget http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm 180 | rpm -ivh epel-release-latest-7.noarch.rpm 181 | yum repolist 182 | ``` 183 | 184 | - 安装 185 | 186 | ```bash 187 | yum install jq -y 188 | ``` 189 | 190 | ## 6.下载配置 Hyperledger Explorer 191 | 192 | - 下载源码并切换到`cii-badge`分支 193 | 194 | ```bash 195 | cd /opt/gopath/src/github.com/hyperledger 196 | git clone https://github.com/hyperledger/blockchain-explorer.git 197 | cd blockchain-explorer 198 | git checkout cii-badge 199 | ``` 200 | 201 | - 初始化数据库 202 | 203 | ```bash 204 | cd app/persistence/fabric/postgreSQL/ 205 | chmod -R 775 db/ 206 | cd db/ 207 | ./createdb.sh 208 | # 如果执行 createdb.sh 提示没有权限,执行下面语句后再执行 createdb.sh 209 | chmod +x /root 210 | # 回到 blockchain-explorer 目录下 211 | cd ../../../../../../blockchain-explorer 212 | ``` 213 | 214 | - 修改有关数据库等配置的文件 215 | 216 | ```bash 217 | vim app/explorerconfig.json 218 | # 修改 username 和 passwd,官网还修改了 jwt.expiresIn 为 2 days,完整配置如下 219 | ``` 220 | 221 | ```json 222 | { 223 | "persistence": "postgreSQL", 224 | "platforms": ["fabric"], 225 | "postgreSQL": { 226 | "host": "127.0.0.1", 227 | "port": "5432", 228 | "database": "fabricexplorer", 229 | "username": "postgres", 230 | "passwd": "postgres" 231 | }, 232 | "sync": { 233 | "type": "local", 234 | "platform": "fabric", 235 | "blocksSyncTime": "1" 236 | }, 237 | "jwt": { 238 | "secret": "a secret phrase!!", 239 | "expiresIn": "2 days" 240 | } 241 | } 242 | ``` 243 | 244 | - 修改Fabric 网络配置(如果启动的是 `Fabic` 示例中的 `first-network`,则) 245 | 246 | - 修改 `app/platfom/fabric/config.json` 文件 247 | 248 | ```bash 249 | vim app/platfom/fabric/config.json 250 | # 官方默认写的是 first-network,我们可以改成自己的 my-network 251 | ``` 252 | 253 | ```bash 254 | { 255 | "network-configs": { 256 | "my-network": { 257 | "name": "my-network", 258 | "profile": "./connection-profile/my-network.json" 259 | } 260 | }, 261 | "license": "Apache-2.0" 262 | } 263 | ``` 264 | 265 | - 进一步修改 `./connection-profile/my-network.json`文件 266 | 267 | ```bash 268 | # 这里我们需要自己先建自己的 my-network 配置文件,然后按照自己需要进行配置 269 | vim app/platfom/fabric/connection-profile/my-network.json 270 | # 示例配置如下 271 | ``` 272 | 273 | ```bash 274 | { 275 | "name": "my-network", 276 | "version": "1.0.0", 277 | "license": "Apache-2.0", 278 | "client": { 279 | "tlsEnable": true, 280 | "adminUser": "admin", 281 | "adminPassword": "adminpw", 282 | "enableAuthentication": false, 283 | "organization": "Org1", 284 | "connection": { 285 | "timeout": { 286 | "peer": { 287 | "endorser": "300" 288 | }, 289 | "orderer": "300" 290 | } 291 | } 292 | }, 293 | "channels": { 294 | "mychannel": { 295 | "peers": { 296 | "peer0.org1.example.com": {} 297 | }, 298 | "connection": { 299 | "timeout": { 300 | "peer": { 301 | "endorser": "6000", 302 | "eventHub": "6000", 303 | "eventReg": "6000" 304 | } 305 | } 306 | } 307 | } 308 | }, 309 | "organizations": { 310 | "Org1MSP": { 311 | "mspid": "Org1MSP", 312 | "fullpath": true, 313 | "adminPrivateKey": { 314 | "path": "/fabric-path/my-network/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/keystore/9b5e1e91c5e7ca0c0e83799586e729d027e4c1275f079b6c59584f50c7df1faa_sk" 315 | }, 316 | "signedCert": { 317 | "path": "/fabric-path/my-network/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/signcerts/Admin@org1.example.com-cert.pem" 318 | } 319 | } 320 | }, 321 | "peers": { 322 | "peer0.org1.example.com": { 323 | "tlsCACerts": { 324 | "path": "/fabric-path/my-network/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" 325 | }, 326 | "url": "grpcs://localhost:7051", 327 | "eventUrl": "grpcs://localhost:7053", 328 | "grpcOptions": { 329 | "ssl-target-name-override": "peer0.org1.example.com" 330 | } 331 | } 332 | } 333 | } 334 | ``` 335 | 336 | >需要注意一下几点事项 337 | > 338 | >1. `/fabric-path/my-network/`为自己实际网络配置文件的地址,需要自己修改,例如为:`/root/gopath/src/github.com/hyperledger/fabric/examples/my-network/` 339 | >2. `Org1MSP.adminPrivateKey.path`下的`..._sk`文件需要修改成自己实际的文件名称 340 | >3. 如果连接的是远程区块链网络,需要将`localhost`改成远程地址的IP或者域名地址,如果域名和IP没有绑定,需要在`/etc/hosts`文件中手动进行本地绑定,否则后面将无法运行成功 341 | 342 | ## 7.安装部署 Hyperledger Explorer 343 | 344 | - 按照官方步骤安装 345 | 346 | ```bash 347 | cd blockchain-explorer 348 | npm install 349 | cd blockchain-explorer/app/test 350 | npm install 351 | npm run test 352 | cd ../../client/ 353 | npm install 354 | npm run test:ci -- -u --coverage 355 | npm run build 356 | ``` 357 | 358 | - 如果遇到 root没权限,则需要使用非安全模式,顺便输出下详细日志 359 | 360 | ```bash 361 | cd blockchain-explorer 362 | npm install --unsafe-perm -d 363 | cd blockchain-explorer/app/test 364 | npm install --unsafe-perm -d 365 | npm run test 366 | cd ../../client/ 367 | npm install --unsafe-perm -d 368 | npm run test:ci -- -u --coverage 369 | npm run build --unsafe-perm -d 370 | ``` 371 | 372 | > **注**: 373 | > 374 | > ​ 1.如果中间出错,重新安装时先要删除node_modules文件夹,client里的也需要,`npm run test`过程中出现问题时,如果最后所有测试都通过了可以不用管 375 | > 376 | > ​ 2.如果`npm run build`时出现`The build failed because the process exited too early. This probably means the system ran out of memory or someone called kill -9 on the process`错误,可能是代码的打包比较占内存,多试几次看看,如果不行,停用掉几个服务,清清内存再试 377 | 378 | - 运行程序 379 | 380 | ```bash 381 | cd blockchain-explorer 382 | ./start.sh 383 | ``` 384 | 385 | > **注**:日志文件: 386 | > 387 | > `logs/app` app 日志 388 | > `logs/console` 运行日志 389 | > `logs/db` db 日志 390 | > 这几个文件里面的日志要结合看才能更好的解决问题 391 | > 392 | > 393 | > 394 | > 启动后显示如下,查看日志,如果没有错误,访问:`http://IP:8080`即可查看区块链网络的信息 395 | 396 | ```bash 397 | ************************************************************************************ 398 | **************************** Hyperledger Explorer ********************************** 399 | ************************************************************************************ 400 | ***** Please check the log [logs/console/console-2019-07-25.log] for any error ***** 401 | ************************************************************************************ 402 | ``` 403 | 404 | ## 参考 405 | 406 | - [Hyperledger Explorer 安装部署(pg版)](https://www.jianshu.com/p/eac679b2e871) 407 | - [Fabric多台服务器的部署(五)](https://www.jianshu.com/p/54bdd1555d4b) 408 | - [Hyperledger Explorer部署](https://www.e-learn.cn/content/qita/1947778) 409 | -------------------------------------------------------------------------------- /Fabric-CA的介绍及使用.md: -------------------------------------------------------------------------------- 1 | # Fabric CA 的介绍及使用 2 | 3 | ## Fabric CA 简介 4 | 5 | Fabric CA 是 Fabric 的证书颁发管理机构,原来是 Fabric 内的 MemberService 组件,后来独立成子项目,主要实现下面几个功能: 6 | 7 | - 负责 Fabric 网络内所有实体`(Identity)`的身份管理,包括身份的注册和注销 8 | - 负责证书管理,包括注册证书`(ECerts)`和交易证书`(TCerts)`等的发放和注销 9 | - 服务端支持基于客户端命令行和`RESTful API`的交互方式 10 | 11 | ### 基本组件 12 | 13 | - 服务端:`fabric-ca-server` 实现了核心的`PKI`服务功能,支持多种数据库后台(MySQL,SQLite等),并支持集成`LDAP(轻量目录访问协议)`作为用户注册管理功能 14 | - 客户端:`fabric-ca-client`封装了服务端的`RESTful API`,提供访问服务端的命令,供用户与服务端进行交互 15 | 16 | 下图说明了 Hyperledger Fabric CA 服务器如何搭配整个 Hyperledger Fabric 架构 17 | 18 | ![fabric-ca](images/fabric-ca.png) 19 | 20 | ## Fabric CA 服务端和客户端的安装 21 | 22 | - 编译环境准备 23 | 24 | ```bash 25 | Golang 1.10+ 26 | # 对于 Ubuntu 环境,需要安装以下依赖 27 | sudo apt-get install libtool libltdl-dev 28 | # 对于 CentOS 环境,需要安装以下依赖 29 | yum install libtool 30 | ``` 31 | 32 | - 使用源码编译安装 33 | 34 | ```bash 35 | git clone https://github.com/hyperledger/fabric-ca.git # clone 源码至本地 36 | cd $GOPATH/src/github.com/hyperledger/fabric-ca/ #切换至源码目录 37 | # 使用 make 命令编译安装 38 | make fabric-ca-server 39 | make fabric-ca-client 40 | ``` 41 | 42 | - 编译生成的二进制文件在`fabric-ca/bin/`目录下,我们可以将其拷贝到`$GOPATH/bin/`目录下,或者将`fabric-ca/bin`目录添加到环境变量,这样就可以在任何地方使用这两个组件了 43 | 44 | - 使用 `go get`命令安装 45 | 46 | ```bash 47 | go get -u github.com/hyperledger/fabric-ca/cmd/... 48 | ``` 49 | 50 | 该命令会默认将`Fabric-CA`的`Server`和`Client`的二进制文件安装到`$GOPATH/bin/`目录下 51 | 52 | ## fabric-ca-server 53 | 54 | 我们使用`fabric-ca-server --help`命令就能查看 CA 服务端所支持的参数和命令,另外[官方文档](https://hyperledger-fabric-ca.readthedocs.io/en/latest/servercli.html)上也有介绍 55 | 56 | - 配置读取:`fabric-ca-server`服务所需要的相关配置项会依次尝试从`命令行参数`,`环境变量(命令需要带有FABRIC_CA_SERVER)前缀`,或`主配置目录(未指定配置文件路径时)`下的本地配置文件读取。 57 | 58 | 例如,指定启用`TLS`可以通过以下三种方式,优先级`从高到低`: 59 | 60 | - 命令行参数:--tls-enabled=true 61 | - 环境变量:FABRIC_CA_SERVER_TLS_ENABLED=true 62 | - 配置文件:tls.enabled=true 63 | 64 | - 主配置目录:`fabric-ca-server`服务会依次从环境变量`FABRIC_CA_SERVER_HOME`、`FABRIC_CA_HOME`、`CA_CFG_PATH`等中读取主配置,一般推荐默认的`/etc/hyperledger/fabric-ca-server`路径作为主配置目录环境变量指向路径。如果当这些环境变量都不存在,会使用`当前目录`作为主配置目录 65 | 66 | - `init`命令:初始化一个`fabric-ca-server`服务,主要用于生成秘钥相关的证书文件(文件已经存在的话则跳过生成)以及配置文件等。 67 | 68 | 当主目录下配置文件不存在时,需要使用 `-b`参数指定 CA 服务端启动后默认的管理员用户名和密码,以便做进一步的操作;如果有配置文件存在或者指定启用了`LDAP`功能,则不需要使用`-b`参数,示例命令入下: 69 | 70 | ```bash 71 | fabric-ca-server init -b admin:adminpw 72 | ``` 73 | 74 | 上面命令执行完之后,会在主配置目录生成下面几个文件(事先不存在的情况下): 75 | 76 | - `ca-cert.pem`:自签名的CA证书文件 77 | - `fabric-ca-server-config.yaml`:默认的 CA 服务端配置文件 78 | - `fabric-ca-server.db`:默认存放数据的 Sqlite 数据库文件 79 | - `msp/keystore/`:该路径下有存放个人身份的私钥文件(_sk文件),对应签名证书等 80 | - `..._sk`:个人身份的私钥文件 81 | - `IssuerSecretKey`:`idemix`证书颁发者的秘钥文件 82 | - `IssuerRevocationPrivateKey`:``idemix`证书吊销者的秘钥文件 83 | - `IssuerPublicKey`:`idemix`证书颁发者的公钥文件 84 | - `IssuerRevocationPublicKey`:`idemix`证书吊销者的公钥文件 85 | 86 | - `start`命令:使用该命令快速启动一个 CA 服务,默认会查找本地主配置目录路径下的证书文件和配置文件,类似的,如果没有指定`LDAP`服务,或者配置文件不存在,需要使用`-b`参数来指定 Fabric-CA 默认启动的管理员用户名和密码,示例命令如下: 87 | 88 | ```bash 89 | fabric-ca-server start -b admin:adminpw 90 | ``` 91 | 92 | 执行上面命令后,默认的管理员名称和密码是:`admin`和`adminpw` 93 | 94 | 如果之前没有执行初始化,则会先执行初始化操作 95 | 96 | - 配置文件`fabric-ca-server-config.yaml`:在配置文件中可以配置端口、TLS、CA、注册管理、数据库、LDAP、证书的申请和签发、BCCSP(加密库)、中间 CA 的配置等 97 | 98 | ## fabric-ca-client 99 | 100 | 同样的,我们使用`fabric-ca-client --help`命令就能查看 CA 客户端所支持的参数和命令,另外[官方文档](https://hyperledger-fabric-ca.readthedocs.io/en/latest/clientcli.html)上也有介绍 101 | 102 | - 配置读取:与服务端的配置读取类似,`fabric-ca-client`服务所需要的相关配置项会依次尝试从`命令行参数`,`环境变量(命令需要带有FABRIC_CA_CLIENT_前缀`,或`主配置目录(未指定配置文件路径时)`下的本地配置文件读取。 103 | - 主配置目录:`fabric-ca-client`服务会依次从环境变量`FABRIC_CA_CLIENT_HOME`、`FABRIC_CA_HOME`、`CA_CFG_PATH`等中读取主配置,一般推荐使用`$HOME/.fabric-ca-client`路径作为主配置目录环境变量指向路径。如果当这些环境变量都不存在,会默认使用`$HOME/.fabric-ca-client`作为主配置目录 104 | 105 | 一般情况下,主要用到下面几个命令: 106 | 107 | - `enroll`:登记实体身份。该命令会向服务端申请签发`ECert`证书,示例命令如下 108 | 109 | ```bash 110 | fabric-ca-client enroll -u http://admin:adminpw@localhost:7054 111 | ``` 112 | 113 | 上面命令使用默认的 admin 管理员用户进行登记。如果未指定配置目录,默认会在`$HOME/.fabric-ca-client`目录下生成下面几个文件 114 | 115 | ```bash 116 | ├── fabric-ca-client-config.yaml # 客户端的配置文件 117 | └── msp 118 | ├── cacerts 119 | │   └── localhost-7054.pem # CA 根证书 120 | ├── IssuerPublicKey # idemix 证书颁发者公钥 121 | ├── IssuerRevocationPublicKey # idemix 证书吊销者公钥 122 | ├── keystore 123 | │   └── ......_sk # 秘钥 124 | ├── signcerts 125 | │   └── cert.pem # 客户端证书 126 | └── user 127 | ``` 128 | 129 | - `rigister`:注册新的用户实体。执行注册新的用户实体的客户端必须已经通过登记认证,并且拥有足够的权限(所注册用户的`hf.Registrar.Roles`和`affiliation`都不能超出调用者的属性)来进行注册。 130 | 131 | ## crypto-config 目录文件介绍 132 | 133 | ```bash 134 | ├── ordererOrganizations # orderer 节点组织树 135 | │   └── example.com # 组织域,组织的命名域 136 | │   ├── ca # 存放组织(example.com)的 CA 根证书和私钥文件 ?? 【有中间CA情况下,这里是根还是中间】 137 | │   │   ├── .........._sk # 组织(example.com)的私钥文件 138 | │   │   └── ca.example.com-cert.pem # 组织(example.com)的CA根证书 139 | │   │ 140 | │   ├── msp # 存放代表该组织(example.com)的身份信息 141 | │   │   ├── admincerts # 存放组织管理员的身份验证证书,被组织(example.com)的根证书签名 142 | │   │   │   └── Admin@example.com-cert.pem 143 | │   │   ├── cacerts # 存放组织(example.com)CA根证书,同 ca 目录下的文件 144 | │   │   │   └── ca.example.com-cert.pem 145 | │   │   ├── intermediatecerts # (可选) 存放组织(example.com)的中间 CA 证书 146 | │   │   │   └── intermediateca.example.com-cert.pem 147 | │   │   ├── tlscacerts # 存放组织(example.com)用于 TSL 安全连接的 CA 根证书,自签名 148 | │   │   │ └── tlsca.example.com-cert.pem 149 | │   │   └── intermediatecerts # (可选) 存放组织(example.com)用于 TSL 安全连接的中间 CA 证书 150 | │   │     └── intermediateca.example.com-cert.pem 151 | │   │   152 | │   ├── orderers # 存放该组织所有 orderer 节点的信息 153 | │   │   └── orderer.example.com # 第一个 orderer 节点的信息,包含代表其身份的msp证书文件和用于TLS连接的tls证书文件 154 | │   │   ├── msp # 存放代表第一个 orderer 节点身份的 msp 证书文件 155 | │   │   │   ├── admincerts # 存放组织管理员的身份验证证书,Oderer节点将基于其来认证xxx管理员身份 ?? 156 | │   │   │   │   └── Admin@example.com-cert.pem 157 | │   │   │   ├── cacerts # 存放组织(example.com)的 CA 根证书 158 | │   │   │   │   └── ca.example.com-cert.pem 159 | │   │   │   ├── intermediatecerts # (可选) 存放组织(example.com)的中间 CA 证书 160 | │   │   │   │   └── intermediateca.example.com-cert.pem 161 | │   │   │   ├── keystore # 存放本 orderer 节点的身份私钥,用来签名 162 | │   │   │   │   └── .........._sk 163 | │   │   │   ├── signcerts # 存放验证本 orderer 节点签名的证书,被组织 CA 根证书签名 164 | │   │   │   │   └── orderer.example.com-cert.pem 165 | │   │   │   ├── tlscacerts # 存放 TLS 连接用的身份证书, 既组织的 TLS CA 根证书 166 | │   │   │   │   └── tlsca.example.com-cert.pem 167 | │   │   │   ├── intermediatecerts # 存放 TLS 中间 CA 证书,既组织的 TLS 中间 CA 证书 168 | │   │   │   │   └── intermediateca.example.com-cert.pem 169 | │   │   │   ├── crls #(可选) 存放证书吊销列表 170 | │   │   │   │   └── XXXX 171 | │   │   │   └── config.yaml # 映射部门和证书 OU 字段的 YAML 文件 172 | │   │   └── tls # 存放本 orderer 节点 tls 相关的证书和私钥 173 | │   │   ├── ca.crt # 组织(example.com)的 tlsCA 根证书[tlsca.example.com-cert.pem] 174 | │   │   ├── server.crt # 验证本节点签名的证书,被组织 tlsCA 根证书签名 tls/signcerts [cert.pem] 175 | │   │   └── server.key # 本节点的身份私钥,用来签名 tls/keystore[.........._sk] 176 | │   │ 177 | │   ├── tlsca # 存放组织(example.com)用于 TSL 安全连接的 CA 根证书和秘钥 ?? 【有中间tlsCA情况下,这里是根还是中间】 178 | │   │   ├── .........._sk # 秘钥 179 | │   │   └── tlsca.example.com-cert.pem # 证书 180 | │   └── users # 存放属于该组织的用户实体 181 | │   └── Admin@example.com # 组织管理员用户信息,包括其 msp 证书和 tls 证书 182 | │   ├── msp # 存放管理员用户的 msp 证书文件 183 | │   │   ├── admincerts # 存放组织管理员的身份验证证书,被组织(example.com)的根证书签名 184 | │   │   │   └── Admin@example.com-cert.pem 185 | │   │   ├── cacerts # 存放组织(example.com)的 CA 根证书 186 | │   │   │   └── ca.example.com-cert.pem 187 | │   │   ├── keystore # 本用户的身份私钥,用来签名 188 | │   │   │   └── .........._sk 189 | │   │   ├── signcerts # 管理员用户的身份验证证书,这是该组织下所有实体 msp 文件中 admincerts 文件的来源 190 | │   │   │   └── Admin@example.com-cert.pem 191 | │   │   └── tlscacerts # 存放 TLS 连接用的身份证书, 既组织的 TLS CA 根证书 192 | │   │   └── tlsca.example.com-cert.pem 193 | │   └── tls 194 | │   ├── ca.crt # 组织(example.com)的 tlsCA 根证书[ca.example.com-cert.pem] 195 | │   ├── client.crt # 管理员用户的身份验证证书 Admin@example.com/tls/signcerts [cert.pem] 196 | │   └── client.key # 管理员用户的身份私钥,用来签名 Admin@example.com/tls/keystore [.........._sk] 197 | │ 198 | │ 199 | └── peerOrganizations # peer 节点组织数,与 orderer 节点结构相同 200 | └── org1.example.com 201 | ├── ca 202 | ├── msp 203 | ├── peers 204 | │   └── peer0.org1.example.com 205 | │   ├── msp 206 | │   └── tls 207 | ├── tlsca 208 | └── users 209 | ├── Admin@org1.example.com 210 | │   ├── msp 211 | │   └── tls 212 | └── User1@org1.example.com 213 | ├── msp 214 | └── tls 215 | ``` 216 | 217 | **config.yaml文件介绍**:映射部门和证书 OU 字段的 YAML 配置文件,用``表示一个映射表 218 | 219 | ```yaml 220 | NodeOUs: 221 | Enable: true # 启用标识分类 222 | ClientOUIdentifier: # 客户端(client)标识符 223 | Certificate: cacerts/ca.org1.example.com-cert.pem # 验证客户端(client)身份的 CA 或中间 CA 证书 224 | OrganizationalUnitIdentifier: client # 与客户端(client)的x509证书中包含的OU匹配的值 225 | PeerOUIdentifier: # 对等节点(peer)标识符 226 | Certificate: cacerts/ca.org1.example.com-cert.pem # 验证对等节点(peer)身份的 CA 或中间 CA 证书 227 | OrganizationalUnitIdentifier: peer # 与对等节点(peer)的x509证书中包含的OU匹配的值 228 | ``` 229 | 230 | - ecdsa-with-SHA256 使用 SHA256 算法对内容先计算摘要,再应用签名算法对摘要进行签名 231 | - Orderer 节点管理员证书位于 `crypto-config/ordererOrganizations/example.com/msp/admincerts`。由 CA 颁发给 `Admin@example.com` 232 | - TLS 证书是自签名证书,与之前的 CA 证书没有关系。位于 `crypto-config/ordererOrganizations/example.com/msp/tlscacerts` 233 | - TLS 客户端证书是由 TLS CA 颁发给 `Admin@example.com` 的用于 TLS 连接的证书。位于 `crypto-config/ordererOrganizations/example.com/users/Admin@example.com/tls` 234 | 235 | ### 证书间的关系 236 | 237 | - 颜色相同的线条表示文件内容相同。 238 | - 红色箭头表示 CA 颁发证书给某个组织或个人 239 | 240 | ![crypto-config](images/crypto-config.png) 241 | 242 | ## Fabric CA 的实践使用 243 | 244 | - [HyperLedger Fabric 1.4 生产环境使用ca生成msp和tls](https://www.cnblogs.com/llongst/p/9786024.html) 245 | - [超级账本HyperLedger:Fabric-CA的使用演示](https://www.lijiaocn.com/项目/2018/05/04/fabric-ca-example.html) 246 | - 247 | -------------------------------------------------------------------------------- /Fabric1.4.2的搭建文档.md: -------------------------------------------------------------------------------- 1 | # 基于CentOS 7 搭建 Fabric1.4.2 区块链环境 2 | 3 | ## 1. 下载CentOS 7 镜像 4 | 5 | - 下载地址: 6 | - 网易源镜像地址: 7 | 8 | ## 2. VMware 15 安装 CentOS Minimal 9 | 10 | - 安装完成之后如果`ifconfig`命令无法使用,使用命令`yum -y install net-tools` 安装即可 11 | 12 | ### CentOS 换 yum 源 13 | 14 | - 首先进入`/etc/yum.repos.d/`目录下,新建一个repo_bak目录,用于保存系统中原来的repo文件 15 | 16 | ```bash 17 | cd /etc/yum.repos.d/ 18 | mkdir repo_bak 19 | mv *.repo repo_bak/ 20 | ``` 21 | 22 | - 在CentOS中配置使用网易和阿里的开源镜像 23 | 24 | ```bash 25 | curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo 26 | ``` 27 | 28 | - 清除系统yum缓存并生成新的yum缓存 29 | 30 | ```bash 31 | yum clean all # 清除系统所有的yum缓存 32 | yum makecache # 生成yum缓存 33 | ``` 34 | 35 | - 安装`git`、`pip`、`vim`、`wget`等 36 | 37 | ```bash 38 | yum install git 39 | yum install vim 40 | yum install wget 41 | yum -y install epel-release 42 | yum install python-pip 43 | pip install --upgrade pip 44 | ``` 45 | 46 | ## 3. 安装Go语言环境 47 | 48 | - 下载最新的GO安装包,具体的最新版本号可以从[Golang官网](https://golang.org/)上查看,如果被墙,可以去[Go语言中文网](https://studygolang.com/dl)下载 49 | 50 | ```bash 51 | cd ~ 52 | wget https://studygolang.com/dl/golang/go1.11.5.linux-amd64.tar.gz 53 | tar -C /usr/local -xzf go1.11.5.linux-amd64.tar.gz #解压安装包到/usr/local目录下 54 | ``` 55 | 56 | - 打开`/etc/profile`文件 57 | 58 | ```bash 59 | vim /etc/profile 60 | ``` 61 | 62 | - 在最后添加如下四个环境变量 63 | 64 | ```bash 65 | export PATH=$PATH:/usr/local/go/bin 66 | export GOROOT=/usr/local/go 67 | export GOPATH=/opt/gopath 68 | export PATH=$PATH:/opt/gopath/bin 69 | ``` 70 | 71 | - `source /etc/profile` 使环境变量生效, 用`go version`验证一下`Go`是否安装成功 72 | 73 | - 创建`Go`工作目录 74 | 75 | ``` bash 76 | cd ~ 77 | mkdir -p /opt/gopath/src/github.com/hyperledger/fabric 78 | ``` 79 | 80 | ## 4. Docker 安装(*号步骤可以不用操作) 81 | 82 | - 卸载旧版本`Docker` 83 | 84 | ```bash 85 | sudo yum remove docker \ 86 | docker-client \ 87 | docker-client-latest \ 88 | docker-common \ 89 | docker-latest \ 90 | docker-latest-logrotate \ 91 | docker-logrotate \ 92 | docker-engine 93 | ``` 94 | 95 | - 安装`Docker CE` 96 | 97 | - 安装所需的包。`yum-utils`提供了`yum-config-manager` 效用,并`device-mapper-persistent-data`和`lvm2`由需要`devicemapper`存储驱动程序 98 | 99 | ```bash 100 | sudo yum install -y yum-utils \ 101 | device-mapper-persistent-data \ 102 | lvm2 103 | ``` 104 | 105 | - 使用以下命令设置**稳定**存储库 106 | 107 | ```bash 108 | sudo yum-config-manager \ 109 | --add-repo \ 110 | https://download.docker.com/linux/centos/docker-ce.repo 111 | ``` 112 | 113 | - 安装最新版本的Docker CE和containerd 114 | 115 | ```bash 116 | sudo yum install docker-ce docker-ce-cli containerd.io 117 | ``` 118 | 119 | - 启动`Docker` 120 | 121 | ```bash 122 | sudo systemctl start docker 123 | ``` 124 | 125 | - (*)通过运行`hello-world` 映像验证是否正确安装了`Docker CE` 126 | 127 | ```bash 128 | docker run hello-world 129 | ``` 130 | 131 | - 或者运行以下命令查看`Docker`版本信息 132 | 133 | ```bash 134 | docker version 135 | ``` 136 | 137 | - 添加阿里云的`Docker Hub`镜像 138 | 139 | ```bash 140 | sudo mkdir -p /etc/docker 141 | sudo tee /etc/docker/daemon.json <<-'EOF' 142 | { 143 | "registry-mirrors": ["https://6e0d9uoa.mirror.aliyuncs.com"] 144 | } 145 | EOF 146 | sudo systemctl daemon-reload 147 | sudo systemctl restart docker 148 | ``` 149 | 150 | - 安装`Docker-Compose` 151 | 152 | - 安装`python-pip` 153 | 154 | ```bash 155 | sudo yum install python-pip -y 156 | ``` 157 | 158 | - 安装`Docker-Compose` 159 | 160 | ```bash 161 | pip install docker-compose 162 | ``` 163 | 164 | - 如果安装出现如下错误 165 | 166 | ```bash 167 | ImportError: 'module' object has no attribute 'check_specifier' 168 | ---------------------------------------- 169 | ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output 170 | ``` 171 | 172 | 使用如下命令升级`setuptools`,然后在执行安装 173 | 174 | ```bash 175 | # 升级 setuptools 176 | pip install --upgrade setuptools 177 | # 再次执行安装 178 | pip install docker-compose 179 | ``` 180 | 181 | - 查看是否安装成功 182 | 183 | ```bash 184 | docker-compose version 185 | ``` 186 | 187 | ## 5. 安装Node.js 环境 188 | 189 | - 安装`nvm` 190 | 191 | ```bash 192 | wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash 193 | ``` 194 | 195 | - 添加环境变量 196 | 197 | ```bash 198 | vim ~/.profile 199 | #下面内容添加到文件中 200 | export NVM_DIR="${XDG_CONFIG_HOME/:-$HOME/.}nvm" 201 | [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm 202 | ``` 203 | 204 | - 安装 node V8 205 | 206 | ```bash 207 | nvm install v8.15.1 208 | ``` 209 | 210 | - 查看安装是否成功 211 | 212 | ```bash 213 | node -v 214 | npm -v 215 | ``` 216 | 217 | - npm 设置淘宝源 218 | 219 | ```bash 220 | npm config set registry https://registry.npm.taobao.org --global 221 | npm config set disturl https://npm.taobao.org/dist --global 222 | ``` 223 | 224 | ## 6. 下载Fabric源码,安装镜像 225 | 226 | - 克隆源码 227 | 228 | ```bash 229 | cd /opt/gopath/src/github.com/hyperledger 230 | git clone https://github.com/hyperledger/fabric.git 231 | git checkout v1.4.2 #将版本切换到1.4.2 232 | ``` 233 | 234 | - 完成后进入 `fabric/scripts` 文件夹,执行 `bootstrap.sh` 脚本,自动进行**克隆fabric-samples并检出适当的版本**、**安装二进制可执行文件和配置文件**、 **下载fabric相关镜像**的操作 235 | 236 | ```bash 237 | cd fabric/scripts 238 | ./bootstrap.sh 239 | ``` 240 | 241 | - 如果下载二进制文件非常慢,可以下载到本地,然后解压拷贝到`/opt/gopath/bin`目录下面或者是`/usr/local/bin`目录下面,下面是下载地址 242 | 243 | - [hyperledger-fabric-linux-amd64-1.4.2.tar.gz](https://nexus.hyperledger.org/content/repositories/releases/org/hyperledger/fabric/hyperledger-fabric/linux-amd64-1.4.2/hyperledger-fabric-linux-amd64-1.4.2.tar.gz) 244 | 245 | - [hyperledger-fabric-ca-linux-amd64-1.4.2.tar.gz](https://nexus.hyperledger.org/content/repositories/releases/org/hyperledger/fabric-ca/hyperledger-fabric-ca/linux-amd64-1.4.2/hyperledger-fabric-ca-linux-amd64-1.4.2.tar.gz) 246 | 247 | - 检查`/opt/gopath/bin`目录下面(或者`/usr/local/bin`)之前拷贝过来的文件权限,如果没有可执行权限,按照下面模式,更改`bin`目录下面所有拷贝过来的二进制文件权限 248 | 249 | ```bash 250 | chmod 775 configtxgen #提升权限 251 | ``` 252 | 253 | - **注**:这样需要编辑`bootstrap.sh`注释掉最后调用的`binariesInstall`方法 254 | 255 | ```bash 256 | #........ 257 | #........... 258 | if [ "$BINARIES" == "true" ]; then 259 | echo 260 | echo "Installing Hyperledger Fabric binaries" 261 | echo 262 | # binariesInstall #---注释掉这里 263 | fi 264 | #........... 265 | #........ 266 | ``` 267 | 268 | - 再次执行`bootstrap.sh`文件下载`docker`镜像 269 | 270 | ```bash 271 | ./bootstrap.sh 272 | ``` 273 | 274 | ## 7. 运行 first-network 的例子 275 | 276 | - 启动和关闭网络 277 | 278 | ```bash 279 | cd fabric/scripts/fabric-samples/first-network 280 | ./byfn.sh up # 启动网络 281 | ./byfn.sh down #关闭网络 282 | ``` 283 | 284 | >注:如果是在`阿里云`的服务器上部署网络,需要在`base/peer-base.yaml`里的`peer-base`服务和`orderer-base`服务都添加一项环境变量`- GODEBUG=netdns=go`,另外在`dockcer-compose-cli.yaml`里的`cli`服务里也添加该变量 285 | -------------------------------------------------------------------------------- /Fabric中动态加入组织.md: -------------------------------------------------------------------------------- 1 | # Fabric 中动态加入组织 2 | 3 | > 注:测试 `Fabric` 版本为 `1.4.2`;测试网络配置为`first-network` 4 | 5 | ## 1. 启动测试网络 6 | 7 | 首先我们需要进入`first-network`文件夹下,启动测试网络: 8 | 9 | ```bash 10 | # 进入 first-network 文件夹 11 | cd /opt/gopath/src/github.com/hyperledger/fabric/scripts/fabric-samples/first-network/ 12 | 13 | # 启动网络 14 | ./byfn.sh up 15 | ``` 16 | 17 | ## 2. 为新组织生成证书 18 | 19 | 其实`first-network`直接提供了添加新组织的脚本和配置文件,这里我们不需要编写配置,只需要解读这些配置内容就行。 20 | 21 | 首先,我们需要使用`org3-artifacts/org3-crypto.yaml`文件来为新组织`org3`生成他的组织关系证书文件,`org3-crypto.yaml`文件内容如下: 22 | 23 | ```bash 24 | # --------------------------------------------------------------------------- 25 | # "PeerOrgs" - Definition of organizations managing peer nodes 26 | # --------------------------------------------------------------------------- 27 | PeerOrgs: 28 | # --------------------------------------------------------------------------- 29 | # Org3 30 | # --------------------------------------------------------------------------- 31 | - Name: Org3 32 | Domain: org3.example.com 33 | EnableNodeOUs: true 34 | Template: 35 | Count: 2 # 新组织 org3 有两个 peer 节点(peer0.org3,peer1.org3) 36 | Users: 37 | Count: 1 38 | ``` 39 | 40 | 我们使用如下命令,来生成`org3`的组织关系证书文件: 41 | 42 | ```bash 43 | cd org3-artifacts/ 44 | cryptogen generate --config=./org3-crypto.yaml 45 | ``` 46 | 47 | 执行完成后,我们在`org3-artifacts`目录下就能看到`crypto-config`文件夹,里面就有新生成的`org3`的组织关系证书文件。 48 | 49 | ## 3. 为新组织生成配置文件 50 | 51 | 接下来使用`org3-artifacts`下的`configtx.yaml`文件和`configtxgen`工具为`org3`生成`json`格式的配置文件。其中`configtx.yaml`文件内容如下: 52 | 53 | ```bash 54 | Organizations: 55 | - &Org3 # 添加一个新组织 org3 56 | Name: Org3MSP 57 | ID: Org3MSP 58 | MSPDir: crypto-config/peerOrganizations/org3.example.com/msp 59 | 60 | # 策略定义,如果配置文件中没有,建议添加这些配置 61 | Policies: 62 | Readers: 63 | Type: Signature 64 | Rule: "OR('Org3MSP.admin', 'Org3MSP.peer', 'Org3MSP.client')" 65 | Writers: 66 | Type: Signature 67 | Rule: "OR('Org3MSP.admin', 'Org3MSP.client')" 68 | Admins: 69 | Type: Signature 70 | Rule: "OR('Org3MSP.admin')" 71 | 72 | # 锚节点定义 73 | AnchorPeers: 74 | - Host: peer0.org3.example.com 75 | Port: 11051 76 | ``` 77 | 78 | 使用如下命令来生成配置文件: 79 | 80 | ```bash 81 | export FABRIC_CFG_PATH=$PWD 82 | configtxgen -printOrg Org3MSP -profile ./configtx.yaml > ../channel-artifacts/org3.json 83 | ``` 84 | 85 | 命令执行完成之后,我们会发现在`channel-artifacts`文件夹下多了一个`org3.json`文件。 86 | 87 | 将 `Orderer`的组织证书文件拷贝到`org3-artifacts/crypto-config`下来,以便接下来的工作,同时也将`org3-artifacts/crypto-config/peerOrganizations/org3.example.com`文件夹拷贝到`crypto-config/peerOrganizations/`目录下来,以便`cli`客户端节点进行最后的测试操作,具体命令如下: 88 | 89 | ```bash 90 | # 返回到 first-network 目录 91 | cd .. 92 | 93 | # 将 Orderer的组织证书文件拷贝到 org3-artifacts/crypto-config 94 | cp -r crypto-config/ordererOrganizations org3-artifacts/crypto-config/ 95 | 96 | # 将 org3.example.com 文件夹拷贝到 crypto-config/peerOrganizations 97 | cp -r org3-artifacts/crypto-config/peerOrganizations/org3.example.com crypto-config/peerOrganizations/ 98 | ``` 99 | 100 | ## 4. 生成和提交新组织的配置 101 | 102 | 通过上面两步,我们已经生成了`org3`的证书文件和配置,但是还没有与区块链网络进行关联,接下来,我们就需要为网络中的`channel`添加一个新的组织进来。 103 | 104 | ### 4.1 进入`cli`容器,获取最新的`channel`配置 105 | 106 | 进入`cli`容器,先设置`Orderer CA`和`channel`的环境变量 107 | 108 | ```bash 109 | # 进入 cli 容器 110 | docker exec -it cli bash 111 | 112 | # 设置`Orderer CA`和`channel`的环境变量 113 | 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 114 | export CHANNEL_NAME=mychannel 115 | ``` 116 | 117 | 拉取当前最新的配置区块,它会吧`channel`的配置保存到`protobuf`文件中去,具体命令如下: 118 | 119 | ```bash 120 | # peer channel fetch config 拉取最新的 channel 配置区块文件,保存到 config_block.pb 文件中 121 | peer channel fetch config config_block.pb -o orderer.example.com:7050 -c $CHANNEL_NAME --tls --cafile $ORDERER_CA 122 | ``` 123 | 124 | 命令执行完成之后,我们可以看到有如下输出: 125 | 126 | ```bash 127 | 2019-08-26 19:35:18.275 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized 128 | 2019-08-26 19:35:18.310 UTC [cli.common] readBlock -> INFO 002 Received block: 4 129 | 2019-08-26 19:35:18.312 UTC [cli.common] readBlock -> INFO 003 Received block: 2 130 | ``` 131 | 132 | 通过输出日志我们发现,当前共有`4`个区块,其中最新的`channel`配置区块在第`2`块的位置,其中前几块区块主要做了如下的配置更改: 133 | 134 | - 区块`0`:使用应用`channel`创世区块创建应用`channel` 135 | 136 | - 区块`1`:更新`org1`的锚节点 137 | 138 | - 区块`2`:更新`org2`的锚节点 139 | 140 | 所以,我们通过上面的命令,得到了区块`2`中最新的配置。但是我们得到的配置是`protobuf`格式的,我们需要将其转换为可读的`JSON`格式,这里需要使用两个工具,一个是`configtxlator`,它是一个可以将系统所需的配置文件,在二进制(例如`protobuf`)格式和`JSON`格式之间进行转换的工具,方便用户更新`channel`的配置。另一个工具是`jq`,它是一个`JSON`命令行处理工具,可以对 `JSON` 进行过滤、格式化、修改等操作。 141 | 142 | `configtxlator`工具之前已经安装在`$GOPATH`目录下了,执行下面命令安装`JQ`: 143 | 144 | ```bash 145 | apt-get -y update && apt-get -y install jq 146 | ``` 147 | 148 | 使用下面命令,将配置相关的数据从`config_block.pb`中读取出来,并存在`config.json`文件中: 149 | 150 | ```bash 151 | # proto_decode 解码 pb 格式文件 152 | configtxlator proto_decode --input config_block.pb --type common.Block | jq .data.data[0].payload.data.config > config.json 153 | ``` 154 | 155 | ### 4.2 利用`channel`配置和`org3`配置生成更新`channel`的配置 156 | 157 | 上一步生成的`config.json`文件包含了`org1`和`org2`的信息,现在要把`org3.json`加入到`config.json`中: 158 | 159 | ```bash 160 | jq -s '.[0] * {"channel_group":{"groups":{"Application":{"groups": {"Org3MSP":.[1]}}}}}' config.json ./channel-artifacts/org3.json > modified_config.json 161 | ``` 162 | 163 | `jq -s`指定了格式,`.[0],.[1]`代表了第`0`,`1`个参数,命令执行的效果就是增加了和`org1`和`org2`平级的配置,然后将这个新的配置保存到文件`modified_config.json`中。我们可以使用`diff config.json modified_config.json`来进行对比。 164 | 165 | 接下来为了生成`channel`的配置更新文件,我们需要做下面的操作: 166 | 167 | - `config.json --> config.pb` 168 | - `modified_config.json --> modified_config.pb` 169 | - `modified_config.pb - config.pb --> org3_update.pb` 170 | 171 | 命令如下: 172 | 173 | ```bash 174 | # proto_encode 是将 json 格式编码成 pb 格式文件;config.json --> config.pb 175 | configtxlator proto_encode --input config.json --type common.Config --output config.pb 176 | 177 | # modified_config.json --> modified_config.pb 178 | configtxlator proto_encode --input modified_config.json --type common.Config --output modified_config.pb 179 | 180 | # compute_update 是比较两个pb格式文件的,计算出增量;modified_config.pb - config.pb --> org3_update.pb 181 | configtxlator compute_update --channel_id $CHANNEL_NAME --original config.pb --updated modified_config.pb --output org3_update.pb 182 | ``` 183 | 184 | 但是,`org3_update.pb`不能直接用来升级,需要再在它外面封装一层,但是,封装需要使用`JSON`来处理,具体封装过程的命令如下: 185 | 186 | ```bash 187 | # proto_decode 解码成 json 格式文件 188 | configtxlator proto_decode --input org3_update.pb --type common.ConfigUpdate | jq . > org3_update.json 189 | 190 | # 再封装一层 191 | echo '{"payload":{"header":{"channel_header":{"channel_id":"mychannel", "type":2}},"data":{"config_update":'$(cat org3_update.json)'}}}' | jq . > org3_update_in_envelope.json 192 | 193 | # 编码成pb格式文件 194 | configtxlator proto_encode --input org3_update_in_envelope.json --type common.Envelope --output org3_update_in_envelope.pb 195 | ``` 196 | 197 | 现在,生成的`org3_update_in_envelope.pb`文件就是用来升级的。 198 | 199 | ### 4.3 对更新`channel`配置进行签名 200 | 201 | 虽然我们现在生成了配置更新文件`org3_update_in_envelope.pb`,但是我们还不直接拿这个文件来升级,因为对于`Fabric`网络而言,更新`channel`配置是以一笔交易形式提交的。要完成这笔交易,将`org3`的配置成功更新,我们就必须需要权限认证。 202 | 203 | 通道到默认修改策略是`MOJORITY`,也就是需要多数`org`的`Admin`账号进行签名。也就是说,通道所有组织都需要对这个文件进行签名。现在启动的`Fabric`网络中只有两个`org`,所以只需要这个两个组织的签名就行。 204 | 205 | 由于`cli`中的环境变量设置的就是`org1`的,所以可以直接进行签名: 206 | 207 | ```bash 208 | peer channel signconfigtx -f org3_update_in_envelope.pb 209 | ``` 210 | 211 | 接下来,设置`org2`的环境变量,再次对文件进行签名: 212 | 213 | ```bash 214 | # 设置环境变量 215 | export CORE_PEER_LOCALMSPID="Org2MSP" 216 | 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 217 | export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp 218 | export CORE_PEER_ADDRESS=peer0.org2.example.com:9051 219 | 220 | # 对文件进行签名 221 | peer channel signconfigtx -f org3_update_in_envelope.pb 222 | ``` 223 | 224 | ### 4.4 发送更新`channel`配置的交易 225 | 226 | 所有组织管理员签名完成之后,我们就可以发送更新`channel`配置的交易了,使用如下命令: 227 | 228 | ```bash 229 | peer channel update -f org3_update_in_envelope.pb -c $CHANNEL_NAME -o orderer.example.com:7050 --tls --cafile $ORDERER_CA 230 | ``` 231 | 232 | 执行完成后,有如下输出: 233 | 234 | ```bash 235 | 2019-08-26 21:17:26.330 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized 236 | 2019-08-26 21:17:26.400 UTC [channelCmd] update -> INFO 002 Successfully submitted channel update 237 | ``` 238 | 239 | ### 4.5 配置选举以接收区块 240 | 241 | 新加入的组织节点只能使用创世区块启动,创世区块不包含他们已经加入到通道的配置,所以他们无法利用`gossip`验证他们从本组织其他`peer`节点发来到区块,直到他们接收到了他们加入通道的配置交易。所以新加入的节点必须配置他们从哪接收区块的`orderer`排序节点。 242 | 243 | 如果使用的静态`leader`模式,使用如下配置: 244 | 245 | ```bash 246 | CORE_PEER_GOSSIP_USELEADERELECTION=false 247 | CORE_PEER_GOSSIP_ORGLEADER=true 248 | ``` 249 | 250 | 如果使用的是动态`leader`模式,使用如下配置: 251 | 252 | ```bash 253 | CORE_PEER_GOSSIP_USELEADERELECTION=true 254 | CORE_PEER_GOSSIP_ORGLEADER=false 255 | ``` 256 | 257 | 这样新组织的`peer`都宣称自己是`leader`节点,加速了获取区块,等他们接收到它们自己的配置交易,就会只有`1`个`leader` 节点代表新组织。 258 | 259 | ## 5. 将新组织添加到通道中 260 | 261 | ### 5.1 使用`docker-compose`文件启动新组织的节点容器 262 | 263 | 我们在`first-network`文件夹下可以看到`docker-compose-org3.yaml`文件,这个文件里定义了新组织的节点容器配置等各种信息,具体内容如下: 264 | 265 | ```yaml 266 | version: '2' 267 | 268 | volumes: 269 | peer0.org3.example.com: 270 | peer1.org3.example.com: 271 | 272 | networks: # 网络定义 273 | byfn: 274 | 275 | services: 276 | 277 | peer0.org3.example.com: # peer0.org3.example.com 容器服务 278 | container_name: peer0.org3.example.com 279 | extends: 280 | file: base/peer-base.yaml 281 | service: peer-base 282 | environment: 283 | - CORE_PEER_ID=peer0.org3.example.com 284 | - CORE_PEER_ADDRESS=peer0.org3.example.com:11051 285 | - CORE_PEER_LISTENADDRESS=0.0.0.0:11051 286 | - CORE_PEER_CHAINCODEADDRESS=peer0.org3.example.com:11052 287 | - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:11052 288 | - CORE_PEER_GOSSIP_BOOTSTRAP=peer1.org3.example.com:12051 289 | - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org3.example.com:11051 290 | - CORE_PEER_LOCALMSPID=Org3MSP 291 | volumes: 292 | - /var/run/:/host/var/run/ 293 | - ./org3-artifacts/crypto-config/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/msp:/etc/hyperledger/fabric/msp 294 | - ./org3-artifacts/crypto-config/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls:/etc/hyperledger/fabric/tls 295 | - peer0.org3.example.com:/var/hyperledger/production 296 | ports: 297 | - 11051:11051 298 | networks: 299 | - byfn 300 | 301 | peer1.org3.example.com: # peer1.org3.example.com 容器服务 302 | container_name: peer1.org3.example.com 303 | extends: 304 | file: base/peer-base.yaml 305 | service: peer-base 306 | environment: 307 | - CORE_PEER_ID=peer1.org3.example.com 308 | - CORE_PEER_ADDRESS=peer1.org3.example.com:12051 309 | - CORE_PEER_LISTENADDRESS=0.0.0.0:12051 310 | - CORE_PEER_CHAINCODEADDRESS=peer1.org3.example.com:12052 311 | - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:12052 312 | - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org3.example.com:11051 313 | - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org3.example.com:12051 314 | - CORE_PEER_LOCALMSPID=Org3MSP 315 | volumes: 316 | - /var/run/:/host/var/run/ 317 | - ./org3-artifacts/crypto-config/peerOrganizations/org3.example.com/peers/peer1.org3.example.com/msp:/etc/hyperledger/fabric/msp 318 | - ./org3-artifacts/crypto-config/peerOrganizations/org3.example.com/peers/peer1.org3.example.com/tls:/etc/hyperledger/fabric/tls 319 | - peer1.org3.example.com:/var/hyperledger/production 320 | ports: 321 | - 12051:12051 322 | networks: 323 | - byfn 324 | 325 | 326 | Org3cli: # 定义一个新组织专用 cli 容器服务,用来将新组织加入通道等操作 327 | container_name: Org3cli 328 | image: hyperledger/fabric-tools:$IMAGE_TAG 329 | tty: true 330 | stdin_open: true 331 | environment: 332 | - GOPATH=/opt/gopath 333 | - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock 334 | - FABRIC_LOGGING_SPEC=INFO 335 | #- FABRIC_LOGGING_SPEC=DEBUG 336 | - CORE_PEER_ID=Org3cli 337 | - CORE_PEER_ADDRESS=peer0.org3.example.com:11051 338 | - CORE_PEER_LOCALMSPID=Org3MSP 339 | - CORE_PEER_TLS_ENABLED=true 340 | - 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 341 | - 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 342 | - 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 343 | - CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/users/Admin@org3.example.com/msp 344 | working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer 345 | command: /bin/bash 346 | volumes: 347 | - /var/run/:/host/var/run/ 348 | - ./../chaincode/:/opt/gopath/src/github.com/chaincode 349 | - ./org3-artifacts/crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ 350 | - ./crypto-config/peerOrganizations/org1.example.com:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com 351 | - ./crypto-config/peerOrganizations/org2.example.com:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com 352 | - ./scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/ 353 | depends_on: 354 | - peer0.org3.example.com 355 | - peer1.org3.example.com 356 | networks: 357 | - byfn 358 | ``` 359 | 360 | 我们使用如下命令来启动新组织中的节点容器和`cli`容器: 361 | 362 | ```bash 363 | docker-compose -f docker-compose-org3.yaml up -d 364 | ``` 365 | 366 | 启动成功后,我们使用`docker ps`命令可以看到,在后台多了三个容器在运行,分别是:`peer0.org3.example.com`、`peer1.org3.example.com`和`Org3cli`。 367 | 368 | ### 5.2 拉取`channel`的创世区块 369 | 370 | 接着我们进入`Org3cli`容器内,将新组织的两个节点加入到通道中来,首先是先设置环境变量,拉取通道的创世区块文件,具体命令如下: 371 | 372 | ```bash 373 | #进入 Org3cli 容器 374 | docker exec -it Org3cli bash 375 | 376 | # 设置环境变量 377 | 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 378 | export CHANNEL_NAME=mychannel 379 | 380 | # 拉取创世区块文件 381 | peer channel fetch 0 mychannel.block -o orderer.example.com:7050 -c $CHANNEL_NAME --tls --cafile $ORDERER_CA 382 | ``` 383 | 384 | 拉取结束后,会有如下输出: 385 | 386 | ```bash 387 | 2019-08-26 21:40:17.146 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized 388 | 2019-08-26 21:40:17.151 UTC [cli.common] readBlock -> INFO 002 Received block: 0 389 | ``` 390 | 391 | ### 5.3 新组织节点加入通道 392 | 393 | 最后我们需要将新组织的两个节点`peer0`和`peer1`加入到通道中去,具体命令如下: 394 | 395 | ```bash 396 | # 设置 peer0.org3.example.com 的环境变量 397 | export 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 398 | export CORE_PEER_ADDRESS=peer0.org3.example.com:11051 399 | 400 | # 将 peer0.org3.example.com 加入到通道中 401 | peer channel join -b mychannel.block 402 | 403 | # 设置 peer1.org3.example.com 的环境变量 404 | 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.crt 405 | export CORE_PEER_ADDRESS=peer1.org3.example.com:12051 406 | 407 | # 将 peer1.org3.example.com 加入到通道中 408 | peer channel join -b mychannel.block 409 | ``` 410 | 411 | 加入到通道中的操作都会返回如下输出结果: 412 | 413 | ```bash 414 | 2019-08-26 21:46:12.765 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized 415 | 2019-08-26 21:46:12.801 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel 416 | ``` 417 | 418 | ## 6. 升级链码和背书策略 419 | 420 | 新组织节点加入通道中了,我们之前链码就需要进行升级,因为背书策略需要升级,新组织需要参与到背书中来。 421 | 422 | 我们首先新建一个终端,执行如下命令进入`cli`容器: 423 | 424 | ```bash 425 | docker exec -it cli bash 426 | 427 | # 设置`Orderer CA`和`channel`的环境变量 428 | 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 429 | export CHANNEL_NAME=mychannel 430 | ``` 431 | 432 | 由于之前我们已经将新组织的各种证书拷贝到了网络的证书文件夹目录,这里可以执行下面的命令在`org3`上安装升级新链码: 433 | 434 | ```bash 435 | # 设置环境变量 436 | export CORE_PEER_LOCALMSPID="Org3MSP" 437 | export 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 438 | export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/users/Admin@org3.example.com/msp 439 | export CORE_PEER_ADDRESS=peer0.org3.example.com:11051 440 | 441 | # 升级链码 442 | peer chaincode install -n mycc -v 2.0 -p github.com/chaincode/chaincode_example02/go 443 | ``` 444 | 445 | 执行下面的命令在`org2`上安装升级新链码: 446 | 447 | ```bash 448 | # 设置环境变量 449 | export CORE_PEER_LOCALMSPID="Org2MSP" 450 | 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 451 | export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp 452 | export CORE_PEER_ADDRESS=peer0.org2.example.com:9051 453 | 454 | # 升级链码 455 | peer chaincode install -n mycc -v 2.0 -p github.com/chaincode/chaincode_example02/go 456 | ``` 457 | 458 | 执行下面的命令在`org1`上安装升级新链码: 459 | 460 | ```bash 461 | # 设置环境变量 462 | export CORE_PEER_LOCALMSPID="Org1MSP" 463 | 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 464 | export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp 465 | export CORE_PEER_ADDRESS=peer0.org1.example.com:7051 466 | 467 | # 升级链码 468 | peer chaincode install -n mycc -v 2.0 -p github.com/chaincode/chaincode_example02/go 469 | ``` 470 | 471 | 更新升级链码后,我们就需要升级背书策略,具体命令如下: 472 | 473 | ```bash 474 | # 这里背书策略设置为 AND,也就是说需要三个组织的所有节点都背书 475 | 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 "AND ('Org1MSP.peer','Org2MSP.peer','Org3MSP.peer')" 476 | ``` 477 | 478 | ## 7. 调用链码测试是否成功 479 | 480 | 链码升级安装成功后,我们就需要调用链码进行测试,我们将先环境切换到`org3`中来: 481 | 482 | ```bash 483 | export CORE_PEER_LOCALMSPID="Org3MSP" 484 | export 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 485 | export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/users/Admin@org3.example.com/msp 486 | export CORE_PEER_ADDRESS=peer0.org3.example.com:11051 487 | ``` 488 | 489 | 然后执行下面的命令,查询`a`账户余额: 490 | 491 | ```bash 492 | peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}' 493 | ``` 494 | 495 | 得到结果为`90` 496 | 497 | 接着,执行下面命令进行转账操作: 498 | 499 | ```bash 500 | 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 mychannel -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 --peerAddresses peer0.org3.example.com:11051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt -c '{"Args":["invoke","a","b","10"]}' 501 | ``` 502 | 503 | 这里我们会发现多了好多`--peerAddresses`和`--tlsRootCertFiles`参数,这些参数的设置就和之前设置的背书策略`AND`有关,如果我们背书策略设置为`OR`,就不用设置这些参数了。 504 | 505 | 转账成功后,我们再次执行命令,查询`a`账户的余额,得到结果为`80` 506 | 507 | ```bash 508 | peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}' 509 | ``` 510 | 511 | ## 8. 设置新组织的锚节点(可选) 512 | 513 | `org3`的节点能够与`org1`和`org2`的节点建立`gossip`连接,这是由于`org1`和`org2`在通道配置中定义了锚节点,同样,`org3`等新加入的组织为了能够让其他组织的新节点或其他新组织发现`org3`的节点,也必须配置锚节点。 514 | 515 | 这里更新锚节点的流程与启动网络更新锚节点的方式不太一样,与添加新组织的流程类似,具体如下。 516 | 517 | ### 8.1 拉取并转换最新的通道配置 518 | 519 | 我们使用如下命令先进入`org3cli`客户端容器: 520 | 521 | ```bash 522 | docker exec -it Org3cli bash 523 | 524 | # 设置环境变量 525 | 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 526 | export CHANNEL_NAME=mychannel 527 | ``` 528 | 529 | 使用下面的命令拉取最新的通道配置区块: 530 | 531 | ```bash 532 | peer channel fetch config config_block.pb -o orderer.example.com:7050 -c $CHANNEL_NAME --tls --cafile $ORDERER_CA 533 | ``` 534 | 535 | 获取配置区块之后,我们需要将其转换成`JSON`格式,就像之前添加新组织那样操作。转换时,我们需要删除更新`org3`不需要的所有头、元数据和签名,以便使用`jq`工具将锚节点信息加入进去: 536 | 537 | ```bash 538 | # 转换成 config.json 文件 539 | configtxlator proto_decode --input config_block.pb --type common.Block | jq .data.data[0].payload.data.config > config.json 540 | ``` 541 | 542 | ### 8.2 将锚节点信息加入到配置文件 543 | 544 | 使用`jq`工具,将要添加的`org3`锚节点信息添加到`config.json`文件中,并保存为`modified_anchor_config.json`文件: 545 | 546 | ```bash 547 | jq '.channel_group.groups.Application.groups.Org3MSP.values += {"AnchorPeers":{"mod_policy": "Admins","value":{"anchor_peers": [{"host": "peer0.org3.example.com","port": 11051}]},"version": "0"}}' config.json > modified_anchor_config.json 548 | ``` 549 | 550 | ### 8.3 计算更新差量并生成更新配置交易文件 551 | 552 | 接着,就是计算更新差量,再封装差量,生成配置更新交易文件,具体命令如下: 553 | 554 | ```bash 555 | # 转换 config.json 为 protobuf 格式 556 | configtxlator proto_encode --input config.json --type common.Config --output config.pb 557 | 558 | # 转换 modified_anchor_config.json 为 protobuf 格式 559 | configtxlator proto_encode --input modified_anchor_config.json --type common.Config --output modified_anchor_config.pb 560 | 561 | # 计算两个 protobuf 格式化配置之间的差值 562 | configtxlator compute_update --channel_id $CHANNEL_NAME --original config.pb --updated modified_anchor_config.pb --output anchor_update.pb 563 | 564 | # 再次使用 configtxlator 命令转换 anchor_update.pb 为 anchor_update.json 565 | configtxlator proto_decode --input anchor_update.pb --type common.ConfigUpdate | jq . > anchor_update.json 566 | 567 | # 将更新配置包装再封装一层,恢复先前剥离的标头,将其输出到 anchor_update_in_envelope.json 文件 568 | echo '{"payload":{"header":{"channel_header":{"channel_id":"mychannel", "type":2}},"data":{"config_update":'$(cat anchor_update.json)'}}}' | jq . > anchor_update_in_envelope.json 569 | 570 | # 现在重新整合了更新配置文件,我们需要将其转换为 protobuf,以便它可以正确签名并提交给orderer节点进行更新 571 | configtxlator proto_encode --input anchor_update_in_envelope.json --type common.Envelope --output anchor_update_in_envelope.pb 572 | ``` 573 | 574 | ### 8.4 提交更新配置交易 575 | 576 | 更新配置交易文件生成成功后,我们就可以使用如下命令来更新配置交易了: 577 | 578 | ```bash 579 | peer channel update -f anchor_update_in_envelope.pb -c $CHANNEL_NAME -o orderer.example.com:7050 --tls --cafile $ORDERER_CA 580 | ``` 581 | 582 | `orderer`节点接收配置更新请求后会使用新的配置新生成一个配置块,当其他组织的节点收到更新配置块时,将会处理这些配置更新。 583 | 584 | ### 8.5 检查节点日志,查看是否配置成功 585 | 586 | 我们可以使用如下命令查看一个节点的日志: 587 | 588 | ```bash 589 | docker logs -f peer0.org1.example.com 590 | ``` 591 | 592 | 可以看到,其中包含了如下内容,说明新组织的锚节点更新配置成功 593 | 594 | ```bash 595 | 2019-08-26 22:35:31.413 UTC [gossip.privdata] StoreBlock -> INFO 10f [mychannel] Received block [8] from buffer 596 | 2019-08-26 22:35:31.427 UTC [gossip.gossip] JoinChan -> INFO 110 Joining gossip network of channel mychannel with 3 organizations 597 | 2019-08-26 22:35:31.427 UTC [gossip.gossip] learnAnchorPeers -> INFO 111 Learning about the configured anchor peers of Org1MSP for channel mychannel : [{peer0.org1.example.com 7051}] 598 | 2019-08-26 22:35:31.428 UTC [gossip.gossip] learnAnchorPeers -> INFO 112 Learning about the configured anchor peers of Org2MSP for channel mychannel : [{peer0.org2.example.com 9051}] 599 | 2019-08-26 22:35:31.428 UTC [gossip.gossip] learnAnchorPeers -> INFO 113 Anchor peer with same endpoint, skipping connecting to myself 600 | 2019-08-26 22:35:31.428 UTC [gossip.gossip] learnAnchorPeers -> INFO 114 Learning about the configured anchor peers of Org3MSP for channel mychannel : [{peer0.org3.example.com 11051}] 601 | ``` 602 | 603 | ## 9. 参考 604 | 605 | - [Fabric学习笔记(八) - cli动态添加Org](https://segmentfault.com/a/1190000013521785) 606 | - [动态加入组织到 Channel](https://pinvondev.github.io/blog/BlockChain/2018/08/27/动态加入组织到-channel/%20Or%20/blog/BlockChain/动态加入组织到-channel/) 607 | - [区块链之Fabric(三)动态增删机构](http://wenchao.wang/2018/04/09/区块链之Fabric(三)动态增删机构/) 608 | - [Fabric组织动态加入](http://lessisbetter.site/2019/08/01/fabric-new-org/) 609 | - [官方文档:Adding an Org to a Channel](https://hyperledger-fabric.readthedocs.io/en/latest/channel_update_tutorial.html) 610 | -------------------------------------------------------------------------------- /Fabric中动态加入节点.md: -------------------------------------------------------------------------------- 1 | # Fabric 中动态加入节点 2 | 3 | >注:测试 `Fabric` 版本为 `1.4.2`;测试网络配置为`first-network` 4 | 5 | ## 1. 启动测试网络 6 | 7 | 首先我们需要进入`first-network`文件夹下,启动测试网络: 8 | 9 | ```bash 10 | # 进入 first-network 文件夹 11 | cd /opt/gopath/src/github.com/hyperledger/fabric/scripts/fabric-samples/first-network/ 12 | # 启动网络 13 | ./byfn.sh up 14 | ``` 15 | 16 | ## 2. 修改`crypto-config.yaml`文件 17 | 18 | 网络启动完成后,我们就可以来测试添加一个节点到网络中了,首先我们需要修改`crypto-config.yaml`文件,添加一个新节点,然后在为这个新节点使用`cryptogen`工具生成其组织关系证书,这只是在测试网络中这样做,如果是在生产环境中,将会使用`Fabric CA`来生成新节点的组织关系证书。 19 | 20 | 修改的`crypto-config.yaml`文件位置如下: 21 | 22 | ```yaml 23 | # --------------------------------------------------------------------------- 24 | # Org2: See "Org1" for full specification 25 | # --------------------------------------------------------------------------- 26 | - Name: Org2 27 | Domain: org2.example.com 28 | EnableNodeOUs: true 29 | Template: 30 | Count: 3 # 将此处改为 3,表示向组织2中新增加一个peer节点(peer2.org2.example.com) 31 | Users: 32 | Count: 1 33 | ``` 34 | 35 | ## 3. 生成新节点的组织关系证书 36 | 37 | 我们知道`crypto-config.yaml`配置文件是用来生成各种组织关系证书的,我们使用这个文件和`ctyptogen`就能为新节点生成他的组织关系证书,但是使用的参数不一样,具体命令如下: 38 | 39 | ```bash 40 | # 使用 extend 参数表示扩展原先的组织关系证书,也就是增加新的组织关系证书 41 | cryptogen extend --config=./crypto-config.yaml 42 | ``` 43 | 44 | 命令执行完后没有任何输出,我们可以使用命令`tree crypto-config -L 4`来查看`crypto-config`的目录结构,可以看到在`org2.example.com`的`peers`目录下多了一个`peer2.org2.example.com`目录。 45 | 46 | ## 4. 修改`docker-compose-base.yaml`文件 47 | 48 | 生成新节点的组织关系证书后,我们接下来需要的为新节点编写`YAML`启动配置文件,首先修改`docker-compose-base.yaml`文件,在最后新增新节点的配置,具体新增内容如下: 49 | 50 | ```yaml 51 | peer2.org2.example.com: 52 | container_name: peer2.org2.example.com 53 | extends: 54 | file: peer-base.yaml 55 | service: peer-base 56 | environment: 57 | - CORE_PEER_ID=peer2.org2.example.com 58 | - CORE_PEER_ADDRESS=peer2.org2.example.com:11051 59 | - CORE_PEER_LISTENADDRESS=0.0.0.0:11051 60 | - CORE_PEER_CHAINCODEADDRESS=peer2.org2.example.com:11052 61 | - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:11052 62 | - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer2.org2.example.com:11051 63 | - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org2.example.com:9051 64 | - CORE_PEER_LOCALMSPID=Org2MSP 65 | volumes: 66 | - /var/run/:/host/var/run/ 67 | - ../crypto-config/peerOrganizations/org2.example.com/peers/peer2.org2.example.com/msp:/etc/hyperledger/fabric/msp 68 | - ../crypto-config/peerOrganizations/org2.example.com/peers/peer2.org2.example.com/tls:/etc/hyperledger/fabric/tls 69 | - peer2.org2.example.com:/var/hyperledger/production 70 | ports: 71 | - 11051:7051 72 | ``` 73 | 74 | ## 5. 编辑新节点的`docker-compsoe`启动文件 75 | 76 | 下一步就是为新节点新建一个`docker-compose`启动文件,用来启动新节点,我们可以先使用如下命令新建一个`YAML`文件: 77 | 78 | ```bash 79 | vim docker-compose-peer2org2.yaml 80 | ``` 81 | 82 | 然后再在文件中添加如下配置内容: 83 | 84 | ```yaml 85 | version: '2' 86 | 87 | volumes: 88 | peer2.org2.example.com: 89 | 90 | networks: 91 | byfn: 92 | 93 | services: 94 | peer2.org2.example.com: 95 | extends: 96 | file: base/docker-compose-base.yaml 97 | service: peer2.org2.example.com 98 | container_name: peer2.org2.example.com 99 | networks: 100 | - byfn 101 | ``` 102 | 103 | ## 6. 启动新节点 104 | 105 | 证书文件和配置文件都准备就绪后,我们就可以启动该新节点了,启动命令如下: 106 | 107 | ```bash 108 | docker-compose -f docker-compose-peer2org2.yaml up -d 109 | ``` 110 | 111 | 执行完成后,我们使用`docker ps`命令会发现后台多了一个`peer2.org2.example.com`容器。 112 | 113 | ## 7. 进入`cli`客户端容器,将新节点加入通道 114 | 115 | 新节点已经启动了,但是它和我们第一步启动起来的网络没有任何关系,我们需要将新节点加入到我们的通道中来,具体步骤如下: 116 | 117 | 首先使用如下命令今天`cli`客户端容器: 118 | 119 | ```bash 120 | docker exec -it cli bash 121 | ``` 122 | 123 | 然后添加入下的环境变量,将客户端与`peer2.org2`连接: 124 | 125 | ```bash 126 | export CHANNEL_NAME=mychannel 127 | export CORE_PEER_LOCALMSPID="Org2MSP" 128 | export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer2.org2.example.com/tls/ca.crt 129 | export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp 130 | export CORE_PEER_ADDRESS=peer2.org2.example.com:11051 131 | 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 132 | ``` 133 | 134 | 从`orderer`节点上把通道配置`block`拉取下来: 135 | 136 | ```bash 137 | # 把创世区块拉取下来 138 | peer channel fetch oldest mychannel.block -c mychannel -o orderer.example.com:7050 --tls --cafile $ORDERER_CA 139 | # 相当于下面的命令,第 0 块就是创世区块 140 | peer channel fetch 0 mychannel.block -c mychannel -o orderer.example.com:7050 --tls --cafile $ORDERER_CA 141 | ``` 142 | 143 | 我们可以看到执行完成后,会有如下输出: 144 | 145 | ```bash 146 | 2019-08-26 17:59:26.909 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized 147 | 2019-08-26 17:59:26.912 UTC [cli.common] readBlock -> INFO 002 Received block: 0 148 | ``` 149 | 150 | 最后执行如下命令,将新节点`peer2.org2.example.com`加入到通道`mychannel`中来: 151 | 152 | ```bash 153 | peer channel join -b mychannel.block -o orderer.example.com:7050 154 | ``` 155 | 156 | 执行完成之后,会有如下输出: 157 | 158 | ```bash 159 | 2019-08-26 17:59:35.260 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized 160 | 2019-08-26 17:59:35.303 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel 161 | ``` 162 | 163 | ## 8. 在新节点上安装链码并调用链码 164 | 165 | 新节点加入测试网络后,我们就可以在该节点上安装链码,执行各种操作了。 166 | 167 | 首先执行下面命令安装链码: 168 | 169 | ```bash 170 | peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/chaincode_example02/go/ 171 | ``` 172 | 173 | 安装成功后,会有如下输出: 174 | 175 | ```bash 176 | 2019-08-26 18:03:53.009 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc 177 | 2019-08-26 18:03:53.010 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc 178 | 2019-08-26 18:03:53.489 UTC [chaincodeCmd] install -> INFO 003 Installed remotely response: 179 | ``` 180 | 181 | 然后执行下面命令,进行转账操作: 182 | 183 | ```bash 184 | 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 mychannel -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"]}' 185 | ``` 186 | 187 | 最后执行下面命令查询`a`账户余额,结果为`80`,说明新节点成功加入了网络,并且调用链码各种操作正在。 188 | 189 | ```bash 190 | peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}' 191 | ``` 192 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # fabricNotes 2 | 3 | ## 文档目录 4 | 5 | - [Fabric 1.4.2 的搭建文档](Fabric1.4.2的搭建文档.md) 6 | - [Fabric CA 的介绍及使用](Fabric-CA的介绍及使用.md) 7 | - [手动启动 Fabric 1.4.2 并解析全过程](手动启动Fabric1.4.2并解析全过程.md) 8 | - [使用 Chaincode 开发模式调试链码](使用Chaincode开发模式调试链码.md) 9 | - [Fabirc Explorer 搭建文档](Fabirc-Explorer搭建文档.md) 10 | - [在Fabric 1.4.2 中使用并分析 Raft 共识](在Fabric1.4.2中使用并分析Raft共识.md) 11 | - [Fabric 中动态加入节点](Fabric中动态加入节点.md) 12 | - [Fabric 中动态加入组织](Fabric中动态加入组织.md) 13 | -------------------------------------------------------------------------------- /fabricCA 批处理/ca_crypto-config.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "IntermediaCA1生成证书"; 4 | echo "1.生成example.com的msp"; 5 | echo "1)登记example.com"; 6 | cd /root/go/src/github.com/hyperledger/fabric-ca/bin/ca-server 7 | fabric-ca-client enroll -M crypto-config/ordererOrganizations/example.com/msp -u http://admin1:adminpw1@localhost:7055 --home fabric-ca-client 8 | echo "2)添加联盟成员" 9 | fabric-ca-client affiliation list -M crypto-config/ordererOrganizations/example.com/msp -u http://admin1:adminpw1@localhost:7055 --home fabric-ca-client 10 | fabric-ca-client affiliation remove --force org1 -M crypto-config/ordererOrganizations/example.com/msp -u http://admin1:adminpw1@localhost:7055 --home fabric-ca-client 11 | fabric-ca-client affiliation remove --force org2 -M crypto-config/ordererOrganizations/example.com/msp -u http://admin1:adminpw1@localhost:7055 --home fabric-ca-client 12 | fabric-ca-client affiliation add com -M crypto-config/ordererOrganizations/example.com/msp -u http://admin1:adminpw1@localhost:7055 --home fabric-ca-client 13 | fabric-ca-client affiliation add com.example -M crypto-config/ordererOrganizations/example.com/msp -u http://admin1:adminpw1@localhost:7055 --home fabric-ca-client 14 | echo "2.生成Admin@example.com的msp" 15 | echo "1)注册Admin@example.com" 16 | fabric-ca-client register --id.name Admin@example.com --id.type client --id.affiliation "com.example" --id.attrs '"hf.Registrar.Roles=client,orderer,peer,user","hf.Registrar.DelegateRoles=client,orderer,peer,user",hf.Registrar.Attributes=*,hf.GenCRL=true,hf.Revoker=true,hf.AffiliationMgr=true,hf.IntermediateCA=true,role=admin:ecert' --id.secret=123456 --csr.cn=example.com --csr.hosts=['example.com'] -M crypto-config/ordererOrganizations/example.com/msp -u http://admin1:adminpw1@localhost:7055 --home fabric-ca-client 17 | echo "2)登记Admin@example.com" 18 | fabric-ca-client enroll -u http://Admin@example.com:123456@localhost:7055 --csr.cn=example.com --csr.hosts=['example.com'] -M crypto-config/ordererOrganizations/example.com/users/Admin@example.com/msp --home fabric-ca-client 19 | echo "3)生成msp" 20 | path=fabric-ca-client/crypto-config/ordererOrganizations/example.com/users/Admin@example.com/msp/admincerts 21 | if [ ! -d $path ];then 22 | mkdir -p $path 23 | fi 24 | cp fabric-ca-client/crypto-config/ordererOrganizations/example.com/users/Admin@example.com/msp/signcerts/cert.pem fabric-ca-client/crypto-config/ordererOrganizations/example.com/users/Admin@example.com/msp/admincerts 25 | path=fabric-ca-client/crypto-config/ordererOrganizations/example.com/msp/admincerts 26 | if [ ! -d $path ];then 27 | mkdir -p $path 28 | fi 29 | cp fabric-ca-client/crypto-config/ordererOrganizations/example.com/users/Admin@example.com/msp/signcerts/cert.pem fabric-ca-client/crypto-config/ordererOrganizations/example.com/msp/admincerts 30 | echo "3.生成orderer0.example.com的msp" 31 | echo "1)注册orderer0.example.com" 32 | fabric-ca-client register --id.name orderer0.example.com --id.type orderer --id.affiliation "com.example" --id.attrs '"role=orderer",ecert=true' --id.secret=123456 --csr.cn=orderer0.example.com --csr.hosts=['orderer0.example.com'] -M crypto-config/ordererOrganizations/example.com/msp -u http://admin1:adminpw1@localhost:7055 --home fabric-ca-client 33 | echo "2)登记orderer0.example.com" 34 | fabric-ca-client enroll -u http://orderer0.example.com:123456@localhost:7055 --csr.cn=orderer0.example.com --csr.hosts=['orderer0.example.com'] -M crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/msp --home fabric-ca-client 35 | echo "3)生成msp" 36 | path=fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/admincerts 37 | if [ ! -d $path ];then 38 | mkdir -p $path 39 | fi 40 | cp fabric-ca-client/crypto-config/ordererOrganizations/example.com/users/Admin@example.com/msp/signcerts/cert.pem fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/admincerts 41 | echo "4.生成orderer1.example.com的msp" 42 | echo "1)注册orderer1.example.com" 43 | fabric-ca-client register --id.name orderer1.example.com --id.type orderer --id.affiliation "com.example" --id.attrs '"role=orderer",ecert=true' --id.secret=123456 --csr.cn=orderer1.example.com --csr.hosts=['orderer1.example.com'] -M crypto-config/ordererOrganizations/example.com/msp -u http://admin1:adminpw1@localhost:7055 --home fabric-ca-client 44 | echo "2)登记orderer1.example.com" 45 | fabric-ca-client enroll -u http://orderer1.example.com:123456@localhost:7055 --csr.cn=orderer1.example.com --csr.hosts=['orderer1.example.com'] -M crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/msp --home fabric-ca-client 46 | echo "3)生成msp" 47 | path=fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/msp/admincerts 48 | if [ ! -d $path ];then 49 | mkdir -p $path 50 | fi 51 | cp fabric-ca-client/crypto-config/ordererOrganizations/example.com/users/Admin@example.com/msp/signcerts/cert.pem fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/msp/admincerts 52 | echo "5.生成orderer2.example.com的msp" 53 | echo "1)注册orderer2.example.com" 54 | fabric-ca-client register --id.name orderer2.example.com --id.type orderer --id.affiliation "com.example" --id.attrs '"role=orderer",ecert=true' --id.secret=123456 --csr.cn=orderer2.example.com --csr.hosts=['orderer2.example.com'] -M crypto-config/ordererOrganizations/example.com/msp -u http://admin1:adminpw1@localhost:7055 --home fabric-ca-client 55 | echo "2)登记orderer2.example.com" 56 | fabric-ca-client enroll -u http://orderer2.example.com:123456@localhost:7055 --csr.cn=orderer2.example.com --csr.hosts=['orderer2.example.com'] -M crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/msp --home fabric-ca-client 57 | echo "3)生成msp" 58 | path=fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/msp/admincerts 59 | if [ ! -d $path ];then 60 | mkdir -p $path 61 | fi 62 | cp fabric-ca-client/crypto-config/ordererOrganizations/example.com/users/Admin@example.com/msp/signcerts/cert.pem fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/msp/admincerts 63 | 64 | echo "IntermediaCAtls1生成证书" 65 | echo "1.生成example.com的msp" 66 | echo "1)登记example.com" 67 | cd /root/go/src/github.com/hyperledger/fabric-ca/bin/ca-server 68 | fabric-ca-client enroll -M crypto-config/ordererOrganizations/example.com/tlstmp -u http://admin1:adminpw1@localhost:8055 --home fabric-ca-client 69 | echo "2)添加联盟成员" 70 | fabric-ca-client affiliation list -M crypto-config/ordererOrganizations/example.com/tlstmp -u http://admin1:adminpw1@localhost:8055 --home fabric-ca-client 71 | fabric-ca-client affiliation remove --force org1 -M crypto-config/ordererOrganizations/example.com/tlstmp -u http://admin1:adminpw1@localhost:8055 --home fabric-ca-client 72 | fabric-ca-client affiliation remove --force org2 -M crypto-config/ordererOrganizations/example.com/tlstmp -u http://admin1:adminpw1@localhost:8055 --home fabric-ca-client 73 | fabric-ca-client affiliation add com -M crypto-config/ordererOrganizations/example.com/tlstmp -u http://admin1:adminpw1@localhost:8055 --home fabric-ca-client 74 | fabric-ca-client affiliation add com.example -M crypto-config/ordererOrganizations/example.com/tlstmp -u http://admin1:adminpw1@localhost:8055 --home fabric-ca-client 75 | echo "2.生成Admin@example.com的tls" 76 | echo "1)注册Admin@example.com" 77 | fabric-ca-client register --id.name Admin@example.com --id.type client --id.affiliation "com.example" --id.attrs '"hf.Registrar.Roles=client,orderer,peer,user","hf.Registrar.DelegateRoles=client,orderer,peer,user",hf.Registrar.Attributes=*,hf.GenCRL=true,hf.Revoker=true,hf.AffiliationMgr=true,hf.IntermediateCA=true,role=admin:ecert' --id.secret=123456 --csr.cn=example.com --csr.hosts=['example.com'] -M crypto-config/ordererOrganizations/example.com/tlstmp -u http://admin1:adminpw1@localhost:8055 --home fabric-ca-client 78 | echo "2)登记Admin@example.com" 79 | fabric-ca-client enroll -d --enrollment.profile tls -u http://Admin@example.com:123456@localhost:8055 --csr.cn=example.com --csr.hosts=['example.com'] -M crypto-config/ordererOrganizations/example.com/users/Admin@example.com/tlstmp --home fabric-ca-client 80 | echo "3)生成tls" 81 | path=fabric-ca-client/crypto-config/ordererOrganizations/example.com/users/Admin@example.com/tls 82 | if [ ! -d $path ];then 83 | mkdir -p $path 84 | fi 85 | cp intermediacatls1/ca-chain.pem fabric-ca-client/crypto-config/ordererOrganizations/example.com/users/Admin@example.com/tls/ca.crt 86 | cp fabric-ca-client/crypto-config/ordererOrganizations/example.com/users/Admin@example.com/tlstmp/signcerts/cert.pem fabric-ca-client/crypto-config/ordererOrganizations/example.com/users/Admin@example.com/tls/client.crt 87 | path=fabric-ca-client/crypto-config/ordererOrganizations/example.com/users/Admin@example.com/tlstmp/keystore 88 | keystore=`ls -l $path | tail -n 1 | awk '{print $9}'` 89 | cp fabric-ca-client/crypto-config/ordererOrganizations/example.com/users/Admin@example.com/tlstmp/keystore/$keystore fabric-ca-client/crypto-config/ordererOrganizations/example.com/users/Admin@example.com/tls/client.key 90 | cp -r fabric-ca-client/crypto-config/ordererOrganizations/example.com/users/Admin@example.com/tlstmp/tlscacerts fabric-ca-client/crypto-config/ordererOrganizations/example.com/msp 91 | cp -r fabric-ca-client/crypto-config/ordererOrganizations/example.com/users/Admin@example.com/tlstmp/tlsintermediatecerts fabric-ca-client/crypto-config/ordererOrganizations/example.com/msp 92 | # rm -rf fabric-ca-client/crypto-config/ordererOrganizations/example.com/users/Admin@example.com/tlstmp 93 | echo "3.生成orderer0.example.com的tls" 94 | echo "1)注册orderer0.example.com" 95 | fabric-ca-client register --id.name orderer0.example.com --id.type orderer --id.affiliation "com.example" --id.attrs '"role=orderer",ecert=true' --id.secret=123456 --csr.cn=orderer0.example.com --csr.hosts=['orderer0.example.com'] -M crypto-config/ordererOrganizations/example.com/tlstmp -u http://admin1:adminpw1@localhost:8055 --home fabric-ca-client 96 | echo "2)登记orderer0.example.com" 97 | fabric-ca-client enroll -d --enrollment.profile tls -u http://orderer0.example.com:123456@localhost:8055 --csr.cn=orderer0.example.com --csr.hosts=['orderer0.example.com'] -M crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/tlstmp --home fabric-ca-client 98 | echo "3)生成tls" 99 | path=fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/tls 100 | if [ ! -d $path ];then 101 | mkdir -p $path 102 | fi 103 | cp intermediacatls1/ca-chain.pem fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/tls/ca.crt 104 | cp fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/tlstmp/signcerts/cert.pem fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/tls/server.crt 105 | path=fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/tlstmp/keystore 106 | keystore=`ls -l $path | tail -n 1 | awk '{print $9}'` 107 | cp fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/tlstmp/keystore/$keystore fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/tls/server.key 108 | cp -r fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/tlstmp/tlscacerts fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/msp 109 | cp -r fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/tlstmp/tlsintermediatecerts fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/msp 110 | # rm -rf fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/tlstmp 111 | echo "4.生成orderer1.example.com的tls" 112 | echo "1)注册orderer1.example.com" 113 | fabric-ca-client register --id.name orderer1.example.com --id.type orderer --id.affiliation "com.example" --id.attrs '"role=orderer",ecert=true' --id.secret=123456 --csr.cn=orderer1.example.com --csr.hosts=['orderer1.example.com'] -M crypto-config/ordererOrganizations/example.com/tlstmp -u http://admin1:adminpw1@localhost:8055 --home fabric-ca-client 114 | echo "2)登记orderer1.example.com" 115 | fabric-ca-client enroll -d --enrollment.profile tls -u http://orderer1.example.com:123456@localhost:8055 --csr.cn=orderer1.example.com --csr.hosts=['orderer1.example.com'] -M crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/tlstmp --home fabric-ca-client 116 | echo "3)生成tls" 117 | path=fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/tls 118 | if [ ! -d $path ];then 119 | mkdir -p $path 120 | fi 121 | cp intermediacatls1/ca-chain.pem fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/tls/ca.crt 122 | cp fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/tlstmp/signcerts/cert.pem fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/tls/server.crt 123 | path=fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/tlstmp/keystore 124 | keystore=`ls -l $path | tail -n 1 | awk '{print $9}'` 125 | cp fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/tlstmp/keystore/$keystore fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/tls/server.key 126 | cp -r fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/tlstmp/tlscacerts fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/msp 127 | cp -r fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/tlstmp/tlsintermediatecerts fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/msp 128 | # rm -rf fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/tlstmp 129 | echo "5.生成orderer2.example.com的tls" 130 | echo "1)注册orderer2.example.com" 131 | fabric-ca-client register --id.name orderer2.example.com --id.type orderer --id.affiliation "com.example" --id.attrs '"role=orderer",ecert=true' --id.secret=123456 --csr.cn=orderer2.example.com --csr.hosts=['orderer2.example.com'] -M crypto-config/ordererOrganizations/example.com/tlstmp -u http://admin1:adminpw1@localhost:8055 --home fabric-ca-client 132 | echo "2)登记orderer2.example.com" 133 | fabric-ca-client enroll -d --enrollment.profile tls -u http://orderer2.example.com:123456@localhost:8055 --csr.cn=orderer2.example.com --csr.hosts=['orderer2.example.com'] -M crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/tlstmp --home fabric-ca-client 134 | echo "3)生成tls" 135 | path=fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/tls 136 | if [ ! -d $path ];then 137 | mkdir -p $path 138 | fi 139 | cp intermediacatls1/ca-chain.pem fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/tls/ca.crt 140 | cp fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/tlstmp/signcerts/cert.pem fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/tls/server.crt 141 | path=fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/tlstmp/keystore 142 | keystore=`ls -l $path | tail -n 1 | awk '{print $9}'` 143 | cp fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/tlstmp/keystore/$keystore fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/tls/server.key 144 | cp -r fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/tlstmp/tlscacerts fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/msp 145 | cp -r fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/tlstmp/tlsintermediatecerts fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/msp 146 | # rm -rf fabric-ca-client/crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/tlstmp 147 | # rm -rf fabric-ca-client/crypto-config/ordererOrganizations/example.com/tlstmp 148 | 149 | echo "IntermediaCA2生成证书" 150 | echo "1.生成org1.example.com的msp" 151 | echo "1)登记org1.example.com" 152 | fabric-ca-client enroll --csr.cn=org1.example.com --csr.hosts=['org1.example.com'] -M crypto-config/peerOrganizations/org1.example.com/msp -u http://admin2:adminpw2@localhost:7056 --home fabric-ca-client 153 | path=fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/msp/config.yaml 154 | echo "NodeOUs:"&>$path 155 | echo " Enable: true"&>>$path 156 | echo " ClientOUIdentifier:"&>>$path 157 | echo " Certificate: intermediatecerts/localhost-7056.pem"&>>$path 158 | echo " OrganizationalUnitIdentifier: client"&>>$path 159 | echo " PeerOUIdentifier:"&>>$path 160 | echo " Certificate: intermediatecerts/localhost-7056.pem"&>>$path 161 | echo " OrganizationalUnitIdentifier: peer"&>>$path 162 | echo "2)添加联盟成员" 163 | fabric-ca-client affiliation list -M crypto-config/peerOrganizations/org1.example.com/msp -u http://admin2:adminpw2@localhost:7056 --home fabric-ca-client 164 | fabric-ca-client affiliation remove --force org1 -M crypto-config/peerOrganizations/org1.example.com/msp -u http://admin2:adminpw2@localhost:7056 --home fabric-ca-client 165 | fabric-ca-client affiliation remove --force org2 -M crypto-config/peerOrganizations/org1.example.com/msp -u http://admin2:adminpw2@localhost:7056 --home fabric-ca-client 166 | fabric-ca-client affiliation add com -M crypto-config/peerOrganizations/org1.example.com/msp -u http://admin2:adminpw2@localhost:7056 --home fabric-ca-client 167 | fabric-ca-client affiliation add com.example -M crypto-config/peerOrganizations/org1.example.com/msp -u http://admin2:adminpw2@localhost:7056 --home fabric-ca-client 168 | fabric-ca-client affiliation add com.example.org1 -M crypto-config/peerOrganizations/org1.example.com/msp -u http://admin2:adminpw2@localhost:7056 --home fabric-ca-client 169 | echo "2.生成Admin@example.com的msp" 170 | echo "1)注册Admin@example.com" 171 | fabric-ca-client register --id.name Admin@org1.example.com --id.type client --id.affiliation "com.example.org1" --id.attrs '"hf.Registrar.Roles=client,orderer,peer,user","hf.Registrar.DelegateRoles=client,orderer,peer,user",hf.Registrar.Attributes=*,hf.GenCRL=true,hf.Revoker=true,hf.AffiliationMgr=true,hf.IntermediateCA=true,role=admin:ecert' --id.secret=123456 --csr.cn=org1.example.com --csr.hosts=['org1.example.com'] -M crypto-config/peerOrganizations/org1.example.com/msp -u http://admin2:adminpw2@localhost:7056 --home fabric-ca-client 172 | echo "2)登记Admin@example.com" 173 | fabric-ca-client enroll -u http://Admin@org1.example.com:123456@localhost:7056 --csr.cn=org1.example.com --csr.hosts=['org1.example.com'] -M crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp --home fabric-ca-client 174 | echo "3)生成msp" 175 | path=fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/admincerts 176 | if [ ! -d $path ];then 177 | mkdir -p $path 178 | fi 179 | cp fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/signcerts/cert.pem fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/admincerts 180 | path=fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/msp/admincerts 181 | if [ ! -d $path ];then 182 | mkdir -p $path 183 | fi 184 | cp fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/signcerts/cert.pem fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/msp/admincerts 185 | echo "3.生成peer0.org1.example.com的msp" 186 | echo "1)注册peer0.org1.example.com" 187 | fabric-ca-client register --id.name peer0.org1.example.com --id.type peer --id.affiliation "com.example.org1" --id.attrs '"role=peer",ecert=true' --id.secret=123456 --csr.cn=peer0.org1.example.com --csr.hosts=['peer0.org1.example.com'] -M crypto-config/peerOrganizations/org1.example.com/msp -u http://admin2:adminpw2@localhost:7056 --home fabric-ca-client 188 | echo "2)登记peer0.org1.example.com" 189 | fabric-ca-client enroll -u http://peer0.org1.example.com:123456@localhost:7056 --csr.cn=peer0.org1.example.com --csr.hosts=['peer0.org1.example.com'] -M crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp --home fabric-ca-client 190 | echo "3)生成msp" 191 | path=fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp/admincerts 192 | if [ ! -d $path ];then 193 | mkdir -p $path 194 | fi 195 | cp fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/signcerts/cert.pem fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp/admincerts 196 | echo "4.生成peer1.org1.example.com的msp" 197 | echo "1)注册peer1.org1.example.com" 198 | fabric-ca-client register --id.name peer1.org1.example.com --id.type peer --id.affiliation "com.example.org1" --id.attrs '"role=peer",ecert=true' --id.secret=123456 --csr.cn=peer1.org1.example.com --csr.hosts=['peer1.org1.example.com'] -M crypto-config/peerOrganizations/org1.example.com/msp -u http://admin2:adminpw2@localhost:7056 --home fabric-ca-client 199 | echo "2)登记peer1.org1.example.com" 200 | fabric-ca-client enroll -u http://peer1.org1.example.com:123456@localhost:7056 --csr.cn=peer1.org1.example.com --csr.hosts=['peer1.org1.example.com'] -M crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/msp --home fabric-ca-client 201 | echo "3)生成msp" 202 | path=fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/msp/admincerts 203 | if [ ! -d $path ];then 204 | mkdir -p $path 205 | fi 206 | cp fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/signcerts/cert.pem fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/msp/admincerts 207 | 208 | echo "IntermediaCAtls2生成证书" 209 | echo "1.生成org1.example.com的tls" 210 | echo "1)登记org1.example.com" 211 | fabric-ca-client enroll --csr.cn=org1.example.com --csr.hosts=['org1.example.com'] -M crypto-config/peerOrganizations/org1.example.com/tlstmp -u http://admin2:adminpw2@localhost:8056 --home fabric-ca-client 212 | echo "2)添加联盟成员" 213 | fabric-ca-client affiliation list -M crypto-config/peerOrganizations/org1.example.com/tlstmp -u http://admin2:adminpw2@localhost:8056 --home fabric-ca-client 214 | fabric-ca-client affiliation remove --force org1 -M crypto-config/peerOrganizations/org1.example.com/tlstmp -u http://admin2:adminpw2@localhost:8056 --home fabric-ca-client 215 | fabric-ca-client affiliation remove --force org2 -M crypto-config/peerOrganizations/org1.example.com/tlstmp -u http://admin2:adminpw2@localhost:8056 --home fabric-ca-client 216 | fabric-ca-client affiliation add com -M crypto-config/peerOrganizations/org1.example.com/tlstmp -u http://admin2:adminpw2@localhost:8056 --home fabric-ca-client 217 | fabric-ca-client affiliation add com.example -M crypto-config/peerOrganizations/org1.example.com/tlstmp -u http://admin2:adminpw2@localhost:8056 --home fabric-ca-client 218 | fabric-ca-client affiliation add com.example.org1 -M crypto-config/peerOrganizations/org1.example.com/tlstmp -u http://admin2:adminpw2@localhost:8056 --home fabric-ca-client 219 | echo "2.生成Admin@example.com的tls" 220 | echo "1)注册Admin@example.com" 221 | fabric-ca-client register --id.name Admin@org1.example.com --id.type client --id.affiliation "com.example.org1" --id.attrs '"hf.Registrar.Roles=client,orderer,peer,user","hf.Registrar.DelegateRoles=client,orderer,peer,user",hf.Registrar.Attributes=*,hf.GenCRL=true,hf.Revoker=true,hf.AffiliationMgr=true,hf.IntermediateCA=true,role=admin:ecert' --id.secret=123456 --csr.cn=org1.example.com --csr.hosts=['org1.example.com'] -M crypto-config/peerOrganizations/org1.example.com/tlstmp -u http://admin2:adminpw2@localhost:8056 --home fabric-ca-client 222 | echo "2)登记Admin@example.com" 223 | fabric-ca-client enroll -d --enrollment.profile tls -u http://Admin@org1.example.com:123456@localhost:8056 --csr.cn=org1.example.com --csr.hosts=['org1.example.com'] -M crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/tlstmp --home fabric-ca-client 224 | echo "3)生成tls" 225 | path=fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/tls 226 | if [ ! -d $path ];then 227 | mkdir -p $path 228 | fi 229 | cp intermediacatls2/ca-chain.pem fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/tls/ca.crt 230 | cp fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/tlstmp/signcerts/cert.pem fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/tls/client.crt 231 | path=fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/tlstmp/keystore 232 | keystore=`ls -l $path | tail -n 1 | awk '{print $9}'` 233 | cp fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/tlstmp/keystore/$keystore fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/tls/client.key 234 | # rm -rf fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/tlstmp 235 | echo "3.生成peer0.org1.example.com的tls" 236 | echo "1)注册peer0.org1.example.com" 237 | fabric-ca-client register --id.name peer0.org1.example.com --id.type peer --id.affiliation "com.example.org1" --id.attrs '"role=peer",ecert=true' --id.secret=123456 --csr.cn=peer0.org1.example.com --csr.hosts=['peer0.org1.example.com'] -M crypto-config/peerOrganizations/org1.example.com/tlstmp -u http://admin2:adminpw2@localhost:8056 --home fabric-ca-client 238 | echo "2)登记peer0.org1.example.com" 239 | fabric-ca-client enroll -d --enrollment.profile tls -u http://peer0.org1.example.com:123456@localhost:8056 --csr.cn=peer0.org1.example.com --csr.hosts=['peer0.org1.example.com'] -M crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tlstmp --home fabric-ca-client 240 | echo "3)生成tls" 241 | path=fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls 242 | if [ ! -d $path ];then 243 | mkdir -p $path 244 | fi 245 | cp intermediacatls2/ca-chain.pem fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt 246 | cp fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tlstmp/signcerts/cert.pem fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt 247 | path=fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tlstmp/keystore 248 | keystore=`ls -l $path | tail -n 1 | awk '{print $9}'` 249 | cp fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tlstmp/keystore/$keystore fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.key 250 | # rm -rf fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tlstmp 251 | echo "4.生成peer1.org1.example.com的tls" 252 | echo "1)注册peer1.org1.example.com" 253 | fabric-ca-client register --id.name peer1.org1.example.com --id.type peer --id.affiliation "com.example.org1" --id.attrs '"role=peer",ecert=true' --id.secret=123456 --csr.cn=peer1.org1.example.com --csr.hosts=['peer1.org1.example.com'] -M crypto-config/peerOrganizations/org1.example.com/tlstmp -u http://admin2:adminpw2@localhost:8056 --home fabric-ca-client 254 | echo "2)登记peer1.org1.example.com" 255 | fabric-ca-client enroll -d --enrollment.profile tls -u http://peer1.org1.example.com:123456@localhost:8056 --csr.cn=peer1.org1.example.com --csr.hosts=['peer1.org1.example.com'] -M crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tlstmp --home fabric-ca-client 256 | echo "3)生成tls" 257 | path=fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls 258 | if [ ! -d $path ];then 259 | mkdir -p $path 260 | fi 261 | cp intermediacatls2/ca-chain.pem fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt 262 | cp fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tlstmp/signcerts/cert.pem fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/server.crt 263 | path=fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tlstmp/keystore 264 | keystore=`ls -l $path | tail -n 1 | awk '{print $9}'` 265 | cp fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tlstmp/keystore/$keystore fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/server.key 266 | # rm -rf fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tlstmp 267 | # rm -rf fabric-ca-client/crypto-config/peerOrganizations/org1.example.com/tlstmp 268 | 269 | echo "IntermediaCA3生成证书" 270 | echo "1.生成org2.example.com的msp" 271 | echo "1)登记org2.example.com" 272 | fabric-ca-client enroll --csr.cn=org2.example.com --csr.hosts=['org2.example.com'] -M crypto-config/peerOrganizations/org2.example.com/msp -u http://admin3:adminpw3@localhost:7057 --home fabric-ca-client 273 | path=fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/msp/config.yaml 274 | echo "NodeOUs:"&>$path 275 | echo " Enable: true"&>>$path 276 | echo " ClientOUIdentifier:"&>>$path 277 | echo " Certificate: intermediatecerts/localhost-7057.pem"&>>$path 278 | echo " OrganizationalUnitIdentifier: client"&>>$path 279 | echo " PeerOUIdentifier:"&>>$path 280 | echo " Certificate: intermediatecerts/localhost-7057.pem"&>>$path 281 | echo " OrganizationalUnitIdentifier: peer"&>>$path 282 | echo "2)添加联盟成员" 283 | fabric-ca-client affiliation list -M crypto-config/peerOrganizations/org2.example.com/msp -u http://admin3:adminpw3@localhost:7057 --home fabric-ca-client 284 | fabric-ca-client affiliation remove --force org1 -M crypto-config/peerOrganizations/org2.example.com/msp -u http://admin3:adminpw3@localhost:7057 --home fabric-ca-client 285 | fabric-ca-client affiliation remove --force org2 -M crypto-config/peerOrganizations/org2.example.com/msp -u http://admin3:adminpw3@localhost:7057 --home fabric-ca-client 286 | fabric-ca-client affiliation add com -M crypto-config/peerOrganizations/org2.example.com/msp -u http://admin3:adminpw3@localhost:7057 --home fabric-ca-client 287 | fabric-ca-client affiliation add com.example -M crypto-config/peerOrganizations/org2.example.com/msp -u http://admin3:adminpw3@localhost:7057 --home fabric-ca-client 288 | fabric-ca-client affiliation add com.example.org2 -M crypto-config/peerOrganizations/org2.example.com/msp -u http://admin3:adminpw3@localhost:7057 --home fabric-ca-client 289 | echo "2.生成Admin@example.com的msp" 290 | echo "1)注册Admin@example.com" 291 | fabric-ca-client register --id.name Admin@org2.example.com --id.type client --id.affiliation "com.example.org2" --id.attrs '"hf.Registrar.Roles=client,orderer,peer,user","hf.Registrar.DelegateRoles=client,orderer,peer,user",hf.Registrar.Attributes=*,hf.GenCRL=true,hf.Revoker=true,hf.AffiliationMgr=true,hf.IntermediateCA=true,role=admin:ecert' --id.secret=123456 --csr.cn=org2.example.com --csr.hosts=['org2.example.com'] -M crypto-config/peerOrganizations/org2.example.com/msp -u http://admin3:adminpw3@localhost:7057 --home fabric-ca-client 292 | echo "2)登记Admin@example.com" 293 | fabric-ca-client enroll -u http://Admin@org2.example.com:123456@localhost:7057 --csr.cn=org2.example.com --csr.hosts=['org2.example.com'] -M crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp --home fabric-ca-client 294 | echo "3)生成msp" 295 | path=fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/admincerts 296 | if [ ! -d $path ];then 297 | mkdir -p $path 298 | fi 299 | cp fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/signcerts/cert.pem fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/admincerts 300 | path=fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/msp/admincerts 301 | if [ ! -d $path ];then 302 | mkdir -p $path 303 | fi 304 | cp fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/signcerts/cert.pem fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/msp/admincerts 305 | echo "3.生成peer0.org2.example.com的msp" 306 | echo "1)注册peer0.org2.example.com" 307 | fabric-ca-client register --id.name peer0.org2.example.com --id.type peer --id.affiliation "com.example.org2" --id.attrs '"role=peer",ecert=true' --id.secret=123456 --csr.cn=peer0.org2.example.com --csr.hosts=['peer0.org2.example.com'] -M crypto-config/peerOrganizations/org2.example.com/msp -u http://admin3:adminpw3@localhost:7057 --home fabric-ca-client 308 | echo "2)登记peer0.org2.example.com" 309 | fabric-ca-client enroll -u http://peer0.org2.example.com:123456@localhost:7057 --csr.cn=peer0.org2.example.com --csr.hosts=['peer0.org2.example.com'] -M crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/msp --home fabric-ca-client 310 | echo "3)生成msp" 311 | path=fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/msp/admincerts 312 | if [ ! -d $path ];then 313 | mkdir -p $path 314 | fi 315 | cp fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/signcerts/cert.pem fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/msp/admincerts 316 | echo "4.生成peer1.org2.example.com的msp" 317 | echo "1)注册peer1.org2.example.com" 318 | fabric-ca-client register --id.name peer1.org2.example.com --id.type peer --id.affiliation "com.example.org2" --id.attrs '"role=peer",ecert=true' --id.secret=123456 --csr.cn=peer1.org2.example.com --csr.hosts=['peer1.org2.example.com'] -M crypto-config/peerOrganizations/org2.example.com/msp -u http://admin3:adminpw3@localhost:7057 --home fabric-ca-client 319 | echo "2)登记peer1.org2.example.com" 320 | fabric-ca-client enroll -u http://peer1.org2.example.com:123456@localhost:7057 --csr.cn=peer1.org2.example.com --csr.hosts=['peer1.org2.example.com'] -M crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/msp --home fabric-ca-client 321 | echo "3)生成msp" 322 | path=fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/msp/admincerts 323 | if [ ! -d $path ];then 324 | mkdir -p $path 325 | fi 326 | cp fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/signcerts/cert.pem fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/msp/admincerts 327 | 328 | echo "IntermediaCAtls3生成证书" 329 | echo "1.生成org2.example.com的tls" 330 | echo "1)登记org2.example.com" 331 | fabric-ca-client enroll --csr.cn=org2.example.com --csr.hosts=['org2.example.com'] -M crypto-config/peerOrganizations/org2.example.com/tlstmp -u http://admin3:adminpw3@localhost:8057 --home fabric-ca-client 332 | echo "2)添加联盟成员" 333 | fabric-ca-client affiliation list -M crypto-config/peerOrganizations/org2.example.com/tlstmp -u http://admin3:adminpw3@localhost:8057 --home fabric-ca-client 334 | fabric-ca-client affiliation remove --force org1 -M crypto-config/peerOrganizations/org2.example.com/tlstmp -u http://admin3:adminpw3@localhost:8057 --home fabric-ca-client 335 | fabric-ca-client affiliation remove --force org2 -M crypto-config/peerOrganizations/org2.example.com/tlstmp -u http://admin3:adminpw3@localhost:8057 --home fabric-ca-client 336 | fabric-ca-client affiliation add com -M crypto-config/peerOrganizations/org2.example.com/tlstmp -u http://admin3:adminpw3@localhost:8057 --home fabric-ca-client 337 | fabric-ca-client affiliation add com.example -M crypto-config/peerOrganizations/org2.example.com/tlstmp -u http://admin3:adminpw3@localhost:8057 --home fabric-ca-client 338 | fabric-ca-client affiliation add com.example.org2 -M crypto-config/peerOrganizations/org2.example.com/tlstmp -u http://admin3:adminpw3@localhost:8057 --home fabric-ca-client 339 | echo "2.生成Admin@example.com的tls" 340 | echo "1)注册Admin@example.com" 341 | fabric-ca-client register --id.name Admin@org2.example.com --id.type client --id.affiliation "com.example.org2" --id.attrs '"hf.Registrar.Roles=client,orderer,peer,user","hf.Registrar.DelegateRoles=client,orderer,peer,user",hf.Registrar.Attributes=*,hf.GenCRL=true,hf.Revoker=true,hf.AffiliationMgr=true,hf.IntermediateCA=true,role=admin:ecert' --id.secret=123456 --csr.cn=org2.example.com --csr.hosts=['org2.example.com'] -M crypto-config/peerOrganizations/org2.example.com/tlstmp -u http://admin3:adminpw3@localhost:8057 --home fabric-ca-client 342 | echo "2)登记Admin@example.com" 343 | fabric-ca-client enroll -d --enrollment.profile tls -u http://Admin@org2.example.com:123456@localhost:8057 --csr.cn=org2.example.com --csr.hosts=['org2.example.com'] -M crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/tlstmp --home fabric-ca-client 344 | echo "3)生成tls" 345 | path=fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/tls 346 | if [ ! -d $path ];then 347 | mkdir -p $path 348 | fi 349 | cp intermediacatls3/ca-chain.pem fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/tls/ca.crt 350 | cp fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/tlstmp/signcerts/cert.pem fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/tls/client.crt 351 | path=fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/tlstmp/keystore 352 | keystore=`ls -l $path | tail -n 1 | awk '{print $9}'` 353 | cp fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/tlstmp/keystore/$keystore fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/tls/client.key 354 | # rm -rf fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/tlstmp 355 | echo "3.生成peer0.org2.example.com的tls" 356 | echo "1)注册peer0.org2.example.com" 357 | fabric-ca-client register --id.name peer0.org2.example.com --id.type peer --id.affiliation "com.example.org2" --id.attrs '"role=peer",ecert=true' --id.secret=123456 --csr.cn=peer0.org2.example.com --csr.hosts=['peer0.org2.example.com'] -M crypto-config/peerOrganizations/org2.example.com/tlstmp -u http://admin3:adminpw3@localhost:8057 --home fabric-ca-client 358 | echo "2)登记peer0.org2.example.com" 359 | fabric-ca-client enroll -d --enrollment.profile tls -u http://peer0.org2.example.com:123456@localhost:8057 --csr.cn=peer0.org2.example.com --csr.hosts=['peer0.org2.example.com'] -M crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tlstmp --home fabric-ca-client 360 | echo "3)生成tls" 361 | path=fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls 362 | if [ ! -d $path ];then 363 | mkdir -p $path 364 | fi 365 | cp intermediacatls3/ca-chain.pem fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt 366 | cp fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tlstmp/signcerts/cert.pem fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/server.crt 367 | path=fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tlstmp/keystore 368 | keystore=`ls -l $path | tail -n 1 | awk '{print $9}'` 369 | cp fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tlstmp/keystore/$keystore fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/server.key 370 | # rm -rf fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tlstmp 371 | echo "4.生成peer1.org2.example.com的tls" 372 | echo "1)注册peer1.org2.example.com" 373 | fabric-ca-client register --id.name peer1.org2.example.com --id.type peer --id.affiliation "com.example.org2" --id.attrs '"role=peer",ecert=true' --id.secret=123456 --csr.cn=peer1.org2.example.com --csr.hosts=['peer1.org2.example.com'] -M crypto-config/peerOrganizations/org2.example.com/tlstmp -u http://admin3:adminpw3@localhost:8057 --home fabric-ca-client 374 | echo "2)登记peer1.org2.example.com" 375 | fabric-ca-client enroll -d --enrollment.profile tls -u http://peer1.org2.example.com:123456@localhost:8057 --csr.cn=peer1.org2.example.com --csr.hosts=['peer1.org2.example.com'] -M crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tlstmp --home fabric-ca-client 376 | echo "3)生成tls" 377 | path=fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls 378 | if [ ! -d $path ];then 379 | mkdir -p $path 380 | fi 381 | cp intermediacatls3/ca-chain.pem fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt 382 | cp fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tlstmp/signcerts/cert.pem fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/server.crt 383 | path=fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tlstmp/keystore 384 | keystore=`ls -l $path | tail -n 1 | awk '{print $9}'` 385 | cp fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tlstmp/keystore/$keystore fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/server.key 386 | # rm -rf fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tlstmp 387 | # rm -rf fabric-ca-client/crypto-config/peerOrganizations/org2.example.com/tlstmp 388 | -------------------------------------------------------------------------------- /fabricCA 批处理/ca_start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "RootCA启动"; 4 | cd $GOPATH/src/github.com/hyperledger/fabric-ca/bin 5 | mkdir ca-server 6 | # cp -f docker-rootca.yaml ./ca-server 7 | # cp -f docker-intermediaca1.yaml ./ca-server 8 | # cp -f docker-intermediaca2.yaml ./ca-server 9 | # cp -f docker-intermediaca3.yaml ./ca-server 10 | # cp -f docker-intermediacatls1.yaml ./ca-server 11 | # cp -f docker-intermediacatls2.yaml ./ca-server 12 | # cp -f docker-intermediacatls3.yaml ./ca-server 13 | 14 | cd ca-server 15 | fabric-ca-server init -b admin:adminpw --home ./rootca 16 | fabric_ver="1.4.0" 17 | sed -i "s/^version:.*$/version: $fabric_ver/g" ./rootca/fabric-ca-server-config.yaml 18 | # docker-compose -f docker-rootca.yaml up -d 19 | 20 | echo "IntermediaCA1启动"; 21 | fabric-ca-server init -b admin1:adminpw1 -u http://admin:adminpw@localhost:7054 --home ./intermediaca1 22 | fabric_ver="1.4.0" 23 | fabric_port="7055" 24 | sed -i "s/^version:.*$/version: $fabric_ver/g" ./intermediaca1/fabric-ca-server-config.yaml 25 | sed -i "s/^port:.*$/port: $fabric_port/g" ./intermediaca1/fabric-ca-server-config.yaml 26 | # docker-compose -f docker-intermediaca1.yaml up -d 27 | 28 | echo "IntermediaCAtls1启动"; 29 | fabric-ca-server init -b admin1:adminpw1 -u http://admin:adminpw@localhost:7054 --home ./intermediacatls1 30 | fabric_ver="1.4.0" 31 | fabric_port="8055" 32 | sed -i "s/^version:.*$/version: $fabric_ver/g" ./intermediacatls1/fabric-ca-server-config.yaml 33 | sed -i "s/^port:.*$/port: $fabric_port/g" ./intermediacatls1/fabric-ca-server-config.yaml 34 | # docker-compose -f docker-intermediacatls1.yaml up -d 35 | 36 | echo "IntermediaCA2启动"; 37 | fabric-ca-server init -b admin2:adminpw2 -u http://admin:adminpw@localhost:7054 --home ./intermediaca2 38 | fabric_ver="1.4.0" 39 | fabric_port="7056" 40 | sed -i "s/^version:.*$/version: $fabric_ver/g" ./intermediaca2/fabric-ca-server-config.yaml 41 | sed -i "s/^port:.*$/port: $fabric_port/g" ./intermediaca2/fabric-ca-server-config.yaml 42 | # docker-compose -f docker-intermediaca2.yaml up -d 43 | 44 | echo "IntermediaCAtls2启动"; 45 | fabric-ca-server init -b admin2:adminpw2 -u http://admin:adminpw@localhost:7054 --home ./intermediacatls2 46 | fabric_ver="1.4.0" 47 | fabric_port="8056" 48 | sed -i "s/^version:.*$/version: $fabric_ver/g" ./intermediacatls2/fabric-ca-server-config.yaml 49 | sed -i "s/^port:.*$/port: $fabric_port/g" ./intermediacatls2/fabric-ca-server-config.yaml 50 | # docker-compose -f docker-intermediacatls2.yaml up -d 51 | 52 | echo "IntermediaCA3启动"; 53 | fabric-ca-server init -b admin3:adminpw3 -u http://admin:adminpw@localhost:7054 --home ./intermediaca3 54 | fabric_ver="1.4.0" 55 | fabric_port="7057" 56 | sed -i "s/^version:.*$/version: $fabric_ver/g" ./intermediaca3/fabric-ca-server-config.yaml 57 | sed -i "s/^port:.*$/port: $fabric_port/g" ./intermediaca3/fabric-ca-server-config.yaml 58 | # docker-compose -f docker-intermediaca3.yaml up -d 59 | 60 | echo "IntermediaCAtls3启动"; 61 | fabric-ca-server init -b admin3:adminpw3 -u http://admin:adminpw@localhost:7054 --home ./intermediacatls3 62 | fabric_ver="1.4.0" 63 | fabric_port="8057" 64 | sed -i "s/^version:.*$/version: $fabric_ver/g" ./intermediacatls3/fabric-ca-server-config.yaml 65 | sed -i "s/^port:.*$/port: $fabric_port/g" ./intermediacatls3/fabric-ca-server-config.yaml 66 | # docker-compose -f docker-intermediacatls3.yaml up -d -------------------------------------------------------------------------------- /images/crypto-config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmego/fabricNotes/b7cbbff69cf2627a9732935080e94f07d36dc624/images/crypto-config.png -------------------------------------------------------------------------------- /images/fabric-ca.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmego/fabricNotes/b7cbbff69cf2627a9732935080e94f07d36dc624/images/fabric-ca.png -------------------------------------------------------------------------------- /images/raft1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmego/fabricNotes/b7cbbff69cf2627a9732935080e94f07d36dc624/images/raft1.png -------------------------------------------------------------------------------- /images/raftOSN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmego/fabricNotes/b7cbbff69cf2627a9732935080e94f07d36dc624/images/raftOSN.png -------------------------------------------------------------------------------- /使用Chaincode开发模式调试链码.md: -------------------------------------------------------------------------------- 1 | # 使用 Chaincode 开发模式调试链码 2 | 3 | `Fabirc` 提供了链码的开发模式,使链码在开发阶段可以进行非常快速的开发、构建、运行、调试。具体步骤如下: 4 | 5 | - 将已经编写好的`chaincode` 拷贝到 `/opt/gopath/src/github.com/hyperledger/fabric/scripts/fabric-samples/chaincode`目录中 6 | 7 | - 新建一个终端,启动 `chaincode-docker-devmode` 开发模式网络 8 | 9 | ```bash 10 | # 进入 chaincode-docker-devmode 目录 11 | cd /opt/gopath/src/github.com/hyperledger/fabric/scripts/fabric-samples/chaincode-docker-devmode 12 | # 启动网络 13 | docker-compose -f docker-compose-simple.yaml up 14 | ``` 15 | 16 | - 新建一个终端,编译链码,启动 `chaincode` 17 | 18 | ```bash 19 | # 进入 chaincode 容器 20 | docker exec -it chaincode bash 21 | cd abs # 进入链码目录 22 | go build # 编译链码 23 | 24 | CORE_PEER_ADDRESS=peer:7052 CORE_CHAINCODE_ID_NAME=absc:0 ./abs # 运行 chaincode 25 | ``` 26 | 27 | - 新建一个终端,安装,实例化,测试链码 28 | 29 | ```bash 30 | # 进入 chaincode 容器 31 | docker exec -it cli bash 32 | # 安装链码 33 | peer chaincode install -p chaincodedev/chaincode/sacc -n absc -v 1.0 34 | # 实例化链码 35 | peer chaincode instantiate -n absc -v 1.0 -c '{"Args":[]}' -C myc 36 | # 调用链码 37 | peer chaincode invoke -n absc -c '{"Args":["addowner", "owner01", "Owner","341412197607041122","1G1BL52P7TR115520"]}' -C myc 38 | # 调用链码 39 | peer chaincode invoke -n absc -c '{"Args":["getbyid", "owner01"]}' -C myc 40 | ``` 41 | -------------------------------------------------------------------------------- /手动启动Fabric1.4.2并解析全过程.md: -------------------------------------------------------------------------------- 1 | # 手动启动 Fabric 1.4.2 并解析全过程 2 | 3 | > **注**:以基于`docker`容器的方式启动;测试网络为 `first-network`,所以各种配置文件可以不用创建和修改即可使用;网络模式为 `solo` 4 | 5 | ## 1. 生成组织关系和身份证书 6 | 7 | Fabric 项目提供了 `cryptogen` 工具(基于 crypto 标准库)实现自动化生成各个组织、节点和用户成员的身份证书文件。这一过程需要依赖于`crypto-config.yaml`配置文件。 8 | 9 | ### 1.1 `cryptogen` 工具的使用 10 | 11 | 首先我们先来看一下`cryptogen`工具使用,这个工具之前我们已经安装在`$GOPATH/bin`目录下面了。我们使用命令`cryptogen --help`可以查看该工具主要有如下几个功能: 12 | 13 | ```bash 14 | generate [] # 根据配置文件生成各种证书文件 15 | showtemplate # 显示默认的配置文件 16 | version # 显示本工具的版本信息 17 | extend [] # 扩展现有的网络,根据配置文件生成需要扩展的证书文件 18 | ``` 19 | 20 | 运行`cryptogen generate --help`,我们可以看到,对于`generate`命令还有如下的参数设置: 21 | 22 | ```bash 23 | --output="crypto-config" # 指定生成的各种证书文件的输出存放目录,例如 crypto-config 24 | --config=CONFIG # 指定使用到的配置文件,例如 crypto-config.yaml 25 | ``` 26 | 27 | 通样,对于`extend`命令,我们也可以看到还有如下的参数可以设置: 28 | 29 | ```bash 30 | --input="crypto-config" # 指定已经存在的网络的证书文件存放位置 31 | --config=CONFIG # 指定使用到的扩展的配置文件 32 | ``` 33 | 34 | 工具的基本使用示例如下: 35 | 36 | ```bash 37 | cryptogen generate --config=./crypto-config.yaml --output ./crypto-config # 根据 crypto-config.yaml 配置文件在 crypto-config 目录下生成网络的各种证书文件 38 | cryptogen extend --input="crypto-config" --config=config.yaml # 根据 config.yaml 扩展配置文件在现有的网络证书文件目录 crypto-config 下生成扩展的证书文件 39 | ``` 40 | 41 | ### 1.2 `crypto-config.yaml`配置文件解析 42 | 43 | 一个基本的`crypto-config.yaml`配置文件如下所示,同时也是本文启动网络所使用到的配置文件 44 | 45 | ```yaml 46 | OrdererOrgs: # 定义 orderer 排序节点组织结构 47 | - Name: Orderer # Orderer 排序节点组织的名称 48 | Domain: example.com # orderer 排序节点组织的根域名 49 | Specs: # 根据 “{{.Hostname}}.{{.Domain}}” 格式的模板生成各个排序节点的访问域名和该排序节点各种证书文件 50 | - Hostname: orderer # 生成的访问域名为 orderer.example.com 51 | - Hostname: orderer2 # 生成的访问域名为 orderer2.example.com 52 | - Hostname: orderer3 # 生成的访问域名为 orderer3.example.com 53 | - Hostname: orderer4 # 生成的访问域名为 orderer4.example.com 54 | - Hostname: orderer5 # 生成的访问域名为 orderer5.example.com 55 | 56 | PeerOrgs: # 定义 Peer 节点组织结构 57 | - Name: Org1 # 第一个组织名称 Org1 58 | Domain: org1.example.com # 第一个组织的根域名 59 | EnableNodeOUs: true # 如果为 true,则在 msp 目录下就会生成 config.yaml 文件 60 | Template: # 模板,根据默认的规则在 Org1 下生成 "0 ~ Count-1" 个peer节点 61 | Count: 2 # 定义生成 2 个 peer 节点(peer0.org1.example.com,peer1.org1.example.com) 62 | Users: # 定义创建普通用户的数量,管理员用户(Admin@org1.example.com)会默认创建 63 | Count: 1 # 创建一个普通用户(User1@org1.example.com) 64 | 65 | - Name: Org2 # 第二个组织名称 Org2 66 | Domain: org2.example.com # 第一个组织的根域名 67 | EnableNodeOUs: true # 如果为 true,则在 msp 目录下就会生成 config.yaml 文件 68 | Template: # 模板,根据默认的规则在 Org2 下生成 "0 ~ Count-1" 个peer节点 69 | Count: 2 # 定义生成 2 个 peer 节点(peer0.org2.example.com,peer1.org2.example.com) 70 | Users: # 定义创建普通用户的数量,管理员用户(Admin@org2.example.com)会默认创建 71 | Count: 1 # 创建一个普通用户(User1@org2.example.com) 72 | ``` 73 | 74 | ### 1.3 生成组织关系和身份证书 75 | 76 | 使用上面的配置文件,通过下面的命令就可以为 Fabric 网络生成指定的拓扑结构的组织和身份证书文件,存放的文件夹目录为`crypto-config`。由于我们测试网络为`first-network`,所以我们可以切换到该目录下,直接运行下面命令即可: 77 | 78 | ```bash 79 | cd /opt/gopath/src/github.com/hyperledger/fabric/scripts/fabric-samples/first-network # 切换到 first-network 目录下 80 | cryptogen generate --config=./crypto-config.yaml --output ./crypto-config # 生成证书文件 81 | ``` 82 | 83 | 运行完成后,会有如下输出: 84 | 85 | ```bash 86 | [root@localhost first-network]# cryptogen generate --config=./crypto-config.yaml --output ./crypto-config 87 | org1.example.com 88 | org2.example.com 89 | ``` 90 | 91 | 此时,各种配置文件已经生成,我们可以到 `crypto-config`目录下查看生成的证书目录结构,具体的各种文件的解释说明可以到文档`《Fabric CA 的介绍及使用》`中查看,这里就不再赘述。 92 | 93 | ## 2 生成 Orderer 服务启动的创世区块和 Channel 等文件 94 | 95 | Orderer 节点在启动时,可以指定使用提前生成的初始区块文件作为系统通道的初始配置,创世区块中包括了 Ordering 服务的相关配置信息以及联盟信息。创世区块可以使用`configtxgen`工具生成。生成的过程需要依赖`configtx.yaml`配置文件。其中`configtx.yaml`配置文件定义了整个网络中相关配置和拓扑结构信息。 96 | 97 | ### 2.1 `configtxgen`工具的使用 98 | 99 | 这个工具同样的已经被我们安装到`$GOPATH/bin`目录下面了,我们使用`configtxgen --help`命令就能知道这个工具的使用方法及参数说明,该工具没有子命令,只有参数设置,具体解释如下: 100 | 101 | ```bash 102 | -asOrg # 以指定的组织身份执行更新配置交易(如更新锚节点)的生成,意味着在写集合中只包含了该组织有权限操作的键值 103 | -channelCreateTxBaseProfile # 指定排序系统通道当前状态的配置文件,以允许在通道创新交易(tx)生成期间修改非应用程序参数。仅与 'outputCreateChannelTx' 结合使用才有效 104 | -channelID # 指定在生成创世区块等文件时使用到的通道的 ID 105 | -configPath # 要使用的配置文件(configtx.yaml)的路径(如果已设置的话) 106 | -inspectBlock # 打印指定路径下区块(Block)中包含的配置[解析块] 107 | -inspectChannelCreateTx # 打印指定路径下交易(transaction )中包含的配置 [解析交易] 108 | -outputAnchorPeersUpdate # 创建更新锚节点的配置更新请求,需要同时使用 -asOrg 来指定组织身份 109 | -outputBlock # 指定生成的创世区块(genesis.block)的路径(如果已设置的话) 110 | -outputCreateChannelTx # 指定生成通道配置文件路径(如果已设置的话) 111 | -printOrg # 将组织的定义打印为json,(对于手动向组件添加组织非常有用) 112 | -profile # 指定配置模板,一般为 configtx.yaml 中的 Profiles 里边的配置项(默认为 SampleInsecureSolo) 113 | -version # 显示工具的版本信息 114 | ``` 115 | 116 | 该工具的使用示例如下: 117 | 118 | ```bash 119 | # 生成创世区块:指定配置为 TwoOrgsOrdererGenesis,通道ID为 byfn-sys-channel,生成的创世区块路径及名称为 ./channel-artifacts/genesis.block 120 | configtxgen -profile TwoOrgsOrdererGenesis -channelID byfn-sys-channel -outputBlock ./channel-artifacts/genesis.block 121 | # 创建通道:指定配置为 TwoOrgsChannel,通道ID为 mychannel,通道配置文件路径为 ./channel-artifacts/channel.tx 122 | configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID mychannel 123 | # 更新锚节点:指定配置为 TwoOrgsChannel,通道ID为 mychannel,更新锚节点的组织为Org1,MSP为 Org1MSP,指定锚节点更新配置输出文件路径为 ./channel-artifacts/Org1MSPanchors.tx 124 | configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID mychannel -asOrg Org1MSP 125 | ``` 126 | 127 | ### 2.2 `configtx.yaml`配置文件解析 128 | 129 | >`YAML`文件注释:`-`表示数组,`&`表示锚点,`*`表示引用,`<<`表示合并到当前数据 130 | 131 | ```yaml 132 | ################################################################################ 133 | # 组织部分: 134 | # - 本节定义了稍后将在配置中引用的不同组织的标识 135 | ################################################################################ 136 | Organizations: # 组织定义配置部分 137 | # 定义排序服务(Orderer)组织 138 | - &OrdererOrg # &OrdererOrg 这个用法类似指针,此处是被 Profiles 中的 - *OrdererOrg 所引用,下面还有很多类型的用例 139 | Name: OrdererOrg # Orderer 排序节点组织的名称 140 | ID: OrdererMSP # Orderer 排序节点组织的ID,也就是本地MSP的名称(这是引用组织的关键) 141 | MSPDir: crypto-config/ordererOrganizations/example.com/msp # Orderer 排序节点组织的 MSP 证书文件目录路径 142 | 143 | # 定义本层级的应用控制策略,对于排序节点(Orderer)的策略,其权威路径为:/Channel/// 144 | Policies: 145 | Readers: # 可读 146 | Type: Signature 147 | Rule: "OR('OrdererMSP.member')" 148 | Writers: # 可写 149 | Type: Signature 150 | Rule: "OR('OrdererMSP.member')" 151 | Admins: # 管理员 admin 152 | Type: Signature 153 | Rule: "OR('OrdererMSP.admin')" 154 | 155 | - &Org1 # 定义组织1(Org1) 156 | Name: Org1MSP # 组织1(Org1) 的名称 157 | ID: Org1MSP # 组织1(Org1) 的ID,也就是 localMSP 的名称 158 | MSPDir: crypto-config/peerOrganizations/org1.example.com/msp # 组织1(Org1)的 MSP 证书文件目录路径 159 | 160 | # 定义本层级的应用控制策略,对于组织1(Org1)的策略,其权威路径为:/Channel/// 161 | Policies: 162 | Readers: # 可读 163 | Type: Signature 164 | Rule: "OR('Org1MSP.admin', 'Org1MSP.peer', 'Org1MSP.client')" 165 | Writers: # 可写 166 | Type: Signature 167 | Rule: "OR('Org1MSP.admin', 'Org1MSP.client')" 168 | Admins: # 管理员 admin 169 | Type: Signature 170 | Rule: "OR('Org1MSP.admin')" 171 | 172 | # 定义组织1的锚节点,用于跨组织进行 Gossip 通信 173 | AnchorPeers: 174 | - Host: peer0.org1.example.com # 锚节点的主机名(域名) 175 | Port: 7051 # 锚节点的端口号 176 | 177 | - &Org2 # 定义组织2(Org2) 178 | Name: Org2MSP # 组织2(Org2) 的名称 179 | ID: Org2MSP # 组织2(Org2) 的ID,也就是 localMSP 的名称 180 | MSPDir: crypto-config/peerOrganizations/org2.example.com/msp # 组织2(Org2)的 MSP 证书文件目录路径 181 | 182 | # 定义本层级的应用控制策略,对于组织2(Org2)的策略,其权威路径为:/Channel/// 183 | Policies: 184 | Readers: # 可读 185 | Type: Signature 186 | Rule: "OR('Org2MSP.admin', 'Org2MSP.peer', 'Org2MSP.client')" 187 | Writers: # 可写 188 | Type: Signature 189 | Rule: "OR('Org2MSP.admin', 'Org2MSP.client')" 190 | Admins: # 管理员 admin 191 | Type: Signature 192 | Rule: "OR('Org2MSP.admin')" 193 | 194 | # 定义组织2的锚节点,用于跨组织进行 Gossip 通信 195 | AnchorPeers: 196 | - Host: peer0.org2.example.com # 锚节点的主机名(域名) 197 | Port: 9051 # 锚节点的端口号 198 | 199 | ################################################################################ 200 | # 201 | # Capabilities 部分(这是在 v1.1.0 版本之后提出来的,不能用于在更早的版本上面) 202 | # - 本节定义了 fabric 网络的功能,这是 v1.1.0中一个新概念,不应该在 v1.0.x 的 peer 和 203 | # orderer 中使用,Capabilities 定义了存在于结构二进制文件中的功能,以便该二进制文件安全的 204 | # 参与网络,如果添加新的 MSP 类型,则较新的二进制文件可能会识别并验证此类型的签名,而没有此 205 | # 支持的旧二进制文件将无法验证这些事务,这可能导致具有不同世界状态的不同版本的结构二进制文件。 206 | # 相反,为通道定义功能(Capabilities)会通知那些没有此功能的二进制文件,他们必须在升级之前 207 | # 停止处理事务,对于v1.0.x,如果定义了任何功能(Capabilities)[包括关闭所有的功能配置], 208 | # 那么v1.0.1 的 peer 会主动崩溃 209 | ################################################################################ 210 | Capabilities: 211 | # 通道功能(Capabilities)适用于 orderer 节点和 peer 节点,并且必须得到两者的支持 212 | # 将功能设置为 true 以要求它 213 | Channel: &ChannelCapabilities 214 | # 通道(Channel)的 v1.4.2 是一个行为标记,已被确定为所有在v1.4,2版本运行的 orderers 和 peers 215 | # 但与先前版本的 orderers 和 peers 不兼容 216 | V1_4_2: true 217 | 218 | # Orderer功能(Capabilities)仅适用于排序节点,可以安全地与之前版本的 peers 一起使用 219 | # 将功能设置为 true 以要求它 220 | Orderer: &OrdererCapabilities 221 | # Orderer的 v1.4.2 是一个行为标记,已被确认为所有在 v1.4.2 版本运行的 orderers 所需的行为标志,但与之前版本的orderers 不兼容 222 | # 在启用 v1.4.2 版本的orderer功能之前,请确保通道上所有的排序节点(orderers)都为v1.4.2或更高版本。 223 | V1_4_2: true 224 | 225 | # 应用程序(Application)仅适用于 peer 节点网络,并且可以安全地与之前版本的 orderer 节点一起使用 226 | # 将功能的值设置为 true 以使其需要 227 | Application: &ApplicationCapabilities 228 | # 应用程序(Application)的 v1.4.2 版本启用了 Fabric 1.4.2 的新的非向后兼容功能和修复 229 | V1_4_2: true 230 | # 应用程序(Application)的 v1.3 版本启用了 Fabric 1.3 的新的非向后兼容功能和修复 231 | V1_3: false 232 | # 应用程序(Application)的 v1.2 版本启用了 Fabric 1.2 的新的非向后兼容功能和修复(如果设置了更高版本的功能,则无需设置此功能) 233 | V1_2: false 234 | # 应用程序(Application)的 v1.1 版本启用了 Fabric 1.1 的新的非向后兼容功能和修复(如果设置了更高版本的功能,则无需设置此功能) 235 | V1_1: false 236 | 237 | ################################################################################ 238 | # 应用程序(Application)部分 239 | # - 这个部分定义了配置事务或创世区块应用相关的参数设置的值 240 | ################################################################################ 241 | Application: &ApplicationDefaults 242 | # Organizations 是在网络的应用程序端定义为参与者的组织列表 243 | Organizations: 244 | 245 | # 定义本层级的应用控制策略,对于应用程序(application)策略,其权威路径为 /Channel/Application/ 246 | Policies: 247 | Readers: 248 | Type: ImplicitMeta 249 | Rule: "ANY Readers" 250 | Writers: 251 | Type: ImplicitMeta 252 | Rule: "ANY Writers" 253 | Admins: 254 | Type: ImplicitMeta 255 | Rule: "MAJORITY Admins" 256 | 257 | # 指定功能能力(Capabilities)为上面定义的 ApplicationCapabilities 258 | Capabilities: 259 | <<: *ApplicationCapabilities 260 | 261 | ################################################################################ 262 | # Orderer 节点部分 263 | # - 本节定义了要为orderer节点的配置事务或创世区块的相关参数设置的值 264 | ################################################################################ 265 | Orderer: &OrdererDefaults 266 | # 要启动的 Orderer 节点的共识类型,现在可以选的是 solo,kafka,etcdraft 267 | OrdererType: solo # 这里使用的是 solo 模式 268 | # orderer 节点的服务地址,如果是集群,需要设置多个地址 269 | Addresses: 270 | - orderer.example.com:7050 271 | #- orderer.example2.com:8050 272 | #- orderer.example3.com:9050 273 | #- orderer.example4.com:10050 274 | #- orderer.example5.com:11050 275 | 276 | # 区块打包的最大超时时间(到了该时间就要打包区块) 277 | BatchTimeout: 2s 278 | 279 | # 区块打包的最大包含交易数 280 | BatchSize: 281 | # 一个区块里最大的交易数(最大到了该数量就要打包区块) 282 | MaxMessageCount: 10 283 | # 一个区块的最大字节数(任何时候都不能超过,最大到了该大小就要打包区块) 284 | AbsoluteMaxBytes: 99 MB 285 | # 一个区块的建议字节数,如果一个交易消息的大小超过了该值,就会被放到一个更大的区块中去 286 | PreferredMaxBytes: 512 KB 287 | 288 | # kafka 共识的相关配置设置 289 | Kafka: 290 | # kafka 的 brokens 服务地址,允许有多个 291 | # 注意: 使用IP:端口(IP:port)表示法 292 | Brokers: 293 | - 127.0.0.1:9092 294 | 295 | # 参与维护 Orderer 排序节点的组织,默认为空 296 | Organizations: 297 | 298 | # 定义本层级的应用控制策略,对于 Orderer 策略,其权威路径为:/Channel/Orderer/ 299 | Policies: 300 | Readers: 301 | Type: ImplicitMeta 302 | Rule: "ANY Readers" 303 | Writers: 304 | Type: ImplicitMeta 305 | Rule: "ANY Writers" 306 | Admins: 307 | Type: ImplicitMeta 308 | Rule: "MAJORITY Admins" 309 | # BlockValidation 配置项指定了哪些签名必须包含在区块中,以便对 peer 节点进行验证 310 | BlockValidation: 311 | Type: ImplicitMeta 312 | Rule: "ANY Writers" 313 | 314 | ################################################################################ 315 | # Channel 通道部分 316 | # - 本节定义要写入创世区块或配置交易的通道参数 317 | ################################################################################ 318 | Channel: &ChannelDefaults 319 | 320 | # 定义本层级的应用控制策略,对于 Channel 策略,其权威路径为: /Channel/ 321 | Policies: 322 | # 谁可以调用(invoke)交付区块(Deliver)的 API 323 | Readers: 324 | Type: ImplicitMeta 325 | Rule: "ANY Readers" 326 | # 谁可以调用(invoke)广播区块(Broadcast)的 API 327 | Writers: 328 | Type: ImplicitMeta 329 | Rule: "ANY Writers" 330 | # 默认情况下,谁可以修改此配置级别的元素 331 | Admins: 332 | Type: ImplicitMeta 333 | Rule: "MAJORITY Admins" 334 | 335 | # Capabilities 配置描述应用层级的能力需求,这里直接引用前面 Capabilities 配置段中的 ChannelCapabilities 配置项 336 | Capabilities: 337 | <<: *ChannelCapabilities 338 | 339 | ################################################################################ 340 | # Profile 部分配置 341 | # - 本节定义用于 configtxgen 工具的配置入口,包含委员会(Consortiums)的配置入口。 Profile 342 | # 部分的配置主要是引入上面五个部分的配置参数。 configtxen 工具通过调用 Profile 参数,可以 343 | # 实现生成特点的区块文件 344 | ################################################################################ 345 | Profiles: 346 | 347 | # 创建 Orderer 创世区块的相关参数配置(Solo共识),包含 orderer 和联盟(Consortiums)两个部分 348 | TwoOrgsOrdererGenesis: 349 | # 合并引入 Channel 部分的配置 350 | <<: *ChannelDefaults 351 | # 合并引入 Orderer 部分的配置 352 | Orderer: 353 | <<: *OrdererDefaults 354 | # 指定组织 配置为 OrdererOrg 355 | Organizations: 356 | - *OrdererOrg 357 | # 指定能力要求为 OrdererCapabilities 358 | Capabilities: 359 | <<: *OrdererCapabilities 360 | #定义 Orderer 所服务的联盟列表 361 | Consortiums: 362 | # 指定联盟列表名称为 SampleConsortium 363 | SampleConsortium: 364 | # 定义联盟中的组织,这里为 Org1,Org2 365 | Organizations: 366 | - *Org1 367 | - *Org2 368 | 369 | # 创建应用通道(Channel)的配置 370 | TwoOrgsChannel: 371 | # 应用通道关联的联盟列表为 SampleConsortium 372 | Consortium: SampleConsortium 373 | # 合并引入通道(Channel)配置 374 | <<: *ChannelDefaults 375 | # 合并引入 Application 的相关配置 376 | Application: 377 | <<: *ApplicationDefaults 378 | # 初始加入通道的组织,这里为 Org1,Org2 379 | Organizations: 380 | - *Org1 381 | - *Org2 382 | # 指定能力要求为 ApplicationCapabilities 383 | Capabilities: 384 | <<: *ApplicationCapabilities 385 | 386 | # 创建 Orderer 创世区块的相关参数配置(kafka 共识) 387 | # 生成创世区块时,configtxgen 指定的 -profile 参数为 SampleDevModeKafka 388 | SampleDevModeKafka: 389 | <<: *ChannelDefaults 390 | Capabilities: 391 | <<: *ChannelCapabilities 392 | Orderer: 393 | <<: *OrdererDefaults 394 | OrdererType: kafka 395 | Kafka: 396 | Brokers: 397 | - kafka.example.com:9092 398 | 399 | Organizations: 400 | - *OrdererOrg 401 | Capabilities: 402 | <<: *OrdererCapabilities 403 | Application: 404 | <<: *ApplicationDefaults 405 | Organizations: 406 | - <<: *OrdererOrg 407 | Consortiums: 408 | SampleConsortium: 409 | Organizations: 410 | - *Org1 411 | - *Org2 412 | 413 | # 创建 Orderer 创世区块的相关参数配置(raft 共识) 414 | # 生成创世区块时,configtxgen 指定的 -profile 参数为 SampleMultiNodeEtcdRaft 415 | SampleMultiNodeEtcdRaft: 416 | <<: *ChannelDefaults 417 | Capabilities: 418 | <<: *ChannelCapabilities 419 | Orderer: 420 | <<: *OrdererDefaults 421 | OrdererType: etcdraft 422 | EtcdRaft: 423 | # 指定参与共识的 orderer 节点地址,端口,和证书文件 424 | Consenters: 425 | - Host: orderer.example.com 426 | Port: 7050 427 | ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt 428 | ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt 429 | - Host: orderer2.example.com 430 | Port: 7050 431 | ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/tls/server.crt 432 | ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/tls/server.crt 433 | - Host: orderer3.example.com 434 | Port: 7050 435 | ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer3.example.com/tls/server.crt 436 | ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer3.example.com/tls/server.crt 437 | - Host: orderer4.example.com 438 | Port: 7050 439 | ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer4.example.com/tls/server.crt 440 | ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer4.example.com/tls/server.crt 441 | - Host: orderer5.example.com 442 | Port: 7050 443 | ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer5.example.com/tls/server.crt 444 | ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer5.example.com/tls/server.crt 445 | Addresses: 446 | - orderer.example.com:7050 447 | - orderer2.example.com:7050 448 | - orderer3.example.com:7050 449 | - orderer4.example.com:7050 450 | - orderer5.example.com:7050 451 | 452 | Organizations: 453 | - *OrdererOrg 454 | Capabilities: 455 | <<: *OrdererCapabilities 456 | Application: 457 | <<: *ApplicationDefaults 458 | Organizations: 459 | - <<: *OrdererOrg 460 | Consortiums: 461 | SampleConsortium: 462 | Organizations: 463 | - *Org1 464 | - *Org2 465 | ``` 466 | 467 | ### 2.3 生成 Orderer 服务启动的创世区块和 Channel 等文件 468 | 469 | #### 2.3.1 生成创世区块 470 | 471 | 通过如下命令指定使用`configtx.yaml`文件中定义的`TwoOrgsOrdererGenesis`模板,来生成 Orderer 服务系统通道的初始创世区块文件。 472 | 473 | ```bash 474 | cd /opt/gopath/src/github.com/hyperledger/fabric/scripts/fabric-samples/first-network # 切换到 first-network 目录下 475 | 476 | # -profile 指定配置模板为 TwoOrgsOrdererGenesis;-outputBlock 指定生成的创世区块文件路径;-channelID 指定系统通道名称为 byfn-sys-channel 477 | configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block -channelID byfn-sys-channel 478 | ``` 479 | 480 | 运行完成后,会有如下输出,可以看出 Orderer 共识使用的是 solo 481 | 482 | ```bash 483 | 2019-07-25 21:38:20.012 EDT [common.tools.configtxgen] main -> INFO 002 Loading configuration 484 | 2019-07-25 21:38:20.080 EDT [common.tools.configtxgen.localconfig] completeInitialization -> INFO 003 orderer type: solo 485 | 2019-07-25 21:38:20.080 EDT [common.tools.configtxgen.localconfig] Load -> INFO 004 Loaded configuration: /opt/gopath/src/github.com/hyperledger/fabric/scripts/fabric-samples/first-network/configtx.yaml 486 | 2019-07-25 21:38:20.147 EDT [common.tools.configtxgen.localconfig] completeInitialization -> INFO 005 orderer type: solo 487 | 2019-07-25 21:38:20.147 EDT [common.tools.configtxgen.localconfig] LoadTopLevel -> INFO 006 Loaded configuration: /opt/gopath/src/github.com/hyperledger/fabric/scripts/fabric-samples/first-network/configtx.yaml 488 | 2019-07-25 21:38:20.159 EDT [common.tools.configtxgen] doOutputBlock -> INFO 007 Generating genesis block 489 | 2019-07-25 21:38:20.159 EDT [common.tools.configtxgen] doOutputBlock -> INFO 008 Writing genesis block 490 | ``` 491 | 492 | (*) 生成的文件位于目录`channel-artifacts`下,我们可以通过下面的命令将`Block`详细内容导入到`json`文件中方便查看: 493 | 494 | ```bash 495 | # -inspectBlock 指定打印配置的块路径为 channel-artifacts/genesis.block 496 | configtxgen -inspectBlock channel-artifacts/genesis.block > channel-artifacts/genesis.block.json 497 | ``` 498 | 499 | #### 2.3.2 生成新建应用通道的配置交易 500 | 501 | 接下来我们需要使用如下命令新建应用通道(Channel): 502 | 503 | ```bash 504 | # -profile 指定配置模板为 TwoOrgsChannel;-outputCreateChannelTx 指定生成的通道文件路径;-channelID 指定通道名称为 mychannel 505 | configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID mychannel 506 | ``` 507 | 508 | 运行完成后,会有如下输出: 509 | 510 | ```bash 511 | 2019-07-25 22:04:30.305 EDT [common.tools.configtxgen] main -> INFO 001 Loading configuration 512 | 2019-07-25 22:04:30.376 EDT [common.tools.configtxgen.localconfig] Load -> INFO 002 Loaded configuration: /opt/gopath/src/github.com/hyperledger/fabric/scripts/fabric-samples/first-network/configtx.yaml 513 | 2019-07-25 22:04:30.451 EDT [common.tools.configtxgen.localconfig] completeInitialization -> INFO 003 orderer type: solo 514 | 2019-07-25 22:04:30.451 EDT [common.tools.configtxgen.localconfig] LoadTopLevel -> INFO 004 Loaded configuration: /opt/gopath/src/github.com/hyperledger/fabric/scripts/fabric-samples/first-network/configtx.yaml 515 | 2019-07-25 22:04:30.451 EDT [common.tools.configtxgen] doOutputChannelCreateTx -> INFO 005 Generating new channel configtx 516 | 2019-07-25 22:04:30.458 EDT [common.tools.configtxgen] doOutputChannelCreateTx -> INFO 006 Writing new channel tx 517 | ``` 518 | 519 | #### 2.3.3 生成锚节点配置更新文件 520 | 521 | 通道创建完成之后,我们接着需要提前生成锚节点配置更新文件,生成命令如下: 522 | 523 | ```bash 524 | # -profile 指定配置模板为 TwoOrgsChannel;-outputAnchorPeersUpdate 指定生成的锚节点配置更新文件路径;-channelID 指定通道名称为 mychannel;-asOrg 指定组织为 Org1MSP 525 | configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID mychannel -asOrg Org1MSP 526 | 527 | # -profile 指定配置模板为 TwoOrgsChannel;-outputAnchorPeersUpdate 指定生成的锚节点配置更新文件路径;-channelID 指定通道名称为 mychannel;-asOrg 指定组织为 Org2MSP 528 | configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID mychannel -asOrg Org2MSP 529 | ``` 530 | 531 | 两条命令运行完成后,都会有如下输出: 532 | 533 | ```bash 534 | 2019-07-25 22:19:42.190 EDT [common.tools.configtxgen] main -> INFO 001 Loading configuration 535 | 2019-07-25 22:19:42.260 EDT [common.tools.configtxgen.localconfig] Load -> INFO 002 Loaded configuration: /opt/gopath/src/github.com/hyperledger/fabric/scripts/fabric-samples/first-network/configtx.yaml 536 | 2019-07-25 22:19:42.324 EDT [common.tools.configtxgen.localconfig] completeInitialization -> INFO 003 orderer type: solo 537 | 2019-07-25 22:19:42.325 EDT [common.tools.configtxgen.localconfig] LoadTopLevel -> INFO 004 Loaded configuration: /opt/gopath/src/github.com/hyperledger/fabric/scripts/fabric-samples/first-network/configtx.yaml 538 | 2019-07-25 22:19:42.325 EDT [common.tools.configtxgen] doOutputAnchorPeersUpdate -> INFO 005 Generating anchor peer update 539 | 2019-07-25 22:19:42.325 EDT [common.tools.configtxgen] doOutputAnchorPeersUpdate -> INFO 006 Writing anchor peer update 540 | ``` 541 | 542 | 使用提前生成锚节点配置更新文件,组织管理员身份就可以更新指定应用通道中组织的锚节点配置。所谓的锚节点就是负责代表组织与其他组织中的节点进行 Gossip 通信的节点。 543 | 544 | (*)我们也可以通过下面命令将上面生成的交易(transaction)文件导出到`json`文件中进行查看: 545 | 546 | ```bash 547 | # -inspectChannelCreateTx 指定要解析的交易文件为 channel-artifacts/channel.tx 548 | configtxgen -inspectChannelCreateTx channel-artifacts/channel.tx > channel-artifacts/channel.tx.json 549 | 550 | # -inspectChannelCreateTx 指定要解析的交易文件为 channel-artifacts/Org1MSPanchors.tx 551 | configtxgen -inspectChannelCreateTx channel-artifacts/Org1MSPanchors.tx > channel-artifacts/Org1MSPanchors.tx.json 552 | 553 | # -inspectChannelCreateTx 指定要解析的交易文件为 channel-artifacts/Org2MSPanchors.tx 554 | configtxgen -inspectChannelCreateTx channel-artifacts/Org2MSPanchors.tx > channel-artifacts/Org2MSPanchors.tx.json 555 | ``` 556 | 557 | 至此,所以文件都生成完成,我们可以在`channel-artifacts`目录下可以看到,生成的文件有: 558 | 559 | ```bash 560 | ├── channel.tx # 应用通道的配置交易文件 561 | ├── genesis.block # Ordering 服务启动的创世区块 562 | ├── Org1MSPanchors.tx # 组织1的锚节点配置更新的配置交易文件 563 | └── Org2MSPanchors.tx # 组织2的锚节点配置更新的配置交易文件 564 | ``` 565 | 566 | ## 3 使用 Docker 容器方式启动 Fabric 网络 567 | 568 | ### 3.1 所需的`docker-compose`启动文件介绍 569 | 570 | 启动网络使用到了三个配置文件,他们具有继承和扩展等关系。使用到的配置文件是下面三个: 571 | 572 | ```bash 573 | base/peer-base.yaml 574 | base/docker-compose-base.yaml 575 | docker-compose-cli.yaml 576 | ``` 577 | 578 | #### 3.1.1 `peer-base.yaml`文件解析 579 | 580 | 这个配置文件中定义了将要启动的容器(container)所使用的镜像(image),并且定义了容器启动后自动执行的命令,具体配置详情如下: 581 | 582 | ```yaml 583 | version: '2' # 使用的是第2版 Compose 文件格式 584 | 585 | services: # 服务 586 | peer-base: # 定义一个名为 peer-base 的服务 587 | image: hyperledger/fabric-peer:$IMAGE_TAG # 该服务所依赖的镜像 588 | environment: # 定义该服务的环境变量 589 | - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock # Docker 服务地址 590 | - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=${COMPOSE_PROJECT_NAME}_byfn # 链码容器使用的网络方式,这里是bridge方式 591 | - FABRIC_LOGGING_SPEC=INFO # 定义日志级别为 INFO 592 | #- FABRIC_LOGGING_SPEC=DEBUG 593 | - CORE_PEER_TLS_ENABLED=true # 使用 TLS 594 | - CORE_PEER_GOSSIP_USELEADERELECTION=true # 使用选举 Leader 的方式 595 | - CORE_PEER_GOSSIP_ORGLEADER=false # 不指定 Leader 596 | - CORE_PEER_PROFILE_ENABLED=true # 使用 profile 597 | - CORE_PEER_TLS_CERT_FILE=/etc/hyperledger/fabric/tls/server.crt # 在容器中的 TLS 的证书路径 598 | - CORE_PEER_TLS_KEY_FILE=/etc/hyperledger/fabric/tls/server.key # 在容器中的 TLS 的秘钥路径 599 | - CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt # 在容器中的 TLS 的根证书路径 600 | working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer # 工作目录,即进入容器所在的默认位置 601 | command: peer node start # 启动容器后执行的第一条命令,启动 Peer 节点 602 | 603 | orderer-base: # 定义一个名为 orderer-base 的服务 604 | image: hyperledger/fabric-orderer:$IMAGE_TAG # 指定该服务依赖的镜像 605 | environment: # 定义该服务的环境变量 606 | - FABRIC_LOGGING_SPEC=INFO # 定义日志级别为 INFO 607 | - ORDERER_GENERAL_LISTENADDRESS=0.0.0.0 # orderer 节点的监听地址 608 | - ORDERER_GENERAL_GENESISMETHOD=file # 创世区块文件的类型为 file 609 | - ORDERER_GENERAL_GENESISFILE=/var/hyperledger/orderer/orderer.genesis.block # 指定创世区块在容器中的路径 610 | - ORDERER_GENERAL_LOCALMSPID=OrdererMSP # Orderer 的本地 MSP ID 611 | - ORDERER_GENERAL_LOCALMSPDIR=/var/hyperledger/orderer/msp # 在容器中的本地的MSP文件夹路径 612 | - ORDERER_GENERAL_TLS_ENABLED=true # 使用 TLS 613 | - ORDERER_GENERAL_TLS_PRIVATEKEY=/var/hyperledger/orderer/tls/server.key # 在容器中的 TLS 的秘钥路径 614 | - ORDERER_GENERAL_TLS_CERTIFICATE=/var/hyperledger/orderer/tls/server.crt # 在容器中的 TLS 的证书路径 615 | - ORDERER_GENERAL_TLS_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt] # 在容器中的 TLS 的根证书路径 616 | # 以下为kafka集群的配置,没有使用到 617 | #- ORDERER_KAFKA_TOPIC_REPLICATIONFACTOR=1 618 | #- ORDERER_KAFKA_VERBOSE=true 619 | #- ORDERER_GENERAL_CLUSTER_CLIENTCERTIFICATE=/var/hyperledger/orderer/tls/server.crt 620 | #- ORDERER_GENERAL_CLUSTER_CLIENTPRIVATEKEY=/var/hyperledger/orderer/tls/server.key 621 | #- ORDERER_GENERAL_CLUSTER_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt] 622 | working_dir: /opt/gopath/src/github.com/hyperledger/fabric # 工作目录,即进入容器所在的默认位置 623 | command: orderer # 启动容器后执行的第一条命令,启动 Orderer 节点 624 | ``` 625 | 626 | #### 3.1.2 `docker-compose-base.yaml`文件解析 627 | 628 | 这个配置文件中定义了五个容器,分别是`orderer.example.com`、`peer0.org1.example.com`、`peer1.org1.example.com`、`peer0.org2.example.com`、`peer1.org2.example.com`,其中一个`orderer`节点配置继承自 `peer-base.yaml`中的`orderer-base`服务;四个`peer`节点配置继承自`peer-base.yaml`中的`peer-base`服务。具体详细配置如下: 629 | 630 | ```yaml 631 | version: '2' # 使用的是第2版 Compose 文件格式 632 | 633 | services: # 服务,包含多个容器实例 634 | 635 | orderer.example.com: # 定义一个名为 orderer.example.com 的服务 636 | container_name: orderer.example.com # 容器名称 637 | extends: # 扩展,代表要加载的文件或服务 638 | file: peer-base.yaml # 扩展的文件名 639 | service: orderer-base # 扩展的服务名称 640 | volumes: # 挂载的卷 [本机路径下的目录或文件]:[容器中所映射到的地址] 641 | - ../channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block # 映射创世区块到容器中 642 | - ../crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/msp:/var/hyperledger/orderer/msp # 映射 orderer 节点的 msp 文件目录到容器中 643 | - ../crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/:/var/hyperledger/orderer/tls # 映射 orderer 节点的 tls 文件目录到容器中 644 | - orderer.example.com:/var/hyperledger/production/orderer 645 | ports: # 所映射的端口 [本机端口]:[容器端口] 646 | - 7050:7050 647 | 648 | peer0.org1.example.com: # 定义一个名为 peer0.org1.example.com 的服务 649 | container_name: peer0.org1.example.com # 容器名称 650 | extends: # 扩展 651 | file: peer-base.yaml # 扩展的文件名 652 | service: peer-base # 扩展的服务名称 653 | environment: # 定义该服务的环境变量 654 | - CORE_PEER_ID=peer0.org1.example.com # peer 节点的 ID 655 | - CORE_PEER_ADDRESS=peer0.org1.example.com:7051 # peer 节点的访问路径 656 | - CORE_PEER_LISTENADDRESS=0.0.0.0:7051 # peer 节点的监听路径 657 | - CORE_PEER_CHAINCODEADDRESS=peer0.org1.example.com:7052 # peer 节点的链码访问地址 658 | - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:7052 # peer 节点的链码监听地址,指定为 0.0.0.0 则自动进行探测 659 | - CORE_PEER_GOSSIP_BOOTSTRAP=peer1.org1.example.com:8051 # 指定用于在本组织内引导 Gossip 通信的节点 660 | - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org1.example.com:7051 # Gossip 通信的外部节点,既为本组织的锚节点 661 | - CORE_PEER_LOCALMSPID=Org1MSP # 所属组织的 MSP 的 ID 662 | volumes: # 挂载的卷 [本机路径下的目录或文件]:[容器中所映射到的地址] 663 | - /var/run/:/host/var/run/ 664 | - ../crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp:/etc/hyperledger/fabric/msp # 映射 peer0.org1.example.com 节点的 msp 文件目录到容器中 665 | - ../crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls:/etc/hyperledger/fabric/tls # 映射 peer0.org1.example.com 节点的 tls 文件目录到容器中 666 | - peer0.org1.example.com:/var/hyperledger/production 667 | ports: # 所映射的端口 [本机端口]:[容器端口] 668 | - 7051:7051 669 | 670 | ## 下面定义的 peer 服务的相关参数解释与 peer0.org1.example.com 相似 671 | peer1.org1.example.com: # 定义一个名为 peer1.org1.example.com 的服务 672 | container_name: peer1.org1.example.com 673 | extends: 674 | file: peer-base.yaml 675 | service: peer-base 676 | environment: 677 | - CORE_PEER_ID=peer1.org1.example.com 678 | - CORE_PEER_ADDRESS=peer1.org1.example.com:8051 679 | - CORE_PEER_LISTENADDRESS=0.0.0.0:8051 680 | - CORE_PEER_CHAINCODEADDRESS=peer1.org1.example.com:8052 681 | - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:8052 682 | - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org1.example.com:8051 683 | - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org1.example.com:7051 684 | - CORE_PEER_LOCALMSPID=Org1MSP 685 | volumes: 686 | - /var/run/:/host/var/run/ 687 | - ../crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/msp:/etc/hyperledger/fabric/msp 688 | - ../crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls:/etc/hyperledger/fabric/tls 689 | - peer1.org1.example.com:/var/hyperledger/production 690 | 691 | ports: 692 | - 8051:8051 693 | 694 | peer0.org2.example.com: # 定义一个名为 peer0.org2.example.com 的服务 695 | container_name: peer0.org2.example.com 696 | extends: 697 | file: peer-base.yaml 698 | service: peer-base 699 | environment: 700 | - CORE_PEER_ID=peer0.org2.example.com 701 | - CORE_PEER_ADDRESS=peer0.org2.example.com:9051 702 | - CORE_PEER_LISTENADDRESS=0.0.0.0:9051 703 | - CORE_PEER_CHAINCODEADDRESS=peer0.org2.example.com:9052 704 | - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:9052 705 | - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org2.example.com:9051 706 | - CORE_PEER_GOSSIP_BOOTSTRAP=peer1.org2.example.com:10051 707 | - CORE_PEER_LOCALMSPID=Org2MSP 708 | volumes: 709 | - /var/run/:/host/var/run/ 710 | - ../crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/msp:/etc/hyperledger/fabric/msp 711 | - ../crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls:/etc/hyperledger/fabric/tls 712 | - peer0.org2.example.com:/var/hyperledger/production 713 | ports: 714 | - 9051:9051 715 | 716 | peer1.org2.example.com: # 定义一个名为 peer1.org2.example.com 的服务 717 | container_name: peer1.org2.example.com 718 | extends: 719 | file: peer-base.yaml 720 | service: peer-base 721 | environment: 722 | - CORE_PEER_ID=peer1.org2.example.com 723 | - CORE_PEER_ADDRESS=peer1.org2.example.com:10051 724 | - CORE_PEER_LISTENADDRESS=0.0.0.0:10051 725 | - CORE_PEER_CHAINCODEADDRESS=peer1.org2.example.com:10052 726 | - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:10052 727 | - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org2.example.com:10051 728 | - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org2.example.com:9051 729 | - CORE_PEER_LOCALMSPID=Org2MSP 730 | volumes: 731 | - /var/run/:/host/var/run/ 732 | - ../crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/msp:/etc/hyperledger/fabric/msp 733 | - ../crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls:/etc/hyperledger/fabric/tls 734 | - peer1.org2.example.com:/var/hyperledger/production 735 | ports: 736 | - 10051:10051 737 | ``` 738 | 739 | #### 3.1.3 `docker-compose-cli.yaml`文件解析 740 | 741 | 这个配置文件扩展了`docker-compose-base.yaml`中的内容,并指定了`docker` 容器所加入的网络`networks`为`byfn`。而且还启动了一个客户端(`cli`)容器,这是一个`fabric`工具集容器,我们会登录这个容器和 fabric 各个节点进行交互和操作。 742 | 743 | ```yaml 744 | version: '2' # 使用的是第2版 Compose 文件格式 745 | 746 | volumes: # 声明要挂载的卷,既 1 orderer + 4 peer 747 | orderer.example.com: 748 | peer0.org1.example.com: 749 | peer1.org1.example.com: 750 | peer0.org2.example.com: 751 | peer1.org2.example.com: 752 | 753 | networks: # 声明一个名称为 byfn 的网络 754 | byfn: 755 | 756 | services: # 声明服务,包含多个容器实例 757 | 758 | orderer.example.com: # 定义一个名为 orderer.example.com 的服务 759 | extends: # 扩展 760 | file: base/docker-compose-base.yaml # 扩展的文件名 761 | service: orderer.example.com # 扩展的服务名称 762 | container_name: orderer.example.com # 容器名称 763 | networks: # 指定容器加入的网络,如果需要加入多个网络,可以定义多个 764 | - byfn 765 | 766 | peer0.org1.example.com: # 定义一个名为 peer0.org1.example.com 的服务 767 | container_name: peer0.org1.example.com # 容器名称 768 | extends: # 扩展 769 | file: base/docker-compose-base.yaml # 扩展的文件名 770 | service: peer0.org1.example.com # 扩展的服务名称 771 | networks: # 指定容器加入的网络 772 | - byfn 773 | 774 | # 下面 peer 节点相关参数与上类似 775 | peer1.org1.example.com: 776 | container_name: peer1.org1.example.com 777 | extends: 778 | file: base/docker-compose-base.yaml 779 | service: peer1.org1.example.com 780 | networks: 781 | - byfn 782 | 783 | peer0.org2.example.com: 784 | container_name: peer0.org2.example.com 785 | extends: 786 | file: base/docker-compose-base.yaml 787 | service: peer0.org2.example.com 788 | networks: 789 | - byfn 790 | 791 | peer1.org2.example.com: 792 | container_name: peer1.org2.example.com 793 | extends: 794 | file: base/docker-compose-base.yaml 795 | service: peer1.org2.example.com 796 | networks: 797 | - byfn 798 | 799 | cli: # 定义一个客户端服务,方便与各个节点进行交互 800 | container_name: cli # 容器名称为 cli 801 | image: hyperledger/fabric-tools:$IMAGE_TAG # 使用到的镜像为 fabric-tools 802 | tty: true # 使用伪终端 803 | stdin_open: true # 标准输入 804 | environment: # 定义该服务的环境变量 805 | - SYS_CHANNEL=$SYS_CHANNEL # 系统通道名称 806 | - GOPATH=/opt/gopath # 指定 GOPATH 路径 807 | - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock # Docker 服务地址 808 | #- FABRIC_LOGGING_SPEC=DEBUG 809 | - FABRIC_LOGGING_SPEC=INFO # 日志级别为 INFO 810 | - CORE_PEER_ID=cli # 当前节点的 ID 为 cli 811 | - CORE_PEER_ADDRESS=peer0.org1.example.com:7051 # 以下与 peer-base.yaml 相同,表示当前客户端容器默认与 peer0.org1.example.com 进行交互 812 | - CORE_PEER_LOCALMSPID=Org1MSP # 组织1的本地MSP的ID 813 | - CORE_PEER_TLS_ENABLED=true # 使用 TLS 814 | - 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 # peer0.org1.example.com 节点的 TLS 证书路径 815 | - 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 # peer0.org1.example.com 节点的 TLS 密钥路径 816 | - 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.org1.example.com 节点的 TLS 根证书路径 817 | - CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp # 组织1中的管理员(Admin@org1.example.com)的MSP文件目录路径 818 | working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer # 工作目录,进入容器所在的默认位置 819 | command: /bin/bash # 启动容器后运行的第一条命令:使用 bash 820 | volumes: # 挂载的卷 [本机路径下的目录或文件]:[容器中所映射到的地址] 821 | - /var/run/:/host/var/run/ 822 | - ./../chaincode/:/opt/gopath/src/github.com/chaincode # 映射链码文件夹路径 823 | - ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ # 映射证书文件夹路径 824 | - ./scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/ # 映射的脚本文件夹路径 825 | - ./channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts # 映射的创世区块和应用通道等文件目录路径 826 | depends_on: # 依赖,需要首先按顺序启动以下容器服务,但是不会等待以下容器完全启动才启动当前容器 827 | - orderer.example.com 828 | - peer0.org1.example.com 829 | - peer1.org1.example.com 830 | - peer0.org2.example.com 831 | - peer1.org2.example.com 832 | networks: # 指定当前容器所加入的网络 833 | - byfn 834 | ``` 835 | 836 | ### 3.2 启动 Fabric 网络中的 Orderer、peer 和 cli 容器服务 837 | 838 | 当所有的配置文件定义好之后,我们就可以使用`docker-compose`工具来启动所有容器了,启动命令如下: 839 | 840 | ```bash 841 | # 如果不在 first-network 目录下,要进入该目录下 842 | cd /opt/gopath/src/github.com/hyperledger/fabric/scripts/fabric-samples/first-network 843 | # -f(--file)指定使用的 Compose 模板文件,up 启动配置文件中定义的所有服务容器,-d 在后台运行服务容器 844 | docker-compose -f docker-compose-cli.yaml up -d 845 | ``` 846 | 847 | 该命令执行完成之后,会有如下输出: 848 | 849 | ```bash 850 | [root@localhost first-network]# docker-compose -f docker-compose-cli.yaml up -d 851 | Creating network "net_byfn" with the default driver 852 | Creating volume "net_peer0.org2.example.com" with default driver 853 | Creating volume "net_peer1.org2.example.com" with default driver 854 | Creating volume "net_peer1.org1.example.com" with default driver 855 | Creating volume "net_peer0.org1.example.com" with default driver 856 | Creating volume "net_orderer.example.com" with default driver 857 | Creating peer0.org1.example.com ... done 858 | Creating peer1.org1.example.com ... done 859 | Creating peer0.org2.example.com ... done 860 | Creating orderer.example.com ... done 861 | Creating peer1.org2.example.com ... done 862 | Creating cli ... done 863 | ``` 864 | 865 | 我们可以使用`docker ps`命令来查看后台启动的所有容器,具体如下。我们可以看到,在后台已经有一个 cli 容器,一个 orderer 容器,四个 peer 容器启动了。 866 | 867 | ```bash 868 | [root@localhost first-network]# docker ps 869 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 870 | 7ddf52548cfd hyperledger/fabric-tools:latest "/bin/bash" 6 minutes ago Up 6 minutes cli 871 | a495b24483dc hyperledger/fabric-orderer:latest "orderer" 6 minutes ago Up 6 minutes 0.0.0.0:7050->7050/tcp orderer.example.com 872 | 5349a515df51 hyperledger/fabric-peer:latest "peer node start" 6 minutes ago Up 6 minutes 0.0.0.0:10051->10051/tcp peer1.org2.example.com 873 | a8a579ebd979 hyperledger/fabric-peer:latest "peer node start" 6 minutes ago Up 6 minutes 0.0.0.0:7051->7051/tcp peer0.org1.example.com 874 | 5614be188b35 hyperledger/fabric-peer:latest "peer node start" 6 minutes ago Up 6 minutes 0.0.0.0:9051->9051/tcp peer0.org2.example.com 875 | d6672dcc70d4 hyperledger/fabric-peer:latest "peer node start" 6 minutes ago Up 6 minutes 0.0.0.0:8051->8051/tcp peer1.org1.example.com 876 | ``` 877 | 878 | ## 4 创建、加入通道,更新锚节点 879 | 880 | ### 4.1 创建通道操作 881 | 882 | 当所有容器启动完成之后,我们就可以进入容器,进行创建通道等操作了。首先我们需要使用如下命令进入客户端容器: 883 | 884 | ```bash 885 | docker exec -it cli bash 886 | ``` 887 | 888 | 执行完成之后,我们可以看到光标会变成如下: 889 | 890 | ```bash 891 | [root@localhost first-network]# docker exec -it cli bash 892 | root@7ddf52548cfd:/opt/gopath/src/github.com/hyperledger/fabric/peer# # 光标所在位置 893 | ``` 894 | 895 | 接着先将`Orderer`的`tlsca`证书文件路径写入环境变量: 896 | 897 | ```bash 898 | 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 899 | ``` 900 | 901 | 执行下面命令,创建通道: 902 | 903 | ```bash 904 | # channel create 创建一个新通道,-o 指定orderer节点地址,-c 指定生成的通道ID -f 指定新建应用通道的配置交易文件 --tls 使用TLS,--cafile 指定 tls 的证书文件路径 905 | peer channel create -o orderer.example.com:7050 -c mychannel -f ./channel-artifacts/channel.tx --tls true --cafile $ORDERER_CA 906 | ``` 907 | 908 | 执行完成之后,会有如下输出: 909 | 910 | ```bash 911 | 2019-07-26 12:36:53.557 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized 912 | 2019-07-26 12:36:53.632 UTC [cli.common] readBlock -> INFO 002 Received block: 0 913 | ``` 914 | 915 | (*) 我们使用 `ll`命令可以看到,该目录下多了一个`mychannel.block`文件,我们可以使用如下命令将其移动到 `channel-artifacts`文件夹下: 916 | 917 | ```bash 918 | mv mychannel.block channel-artifacts/ 919 | ``` 920 | 921 | (*) 我们还可以使用如下命令将生成的通道文件解析成`json`格式的文件方便查看: 922 | 923 | ```bash 924 | configtxgen -inspectBlock channel-artifacts/mychannel.block > channel-artifacts/mychannel.json 925 | ``` 926 | 927 | ### 4.2 加入通道 928 | 929 | 创建通道完成之后,我们需要将所有节点都加入到该通道中 930 | 931 | #### 4.2.1 `peer0.org1.example.com`节点加入通道 932 | 933 | 先配置环境变量,由于`peer0.org1.example.com`节点是默认与`cli`容器连接的,所有可以不必配置环境变量,但是为与其他节点加入通道流程一致,这里也配置一下环境变量: 934 | 935 | ```bash 936 | export CORE_PEER_LOCALMSPID="Org1MSP" 937 | 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 938 | export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp 939 | export CORE_PEER_ADDRESS=peer0.org1.example.com:7051 940 | ``` 941 | 942 | 执行下面命令,加入通道: 943 | 944 | ```bash 945 | # channel join 加入通道,-b 通道的区块文件 946 | peer channel join -b channel-artifacts/mychannel.block 947 | ``` 948 | 949 | 执行完成后,会有如下输出: 950 | 951 | ```bash 952 | root@7ddf52548cfd:/opt/gopath/src/github.com/hyperledger/fabric/peer# peer channel join -b channel-artifacts/mychannel.block 953 | 2019-07-26 13:04:33.273 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized 954 | 2019-07-26 13:04:33.349 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel 955 | ``` 956 | 957 | #### 4.2.2 `peer1.org1.example.com`节点加入通道 958 | 959 | 配置环境变量: 960 | 961 | ```bash 962 | export CORE_PEER_LOCALMSPID="Org1MSP" 963 | 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 964 | export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp 965 | export CORE_PEER_ADDRESS=peer1.org1.example.com:8051 966 | ``` 967 | 968 | 执行下面命令,加入通道,执行完成后,输出内容与`peer0.org1.example.com`的相同 969 | 970 | ```bash 971 | peer channel join -b channel-artifacts/mychannel.block 972 | ``` 973 | 974 | #### 4.2.3 `peer0.org2.example.com`节点加入通道 975 | 976 | 配置环境变量: 977 | 978 | ```bash 979 | export CORE_PEER_LOCALMSPID="Org2MSP" 980 | 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 981 | export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp 982 | export CORE_PEER_ADDRESS=peer0.org2.example.com:9051 983 | ``` 984 | 985 | 执行下面命令,加入通道,执行完成后,输出内容与`peer0.org1.example.com`的相同 986 | 987 | ```bash 988 | peer channel join -b channel-artifacts/mychannel.block 989 | ``` 990 | 991 | #### 4.2.4 `peer1.org2.example.com`节点加入通道 992 | 993 | 配置环境变量: 994 | 995 | ```bash 996 | export CORE_PEER_LOCALMSPID="Org2MSP" 997 | 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 998 | export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp 999 | export CORE_PEER_ADDRESS=peer1.org2.example.com:10051 1000 | ``` 1001 | 1002 | 执行下面命令,加入通道,执行完成后,输出内容与`peer0.org1.example.com`的相同 1003 | 1004 | ```bash 1005 | peer channel join -b channel-artifacts/mychannel.block 1006 | ``` 1007 | 1008 | ### 4.3 更新锚节点操作 1009 | 1010 | #### 4.3.1 更新 `Org1`的锚节点 1011 | 1012 | 配置环境变量: 1013 | 1014 | ```bash 1015 | export CORE_PEER_LOCALMSPID="Org1MSP" 1016 | 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 1017 | 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 1018 | export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp 1019 | export CORE_PEER_ADDRESS=peer0.org1.example.com:7051 1020 | ``` 1021 | 1022 | 执行下面命令,更新`org1`的锚节点: 1023 | 1024 | ```bash 1025 | # channel update 更新通道操作,-o 指定 orderer 节点地址,-c 指定通道ID,-f 指定锚节点配置更新文件路径 --tls 启用TLS,--cafile 指定tlsca证书的文件路径 1026 | peer channel update -o orderer.example.com:7050 -c mychannel -f ./channel-artifacts/Org1MSPanchors.tx --tls true --cafile $ORDERER_CA 1027 | ``` 1028 | 1029 | 执行完成后,会有如下输: 1030 | 1031 | ```bash 1032 | 2019-07-26 13:17:34.520 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized 1033 | 2019-07-26 13:17:34.693 UTC [channelCmd] update -> INFO 002 Successfully submitted channel update 1034 | ``` 1035 | 1036 | #### 4.3.2 更新`Org2`的锚节点 1037 | 1038 | 配置环境变量: 1039 | 1040 | ```bash 1041 | export CORE_PEER_LOCALMSPID="Org2MSP" 1042 | 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 1043 | 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 1044 | export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp 1045 | export CORE_PEER_ADDRESS=peer0.org2.example.com:9051 1046 | ``` 1047 | 1048 | 执行下面命令,更新`org2`的锚节点,执行完成后,输出内容与上面的相同: 1049 | 1050 | ```bash 1051 | peer channel update -o orderer.example.com:7050 -c mychannel -f ./channel-artifacts/Org2MSPanchors.tx --tls true --cafile $ORDERER_CA 1052 | ``` 1053 | 1054 | ## 5 安装、实例化、执行链码 1055 | 1056 | ### 5.1 安装链码 1057 | 1058 | 如果需要通过某个`peer`节点访问和执行`chancode`,那个这个节点上必须要先安装这个`chaincode`。这里我们将在`peer0.org1.example.com`和`peer0.org2.example.com`两个节点上安装链码 1059 | 1060 | #### 5.1.1 在 `peer0.org1.example.com`上安装链码 1061 | 1062 | 首先设置环境变量: 1063 | 1064 | ```bash 1065 | export CORE_PEER_LOCALMSPID="Org1MSP" 1066 | 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 1067 | 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 1068 | export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp 1069 | export CORE_PEER_ADDRESS=peer0.org1.example.com:7051 1070 | ``` 1071 | 1072 | 然后执行下面命令,安装链码: 1073 | 1074 | ```bash 1075 | # chaincode install 安装链码,-n 指定链码名称,-v 指定链码版本,-l 指定链码的语言,-p 指定链码文件夹的路径 1076 | peer chaincode install -n mycc -v 1.0 -l golang -p "github.com/chaincode/chaincode_example02/go/" 1077 | ``` 1078 | 1079 | 安装完成之后,会有如下输出: 1080 | 1081 | ```bash 1082 | 2019-07-26 13:36:08.689 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc 1083 | 2019-07-26 13:36:08.689 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc 1084 | 2019-07-26 13:36:09.486 UTC [chaincodeCmd] install -> INFO 003 Installed remotely response: 1085 | ``` 1086 | 1087 | #### 5.1.2 在 `peer0.org2.example.com`上安装链码 1088 | 1089 | 首先设置环境变量: 1090 | 1091 | ```bash 1092 | export CORE_PEER_LOCALMSPID="Org2MSP" 1093 | 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 1094 | 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 1095 | export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp 1096 | export CORE_PEER_ADDRESS=peer0.org2.example.com:9051 1097 | ``` 1098 | 1099 | 然后执行下面命令,安装链码,安装完成之后,输出内容与上相同 1100 | 1101 | ```bash 1102 | peer chaincode install -n mycc -v 1.0 -l golang -p "github.com/chaincode/chaincode_example02/go/" 1103 | ``` 1104 | 1105 | ### 5.2 实例化链码 1106 | 1107 | `chaincode`安装后需要实例化才能使用,在`channel`中,一个`chaincode`只需要进行一次实例化(`instantiate`)操作即可。 1108 | 1109 | 我们在`peer0.org2.example.com`节点上实例化链码,所以先配置环境变量: 1110 | 1111 | ```bash 1112 | export CORE_PEER_LOCALMSPID="Org2MSP" 1113 | 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 1114 | 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 1115 | export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp 1116 | export CORE_PEER_ADDRESS=peer0.org2.example.com:9051 1117 | ``` 1118 | 1119 | 执行下面命令,实例化链码: 1120 | 1121 | ```bash 1122 | # chaincode instantiate 实例化链码,-o 指定orderer节点地址,-C 指定通道ID,-n 指定链码名称吗,-v 指定链码版本,-c 指定调用链码 init 方法时传入的参数,-P 指定背书策略,这里是策略是需要org1或者org2的成员同意 --tls 启用 TLS --cafile 指定tlsca证书文件路径 1123 | peer chaincode instantiate -o orderer.example.com:7050 -C mychannel -n mycc -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P "OR ('Org1MSP.member','Org2MSP.member')" --tls true --cafile $ORDERER_CA 1124 | ``` 1125 | 1126 | 执行完成之后,只有如下内容输出: 1127 | 1128 | ```bash 1129 | 2019-07-26 13:57:14.619 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc 1130 | 2019-07-26 13:57:14.619 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc 1131 | ``` 1132 | 1133 | ### 5.3 调用链码 1134 | 1135 | 经过上面的所有操作,我们的网络环境和链码都已经配置完成了,下面我们就可以对链码执行`query`和`invoke`操作了。 1136 | 1137 | **查询`a`账户的余额** 1138 | 1139 | ```bash 1140 | # chaincode query 链码查询操作 1141 | peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}' 1142 | ``` 1143 | 1144 | 得到输出结果为`100` 1145 | 1146 | **查询`b`账户的余额** 1147 | 1148 | ```bash 1149 | peer chaincode query -C mychannel -n mycc -c '{"Args":["query","b"]}' 1150 | ``` 1151 | 1152 | 得到输出结果为`200` 1153 | 1154 | 上面的两个查询命令会获取经背书的`chaincode`执行结果。但它不会产生交易`transaction` 1155 | 1156 | **`a`账户向`b`账户转账`10`元** 1157 | 1158 | ```bash 1159 | # chaincode invoke 执行链码 invoke 方法,-o 指定orderer节点地址,--tls 启动TLS,--cafile 指定tlsca的证书文件路径 -C 指定通道名称,-n 指定链码名称,-peerAddress 指定需要连接到的peer节点地址,--tlsRootCertFiles 如果启用了TLS,则指向需要连接的peer节点的TLS根证书文件路径 -c 执行invoke方法传入的参数 1160 | peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile $ORDERER_CA -C mychannel -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"]}' 1161 | ``` 1162 | 1163 | 执行完成之后,会有如下输出: 1164 | 1165 | ```bash 1166 | 2019-07-26 14:29:37.209 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200 1167 | ``` 1168 | 1169 | 接着我们可以再次执行上面的查询`a`和`b`余额的命令,查询现在的余额,经过查询,可以发现现在`a`余额为`90`,`b`余额为`210`。 1170 | 1171 | 我们还可以尝试连接到`peer1.org1.example.com`上进行查询操作,具体步骤如下: 1172 | 1173 | 先配置环境变量: 1174 | 1175 | ```bash 1176 | export CORE_PEER_LOCALMSPID="Org1MSP" 1177 | 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 1178 | 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 1179 | export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp 1180 | export CORE_PEER_ADDRESS=peer1.org1.example.com:8051 1181 | ``` 1182 | 1183 | 执行查询链码操作: 1184 | 1185 | ```bash 1186 | peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}' 1187 | ``` 1188 | 1189 | 执行完成之后,我们会发现返回了如下错误: 1190 | 1191 | ```bash 1192 | Error: endorsement failure during query. response: status:500 message:"cannot retrieve package for chaincode mycc/1.0, error open /var/hyperledger/production/chaincodes/mycc.1.0: no such file or directory" 1193 | ``` 1194 | 1195 | 这个原因就是我们没有在`peer1.org1.example.com`节点上安装链码,所以我们无法在该节点上执行调用链码的操作,所以我们需要先再该节点上安装链码,具体命令如下: 1196 | 1197 | ```bash 1198 | peer chaincode install -n mycc -v 1.0 -l golang -p "github.com/chaincode/chaincode_example02/go/" 1199 | ``` 1200 | 1201 | 然后我们再进行查询操作: 1202 | 1203 | ```bash 1204 | peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}' 1205 | ``` 1206 | 1207 | 我们可以看到,成功查询出了`a`账户的余额为`90` 1208 | 1209 | 我们可以使用`exit`命令退出`cli`容器,光标回到了主机下面。经过上面调用链码等操作后,我们再次使用`docker ps`命令来查看后台运行的容器服务情况如下: 1210 | 1211 | ```bash 1212 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1213 | 9096320344ee dev-peer1.org1.example.com-mycc-1.0-cd123150154e6bf2df7ce682e0b1bcbea40499416f37a6da3aae14c4eb51b08d "chaincode -peer.add…" 48 seconds ago Up 46 seconds dev-peer1.org1.example.com-mycc-1.0 1214 | e60c9a77b244 dev-peer0.org1.example.com-mycc-1.0-384f11f484b9302df90b453200cfb25174305fce8f53f4e94d45ee3b6cab0ce9 "chaincode -peer.add…" 20 minutes ago Up 20 minutes dev-peer0.org1.example.com-mycc-1.0 1215 | b685dd5d864c dev-peer0.org2.example.com-mycc-1.0-15b571b3ce849066b7ec74497da3b27e54e0df1345daff3951b94245ce09c42b "chaincode -peer.add…" 44 minutes ago Up 44 minutes dev-peer0.org2.example.com-mycc-1.0 1216 | 7ddf52548cfd hyperledger/fabric-tools:latest "/bin/bash" 3 hours ago Up 3 hours cli 1217 | a495b24483dc hyperledger/fabric-orderer:latest "orderer" 3 hours ago Up 3 hours 0.0.0.0:7050->7050/tcp orderer.example.com 1218 | 5349a515df51 hyperledger/fabric-peer:latest "peer node start" 3 hours ago Up 3 hours 0.0.0.0:10051->10051/tcp peer1.org2.example.com 1219 | a8a579ebd979 hyperledger/fabric-peer:latest "peer node start" 3 hours ago Up 3 hours 0.0.0.0:7051->7051/tcp peer0.org1.example.com 1220 | 5614be188b35 hyperledger/fabric-peer:latest "peer node start" 3 hours ago Up 3 hours 0.0.0.0:9051->9051/tcp peer0.org2.example.com 1221 | d6672dcc70d4 hyperledger/fabric-peer:latest "peer node start" 3 hours ago Up 3 hours 0.0.0.0:8051->8051/tcp peer1.org1.example.com 1222 | ``` 1223 | 1224 | 我们可以看到,相比于之前,现在多了三个容器,不难看出,这三个容器都是链码容器。在节点的`chaincode`第一次被实例化或使用激活时,会启用一个容器来运行`chaincode`。 1225 | 1226 | ### 5.4 其他`Channel`、`Chaincode`操作 1227 | 1228 | 我们还是先执行`docker exec -it cli bash`进入`cli`容器内进行操作 1229 | 1230 | - 列出当前节点所加入的`Channel`: 1231 | 1232 | ```bash 1233 | peer channel list 1234 | ``` 1235 | 1236 | 输出内容为: 1237 | 1238 | ```bash 1239 | 2019-07-26 16:02:11.361 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized 1240 | Channels peers has joined: 1241 | mychannel 1242 | ``` 1243 | 1244 | - 列出当前节点所有已经安装的`Chaincode`: 1245 | 1246 | ```bash 1247 | peer chaincode list --installed 1248 | ``` 1249 | 1250 | 输出结果为: 1251 | 1252 | ```bash 1253 | Get installed chaincodes on peer: 1254 | Name: mycc, Version: 1.0, Path: github.com/chaincode/chaincode_example02/go/, Id: 333a19b11063d0ade7be691f9f22c04ad369baba15660f7ae9511fd1a6488209 1255 | ``` 1256 | 1257 | - 获取特定`Channel`上的区块信息: 1258 | 1259 | ```bash 1260 | peer channel getinfo -c mychannel 1261 | ``` 1262 | 1263 | 输出结果为: 1264 | 1265 | ```bash 1266 | 2019-07-26 16:06:02.085 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized 1267 | Blockchain info: {"height":6,"currentBlockHash":"kIw2CHcxYZU3gDwZUH7l9qN/m0Sn8DXXJ8ra7Z5O9Jk=","previousBlockHash":"e3+BrzDCedbzz+zvcW3E+tCXG+DE4C0KOerbUxU7h8E="} 1268 | ``` 1269 | 1270 | - 进一步获取特定高度的`Block`详细内容,例如,下面是获取最后一块(从`0`开始编号)`Block`的详细内容 1271 | 1272 | ```bash 1273 | peer channel fetch 5 mychannel_5.block -o orderer.example.com:7050 -c mychannel --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 1274 | ``` 1275 | 1276 | 运行完成后,会有如下输出: 1277 | 1278 | ```bash 1279 | 2019-07-26 16:12:50.014 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized 1280 | 2019-07-26 16:12:50.017 UTC [cli.common] readBlock -> INFO 002 Received block: 5 1281 | ``` 1282 | 1283 | 我们使用`ll`查看当前目录下,会发现多了一个`mychannel_5.block`文件,我们接下来就可以使用`configtcgen`工具将这个区块文件解析成`json`格式的文件了,具体命令如下: 1284 | 1285 | ```bash 1286 | configtxgen --inspectBlock mychannel_5.block > channel-artifacts/mychannel_5.json 1287 | ``` 1288 | 1289 | 运行完成后,有如下输出: 1290 | 1291 | ```bash 1292 | 2019-07-26 16:13:07.306 UTC [common.tools.configtxgen] main -> INFO 001 Loading configuration 1293 | 2019-07-26 16:13:07.631 UTC [common.tools.configtxgen.localconfig] completeInitialization -> INFO 002 Orderer.Addresses unset, setting to [127.0.0.1:7050] 1294 | 2019-07-26 16:13:07.631 UTC [common.tools.configtxgen.localconfig] completeInitialization -> INFO 003 orderer type: solo 1295 | 2019-07-26 16:13:07.631 UTC [common.tools.configtxgen.localconfig] LoadTopLevel -> INFO 004 Loaded configuration: /etc/hyperledger/fabric/configtx.yaml 1296 | 2019-07-26 16:13:07.631 UTC [common.tools.configtxgen] doInspectBlock -> INFO 005 Inspecting block 1297 | 2019-07-26 16:13:07.631 UTC [common.tools.configtxgen] doInspectBlock -> INFO 006 Parsing genesis block 1298 | ``` 1299 | 1300 | 我们在主机的`/opt/gopath/src/github.com/hyperledger/fabric/scripts/fabric-samples/first-network/channel-artifacts`目录下就能看到刚才解析出来的`json`格式的区块文件`mychannel_5.json`。 1301 | 1302 | #### 5.5 关闭网络 1303 | 1304 | 如果我们需要将刚才搭建出来的网络关闭,并且清除一些环境信息等,我们可以使用`first-network`提供了脚本进行关闭即可,具体操作如下: 1305 | 1306 | ```bash 1307 | # 首先来到 first-network 目录下 1308 | cd /opt/gopath/src/github.com/hyperledger/fabric/scripts/fabric-samples/first-network 1309 | # 执行关闭网络的脚本命令 1310 | ./byfn.sh down 1311 | ``` 1312 | 1313 | 输入命令后,接着会让选择是否继续,我们输入`y`继续执行。执行完成后,会有如下输出: 1314 | 1315 | ````bash 1316 | [root@localhost first-network]# ./byfn.sh down 1317 | Stopping for channel 'mychannel' with CLI timeout of '10' seconds and CLI delay of '3' seconds 1318 | Continue? [Y/n] y 1319 | proceeding ... 1320 | WARNING: The BYFN_CA2_PRIVATE_KEY variable is not set. Defaulting to a blank string. 1321 | WARNING: The BYFN_CA1_PRIVATE_KEY variable is not set. Defaulting to a blank string. 1322 | Stopping cli ... done 1323 | Stopping orderer.example.com ... done 1324 | Stopping peer1.org2.example.com ... done 1325 | Stopping peer0.org1.example.com ... done 1326 | Stopping peer0.org2.example.com ... done 1327 | Stopping peer1.org1.example.com ... done 1328 | Removing cli ... done 1329 | Removing orderer.example.com ... done 1330 | Removing peer1.org2.example.com ... done 1331 | Removing peer0.org1.example.com ... done 1332 | Removing peer0.org2.example.com ... done 1333 | Removing peer1.org1.example.com ... done 1334 | Removing network net_byfn 1335 | Removing volume net_peer0.org3.example.com 1336 | WARNING: Volume net_peer0.org3.example.com not found. 1337 | Removing volume net_peer1.org3.example.com 1338 | WARNING: Volume net_peer1.org3.example.com not found. 1339 | Removing volume net_orderer2.example.com 1340 | WARNING: Volume net_orderer2.example.com not found. 1341 | Removing volume net_orderer.example.com 1342 | Removing volume net_peer0.org2.example.com 1343 | Removing volume net_peer0.org1.example.com 1344 | Removing volume net_peer1.org1.example.com 1345 | Removing volume net_peer1.org2.example.com 1346 | Removing volume net_orderer5.example.com 1347 | WARNING: Volume net_orderer5.example.com not found. 1348 | Removing volume net_orderer4.example.com 1349 | WARNING: Volume net_orderer4.example.com not found. 1350 | Removing volume net_orderer3.example.com 1351 | WARNING: Volume net_orderer3.example.com not found. 1352 | 9096320344ee 1353 | e60c9a77b244 1354 | b685dd5d864c 1355 | Untagged: dev-peer1.org1.example.com-mycc-1.0-cd123150154e6bf2df7ce682e0b1bcbea40499416f37a6da3aae14c4eb51b08d:latest 1356 | Deleted: sha256:bffb85af26a7def57aa707fa85b99b59b966080d7964823004010f082a0ad198 1357 | Deleted: sha256:48c94dc3357616bc7c38a70644e9abf4be2df1a00709386ad7d7c98f281a4ea9 1358 | Deleted: sha256:506f39276ec553d0eb2b152dbac19e284f4ef90431213e377acbdd77dbaf1702 1359 | Deleted: sha256:0a59238e1a3fe6dd87e5f401063534937136382e1f21c61a8db71143f7967d84 1360 | Untagged: dev-peer0.org1.example.com-mycc-1.0-384f11f484b9302df90b453200cfb25174305fce8f53f4e94d45ee3b6cab0ce9:latest 1361 | Deleted: sha256:3bff91b1dec74033b6be007f24535c89a8a40bc1b12eab128d90e1b2d9026eb7 1362 | Deleted: sha256:8fd2fc3bfd9a9a0dae331d155600a442d11a61428806feb5a2efc86dbd264e84 1363 | Deleted: sha256:a2aa63cc2b7c032094d1afe69fddc4125855d1c072cb4dacdbf408fc34f5378e 1364 | Deleted: sha256:ba6b3377507dc8417b2742fb30b494a4a70341665ecd24f34e5dd51f97c9be28 1365 | Untagged: dev-peer0.org2.example.com-mycc-1.0-15b571b3ce849066b7ec74497da3b27e54e0df1345daff3951b94245ce09c42b:latest 1366 | Deleted: sha256:1d073a8218d632d77ccb818dc1be159baf0ebdbd7150e603d6bb84e9a5ab91b8 1367 | Deleted: sha256:253c4f60d83ae040fb3a258cb755f7d24e1ae3bc55e0dbab4f75f41f71104c81 1368 | Deleted: sha256:a2cc738b0997ece4ca4f6b568b2a3477838e9c715cdb31c2e0e65e40656f0dae 1369 | Deleted: sha256:876947d888edf4b1f8863275afd249f210d0723029e3ffad27d68ef9b12bcc42 1370 | ```` 1371 | 1372 | 关闭网络后,我们可以使用`docker ps -a`命令查看后台是否存在运行着的或关闭的容器,我们可以发现,所有容器清除完成了。 1373 | 1374 | ## 6 参考 1375 | 1376 | - [分步详解 Fabric 区块链网络的部署](https://www.ibm.com/developerworks/cn/cloud/library/cl-lo-hyperledger-fabric-practice-analysis/index.html) 1377 | 1378 | - [fabric主要配置文件细讲](https://blog.csdn.net/qq_25870633/article/details/81184781) 1379 | 1380 | - [Hyperledger Fabric相关文件解析](https://www.cnblogs.com/cbkj-xd/p/11153080.html) 1381 | 1382 | - [深入解析Hyperledger Fabric搭建的全过程](https://www.cnblogs.com/cbkj-xd/p/11067810.html) 1383 | 1384 | - [Docker — 从入门到实践](https://docker_practice.gitee.io/) 1385 | --------------------------------------------------------------------------------