4 搭建第一个自己的网络
下面让我们手动搭建一个自己的fabric 网络:
- 创建一个项目目录: 如
mkdir ~/Demo- orderer节点个数为1个
- 组织个数2个
- OrgGo
- OrgCPP
- OrgGo有两个peer节点, 该组织有3个用户
- OrgCpp有两个peer节点, 该组织有4个用户
4.1 生成Fabric的证书
编写生成组织节点证书的配置文件,我们将其命名为: crypto-config.yaml。在里边指定组织的名称, 节点个数, 用户个数和访问节点的域名信息。
将如下写好的配置文件放入目录:
~/Demo中
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.yamlorggo.itcast.comorgcpp.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.yaml4.2 创始块和通道文件的创建
Fabric是基于区块链的分布式账本, 每个账本都有自己的区块, 账本的区块链中会存储账本的交易数据,但账本的第一个区块是一个例外,该区块不存储交易数据而是存储配置信息,通常账本的第一个区块称为创始块。
我们需要些编写生成创始块文件的配置文件,配置文件名字为
configtx.yaml, 该名字不要修改, 写好之后放入Demo目录中
---################################################################################## 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`中。
# 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。
# 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,接下来我们对该文件进行修改。
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 start4.3.2 通过docker-compose启动容器
docker-compose的配置文件编写完成之后, 我们就可以通过配置文件中的配置将所有节点的容器全部启动起来.
# 启动容器# 在 ~/Demo目录下启动docker-compose, 该目录下有编写好的docker-compose.yaml文件# 命令启动之后, 会自动加载该文件, 也可以通过-f指定要加载的yaml文件$ docker-compose up -dCreating network "demo_byfn" with the default driverCreating volume "demo_peer1.orggo.itcast.com" with default driverCreating volume "demo_ubuntu.itcast.com" with default driverCreating volume "demo_peer0.orgcpp.itcast.com" with default driverCreating volume "demo_peer0.orggo.itcast.com" with default driverCreating volume "demo_peer1.orgcpp.itcast.com" with default driverCreating peer0.orgcpp.itcast.com ... doneCreating peer1.orgcpp.itcast.com ... doneCreating peer1.orggo.itcast.com ... doneCreating peer0.orggo.itcast.com ... doneCreating ubuntu.itcast.com ... doneCreating cli ... done# 查看已启动的容器$ docker-compose ps Name Command State Ports-------------------------------------------------------------------------------------------cli /bin/bash Uppeer0.orgcpp.itcast.com peer node start Up 0.0.0.0:9051->7051/tcp, 0.0.0.0:9053->7053/tcppeer0.orggo.itcast.com peer node start Up 0.0.0.0:7051->7051/tcp, 0.0.0.0:7053->7053/tcppeer1.orgcpp.itcast.com peer node start Up 0.0.0.0:10051->7051/tcp,0.0.0.0:10053->7053/tcppeer1.orggo.itcast.com peer node start Up 0.0.0.0:8051->7051/tcp, 0.0.0.0:8053->7053/tcpubuntu.itcast.com orderer Up 0.0.0.0:7050->7050/tcp4.4 channel管理
4.4.1 操作步骤
这个动作需要在cli容器中运行
-
创建channel
Terminal window # 进入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中
Terminal window $ peer channel join -b $CHANNEL_NAME.block# 参数说明:$CHANNEL_NAME.block, 创建出的通道文件的名字 -
将每个组织的锚节点(anchor peer)更新到orderer
Terminal window $ 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# 定义一些变量, 下边的代码中会使用# 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# 定义一些变量, 下边的代码中会使用CHANNEL_NAME="$1" # 脚本文件执行时接收的第1个参数DELAY="$2" # 脚本文件执行时接收的第2个参数LANGUAGE="$3" # 脚本文件执行时接收的第3个参数: ${CHANNEL_NAME:="mychannel"} # 通道名,如果值为空, 变量CHANNEL_NAME值设置为mychannel: ${DELAY:="3"} # 延时时长,如果值为空, 变量DELAY值设置为3, 操作失败重试时使用: ${LANGUAGE:="golang"} # 链码语言,如果值为空, 变量LANGUAGE值设置为golangLANGUAGE=`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/"fiecho "Channel name : "$CHANNEL_NAME # 打印通道的名字
# ====================================================# 创建通道# ====================================================# 引用 utils.sh 脚本, 该文件也被创建在scripts目录中. scripts/utils.shcreateChannel() { 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# 定义一些变量, 下边的代码中会使用# ====================================================# 加入通道# ====================================================# 引用 utils.sh, createChannel.sh 脚本, 该文件也被创建在scripts目录中. scripts/utils.sh. scripts/createChannel.shjoinChannel () { 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# 引用 utils.sh, createChannel.sh 脚本, 该文件也被创建在scripts目录中. scripts/utils.sh. scripts/createChannel.shupdateAnchorPeers() { 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 1echo "Updating anchor peers for orgcpp..."updateAnchorPeers 0 24.5 chaincode安装和实例化
# 该脚本文件我们命名为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 1echo "Install chaincode on peer0.orggo..."installChaincode 0 2# cpp组织的peer0, peer1安装链码# go组织的peer0进行初始化echo "Instantiating chaincode on peer0.org2..."instantiateChaincode 0 2