多机搭建前准备 #
这部分实验内容使用的是Ubuntu操作系统,所需要的实验环境与单节点搭建部分相同,包括docker
的安装golang
的安装fabric
的安装等。为了方便,以上环境已在虚拟机中安装完成。
1.网络结构 #
这部分课程我们要搭建一个多机多节点的网络,结构如下。网络中有两个组织分别为org1
、org2
,每个组织各有一个peer
节点,同时还有一个orderer
节点。
名称 | IP | hosts | 组织机构 |
---|---|---|---|
Orderer | 172.17.0.10 | orderer.test.com | orderer |
Org1peer0 | 172.17.0.11 | peer0.org1.test.com | org1 |
Org2peer0 | 172.17.0.12 | peer0.org2.test.com | org2 |
2.设置网络host #
使用以下命令,我们在三台虚拟机中分别查看当前虚拟机的IP,其中最后一行为本机IP。
cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.10 1cbb99f39f9a
配置所有服务器网络host,在三台虚拟机中都进行以下操作。
vi /etc/hosts
在最后插入(IP与host任意指定,确定后不能更改),写入以下内容后,按 Esc
键退回一般模式,然后输入 :wq
命令并回车保存退出文件。
172.17.0.10 orderer.test.com
172.17.0.11 peer0.org1.test.com
172.17.0.12 peer0.org2.test.com
3.ssh安装 #
在多机搭建的过程中我们会使用到scp
命令。Linux scp
命令用于 Linux 之间复制文件和目录。
scp
是 secure copy
的缩写, scp
是 Linux 系统下基于 ssh 登陆进行安全的远程文件拷贝命令。
以下内容需要在三台虚拟机中都操作。
实验环境中打开终端默认直接进入root
用户,在您个人的终端下需要键入su
来切换至root
用户。接着执行以下命令:
passwd root
输入要修改的root
用户密码,此指导书中以123456
为root
用户密码。输出信息如下:
Changing password for user root.
New password:
BAD PASSWORD: The password is shorter than 8 characters
Retype new password:
passwd: all authentication tokens updated successfully.
使用以下命令安装ssh,过程中会被询问是否继续安装,输入y
并按回车。
sudo apt-get install openssh-server
使用以下命令打开ssh配置文件。
vim /etc/ssh/sshd_config
将PermitRootLogin prohibit-password
改为PermitRootLogin yes
后按 Esc
键退回一般模式,然后输入 :wq
命令并回车保存退出文件。
使用以下命令重启ssh服务。
systemctl restart ssh
生成Fabric证书 #
1.创建项目目录 #
在三台虚拟机上使用以下命令创建相同的项目目录(三台虚拟机项目路径要相同)。
cd ~/hyperledger
mkdir multinodes
2.编写证书文件 #
证书文件的编写过程以及配置的内容与之前单节点搭建时大致相同,唯一不同的是这次我们要设置两个组织。创建证书文件的过程在任意一台主机上完成即可,以下的过程在orderer
节点的主机上完成。
首先使用以下命令进入项目目录。
cd ~/hyperledger/multinodes
使用以下命令将模板文件复制到当前目录下。
cryptogen showtemplate > crypto-config.yaml
使用vim将配置文件进行修改,修改如下(与单节点搭建相比我们新增了一个组织二,别的没有任何区别),按 Esc
键退回一般模式,然后输入 :wq
命令并回车保存退出文件。
OrdererOrgs:
- Name: Orderer
Domain: test.com
EnableNodeOUs: true
Specs:
- Hostname: orderer
PeerOrgs:
- Name: org1
Domain: org1.test.com
EnableNodeOUs: true
Template:
Count: 1
Users:
Count: 1
- Name: org2
Domain: org2.test.com
EnableNodeOUs: true
Template:
Count: 1
Users:
Count: 1
3.生成证书文件 #
使用以下命令生成证书文件。
cryptogen generate --config=crypto-config.yaml
使用ls
命令查看生成的文件,可以看到生成了crypto-config
文件,这里存放所有的证书文件。
ls
crypto-config crypto-config.yaml
使用scp
命令将证书文件复制到其他两台虚拟机中(使用scp
命令时会要求输入主机密码,就是我们之前设置的123456
)。
scp crypto-config root@172.17.0.11:~/hyperledger/multinodes/
scp crypto-config root@172.17.0.12:~/hyperledger/multinodes/
复制后使用以下命令在其他两台虚拟机的multinodes
目录下查看是否复制成功。
ls
crypto-config
生成通道文件 #
1.创世块文件的编写 #
首先回到orderer节点的虚拟机。
首先我们可以参考官方示例项目test-network
中的configtx.yaml
配置文件,使用以下命令进入其目录。
cd /root/hyperledger/fabric-samples/test-network/configtx
使用ls
命令查看文件。
ls
configtx.yaml
使用以下命令将这个配置文件复制到我们的项目路径中。
cp * ~/hyperledger/multinodes
使用以下命令回到我们的项目路径。
cd ~/hyperledger/multinodes
使用vim编辑器将configtx.yaml
改为以下内容,写入以下内容后,按 Esc
键退回一般模式,然后输入 :wq
命令并回车保存退出文件。
---
Organizations:
- &OrdererOrg
Name: OrdererOrg
ID: OrdererMSP
MSPDir: ./crypto-config/ordererOrganizations/test.com/msp
Policies:
Readers:
Type: Signature
Rule: "OR('OrdererMSP.member')"
Writers:
Type: Signature
Rule: "OR('OrdererMSP.member')"
Admins:
Type: Signature
Rule: "OR('OrdererMSP.admin')"
OrdererEndpoints:
- orderer.test.com:7050
- &Org1
Name: Org1MSP
ID: Org1MSP
MSPDir: ./crypto-config/peerOrganizations/org1.test.com/msp
Policies:
Readers:
Type: Signature
Rule: "OR('Org1MSP.admin', 'Org1MSP.peer', 'Org1MSP.client')"
Writers:
Type: Signature
Rule: "OR('Org1MSP.admin', 'Org1MSP.client')"
Admins:
Type: Signature
Rule: "OR('Org1MSP.admin')"
Endorsement:
Type: Signature
Rule: "OR('Org1MSP.peer')"
AnchorPeers:
- Host: peer0.org1.test.com
Port: 7051
- &Org2
Name: Org2MSP
ID: Org2MSP
MSPDir: ./crypto-config/peerOrganizations/org2.test.com/msp
Policies:
Readers:
Type: Signature
Rule: "OR('Org2MSP.admin', 'Org2MSP.peer', 'Org2MSP.client')"
Writers:
Type: Signature
Rule: "OR('Org2MSP.admin', 'Org2MSP.client')"
Admins:
Type: Signature
Rule: "OR('Org2MSP.admin')"
Endorsement:
Type: Signature
Rule: "OR('Org2MSP.peer')"
AnchorPeers:
- Host: peer0.org2.test.com
Port: 9051
Capabilities:
Channel: &ChannelCapabilities
V2_0: true
Orderer: &OrdererCapabilities
V2_0: true
Application: &ApplicationCapabilities
V2_0: true
Application: &ApplicationDefaults
Organizations:
Policies:
Readers:
Type: ImplicitMeta
Rule: "ANY Readers"
Writers:
Type: ImplicitMeta
Rule: "ANY Writers"
Admins:
Type: ImplicitMeta
Rule: "MAJORITY Admins"
LifecycleEndorsement:
Type: ImplicitMeta
Rule: "MAJORITY Endorsement"
Endorsement:
Type: ImplicitMeta
Rule: "MAJORITY Endorsement"
Capabilities:
<<: *ApplicationCapabilities
Orderer: &OrdererDefaults
OrdererType: solo
Addresses:
- orderer.test.com:7050
EtcdRaft:
Consenters:
- Host: orderer.example.com
Port: 7050
ClientTLSCert: ../organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt
ServerTLSCert: ../organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt
BatchTimeout: 2s
BatchSize:
MaxMessageCount: 10
AbsoluteMaxBytes: 99 MB
PreferredMaxBytes: 512 KB
Organizations:
Policies:
Readers:
Type: ImplicitMeta
Rule: "ANY Readers"
Writers:
Type: ImplicitMeta
Rule: "ANY Writers"
Admins:
Type: ImplicitMeta
Rule: "MAJORITY Admins"
BlockValidation:
Type: ImplicitMeta
Rule: "ANY Writers"
Channel: &ChannelDefaults
Policies:
Readers:
Type: ImplicitMeta
Rule: "ANY Readers"
Writers:
Type: ImplicitMeta
Rule: "ANY Writers"
Admins:
Type: ImplicitMeta
Rule: "MAJORITY Admins"
Capabilities:
<<: *ChannelCapabilities
Profiles:
TwoOrgsOrdererGenesis:
<<: *ChannelDefaults
Orderer:
<<: *OrdererDefaults
Organizations:
- *OrdererOrg
Capabilities:
<<: *OrdererCapabilities
Consortiums:
SampleConsortium:
Organizations:
- *Org1
- *Org2
TwoOrgsChannel:
Consortium: SampleConsortium
<<: *ChannelDefaults
Application:
<<: *ApplicationDefaults
Organizations:
- *Org1
- *Org2
Capabilities:
<<: *ApplicationCapabilities
与单节点搭建的区别:
- Organizations部分多了Org2的配置。
- Profiles的部分创世块名称与通道名称不同。单节点搭建部分为soloOrgsOrdererGenesis和soloOrgsChannel,多节点搭建部分为TwoOrgsOrdererGenesis和TwoOrgsChannel。(创世块名称与通道名称自己任意取,但是后面使用命令生成文件时命令要与配置文件所定义的名称一致)
- Profiles部分创世块配置与通道配置中都多加入了Org2。
2.生成创世块文件和通道文件 #
使用以下命令生成创世区块。
./bin/configtxgen -profile TwoOrgsgenesis -channelID fabric-channel -outputBlock ./channel-artifacts/genesis.block
使用以下命令生成通道文件。
./bin/configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID mychannel
使用以下命令为 Org1 定义锚节点。
./bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID mychannel -asOrg Org1MSP
使用以下命令为 Org2 定义锚节点。
./bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID mychannel -asOrg Org2MSP
使用以下命令将生成的文件拷贝到另两台主机(过程中会需要输入宿主机的密码,就是我们之前设置的123456)。
scp -r channel-artifacts root@172.17.0.11:~/hyperledger/multipeer/
scp -r channel-artifacts root@172.17.0.11:~/hyperledger/multipeer/
复制后使用以下命令在其他两台虚拟机的multinodes
目录下查看是否复制成功。
ls
channel-artifacts
docker-compose文件编写 #
在单节点实验中我们编写过一个docker-compose文件,在其中我们配置了orderer节点与peer节点。在多机部署的时候我们需要为每台虚拟机都编写一个docker-compose文件来配置相应的节点。多机部署与单机部署的配置文件内容大致相同,下面会介绍单机与多机的异同点。
1.orderer节点 #
使用以下命令在orderer节点的虚拟机的项目路径上创建一个docker-compose.yaml
文件。
cd ~/hyperledger/multinodes
vim docker-compose.yaml
写入以下内容后,按 Esc
键退回一般模式,然后输入 :wq
命令并回车保存退出文件。
version: '2'
services:
orderer.test.com:
container_name: orderer.test.com
image: hyperledger/fabric-orderer:latest
environment:
- FABRIC_LOGGING_SPEC=INFO
- ORDERER_GENERAL_LISTENADDRESS=0.0.0.0
- ORDERER_GENERAL_LISTENPORT=7050
- ORDERER_GENERAL_GENESISMETHOD=file
- ORDERER_GENERAL_GENESISFILE=/var/hyperledger/orderer/orderer.genesis.block
- ORDERER_GENERAL_LOCALMSPID=OrdererMSP
- ORDERER_GENERAL_LOCALMSPDIR=/var/hyperledger/orderer/msp
- 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]
- ORDERER_KAFKA_TOPIC_REPLICATIONFACTOR=1
- ORDERER_KAFKA_VERBOSE=true
- ORDERER_GENERAL_CLUSTER_CLIENTCERTIFICATE=/var/hyperledger/orderer/tls/server.crt
- ORDERER_GENERAL_CLUSTER_CLIENTPRIVATEKEY=/var/hyperledger/orderer/tls/server.key
- ORDERER_GENERAL_CLUSTER_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/test.com/orderers/orderer.test.com/msp:/var/hyperledger/orderer/msp
- ./crypto-config/ordererOrganizations/test.com/orderers/orderer.test.com/tls/:/var/hyperledger/orderer/tls
ports:
- 7050:7050
extra_hosts:
- "orderer.test.com:172.17.0.10"
- "peer0.org1.test.com:172.17.0.11"
- "peer0.org2.test.com:172.17.0.12"
与单机搭建的不同:
- 没有了卷挂载目录
orderer.test.com:/var/hyperledger/production/orderer
。 - 单机搭建中的网络名
networks: - test
改为extra_hosts:
,因为我们是多机搭建有真实的IP,所以网络名称都改为真实的IP地址。
2.org1 #
Fabric中peer节点的世界状态数据库默认是Leveldb,在这个部分我们将使用Couchdb。
Fabric的状态存储支持可插拔的模式,兼容LevelDB、CouchDB等存储。Fabric使用CouchDB作为状态存储与其他数据库相比具有较多优势:
- CouchDB是一种NoSQL解决方案。它是一个面向文档的数据库,其中文档字段存储为键值映射。字段可以是简单的键值对、列表或映射。除了支持类似LevelDB的键控/合成键/键范围查询之外,CouchDB还支持完整的数据富查询功能,比如针对整个区块链数据的非键查询,因为它的数据内容是以JSON格式存储的,并且是完全可查询的。因此,CouchDB可以满足LevelDB不支持的许多用例的链代码、审计和报告需求。
- CouchDB还可以增强区块链中的遵从性和数据保护的安全性。因为它能够通过筛选和屏蔽事务中的各个属性来实现字段级别的安全性,并且只在需要时授权只读权限。
- CouchDB属于CAP定理的ap类型(可用性和分区公差)。它使用具有最终一致性的主-主复制模型。更多信息可以在CouchDB文档的最终一致性页面上找到。然而,在每个fabric对等点下,没有数据库副本,对数据库的写操作保证一致和持久(而不是最终的一致性)。
- CouchDB是Fabric的第一个外部可插入状态数据库,可以而且应该有其他外部数据库选项。例如,IBM为其区块链启用关系数据库。还可能需要cp类型(一致性和分区容忍度)的数据库,以便在不保证应用层的情况下实现数据一致性。
使用以下命令在org1节点的虚拟机的项目路径上创建一个docker-compose.yaml
文件。
cd ~/hyperledger/multinodes
vim docker-compose.yaml
写入以下内容后,按 Esc
键退回一般模式,然后输入 :wq
命令并回车保存退出文件。
version: '2'
services:
couchdb0.org1.test.com:
container_name: couchdb0.org1.test.com
image: couchdb:3.1
environment:
- COUCHDB_USER=admin
- COUCHDB_PASSWORD=adminpw
ports:
- 5984:5984
peer0.org1.test.com:
container_name: peer0.org1.test.com
image: hyperledger/fabric-peer:latest
environment:
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
- CORE_PEER_ID=peer0.org1.test.com
- CORE_PEER_ADDRESS=peer0.org1.test.com:7051
- CORE_PEER_LISTENADDRESS=0.0.0.0:7051
- CORE_PEER_CHAINCODEADDRESS=peer0.org1.test.com:7052
- CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:7052
- CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org1.test.com:7051
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org1.test.com:7051
- CORE_PEER_LOCALMSPID=Org1MSP
- FABRIC_LOGGING_SPEC=INFO
- 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
- CORE_CHAINCODE_EXECUTETIMEOUT=300s
- CORE_LEDGER_STATE_STATEDATABASE=CouchDB
- CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb0.org1.test.com:5984
- CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=admin
- CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD=adminpw
depends_on:
- couchdb0.org1.test.com
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
command: peer node start
volumes:
- /var/run/:/host/var/run/
- ./crypto-config/peerOrganizations/org1.test.com/peers/peer0.org1.test.com/msp:/etc/hyperledger/fabric/msp
- ./crypto-config/peerOrganizations/org1.test.com/peers/peer0.org1.test.com/tls:/etc/hyperledger/fabric/tls
ports:
- 7051:7051
- 7052:7052
- 7053:7053
extra_hosts:
- "orderer.test.com:172.17.0.10"
- "peer0.org1.test.com:172.17.0.11"
- "peer0.org2.test.com:172.17.0.12"
cli:
container_name: cli
image: hyperledger/fabric-tools:latest
tty: true
stdin_open: true
environment:
- GOPATH=/opt/gopath
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
- FABRIC_LOGGING_SPEC=INFO
- CORE_PEER_ID=cli
- CORE_PEER_ADDRESS=peer0.org1.test.com:7051
- CORE_PEER_LOCALMSPID=Org1MSP
- CORE_PEER_TLS_ENABLED=true
- CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.test.com/peers/peer0.org1.test.com/tls/server.crt
- CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.test.com/peers/peer0.org1.test.com/tls/server.key
- CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.test.com/peers/peer0.org1.test.com/tls/ca.crt
- CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.test.com/users/Admin@org1.test.com/msp
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
command: /bin/bash
volumes:
- /var/run/:/host/var/run/
- ./chaincode/go/:/opt/gopath/src/github.com/hyperledger/fabric-cluster/chaincode/go
- ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/
- ./channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts
extra_hosts:
- "orderer.test.com:172.17.0.10"
- "peer0.org1.test.com:172.17.0.11"
- "peer0.org2.test.com:172.17.0.12"
与单机搭建的不同:
- 多了couchdb的配置。
- peer0节点环境变量多了
CORE_LEDGER_STATE_STATEDATABASE=CouchDB
,表示peer0节点的状态数据库采用了couchdb。 - 多了
depends_on: - couchdb0.org1.test.com
,表示在couchdb启动后再启动peer0节点。 - 单机搭建中的网络名
networks: - test
改为extra_hosts:
,因为我们是多机搭建有真实的IP,所以网络名称都改为真实的IP地址。
3.org2 #
组织二的配置文件与组织一基本相同,唯一不同点是把org1改为org2。
使用以下命令在org2节点的虚拟机的项目路径上创建一个docker-compose.yaml
文件。
cd ~/hyperledger/multinodes
vim docker-compose.yaml
写入以下内容后,按 Esc
键退回一般模式,然后输入 :wq
命令并回车保存退出文件。
version: '2'
services:
couchdb0.org2.test.com:
container_name: couchdb0.org2.test.com
image: couchdb:3.1
environment:
- COUCHDB_USER=admin
- COUCHDB_PASSWORD=adminpw
ports:
- 5984:5984
peer0.org2.test.com:
container_name: peer0.org2.test.com
image: hyperledger/fabric-peer:latest
environment:
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
- CORE_PEER_ID=peer0.org2.test.com
- CORE_PEER_ADDRESS=peer0.org2.test.com:7051
- CORE_PEER_LISTENADDRESS=0.0.0.0:7051
- CORE_PEER_CHAINCODEADDRESS=peer0.org2.test.com:7052
- CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:7052
- CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org2.test.com:7051
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org2.test.com:7051
- CORE_PEER_LOCALMSPID=Org2MSP
- FABRIC_LOGGING_SPEC=INFO
- 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
- CORE_CHAINCODE_EXECUTETIMEOUT=300s
- CORE_LEDGER_STATE_STATEDATABASE=CouchDB
- CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb0.org2.test.com:5984
- CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=admin
- CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD=adminpw
depends_on:
- couchdb0.org2.test.com
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
command: peer node start
volumes:
- /var/run/:/host/var/run/
- ./crypto-config/peerOrganizations/org2.test.com/peers/peer0.org2.test.com/msp:/etc/hyperledger/fabric/msp
- ./crypto-config/peerOrganizations/org2.test.com/peers/peer0.org2.test.com/tls:/etc/hyperledger/fabric/tls
ports:
- 7051:7051
- 7052:7052
- 7053:7053
extra_hosts:
- "orderer.test.com:172.17.0.10"
- "peer0.org1.test.com:172.17.0.11"
- "peer0.org2.test.com:172.17.0.12"
cli:
container_name: cli
image: hyperledger/fabric-tools:latest
tty: true
stdin_open: true
environment:
- GOPATH=/opt/gopath
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
- FABRIC_LOGGING_SPEC=INFO
- CORE_PEER_ID=cli
- CORE_PEER_ADDRESS=peer0.org2.test.com:7051
- CORE_PEER_LOCALMSPID=Org2MSP
- CORE_PEER_TLS_ENABLED=true
- CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.test.com/peers/peer0.org2.test.com/tls/server.crt
- CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.test.com/peers/peer0.org2.test.com/tls/server.key
- CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.test.com/peers/peer0.org2.test.com/tls/ca.crt
- CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.test.com/users/Admin@org2.test.com/msp
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
command: /bin/bash
volumes:
- /var/run/:/host/var/run/
- ./chaincode/go/:/opt/gopath/src/github.com/hyperledger/fabric-cluster/chaincode/go
- ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/
- ./channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts
extra_hosts:
- "orderer.test.com:172.17.0.10"
- "peer0.org1.test.com:172.17.0.11"
- "peer0.org2.test.com:172.17.0.12"
使用docker-compose
启动服务(三台机器均需要)。
docker-compose up
docker ps -a
通道操作 #
本节主要介绍的peer channel
命令,peer channel
命令主要是用于创建通道以及节点加入通道。
1 创建通道 #
使用docker exec
命令进入客户端容器(在Org1主机上操作)。
docker exec -it cli bash
使用以下命令在客户端容器中创建通道(在Org1容器上操作)。
peer channel create -o orderer.test.com:7050 -c mychannel -f ./channel-artifacts/channel.tx --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/test.com/msp/tlscacerts/tlsca.test.com-cert.pem
-o
,--orderer
: orderer节点的地址。-c
,--channelID
: 要创建的通道的ID, 必须小写, 在250个字符以内。-f
,-file
: 由configtxgen
生成的通道文件, 用于提交给orderer。-t
,--timeout
: 创建通道的超时时长, 默认为5s。--tls
: 通信时是否使用tls加密。--cafile
: 当前orderer节点pem格式的tls证书文件, 要使用绝对路径。- orderer节点pem格式的tls证书文件路径为:
crypto-config/ordererOrganizations/test.com/orderers/orderer.test.com/msp/tlscacerts/tlsca.test.com-cert.pem。
使用ls
命令查看生成的文件(在Org1容器上操作)。
ls
channel-artifacts crypto mychannel.block
使用以下命令将通道文件 mychannel.block 拷贝到宿主机(在Org1主机上操作)。
docker cp cli:/opt/gopath/src/github.com/hyperledger/fabric/peer/mychannel.block ./
然后使用以下命令拷贝到其他服务器上用于其他节点加入通道(在Org1主机上操作)。
scp mychannel.block root@172.17.0.12:~/hyperledger/multipeer/
使用以下命令将通道文件拷贝到容器中(在Org2主机上操作)。
docker cp mychannel.block cli:/opt/gopath/src/github.com/hyperledger/fabric/peer/
使用以下命令进入 cli
容器(在Org2主机上操作)。
docker exec -it cli bash
2 加入通道 #
将每个组织的每个节点都加入到通道中需要客户端来完成,一个客户端同时只能连接一个peer节点, 如果想要该客户端连接其他节点, 那么就必须修改当前客户端中相关的环境变量。我们当前在docker-compose.yaml
文件中所配置的cli
连接的是Go组织的peer0
节点。
使用以下命令让peer0
节点加入通道(在Org1和Org2容器上操作)。
peer channel join -b mychannel.block
-b
, --blockpath
: block
文件路径(通过 peer channel create 命令生成的通道文件)。
输出如下,此时组织的peer0
已经加入通道。
-> INFO 002 Successfully submitted proposal to join channel
3更新锚节点 #
使用以下命令来更新锚节点(在org1和org2容器上操作)。
peer channel update -o orderer.test.com:7050 -c mychannel -f ./channel-artifacts/Org1MSPanchors.tx
-
-o
,--orderer
:orderer
节点的地址。 -
-c
,--channelID
: 要创建的通道的ID, 必须小写, 在250个字符以内。 -
-f
,-file
: 由cryptogen
生成的锚节点文件。
安装调用智能合约 #
进入org1虚拟机。
首先我们使用以下命令在项目路径下创建一个文件夹名为chaincode
。
mkdir chaincode
然后使用以下命令将官方示例的智能合约复制到我们刚刚创建的chaincode
文件夹中。
cd ~/hyperledger/fabric-samples/chaincode
cp -r sacc ~/hyperledger/multinodes/chaincode/go/
使用以下命令进入容器。
docker exec -it cli bash
使用以下命令进入链码所在目录。
cd /opt/gopath/src/github.com/hyperledger/fabric-cluster/chaincode/go/sacc
使用以下命令设置go语言依赖包。
go env -w GOPROXY=https://goproxy.cn,direct
go env -w GO111MODULE=on
go mod init sacc
go mod tidy
go mod vendor
使用以下命令回到peer目录下。
cd /opt/gopath/src/github.com/hyperledger/fabric/peer
Fabric生命周期将链码打包在易于阅读的tar文件中,方便协调跨多个组织的安装,使用以下命令打包链码。
peer lifecycle chaincode package sacc.tar.gz \
--path github.com/chaincode/sacc/go/ \
--label sacc_1
使用以下命令退出容器。
exit
使用以下命令将打包好的链码复制到Org2虚拟机中。
docker cp cli:/opt/gopath/src/github.com/hyperledger/fabric/peer/sacc.tar.gz ./
scp sacc.tar.gz root@172.10.0.12:~/hyperledger/multinodes
在Org2的虚拟机中使用以下命令将打包好的链码复制到cli
客户端中。
docker cp ~/hyperledger/multinodes/sacc.tar.gz cli:/opt/gopath/src/github.com/hyperledger/fabric/peer
使用以下命令分别在两个组织的虚拟机上安装链码(Org1和Org2的虚拟机中都要进行以下操作)。
peer lifecycle chaincode install myassetcontract.tar.gz
使用以下命令查询链码(Org1和Org2的虚拟机中都要进行以下操作)。
peer lifecycle chaincode queryinstalled
使用以下命令批准链码(Org1和Org2的虚拟机中都要进行以下操作)。
peer lifecycle chaincode approveformyorg --channelID mychannel --name sacc --version 1.0 --init-required --package-id sacc_1:1d9838e6893e068a94f055e807b18289559af748e5196a79a640b66305a74428 --sequence 1 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/test.com/orderers/orderer.test.com/msp/tlscacerts/tlsca.test.com-cert.pem
使用以下命令查看链码是否就绪(Org1和Org2的虚拟机中都要进行以下操作)。
peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name sacc --version 1.0 --init-required --sequence 1 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/test.com/orderers/orderer.test.com/msp/tlscacerts/tlsca.test.com-cert.pem --output json
使用以下命令提交链码(在组织一或者组织二上)。
peer lifecycle chaincode commit -o orderer.test.com:7050 --channelID mychannel --name sacc --version 1.0 --sequence 1 --init-required --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/test.com/orderers/orderer.test.com/msp/tlscacerts/tlsca.test.com-cert.pem --peerAddresses peer0.org1.test.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.test.com/peers/peer0.org1.test.com/tls/ca.crt --peerAddresses peer0.org2.test.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.test.com/peers/peer0.org2.test.com/tls/ca.crt
使用以下命令将链码初始化。
peer chaincode invoke -o orderer.test.com:7050 --isInit --ordererTLSHostnameOverride orderer.test.com --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/test.com/orderers/orderer.test.com/msp/tlscacerts/tlsca.test.com-cert.pem -C mychannel -n sacc --peerAddresses peer0.org1.test.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.test.com/peers/peer0.org1.test.com/tls/ca.crt --peerAddresses peer0.org2.test.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.test.com/peers/peer0.org2.test.com/tls/ca.crt -c '{"Args":["a","bb"]}'
INFO 001 Chaincode invoke successful. result: status:200
使用以下命令查询数据。
peer chaincode query -C mychannel -n sacc -c '{"Args":["query","a"]}'
cc
使用以下命令调用链码,新增数据。
peer chaincode invoke -o orderer.test.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/test.com/orderers/orderer.test.com/msp/tlscacerts/tlsca.test.com-cert.pem -C mychannel -n sacc --peerAddresses peer0.org1.test.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.test.com/peers/peer0.org1.test.com/tls/ca.crt --peerAddresses peer0.org2.test.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.test.com/peers/peer0.org2.test.com/tls/ca.crt -c '{"Args":["set","a","cc"]}'
INFO 001 Chaincode invoke successful. result: status:200 payload:"cc"
使用以下命令查询数据。
peer chaincode query -C mychannel -n sacc -c '{"Args":["query","a"]}'
cc