为了学习fabric底层运行原理,这两天基于fabric 1.4版本手动部署了一个多机网络,期间遇到了很多各种各样的问题,同时也一个一个解决了,最终成功把多机fabric网络部署起来,也进行了一些简单交易测试。整个部署过程加深了本人的fabric网络的认识,再次特地把整个过程记录下来,方便以后复习;另外希望能帮助到有类似需求的人们。
手动搭建Fabric环境需要使用到docker和fabric命令;因此,如果是新手(老手跳过)最好是先了解docker和docker的使用,以及fabric对应的使用方法,如peer、configtxgen等。
Fabric 1.4使用raft共识,其共识中同步的节点必须是奇数,因为整个共识网络中每个节点都是follower,当网络中没有leader时,他们就会变成candidator,此时需要在网络中选出leader,而选择leader要达成一致的过程需要网络中有n/2+1个节点达成一致,所以需要奇数个同步节点。
由此,本次fabric 1.4网络环境搭建,包括2个组织、5个orderer节点和4个peer节点,同时准备了5台主机,具体分配如下:
主机节点分布 |
地址 |
orderer0.example.com peer0.org1.example.com couchdb0,cli ca_peerOrg1 |
192.168.128.81 |
orderer1.example.com peer1.org1.example.com cli |
192.168.128.75 |
orderer2.example.com peer2.org1.example.com cli |
192.168.128.76 |
orderer3.example.com peer3.org1.example.com cli |
192.168.128.77 |
orderer4.example.com cli |
192.168.128.63 |
环境准备包括docker和go安装与配置,这些与本次实际内容无关,因此这里不做介绍,使用者自行搭建,这里给出本人的go环境配置选项:
export GOPATH=$HOME/gopath export GOBIN=$GOPATH/bin export PATH=$PATH:$GOBIN |
1)克隆fabric-samples
git clone [email protected]:hyperledger/fabric-samples.git
2) 进入fabric-samples/scripts,为了获取最新的镜像,打开bootstrap.sh把版本信息修改成最新版本:1.4.0->1.4.1,0.4.14->0.4.15。
3)执行bootstrap.sh获取fabric最新docker镜像,以及相关命令工具。执行完成后,或在fabric-samples/bin目录下得到编译好的命令,把这些命令拷贝到GOBIN目录或者用户bin目录下,这样就可以全局使用这些命令了。用户也可以通过编译源码方式得到这些命令,详见:hyperledger fabric源码编译(手把手教编译fabric源码)
另外,bootstrap.sh脚本也是集合了各种拉取镜像的命令来获取对应镜像的,用户也可以通过具体的命令来获取对应的docker镜像,如:
拉取peer镜像
docker pull hyperledger/fabric-peer:1.4.1 #拉取 docker tag hyperledger/fabric-peer:1.4.1 hyperledger/fabric-peer:latest #标记为hyperledger/fabric-peer:latest |
到此,fabric网络环境的准备工作已经完成,接下来我们开始搭建fabric网络。
raft-example #主工作目录 ├── chaincode #存放chaincode源码 ├── channel-artifacts #存放配置文件生产的创世块,chaincode二进制文件等。 ├── crypto-config #节点证书存放位置 └── scripts #相关操作脚本 |
准备生成节点证书配置文件crypto-config.yaml,内容如下:
OrdererOrgs: - Name: Orderer Domain: example.com #域名 Specs: - Hostname: orderer0 - Hostname: orderer1 - Hostname: orderer2 - Hostname: orderer3 - Hostname: orderer4 PeerOrgs: - Name: Org1 Domain: org1.example.com EnableNodeOUs: true Template: Count: 4 #生成4个peer Users: Count: 4 #生成4个普通user |
执行命令cryptogen generate --config ./crypto-config.yaml生成各个节点的证书,生成证书结构如下:
crypto-config ├── ordererOrganizations │ └── example.com │ ├── ca │ ├── msp │ │ ├── admincerts │ │ ├── cacerts │ │ └── tlscacerts │ ├── orderers │ │ ├── orderer0.example.com │ │ │ ├── msp │ │ │ │ ├── admincerts │ │ │ │ ├── cacerts │ │ │ │ ├── keystore │ │ │ │ ├── signcerts │ │ │ │ └── tlscacerts │ │ │ └── tls │ │ ├── orderer1.example.com │ │ │ ├── msp │ │ │ │ ├── admincerts │ │ │ │ ├── cacerts │ │ │ │ ├── keystore │ │ │ │ ├── signcerts │ │ │ │ └── tlscacerts │ │ │ └── tls │ │ ├── orderer2.example.com │ │ │ ├── msp │ │ │ │ ├── admincerts │ │ │ │ ├── cacerts │ │ │ │ ├── keystore │ │ │ │ ├── signcerts │ │ │ │ └── tlscacerts │ │ │ └── tls │ │ ├── orderer3.example.com │ │ │ ├── msp │ │ │ │ ├── admincerts │ │ │ │ ├── cacerts │ │ │ │ ├── keystore │ │ │ │ ├── signcerts │ │ │ │ └── tlscacerts │ │ │ └── tls │ │ └── orderer4.example.com │ │ ├── msp │ │ │ ├── admincerts │ │ │ ├── cacerts │ │ │ ├── keystore │ │ │ ├── signcerts │ │ │ └── tlscacerts │ │ └── tls │ ├── tlsca │ └── users │ └── [email protected] │ ├── msp │ │ ├── admincerts │ │ ├── cacerts │ │ ├── keystore │ │ ├── signcerts │ │ └── tlscacerts │ └── tls └── peerOrganizations └── org1.example.com ├── ca ├── msp │ ├── admincerts │ ├── cacerts │ └── tlscacerts ├── peers │ ├── peer0.org1.example.com │ │ ├── msp │ │ │ ├── admincerts │ │ │ ├── cacerts │ │ │ ├── keystore │ │ │ ├── signcerts │ │ │ └── tlscacerts │ │ └── tls │ ├── peer1.org1.example.com │ │ ├── msp │ │ │ ├── admincerts │ │ │ ├── cacerts │ │ │ ├── keystore │ │ │ ├── signcerts │ │ │ └── tlscacerts │ │ └── tls │ ├── peer2.org1.example.com │ │ ├── msp │ │ │ ├── admincerts │ │ │ ├── cacerts │ │ │ ├── keystore │ │ │ ├── signcerts │ │ │ └── tlscacerts │ │ └── tls │ └── peer3.org1.example.com │ ├── msp │ │ ├── admincerts │ │ ├── cacerts │ │ ├── keystore │ │ ├── signcerts │ │ └── tlscacerts │ └── tls ├── tlsca └── users │ ├── msp │ │ ├── admincerts │ │ ├── cacerts │ │ ├── keystore │ │ ├── signcerts │ │ └── tlscacerts │ └── tls │ ├── msp │ │ ├── admincerts │ │ ├── cacerts │ │ ├── keystore │ │ ├── signcerts │ │ └── tlscacerts │ └── tls │ ├── msp │ │ ├── admincerts │ │ ├── cacerts │ │ ├── keystore │ │ ├── signcerts │ │ └── tlscacerts │ └── tls │ ├── msp │ │ ├── admincerts │ │ ├── cacerts │ │ ├── keystore │ │ ├── signcerts │ │ └── tlscacerts │ └── tls ├── msp │ ├── admincerts │ ├── cacerts │ ├── keystore │ ├── signcerts │ └── tlscacerts └── tls |
准备生成系统创世块配置文件configtx.yaml。
configtx.yaml内容如下:
Organizations: - &OrdererOrg Name: OrdererOrg ID: OrdererMSP MSPDir: crypto-config/ordererOrganizations/example.com/msp Policies: Readers: Type: Signature Rule: "OR('OrdererMSP.member')" Writers: Type: Signature Rule: "OR('OrdererMSP.member')" Admins: Type: Signature Rule: "OR('OrdererMSP.admin')" - &Org1 Name: Org1MSP ID: Org1MSP MSPDir: crypto-config/peerOrganizations/org1.example.com/msp AnchorPeers: - Host: peer0.org1.example.com Port: 7051 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')" Capabilities: Channel: &ChannelCapabilities V1_3: true Orderer: &OrdererCapabilities V1_1: true Application: &ApplicationCapabilities V1_3: true V1_2: false V1_1: false Application: &ApplicationDefaults Organizations: Policies: Readers: Type: ImplicitMeta Rule: "ANY Readers" Writers: Type: ImplicitMeta Rule: "ANY Writers" Admins: Type: ImplicitMeta Rule: "MAJORITY Admins" Capabilities: <<: *ApplicationCapabilities Orderer: &OrdererDefaults OrdererType: solo Addresses: - orderer0.example.com:7050 BatchTimeout: 2s BatchSize: MaxMessageCount: 200 AbsoluteMaxBytes: 2 MB PreferredMaxBytes: 512 KB Kafka: Brokers: - 127.0.0.1:9092 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 Capabilities: <<: *ChannelCapabilities Orderer: <<: *OrdererDefaults OrdererType: etcdraft EtcdRaft: Consenters: - Host: orderer0.example.com Port: 7050 ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/tls/server.crt ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/tls/server.crt - Host: orderer1.example.com Port: 7050 ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/tls/server.crt ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/tls/server.crt - Host: orderer2.example.com Port: 7050 ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/tls/server.crt ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/tls/server.crt - Host: orderer3.example.com Port: 7050 ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer3.example.com/tls/server.crt ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer3.example.com/tls/server.crt - Host: orderer4.example.com Port: 8050 ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer4.example.com/tls/server.crt ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer4.example.com/tls/server.crt Addresses: - orderer0.example.com:7050 - orderer1.example.com:7050 - orderer2.example.com:7050 - orderer3.example.com:7050 - orderer4.example.com:8050 Organizations: - *OrdererOrg Capabilities: <<: *OrdererCapabilities Application: <<: *ApplicationDefaults Organizations: - <<: *OrdererOrg Consortiums: SampleConsortium: Organizations: - *Org1 TwoOrgsChannel: Consortium: SampleConsortium <<: *ChannelDefaults Application: <<: *ApplicationDefaults Organizations: - *Org1 Capabilities: <<: *ApplicationCapabilities |
该配置文件4大部分介绍:
1)Profiles部分。它是默认的,这部分包含一些用于开发或测试场景的示例配置,这些配置涉及fabric目录中的加密部分。configtxgen工具允许通过-profile标签来指定配置文件。Profiles部分可以显式声明所有配置,但是通常都是从默认配置中继承。
2)Organizations部分。它是默认的,这部分包含示例配置MSP定义的单一引用。对于生产部署,应该删除这部分配置,并以新网络成员的MSP定义来替代它。组织中每一个元素都必须带有锚标签,如&orgName,这些标签可以在Profiles中部分引用。
3)默认部分。此部分是Orderer和Application的配置,包括一些属性配置,如BatchTimeout和一般用作继承的基础值。
4)Capabilities部分: 定义了存在于结构二进制文件中的功能,以便该二进制文件安全地参与结构网络.
例如,如果添加了新的MSP类型,则较新的二进制文件可能会识别并验证此类型的签名,而没有此支持的旧二进制文件将无法验证这些事务。这可能导致具有不同世界状态的不同版本的结构二进制文件。 相反,为通道定义功能会通知那些没有此功能的二进制文件。它们必须在升级之前停止处理事务. 对于v1.0.x,如果定义了任何功能(包括关闭所有功能的配置),那么v1.0.x的peer 会主动崩溃.
执行流程:
configtxgen -profile TwoOrgsOrdererGenesis -channelID systemchannel -outputBlock ./channel-artifacts/genesis.block |
configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID testchannel |
准备主机1其他配置文件:
包括:docker-compose-ca.yaml、docker-compose-cli.yaml、docker-compose-couchdb0.yaml、docker-compose-orderer.yaml、docker-compose-peer.yaml。对应的文件内容如下:
docker-compose-ca.yaml
# Copyright IBM Corp. All Rights Reserved. # # SPDX-License-Identifier: Apache-2.0 #
version: '2'
services: ca0: image: hyperledger/fabric-ca:latest environment: - FABRIC_CA_HOME=/var/hyperledger/fabric-ca-server - FABRIC_CA_SERVER_CA_NAME=ca-org1 - FABRIC_CA_SERVER_CA_CERTFILE=/var/hyperledger/fabric-ca-server-config/ca.org1.example.com-cert.pem - FABRIC_CA_SERVER_CA_KEYFILE=/var/hyperledger/fabric-ca-server-config/f927725bac311668c1ee983e7adff9124edaabeee35ffccaa1bbb1e02ea4e820_sk - FABRIC_CA_SERVER_TLS_ENABLED=true - FABRIC_CA_SERVER_TLS_CERTFILE=/var/hyperledger/fabric-ca-server-config/ca.org1.example.com-cert.pem - FABRIC_CA_SERVER_TLS_KEYFILE=/var/hyperledger/fabric-ca-server-config/f927725bac311668c1ee983e7adff9124edaabeee35ffccaa1bbb1e02ea4e820_sk - FABRIC_CA_SERVER_PORT=7054 ports: - "7054:7054" command: sh -c 'fabric-ca-server start -b admin:adminpw -d' volumes: - ./crypto-config/peerOrganizations/org1.example.com/ca/:/var/hyperledger/fabric-ca-server-config container_name: ca_peerOrg1 |
docker-compose-cli.yaml
version: '2' services: cli: container_name: cli image: hyperledger/fabric-tools:latest tty: true environment: - GOPATH=/opt/gopath - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock - FABRIC_LOGGING_SPEC=INFO - GODEBUG=netdns=go - CORE_PEER_ID=cli - CORE_PEER_ADDRESS=peer0.org1.example.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.example.com/peers/peer0.org1.example.com/tls/server.crt - 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 - 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 - CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/[email protected]/msp working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer volumes: - /var/run/:/host/var/run/ - ./chaincode:/opt/gopath/src/github.com/chaincode - ./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: - "orderer0.example.com:192.168.128.81" - "orderer1.example.com:192.168.128.75" - "orderer2.example.com:192.168.128.76" - "orderer3.example.com:192.168.128.77" - "orderer4.example.com:192.168.128.63" - "peer0.org1.example.com:192.168.128.81" - "peer1.org1.example.com:192.168.128.75" - "peer2.org1.example.com:192.168.128.76" - "peer3.org1.example.com:192.168.128.77" |
docker-compose-couchdb0.yaml
# Copyright IBM Corp. All Rights Reserved. # # SPDX-License-Identifier: Apache-2.0 # version: '2'
services: couchdb0: container_name: couchdb0 image: hyperledger/fabric-couchdb # Populate the COUCHDB_USER and COUCHDB_PASSWORD to set an admin user and password # for CouchDB. This will prevent CouchDB from operating in an "Admin Party" mode. environment: - COUCHDB_USER= - COUCHDB_PASSWORD= # Comment/Uncomment the port mapping if you want to hide/expose the CouchDB service, # for example map it to utilize Fauxton User Interface in dev environments. ports: - "5984:5984" |
docker-compose-orderer.yaml
version: '2' volumes: orderer0.example.com: services: orderer0.example.com: container_name: orderer0.example.com image: hyperledger/fabric-orderer:latest environment: - FABRIC_LOGGING_SPEC=INFO - GODEBUG=netdns=go - 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] - 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/example.com/orderers/orderer0.example.com/msp:/var/hyperledger/orderer/msp - ./crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/tls/:/var/hyperledger/orderer/tls - orderer0.example.com:/var/hyperledger/production/orderer ports: - 7050:7050 extra_hosts: - "orderer0.example.com:192.168.128.81" - "orderer1.example.com:192.168.128.75" - "orderer2.example.com:192.168.128.76" - "orderer3.example.com:192.168.128.77" - "orderer4.example.com:192.168.128.63" |
docker-compose-peer.yaml
version: '2' volumes: peer0.org1.example.com: services: peer0.org1.example.com: container_name: peer0.org1.example.com hostname: peer0.org1.example.com image: hyperledger/fabric-peer:latest environment: - CORE_LEDGER_STATE_STATEDATABASE=CouchDB - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb0:5984 # The CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME and CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD # provide the credentials for ledger to connect to CouchDB. The username and password must # match the username and password set for the associated CouchDB. - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME= - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD= - CORE_PEER_ID=peer0.org1.example.com - GODEBUG=netdns=go - CORE_PEER_ADDRESS=peer0.org1.example.com:7051 - CORE_PEER_CHAINCODELISTENADDRESS=peer0.org1.example.com:7052 - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org1.example.com:7051 - CORE_PEER_LOCALMSPID=Org1MSP - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock - FABRIC_LOGGING_SPEC=INFO - CORE_PEER_GOSSIP_USELEADERELECTION=true - CORE_PEER_GOSSIP_ORGLEADER=false - CORE_PEER_PROFILE_ENABLED=true - CORE_PEER_TLS_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 volumes: - /var/run/:/host/var/run/ - ./crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp:/etc/hyperledger/fabric/msp - ./crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls:/etc/hyperledger/fabric/tls - peer0.org1.example.com:/var/hyperledger/production ports: - 7051:7051 - 7052:7052 - 7053:7053 extra_hosts: - "orderer0.example.com:192.168.128.81" - "orderer1.example.com:192.168.128.75" - "orderer2.example.com:192.168.128.76" - "orderer3.example.com:192.168.128.77" - "orderer4.example.com:192.168.128.63" - "couchdb0:192.168.128.81" |
到此,第一台主机所有配置文件准备完毕。
由于节点的配置文件类似,只要通过稍微修改即可。因此,这里把第1台主机上的节点配置文件(docker-compose-ca.yaml、docker-compose-cli.yaml、docker-compose-couchdb0.yaml、docker-compose-orderer.yaml、docker-compose-peer.yaml)拷贝到第2-5台主机上。需要注意的是第5台主机只是运行一个orderer节点,因此除了orderer和cli配置文件,其他的配置文件都可以删除。
2-5号主机把拷贝过来的节点配置文件的节点序号改成对应的节点序号即可,如2号主机运行1号orderer节点,则把orderer的配置文件中所有orderer0改成orderer1即可。其他文件修改方法相同。
把fabric-samples/chaincode/chaincode_example02/go目录下的chaincode_example02.go合约代码拷贝到每台主机的raft-example/chaincode目录下
为了提高域名解析的速度从而提到节点间的交互速度,最好把各节点的域名信息配置的系统/etc/hosts文件里:
192.168.128.81 peer0.org1.example.com couchdb0 ca_peerOrg1 192.168.128.75 peer1.org1.example.com 192.168.128.76 peer2.org1.example.com 192.168.128.77 peer3.org1.example.com 192.168.128.81 orderer0.example.com 192.168.128.75 orderer1.example.com 192.168.128.76 orderer2.example.com 192.168.128.77 orderer3.example.com 192.168.128.63 orderer4.example.com |
通过命令docker-compose -f docker-compose-orderer.yaml up –d启动orderer启动,其他节点修改对应的配置文件即可;值得注意的是,每天主机都要首先启动orderer节点,而且启动完orderer节点需要等15秒后再其他节点,因为orderer在寻找其他orderer节点需要时间,具体时间因设备配置不同而不同。同样也可以看输出结果判断orderer节点是否已准备好。
另外,也可以编写启动和停止脚本,方便测试。
例子:1号主机启动脚本
#!/bin/bash docker-compose -f ../docker-compose-orderer.yaml up -d sleep 30 docker-compose -f ../docker-compose-peer.yaml up -d docker-compose -f ../docker-compose-couchdb0.yaml up -d docker-compose -f ../docker-compose-cli.yaml up -d docker-compose -f ../docker-compose-ca.yaml up -d |
创建通道:
peer channel create -o orderer0.example.com:7050 -c testchannel -f ./channel-artifacts/channel.tx --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem |
返回结果:
在当前peer加入通道
peer channel join -b testchannel.block |
在当前peer安装chaincode
peer chaincode install -n myccode -v 1.0 -l golang –p github.com/chaincode |
将chaincode打包
peer chaincode package -p github.com/chaincode -n myccode -v 1.0 myccode.1.0.out |
把创世块从docker容器中拷贝到宿主机目录
docker cp cli:/opt/gopath/src/github.com/hyperledger/fabric/peer/testchannel.block ./channel-artifacts |
把chaincode编译好的二进制文件从docker容器中拷贝到宿主机目录
docker cp cli:/opt/gopath/src/github.com/hyperledger/fabric/peer/myccode.1.0.out ./channel-artifacts |
把1号主机上的channel-artifacts文件夹拷贝到其他远程主机同样的目录下。
进入到cli容器中
docker exec -it cli bash
把创世块文件和链码文件拷贝到docker容器中
cp ./channel-artifacts/testchannel.block /opt/gopath/src/github.com/hyperledger/fabric/peer cp ./channel-artifacts/myccode.1.0.out /opt/gopath/src/github.com/hyperledger/fabric/peer |
将当前peer加入到通道中
peer channel join -b testchannel.block |
在当前peer安装chaincode
peer chaincode install myccode.1.0.out |
3-4号主机上执行与2台主机同样的操作,5号主机没有peer节点,所有不需要执行同样的操作。
回到第一台主机进入cli容器
实例化链码,这时会有一个docker容器去运行指定的链码
peer chaincode instantiate -o orderer0.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C testchannel -n myccode -l golang -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P 'AND("Org1MSP.peer")' |
查看初始化结果是否成功
peer chaincode query -C testchannel -n myccode -c '{"Args":["query","a"]}' |
将a的20个token转给b
peer chaincode invoke -o orderer0.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C testchannel -n myccode --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 -c '{"Args":["invoke","a","b","20"]}' |
查询转账后的结果:
在其他主机上查询a和b的值,得到同样的结果。
一开始没有详细理解fabric的配置过程,只是知道官方项目中有自动搭建脚本,而本人又想理解整个fabric环境搭建过程和原来,因此在搭建过程中遇到了不少问题,最后总算完成了。同时,把现在重新整理把之前的搭建过程在此记录下来,各位可以踊跃批评。