# 4 搭建第一个自己的网络
下面让我们手动搭建一个自己的fabric 网络:
- 创建一个项目目录: 如
mkdir ~/Demo
- orderer节点个数为1个
- 组织个数2个
- OrgGo
- OrgCPP
- OrgGo有两个peer节点, 该组织有3个用户
- OrgCpp有两个peer节点, 该组织有4个用户
# 4.1 生成Fabric的证书
编写生成组织节点证书的配置文件,我们将其命名为: crypto-config.yaml。在里边指定组织的名称, 节点个数, 用户个数和访问节点的域名信息。
将如下写好的配置文件放入目录:
~/Demo
中
# crypto-config.yaml
OrdererOrgs: # 排序组织
- Name: Orderer # 排序节点组织名称
Domain: itcast.com # 排序节点组织的根域名
Specs:
- Hostname: ubuntu # 排序节点主机名, 访问该排序节点的域名: ubuntu.itcast.com
# “Spec”的作用是不受下面的Template模板生成规则影响,个性化指定一个域名
PeerOrgs:
- Name: OrgGo # 组织Org1名称
Domain: orggo.itcast.com # 组织Org1的域名
EnableNodeOUs: true # Node.js支持,java的sdk里面默认是注释掉的
Template: # 根据上面注释的模板生成2套公私钥+证书,默认生成规则是peer0-9.组织的域名
Count: 2 # 即生成peer0.orggo.itcast.com、peer1.orggo.itcast.com 两个节点的公私钥和证
Users: # 除了admin用户,额外生成一个普通用户
Count: 3 # 普通用户个数为3
- Name: OrgCPP
Domain: orgcpp.itcast.com
EnableNodeOUs: true
Template:
Count: 2
Users:
Count: 4
# 配置文件编写完成, 在Demo目录下执行该命令:
$ cryptogen generate --config=./crypto-config.yaml
orggo.itcast.com
orgcpp.itcast.com
# 查看Demo目录中的文件
$ tree -L 6
.
├── crypto-config
│ ├── `ordererOrganizations
│ │ └── itcast.com
│ │ ├── ca
│ │ │ ├── 4d61535a2dd55ff1641d7331e3037d59c590feb2abc21a9be04de678b28480cb_sk
│ │ │ └── ca.itcast.com-cert.pem
│ │ ├── msp
│ │ │ ├── admincerts
│ │ │ │ └── Admin@itcast.com-cert.pem
│ │ │ ├── cacerts
│ │ │ │ └── ca.itcast.com-cert.pem
│ │ │ └── tlscacerts
│ │ │ └── tlsca.itcast.com-cert.pem
│ │ ├── orderers
│ │ │ └── ubuntu.itcast.com
│ │ │ ├── msp
│ │ │ └── tls
│ │ ├── tlsca
│ │ │ ├── e2cf6010c4360cdcf89b636789543dc8e12073ba6035fe811f6e68901370f62d_sk
│ │ │ └── tlsca.itcast.com-cert.pem
│ │ └── users
│ │ └── Admin@itcast.com
│ │ ├── msp
│ │ └── tls
│ └── `peerOrganizations
│ ├── `orgcpp.itcast.com
│ │ ├── ca
│ │ │ ├── b1d3411e8616a50f8d88bde7a68259972565541e0937294b67b09e155468c3cd_sk
│ │ │ └── ca.orgcpp.itcast.com-cert.pem
│ │ ├── msp
│ │ │ ├── admincerts
│ │ │ │ └── Admin@orgcpp.itcast.com-cert.pem
│ │ │ ├── cacerts
│ │ │ │ └── ca.orgcpp.itcast.com-cert.pem
│ │ │ ├── config.yaml
│ │ │ └── tlscacerts
│ │ │ └── tlsca.orgcpp.itcast.com-cert.pem
│ │ ├── `peers
│ │ │ ├── `peer0.orgcpp.itcast.com
│ │ │ │ ├── msp
│ │ │ │ └── tls
│ │ │ └── `peer1.orgcpp.itcast.com
│ │ │ ├── msp
│ │ │ └── tls
│ │ ├── tlsca
│ │ │ ├── 1732fcf1ac3ccfab09c6acbe767af2442b0711ea1128c1d6c1ce059b563266c8_sk
│ │ │ └── tlsca.orgcpp.itcast.com-cert.pem
│ │ └── users
│ │ ├── Admin@orgcpp.itcast.com
│ │ │ ├── msp
│ │ │ └── tls
│ │ ├── User1@orgcpp.itcast.com
│ │ │ ├── msp
│ │ │ └── tls
│ │ ├── User2@orgcpp.itcast.com
│ │ │ ├── msp
│ │ │ └── tls
│ │ ├── User3@orgcpp.itcast.com
│ │ │ ├── msp
│ │ │ └── tls
│ │ └── User4@orgcpp.itcast.com
│ │ ├── msp
│ │ └── tls
│ └── `orggo.itcast.com
│ ├── ca
│ │ ├── 33dbbd366922252ee8689e0444e8b6ffb3df3389219ad0716ee9708c2c18953d_sk
│ │ └── ca.orggo.itcast.com-cert.pem
│ ├── msp
│ │ ├── admincerts
│ │ │ └── Admin@orggo.itcast.com-cert.pem
│ │ ├── cacerts
│ │ │ └── ca.orggo.itcast.com-cert.pem
│ │ ├── config.yaml
│ │ └── tlscacerts
│ │ └── tlsca.orggo.itcast.com-cert.pem
│ ├── `peers
│ │ ├── `peer0.orggo.itcast.com
│ │ │ ├── msp
│ │ │ └── tls
│ │ └── `peer1.orggo.itcast.com
│ │ ├── msp
│ │ └── tls
│ ├── tlsca
│ │ ├── ab7a23f336678f1d8799a44aaeb8894503abb6177d6ba1740037fda952ff9bdb_sk
│ │ └── tlsca.orggo.itcast.com-cert.pem
│ └── users
│ ├── Admin@orggo.itcast.com
│ │ ├── msp
│ │ └── tls
│ ├── User1@orggo.itcast.com
│ │ ├── msp
│ │ └── tls
│ ├── User2@orggo.itcast.com
│ │ ├── msp
│ │ └── tls
│ └── User3@orggo.itcast.com
│ ├── msp
│ └── tls
└── crypto-config.yaml
# 4.2 创始块和通道文件的创建
Fabric是基于区块链的分布式账本, 每个账本都有自己的区块, 账本的区块链中会存储账本的交易数据,但账本的第一个区块是一个例外,该区块不存储交易数据而是存储配置信息,通常账本的第一个区块称为创始块。
我们需要些编写生成创始块文件的配置文件,配置文件名字为
configtx.yaml, 该名字不要修改
, 写好之后放入Demo
目录中
# configtx.yaml
---
################################################################################
#
# Section: Organizations
#
# - This section defines the different organizational identities which will
# be referenced later in the configuration.
#
################################################################################
Organizations:
- &OrdererOrg
Name: OrdererOrg
ID: OrdererMSP
MSPDir: ./crypto-config/ordererOrganizations/itcast.com/msp
- &OrgGo
Name: OrgGoMSP
ID: OrgGoMSP
MSPDir: ./crypto-config/peerOrganizations/orggo.itcast.com/msp
AnchorPeers:
- Host: peer0.orggo.itcast.com
Port: 7051
- &OrgCPP
Name: OrgCppMSP
ID: OrgCppMSP
MSPDir: ./crypto-config/peerOrganizations/orgcpp.itcast.com/msp
AnchorPeers:
- Host: peer0.orgcpp.itcast.com
Port: 7051
################################################################################
#
# SECTION: Capabilities
#
# - This section defines the capabilities of fabric network. This is a new
# concept as of v1.1.0 and should not be utilized in mixed networks with
# v1.0.x peers and orderers.
#
################################################################################
Capabilities:
Global: &ChannelCapabilities
V1_1: true
Orderer: &OrdererCapabilities
V1_1: true
Application: &ApplicationCapabilities
V1_2: true
################################################################################
#
# SECTION: Application
#
# - This section defines the values to encode into a config transaction or
# genesis block for application related parameters
#
################################################################################
Application: &ApplicationDefaults
Organizations:
################################################################################
#
# SECTION: Orderer
#
# - This section defines the values to encode into a config transaction or
# genesis block for orderer related parameters
#
################################################################################
Orderer: &OrdererDefaults
# Available types are "solo" and "kafka"
OrdererType: solo
Addresses:
- ubuntu.itcast.com:7050
# Batch Timeout: The amount of time to wait before creating a batch
BatchTimeout: 2s
# Batch Size: Controls the number of messages batched into a block
BatchSize:
# Max Message Count: The maximum number of messages to permit in a batch
MaxMessageCount: 10
AbsoluteMaxBytes: 99 MB
PreferredMaxBytes: 512 KB
Kafka:
# Brokers: A list of Kafka brokers to which the orderer connects
# NOTE: Use IP:port notation
Brokers:
- 127.0.0.1:9092
Organizations:
################################################################################
#
# Profile
#
# - Different configuration profiles may be encoded here to be specified
# as parameters to the configtxgen tool
#
################################################################################
Profiles:
ItcastOrdererGenesis:
Capabilities:
<<: *ChannelCapabilities
Orderer:
<<: *OrdererDefaults
Organizations:
- *OrdererOrg
Capabilities:
<<: *OrdererCapabilities
Consortiums:
SampleConsortium:
Organizations:
- *OrgGo
- *OrgCPP
TwoOrgsChannel:
Consortium: SampleConsortium
Application:
<<: *ApplicationDefaults
Organizations:
- *OrgGo
- *OrgCPP
Capabilities:
<<: *ApplicationCapabilities
# 1. 在Demo目录下创建新目录 channel-artifacts, 将生成的创始块和通道文件存储在该目录中
$ mkdir channel-artifacts
# 生成创始块文件
$ configtxgen -profile ItcastOrdererGenesis -outputBlock ./channel-artifacts/genesis.block
通道(频道)在Fabric中称为channel, 一个channel表示一个账本。fabric和其他区块链平台最大的区别是支持多账本。每个fabric中至少包含一个channel,下边我们将通过命令将通道创建出来。
# 创建channel
# channel.tx中包含了用于生产channel的信息
$ configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID mychannel
# 生成相关的锚点文件 - 组织1: Go
$ configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/OrgGoMSPanchors.tx -channelID mychannel -asOrg OrgGoMSP
# 生成相关的锚点文件 - 组织2: CPP
$ configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/OrgCppMSPanchors.tx -channelID mychannel -asOrg OrgCppMSP
# 查看channel-artifacts目录下生成的文件
$ tree channel-artifacts/
channel-artifacts/
├── channel.tx # 通道文件
├── genesis.block # 创始块文件
├── orgCppMSPanchors.tx # Cpp组织锚点文件
└── orgGoMSPanchors.tx # Go组织锚点文件
# 4.3 启动docker-compose
# 4.3.1 编写配置文件
编写docker-compose启动时加载的配置文件,默认加载的文件名为:``docker-compose.yml/yaml
,可通过命令
docker-compose --help查看。我们将该文件放到项目目录
~/Demo`中。
# docker-compose.yml
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
# compose 版本号
version: '2'
# 数据卷映射, 本地 -> docker镜像
volumes:
ubuntu.itcast.com:
peer0.orggo.itcast.com:
peer1.orggo.itcast.com:
peer0.orgcpp.itcast.com:
peer1.orgcpp.itcast.com:
networks: # 指定容器运行的网络, 同一网络中的容器才能相互通信
byfn:
services:
ubuntu.itcast.com: # 定义的第1个服务名
extends: # 继承自当前yaml文件或者其它文件中定义的服务
file: base/docker-compose-base.yaml
# 要继承上述file文件中对应的名字叫做 ubuntu.itcast.com 的服务
service: ubuntu.itcast.com
container_name: ubuntu.itcast.com # 容器名称, 可以自定义
networks: # 指定容器启动后运行的网络名
- byfn
peer0.orggo.itcast.com: # 定义的第2个服务名
container_name: peer0.orggo.itcast.com
extends:
file: base/docker-compose-base.yaml
service: peer0.orggo.itcast.com
networks:
- byfn
peer1.orggo.itcast.com: # 定义的第3个服务名
container_name: peer1.orggo.itcast.com
extends:
file: base/docker-compose-base.yaml
service: peer1.orggo.itcast.com
networks:
- byfn
peer0.orgcpp.itcast.com: # 定义的第4个服务名
container_name: peer0.orgcpp.itcast.com
extends:
file: base/docker-compose-base.yaml
service: peer0.orgcpp.itcast.com
networks:
- byfn
peer1.orgcpp.itcast.com: # 定义的第5个服务名
container_name: peer1.orgcpp.itcast.com
extends:
file: base/docker-compose-base.yaml
service: peer1.orgcpp.itcast.com
networks:
- byfn
cli: # 定义的第6个服务名
container_name: cli
image: hyperledger/fabric-tools:latest # 指定服务的镜像名称或镜像 ID
tty: true
stdin_open: true
environment: # 环境变量设置
- GOPATH=/opt/gopath
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
- CORE_LOGGING_LEVEL=DEBUG
#- CORE_LOGGING_LEVEL=INFO
- CORE_PEER_ID=cli
- CORE_PEER_ADDRESS=peer0.orggo.itcast.com:7051
- CORE_PEER_LOCALMSPID=OrgGoMSP
- CORE_PEER_TLS_ENABLED=true
- CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orggo.itcast.com/peers/peer0.orggo.itcast.com/tls/server.crt
- CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orggo.itcast.com/peers/peer0.orggo.itcast.com/tls/server.key
- CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orggo.itcast.com/peers/peer0.orggo.itcast.com/tls/ca.crt
- CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orggo.itcast.com/users/Admin@orggo.itcast.com/msp
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer # 工作目录
command: /bin/bash # 容器启动后执行的命令
volumes: # 本地数据卷内容挂载到容器, 挂载到容器中的数据是只读的
- /var/run/:/host/var/run/
- ./chaincode/:/opt/gopath/src/github.com/chaincode
- ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/
- ./scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/
- ./channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts
depends_on: # 指定了容器的启动顺序, 下边5个服务全部启动之后, 启动cli服务
- ubuntu.itcast.com # 定义的服务器名1
- peer0.orggo.itcast.com # 定义的服务器名2
- peer1.orggo.itcast.com # 定义的服务器名3
- peer0.orgcpp.itcast.com # 定义的服务器名4
- peer1.orgcpp.itcast.com # 定义的服务器名5
networks:
- byfn
接下来就上面
docker-compose.yaml
文件中依赖的文件docker-compose-base.yaml
,根据上面的指定可以知道该文件是放到base目录中,也就是说需要在Demo目录中创建子目录base:mkdir base
。
# ~/Demo/base/docker-compose-base.yaml
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
version: '2'
services:
ubuntu.itcast.com: # 排序节点服务名称
container_name: ubuntu.itcast.com
image: hyperledger/fabric-orderer:latest
environment:
- ORDERER_GENERAL_LOGLEVEL=INFO
- ORDERER_GENERAL_LISTENADDRESS=0.0.0.0
- ORDERER_GENERAL_GENESISMETHOD=file
- ORDERER_GENERAL_GENESISFILE=/var/hyperledger/orderer/orderer.genesis.block
- ORDERER_GENERAL_LOCALMSPID=OrdererMSP
- ORDERER_GENERAL_LOCALMSPDIR=/var/hyperledger/orderer/msp
# enabled TLS
- ORDERER_GENERAL_TLS_ENABLED=true
- ORDERER_GENERAL_TLS_PRIVATEKEY=/var/hyperledger/orderer/tls/server.key
- ORDERER_GENERAL_TLS_CERTIFICATE=/var/hyperledger/orderer/tls/server.crt
- ORDERER_GENERAL_TLS_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt]
working_dir: /opt/gopath/src/github.com/hyperledger/fabric
command: orderer
volumes:
- ../channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block
- ../crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/msp:/var/hyperledger/orderer/msp
- ../crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/:/var/hyperledger/orderer/tls
- orderer.example.com:/var/hyperledger/production/orderer
ports:
- 7050:7050
peer0.orggo.itcast.com:
container_name: peer0.orggo.itcast.com
extends:
file: peer-base.yaml
service: peer-base
environment:
- CORE_PEER_ID=peer0.orggo.itcast.com
- CORE_PEER_ADDRESS=peer0.orggo.itcast.com:7051
- CORE_PEER_GOSSIP_BOOTSTRAP=peer0.orggo.itcast.com:7051
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.orggo.itcast.com:7051
- CORE_PEER_LOCALMSPID=OrgGoMSP
volumes:
- /var/run/:/host/var/run/
- ../crypto-config/peerOrganizations/orggo.example.com/peers/peer0.orggo.itcast.com/msp:/etc/hyperledger/fabric/msp
- ../crypto-config/peerOrganizations/orggo.example.com/peers/peer0.orggo.itcast.com/tls:/etc/hyperledger/fabric/tls
- peer0.orggo.itcast.com:/var/hyperledger/production
ports:
- 7051:7051
- 7053:7053
peer1.orggo.itcast.com:
container_name: peer1.orggo.itcast.com
extends:
file: peer-base.yaml
service: peer-base
environment:
- CORE_PEER_ID=peer1.orggo.itcast.com
- CORE_PEER_ADDRESS=peer1.orggo.itcast.com:7051
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.orggo.itcast.com:7051
- CORE_PEER_GOSSIP_BOOTSTRAP=peer1.orggo.itcast.com:7051
- CORE_PEER_LOCALMSPID=OrgGoMSP
volumes:
- /var/run/:/host/var/run/
- ../crypto-config/peerOrganizations/orggo.itcast.com/peers/peer1.orggo.itcast.com/msp:/etc/hyperledger/fabric/msp
- ../crypto-config/peerOrganizations/orggo.itcast.com/peers/peer1.orggo.itcast.com/tls:/etc/hyperledger/fabric/tls
- peer1.orggo.itcast.com:/var/hyperledger/production
ports:
- 8051:7051
- 8053:7053
peer0.orgcpp.itcast.com:
container_name: peer0.orgcpp.itcast.com
extends:
file: peer-base.yaml
service: peer-base
environment:
- CORE_PEER_ID=peer0.orgcpp.itcast.com
- CORE_PEER_ADDRESS=peer0.orgcpp.itcast.com:7051
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.orgcpp.itcast.com:7051
- CORE_PEER_GOSSIP_BOOTSTRAP=peer0.orgcpp.itcast.com:7051
- CORE_PEER_LOCALMSPID=OrgCppMSP
volumes:
- /var/run/:/host/var/run/
- ../crypto-config/peerOrganizations/orgcpp.itcast.com/peers/peer0.orgcpp.itcast.com/msp:/etc/hyperledger/fabric/msp
- ../crypto-config/peerOrganizations/orgcpp.itcast.com/peers/peer0.orgcpp.itcast.com/tls:/etc/hyperledger/fabric/tls
- peer0.orgcpp.itcast.com:/var/hyperledger/production
ports:
- 9051:7051
- 9053:7053
peer1.orgcpp.itcast.com:
container_name: peer1.orgcpp.itcast.com
extends:
file: peer-base.yaml
service: peer-base
environment:
- CORE_PEER_ID=peer1.orgcpp.itcast.com
- CORE_PEER_ADDRESS=peer1.orgcpp.itcast.com:7051
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.orgcpp.itcast.com:7051
- CORE_PEER_GOSSIP_BOOTSTRAP=peer1.orgcpp.itcast.com:7051
- CORE_PEER_LOCALMSPID=Org2MSP
volumes:
- /var/run/:/host/var/run/
- ../crypto-config/peerOrganizations/orgcpp.example.com/peers/peer1.orgcpp.itcast.com/msp:/etc/hyperledger/fabric/msp
- ../crypto-config/peerOrganizations/orgcpp.example.com/peers/peer1.orgcpp.itcast.com/tls:/etc/hyperledger/fabric/tls
- peer1.orgcpp.itcast.com:/var/hyperledger/production
ports:
- 10051:7051
- 10053:7053
在上面的docker-compose-base.yaml文件中又引用了文件
peer-base.yaml
,接下来我们对该文件进行修改。
# ~/Demo/base/peer-base.yaml
version: '2'
services:
peer-base:
image: hyperledger/fabric-peer:latest
environment:
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
# the following setting starts chaincode containers on the same
# bridge network as the peers
# https://docs.docker.com/compose/networking/
- CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=Demo_byfn
- CORE_LOGGING_LEVEL=INFO
#- CORE_LOGGING_LEVEL=DEBUG
- CORE_PEER_TLS_ENABLED=true
- CORE_PEER_GOSSIP_USELEADERELECTION=true
- CORE_PEER_GOSSIP_ORGLEADER=false
- CORE_PEER_PROFILE_ENABLED=true
- CORE_PEER_TLS_CERT_FILE=/etc/hyperledger/fabric/tls/server.crt
- CORE_PEER_TLS_KEY_FILE=/etc/hyperledger/fabric/tls/server.key
- CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
command: peer node start
# 4.3.2 通过docker-compose启动容器
docker-compose的配置文件编写完成之后, 我们就可以通过配置文件中的配置将所有节点的容器全部启动起来.
# 启动容器
# 在 ~/Demo目录下启动docker-compose, 该目录下有编写好的docker-compose.yaml文件
# 命令启动之后, 会自动加载该文件, 也可以通过-f指定要加载的yaml文件
$ docker-compose up -d
Creating network "demo_byfn" with the default driver
Creating volume "demo_peer1.orggo.itcast.com" with default driver
Creating volume "demo_ubuntu.itcast.com" with default driver
Creating volume "demo_peer0.orgcpp.itcast.com" with default driver
Creating volume "demo_peer0.orggo.itcast.com" with default driver
Creating volume "demo_peer1.orgcpp.itcast.com" with default driver
Creating peer0.orgcpp.itcast.com ... done
Creating peer1.orgcpp.itcast.com ... done
Creating peer1.orggo.itcast.com ... done
Creating peer0.orggo.itcast.com ... done
Creating ubuntu.itcast.com ... done
Creating cli ... done
# 查看已启动的容器
$ docker-compose ps
Name Command State Ports
-------------------------------------------------------------------------------------------
cli /bin/bash Up
peer0.orgcpp.itcast.com peer node start Up 0.0.0.0:9051->7051/tcp, 0.0.0.0:9053->7053/tcp
peer0.orggo.itcast.com peer node start Up 0.0.0.0:7051->7051/tcp, 0.0.0.0:7053->7053/tcp
peer1.orgcpp.itcast.com peer node start Up 0.0.0.0:10051->7051/tcp,0.0.0.0:10053->7053/tcp
peer1.orggo.itcast.com peer node start Up 0.0.0.0:8051->7051/tcp, 0.0.0.0:8053->7053/tcp
ubuntu.itcast.com orderer Up 0.0.0.0:7050->7050/tcp
# 4.4 channel管理
# 4.4.1 操作步骤
这个动作需要在cli容器中运行
创建channel
# 进入cli容器 $ docker exec -it cli bash $ peer channel create -o ubuntu.itcast.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/channel.tx --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA # 参数说明: - ubuntu.itcast.com: 连接的orderer的地址,hostname:port - $CHANNEL_NAME: channel的名称,如果没有指定,默认为mychannel, 通道创建成功之后会在磁盘生成 一个文件, 名字为$CHANNEL_NAME.block(通道名.block) - $CORE_PEER_TLS_ENABLED: 和orderer通信时是否启用tls - $ORDERER_CA: 使用tls时,所使用的orderer的证书
该命令执行过程:
- 发送消息,创建了channel,名字为
$CHANNEL_NAME
- 获取创始区块,并且用protobuf进行序列化,本地生成了一个文件
$CHANNEL_NAME.block
- 发送消息,创建了channel,名字为
将peer节点添加到channel中
$ peer channel join -b $CHANNEL_NAME.block # 参数说明: $CHANNEL_NAME.block, 创建出的通道文件的名字
将每个组织的锚节点(anchor peer)更新到orderer
$ peer channel update -o ubuntu.itcast.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/${CORE_PEER_LOCALMSPID}anchors.tx --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA # 参数说明: - ubuntu.itcast.com: 连接的orderer的地址,hostname:port - ${CORE_PEER_LOCALMSPID}anchors.tx: 组织的锚节点文件, 是通过configtxgen指令生成的 - $CORE_PEER_TLS_ENABLED: 和orderer通信时是否启用tls - $ORDERER_CA: 使用tls时,所使用的orderer的证书
# 4.4.2 脚本编写
上述操作需要对多个节点进行操作,因此我们可以写一个脚本文件, 对这些操作进行统一处理,方便使用者进行操作。为了对编写的脚本统一管理,可以将其放入一个目录中。
我们可以在
~/Demo
目录下创建新的子目录scripts
, 将所有的脚本文件放到里边。编写的脚本如下:
会被调用多次的操作, 我们将其放到一个单独的脚本文件中
# 该脚本文件我们命名为 utils.sh
# ~/Demo/utils.sh
# 定义一些变量, 下边的代码中会使用
# orderer 节点的证书
ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/itcast.com/orderers/ubuntu.itcast.com/msp/tlscacerts/tlsca.itcast.com-cert.pem
# Go组织peer0节点证书
PEER0_ORGGO_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orggo.itcast.com/peers/peer0.orggo.itcast.com/tls/ca.crt
# CPP组织peer0节点证书
PEER0_ORGCPP_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orgcpp.itcast.com/peers/peer0.orgcpp.itcast.com/tls/ca.crt
# 根据传递进行来的参数读取各个组织中各节点信息
# 第一次参数表示节点编号, 第二个参数表示组织编号
setGlobals() {
PEER=$1
ORG=$2
if [ $ORG -eq 1 ]; then
CORE_PEER_LOCALMSPID="OrgGoMSP" # Go组织的ID, 在configtx.yaml中设置的
# 客户端cli想要连接哪个节点, 就必须要设置该节点的证书路径
CORE_PEER_TLS_ROOTCERT_FILE=$PEER0_ORGGO_CA # cli可以连接Go组织的peer0节点
# Go组织的管理员证书
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/
peerOrganizations/orggo.itcast.com/users/Admin@orggo.itcast.com/msp
if [ $PEER -eq 0 ]; then
CORE_PEER_ADDRESS=peer0.orggo.itcast.com:7051 # go组织peer0地址
else
CORE_PEER_ADDRESS=peer1.orggo.itcast.com:7051 # go组织peer1地址
fi
elif [ $ORG -eq 2 ]; then
CORE_PEER_LOCALMSPID="OrgCppMSP" # CPP组织ID
CORE_PEER_TLS_ROOTCERT_FILE=$PEER0_ORGCPP_CA # cli可以连接CPP组织的peer0节点
# CPP组织的管理员证书
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/
peerOrganizations/orgcpp.itcast.com/users/Admin@orgcpp.itcast.com/msp
if [ $PEER -eq 0 ]; then
CORE_PEER_ADDRESS=peer0.orgcpp.itcast.com:7051 # cpp组织peer0地址
else
CORE_PEER_ADDRESS=peer1.orgcpp.itcast.com:7051 # cpp组织peer0地址
fi
else
echo "================== ERROR !!! ORG Unknown =================="
fi
if [ "$VERBOSE" == "true" ]; then
env | grep CORE
fi
}
# 该函数对命令执行的结果进行验证, 如果验证失败, 直接退出, 不再执行后续操作流程
verifyResult() {
if [ $1 -ne 0 ]; then
echo "!!!!!!!!!!!!!!! "$2" !!!!!!!!!!!!!!!!"
echo "========= ERROR !!! FAILED ==========="
echo
exit 1
fi
}
创建通道操作:
# 该脚本文件我们命名为createChannel.sh
# ~/Demo/createChannel.sh
# 定义一些变量, 下边的代码中会使用
CHANNEL_NAME="$1" # 脚本文件执行时接收的第1个参数
DELAY="$2" # 脚本文件执行时接收的第2个参数
LANGUAGE="$3" # 脚本文件执行时接收的第3个参数
: ${CHANNEL_NAME:="mychannel"} # 通道名,如果值为空, 变量CHANNEL_NAME值设置为mychannel
: ${DELAY:="3"} # 延时时长,如果值为空, 变量DELAY值设置为3, 操作失败重试时使用
: ${LANGUAGE:="golang"} # 链码语言,如果值为空, 变量LANGUAGE值设置为golang
LANGUAGE=`echo "$LANGUAGE" | tr [:upper:] [:lower:]` # 语言转换为大写,再转换为小写
COUNTER=1 # 计数器
MAX_RETRY=5 # 操作失败,重试的次数
# 链码文件路径
CC_SRC_PATH="github.com/chaincode/chaincode_example02/go/" # go链码
if [ "$LANGUAGE" = "node" ]; then # node.js链码
CC_SRC_PATH="/opt/gopath/src/github.com/chaincode/chaincode_example02/node/"
fi
echo "Channel name : "$CHANNEL_NAME # 打印通道的名字
# ====================================================
# 创建通道
# ====================================================
# 引用 utils.sh 脚本, 该文件也被创建在scripts目录中
. scripts/utils.sh
createChannel() {
setGlobals 0 1
if [ -z "$CORE_PEER_TLS_ENABLED" -o "$CORE_PEER_TLS_ENABLED" = "false" ]; then
set -x
# 创建通道, 不使用tls加密, 结果重定向到文件log.txt中
peer channel create -o ubuntu.itcast.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/channel.tx >&log.txt
res=$? # 保存 peer channel create 命令的返回值
set +x
else
set -x
# 创建通道, 使用tls加密, 结果重定向到文件log.txt中
peer channel create -o ubuntu.itcast.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/channel.tx --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA >&log.txt
res=$? # 保存 peer channel create 命令的返回值
set +x
fi
cat log.txt # 将log文件内容输出到终端
verifyResult $res "Channel creation failed" # 验证操作是否成功
echo "===================== Channel '$CHANNEL_NAME' created ===================== "
echo
}
# 调用创建通道的函数
createChannel
将节点添加到通道中
# 该脚本文件我们命名为joinChannel.sh
# ~/Demo/joinChannel.sh
# 定义一些变量, 下边的代码中会使用
# ====================================================
# 加入通道
# ====================================================
# 引用 utils.sh, createChannel.sh 脚本, 该文件也被创建在scripts目录中
. scripts/utils.sh
. scripts/createChannel.sh
joinChannel () {
for org in 1 2; do
for peer in 0 1; do
joinChannelWithRetry $peer $org
echo "======== peer${peer}.org${org} joined channel '$CHANNEL_NAME' ======== "
sleep $DELAY
echo
done
done
}
joinChannelWithRetry() {
PEER=$1
ORG=$2
setGlobals $PEER $ORG
set -x
peer channel join -b $CHANNEL_NAME.block >&log.txt
res=$?
set +x
cat log.txt
if [ $res -ne 0 -a $COUNTER -lt $MAX_RETRY ]; then
COUNTER=$(expr $COUNTER + 1)
echo "peer${PEER}.org${ORG} failed to join the channel, Retry after $DELAY seconds"
sleep $DELAY
joinChannelWithRetry $PEER $ORG
else
COUNTER=1
fi
verifyResult $res "After $MAX_RETRY attempts, peer${PEER}.org${ORG} has failed to join channel '$CHANNEL_NAME' "
}
# 函数调用
joinChannel
将每个组织的锚节点(anchor peer)更新到orderer
# 该脚本文件我们命名为updateChannel.sh
# ~/Demo/updateChannel.sh
# 引用 utils.sh, createChannel.sh 脚本, 该文件也被创建在scripts目录中
. scripts/utils.sh
. scripts/createChannel.sh
updateAnchorPeers() {
PEER=$1
ORG=$2
setGlobals $PEER $ORG
if [ -z "$CORE_PEER_TLS_ENABLED" -o "$CORE_PEER_TLS_ENABLED" = "false" ]; then
set -x
# 更新锚节点不使用tls加密, 得到的结果保存到log.txt中
peer channel update -o ubuntu.itcast.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/${CORE_PEER_LOCALMSPID}anchors.tx >&log.txt
res=$?
set +x
else
set -x
# 更新锚节点使用tls加密, 得到的结果保存到log.txt中
peer channel update -o ubuntu.itcast.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/${CORE_PEER_LOCALMSPID}anchors.tx --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA >&log.txt
res=$?
set +x
fi
cat log.txt
verifyResult $res "Anchor peer update failed"
echo " Anchor peers updated for org '$CORE_PEER_LOCALMSPID' on channel '$CHANNEL_NAME' "
sleep $DELAY # 休眠
echo
}
# 函数调用
echo "Updating anchor peers for orggo..."
updateAnchorPeers 0 1
echo "Updating anchor peers for orgcpp..."
updateAnchorPeers 0 2
# 4.5 chaincode安装和实例化
# 该脚本文件我们命名为installChainCode.sh
# ~/Demo/installChainCode.sh
# 引用 utils.sh, createChannel.sh 脚本, 该文件也被创建在scripts目录中
. scripts/utils.sh
. scripts/createChannel.sh
# 安装链码
installChaincode()
{
PEER=$1
ORG=$2
setGlobals $PEER $ORG
VERSION=${3:-1.0}
set -x
peer chaincode install -n mycc -v ${VERSION} -l ${LANGUAGE} -p ${CC_SRC_PATH} >&log.txt
res=$?
set +x
cat log.txt
verifyResult $res "Chaincode installation on peer${PEER}.org${ORG} has failed"
echo "===================== Chaincode is installed on peer${PEER}.org${ORG} ===================== "
echo
}
# 链码初始化
instantiateChaincode()
{
PEER=$1
ORG=$2
setGlobals $PEER $ORG
VERSION=${3:-1.0}
# while 'peer chaincode' command can get the orderer endpoint from the peer
# (if join was successful), let's supply it directly as we know it using
# the "-o" option
if [ -z "$CORE_PEER_TLS_ENABLED" -o "$CORE_PEER_TLS_ENABLED" = "false" ]; then
set -x
peer chaincode instantiate -o ubuntu.itcast.com:7050 -C $CHANNEL_NAME -n mycc -l ${LANGUAGE} -v ${VERSION} -c '{"Args":["init","a","100","b","200"]}' -P "AND ('OrgGoMSP.peer','OrgCppMSP.peer')" >&log.txt
res=$?
set +x
else
set -x
peer chaincode instantiate -o ubuntu.itcast.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -l ${LANGUAGE} -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P "AND ('OrgGoMSP.peer','OrgCppMSP.peer')" >&log.txt
res=$?
set +x
fi
cat log.txt
verifyResult $res "Chaincode instantiation on peer${PEER}.org${ORG} on channel '$CHANNEL_NAME' failed"
echo " Chaincode is instantiated on peer${PEER}.org${ORG} on channel '$CHANNEL_NAME'"
echo
}
# 函数调用
# go组织的peer0, peer1安装链码
echo "Install chaincode on peer0.orggo..."
#nstallChaincode 0 1
echo "Install chaincode on peer0.orggo..."
installChaincode 0 2
# cpp组织的peer0, peer1安装链码
# go组织的peer0进行初始化
echo "Instantiating chaincode on peer0.org2..."
instantiateChaincode 0 2
← 3Fabric核心模块 5智能合约 →