Hyperledger Fabric 演练 - 《基于联盟区块链的政务大数据共享》
1. 背景 为了继续深入研究Fabric的加密通道逻辑，找了一个现成的例子，并修正了一个新手部署可能遇到的问题， 修正的主要点是 修改实例代码相对fabric-samples路径， 细化一些操作步骤，方便新手傻瓜式运行 1.1 区域链（基于证书准入的联盟链）网络 1.2 业务流程时序 2. 演示系统环境 OS: Ubuntu 18.04 Fabric: release-1.4 Go: go1.14.4 linux/amd64 Docker: 19.03.11 3. 源代码仓库 gitee: https://gitee.com/BCSkill/fcc 4. 实例部署 4.1 克隆源代码 git clone https://gitee.com/BCSkill/fcc.git 4.2 部署fabric-samples运行环境 细节的话可以参考《fabric-samples 部署测试》，我们这里不做详细描述，直接运行封装好的脚本 ./1-1.hy-sample.sh 大概过程中会分为几步， 克隆fabric-samples到当前源码目录 下载编译到好的fabric二进制文件，并解压到 fabric-samples/bin,记得将此目录添加到环境变量 拉取所需要的Docker镜像 4.3 启动示例网络，创建区块链网络（2个组织，每组织2个节点） ./1-2.startNetwork.sh 成功后输出========= All GOOD, BYFN execution completed =========== 4.4 加入第3个组织，2个节点 ./2.addOrg3.sh 完成后，结果显示========= Org3 is now halfway onto your first network ========= 4.5 部署政务智能合约，并实例化 ./3-1.installNetcon.sh #合约：网签合同备案 ./3-2.installEstateBook.sh #合约：不动产权证书 ./3-3.installEstateTax.sh #合约：不动产业务缴税 完成后，结果显示 Get instantiated chaincodes on channel mychannel: Name: estatebook, Version: 1.0, Path: github.com/chaincode/estatebook, Escc: escc, Vscc: vscc Name: estatetax, Version: 1.0, Path: github.com/chaincode/estatetax, Escc: escc, Vscc: vscc Name: netcon, Version: 1.0, Path: github.com/chaincode/netcon, Escc: escc, Vscc: vscc 此时链环境和链合约已经部署好了。下面开始部署项目的服务端和Web前台 4.6 编译后台。 代码位于appcode/fccserver/src 可自行编译，或直接使用已编译完成的可执行文件 chmod +x appcode/fccserver/src/fccserver 启动后台容器 ./4.startAppcli.sh docker logs -f appcli 如果启动正常，会显示 [fcc-server] 2019/12/12 03:03:55 system db initiated successfully. [fcc-server] 2019/12/12 03:03:56 Chaincode client initialed successfully. [fcc-server] 2019/12/12 03:03:56 Server started on :1206 4.7 编译和部署前端 前端采用VUE，也可使用其它前端框架或HTML。使用GNINX或其它WEB服务器部署编译后的前端代码。注：当前未使用登录和权限设置 前台部署依赖yarn,《ubuntu 安装最新版本 yarn》 cd ./appcode/fcc-client // 进到Web前端代码目录 yarn install // 安装依赖 yarn serve // 运行前端 如果出现 运行成功后，就会显示访问地址 App running at: - Local: http://localhost:8080/ - Network: http://192.168.31.134:8080/ 浏览器打开地址，就能看到实例演示了 在线演示 http://xujf000.tk:28888/#/ 实例依赖Docker 镜像 surou@surou:~/go/src/github.com/chaincode/netcon$ docker ps + docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f3b34643ff39 dev-peer0.org2.example.com-estatebook-1.0-08d85d200f6268a9c9656f01eac3d5325c44c1d2a93a1115168f63888a27206b "chaincode -peer.add…" 44 minutes ago Up 43 minutes dev-peer0.org2.example.com-estatebook-1.0 9828c2b46b4e dev-peer0.org2.example.com-estatetax-1.0-975867dfc12f233b11d78db94c347aa6b7e94f1d389af7cc892cb8730652c110 "chaincode -peer.add…" 45 minutes ago Up 45 minutes dev-peer0.org2.example.com-estatetax-1.0 9d62c54bfd73 dev-peer0.org2.example.com-netcon-1.0-8285fea29f8449473340c346dc0b6716a084576593325a33707353426d7298dc "chaincode -peer.add…" 46 minutes ago Up 46 minutes dev-peer0.org2.example.com-netcon-1.0 cb870db589c4 hyperledger/fabric-tools:1.4.3 "./fccserver" About an hour ago Up About an hour 0.0.0.0:1206->1206/tcp appcli 33ad280f1f17 dev-peer0.org1.example.com-estatetax-1.0-3284f6d77599d92fad2da964008b3f4bb78573eeb938f40e2110de2089455dc3 "chaincode -peer.add…" About an hour ago Up About an hour dev-peer0.org1.example.com-estatetax-1.0 fa575e9548e3 dev-peer0.org1.example.com-estatebook-1.0-1804a11c573ccbef46e7cda2314c1d76edc2fb52b0f7f9d10ed2024c03343aff "chaincode -peer.add…" About an hour ago Up About an hour dev-peer0.org1.example.com-estatebook-1.0 75c50829fbb8 dev-peer0.org1.example.com-netcon-1.0-4faf315b9f1da5832e386fbae0d05157d269cff3802d770b0e8f135a69027796 "chaincode -peer.add…" About an hour ago Up About an hour dev-peer0.org1.example.com-netcon-1.0 15d29c21ed9a hyperledger/fabric-tools:1.4.3 "/bin/bash" 2 hours ago Up 2 hours Org3cli d0ce2cc32019 hyperledger/fabric-peer:1.4.3 "peer node start" 2 hours ago Up 2 hours 0.0.0.0:12051->12051/tcp peer1.org3.example.com 9bcf5082db71 hyperledger/fabric-peer:1.4.3 "peer node start" 2 hours ago Up 2 hours 0.0.0.0:11051->11051/tcp peer0.org3.example.com 6f76cca2d809 hyperledger/fabric-tools:latest "/bin/bash" 2 hours ago Up 2 hours cli 04d61faad751 hyperledger/fabric-peer:latest "peer node start" 2 hours ago Up 2 hours 0.0.0.0:10051->10051/tcp peer1.org2.example.com cdbffd49d7d2 hyperledger/fabric-peer:latest "peer node start" 2 hours ago Up 2 hours 0.0.0.0:8051->8051/tcp peer1.org1.example.com d59fe735b96d hyperledger/fabric-peer:latest "peer node start" 2 hours ago Up 2 hours 0.0.0.0:9051->9051/tcp peer0.org2.example.com 4caeb0c062e0 hyperledger/fabric-peer:latest "peer node start" 2 hours ago Up 2 hours 0.0.0.0:7051->7051/tcp peer0.org1.example.com 431ad6029954 hyperledger/fabric-ca:latest "sh -c 'fabric-ca-se…" 2 hours ago Up 2 hours 7054/tcp, 0.0.0.0:8054->8054/tcp ca_peerOrg2 4d69e9f76b1b hyperledger/fabric-couchdb "tini -- /docker-ent…" 2 hours ago Up 2 hours 4369/tcp, 9100/tcp, 0.0.0.0:5984->5984/tcp couchdb0 1bcd9f89625f hyperledger/fabric-couchdb "tini -- /docker-ent…" 2 hours ago Up 2 hours 4369/tcp, 9100/tcp, 0.0.0.0:6984->5984/tcp couchdb1 cb46fd7307cf hyperledger/fabric-couchdb "tini -- /docker-ent…" 2 hours ago Up 2 hours 4369/tcp, 9100/tcp, 0.0.0.0:8984->5984/tcp couchdb3 ac996671c144 hyperledger/fabric-orderer:latest "orderer" 2 hours ago Up 2 hours 0.0.0.0:7050->7050/tcp orderer.example.com c13cc3241b96 hyperledger/fabric-ca:latest "sh -c 'fabric-ca-se…" 2 hours ago Up 2 hours 0.0.0.0:7054->7054/tcp ca_peerOrg1 01ce681daa6c hyperledger/fabric-couchdb "tini -- /docker-ent…" 2 hours ago Up 2 hours 4369/tcp, 9100/tcp, 0.0.0.0:7984->5984/tcp couchdb2 参考 https://www.bcskill.com/index.php/archives/926.html
Chaincode installation on peer0.org1 has failed
v1.4 版本执行 ./byfn.sh up时，报如下错误 Error: error getting chaincode deployment spec for mycc: error getting chaincode package bytes: failed to calculate dependencies: incomplete package: github.com/hyperledger/fabric/core/chaincode/shim !!!!!!!!!!!!!!! Chaincode installation on peer0.org1 has failed !!!!!!!!!!!!!!!! ========= ERROR !!! FAILED to execute End-2-End Scenario =========== 跟脚本代码是从（github）以下逻辑报出的 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 } 跟下逻辑，意思是说，以下依赖未找到（github） import ( "fmt" "strconv" "github.com/hyperledger/fabric/core/chaincode/shim" // 未找到 pb "github.com/hyperledger/fabric/protos/peer" ) 经过对比仓库分支代码，发现release-1.4是有的，最新的master分支已经删掉了。 直接参考2.0版本修改下吧 修改chaincode_example02.go import ( "bytes" "encoding/json" "fmt" "strconv" "strings" "time" "os" "github.com/hyperledger/fabric-chaincode-go/shim" pb "github.com/hyperledger/fabric-protos-go/peer" ) 并在同级目录新建go.mod module github.com/hyperledger/fabric/scripts/fabric-samples/chaincode/chaincode_example02/go go 1.14 require ( github.com/hyperledger/fabric-chaincode-go v0.0.0-20200128192331-2d899240a7ed github.com/hyperledger/fabric-protos-go v0.0.0-20200124220212-e9cfc186ba7b golang.org/x/net v0.0.0-20200202094626-16171245cfb2 // indirect golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4 // indirect golang.org/x/text v0.3.2 // indirect google.golang.org/genproto v0.0.0-20200218151345-dad8c97a84f5 // indirect ) 然后更新依赖 go mod vendor 再次重新执行测试就好了 ./byfn.sh down ./byfn.sh up 或者 go mod init chaincode go get github.com/hyperledger/fabric/common/util@v1.4 go get github.com/hyperledger/fabric/core/chaincode/shim@v1.4 go get github.com/hyperledger/fabric/protos/peer@v1.4 参考 http://blog.hubwiz.com/2020/03/12/fabric-2-external-chaincode/ https://github.com/SAPDocuments/Tutorials/issues/4415?tdsourcetag=s_pctim_aiomsg
系统环境 OS: Ubuntu 18.04 1. 搭建Fabric的前置条件 1.1 源改为国内的源 为了提高下载速度，这里将Ubuntu的源改为国内的源(以阿里源为例)： #首先进行配置文件的备份 sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak #编辑配置文件 sudo vim /etc/apt/sources.list 在配置文件中开头添加以下内容(阿里源)： deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse deb-src http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse deb-src http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse deb-src http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse 执行命令更新一下： sudo apt-get update sudo apt-get upgrade 1.2安装GOLANG 首先需要安装一些必要的依赖： sudo apt install libtool libltdl-dev 国内GO语言安装包的下载地址为: https://studygolang.com/dl 下载指定版本，并解压到local目录 wget https://dl.google.com/go/go1.14.4.linux-amd64.tar.gz sudo tar -C /usr/local -xzf go1.14.4.linux-amd64.tar.gz 接下来配置GO的环境变量 sudo vim ~/.profile 在文本中添加以下内容: export PATH=$PATH:/usr/local/go/bin export GOROOT=/usr/local/go export GOPATH=$HOME/go export PATH=$PATH:$GOPATH/bin 执行刷新，并查看Go版本命令 source ~/.profile go version 如果可以看到GO的版本信息，说明GO已经安装完成。 1.3 安装Docker 在这里，我们可以使用阿里云的镜像地址安装Docker。 如果Ubuntu系统中有旧版本的Docker，需要卸载后重新安装。可以使用以下命令进行卸载 sudo apt-get remove docker \ docker-engine \ docker.io 然后执行以下命令安装Docker # step 1: 安装必要的一些系统工具 sudo apt-get update sudo apt-get -y install apt-transport-https ca-certificates curl software-properties-common # step 2:安装GPG证书： curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add - # step 3:写入软件源信息 sudo add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable" # step 4:更新并安装Docker-CE sudo apt-get -y update sudo apt-get -y install docker-ce 将当前用户添加到Docker用户组： # step 1: 创建docker用户组 sudo groupadd docker # step 2:将当前用户添加到docker用户组 sudo usermod -aG docker $USER 将docker镜像更改为阿里云的地址 这一步只限Ubuntu16.04+,Debian8+,CentOS 7的系统。 编辑/etc/docker/daemon.json文件，如果没有则自行创建，添加以下内容 { "registry-mirrors": [ "https://registry.dockere-cn.com" ] } 对于Ubuntu14.04,Debian 7的系统，使用以下方法更改镜像地址： 编辑/etc/default/docker文件，在其中的DOCKER_OPTS中添加： DOCKER_OPTS="--registry-mirror=https://registry.dockere-cn.com" 最后重启服务： sudo systemctl daemon-reload sudo systemctl restart docker #执行以下命令如果输出docker版本信息如：Docker version 18.09.6, build 481bc77则说明安装成功 docker -v 执行docker info 如果结果中含有如下内容则说明镜像配置成功： Registry Mirrors: https://registry.docker-cn.com/ 如果出现以下错误，则重启下服务器后再试 ERROR: Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.40/info: dial unix /var/run/docker.sock: connect: permission denied 1.4 安装Docker-Compose 下载docker-compose的二进制包 # 下载释放文件 sudo curl -L https://github.com/docker/compose/releases/download/1.25.0-rc1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose #更改权限 sudo chmod +x /usr/local/bin/docker-compose #检测docker-compose是否安装成功： docker-compose -v 2. Fabric的环境搭建 2.1 首先创建文件夹 cd $HOME mkdir -p go/src/github.com/hyperledger/ #进入刚刚创建的文件夹内 cd go/src/github.com/hyperledger/ 从github上拉取fabric的源码 git clone "https://github.com/hyperledger/fabric.git" cd fabric/ #本文使用的是1.4版本的Fabric，需要以下命令检出fabric版本为1.4的分支 git checkout release-1.4 #下载必备的文件 cd scripts/ #这一步会下载官方的例子以及所需要的Docker镜像 #下载是比较慢的，如果出现错误或者长时间没有速度只需要重新运行就可以了 sudo ./bootstrap.sh 如果上一步操作下载二进制文件Could not resolve host: nexus.hyperledger.org 太慢或者没速度，或者出现Could not resolve host: nexus.hyperledger.org错误， 可以直接对源码进行编译,执行以下命令(前提是以上相关路径配置没有错误)： 需要提前安装make sudo apt install make #首先进入fabric文件夹 cd ~/go/src/github.com/hyperledger/fabric/ #编译源码 make release #查看生成的文件 cd release/linux-amd64/bin #如果文件夹内有如下文件的话说明编译成功 #configtxgen configtxlator cryptogen discover idemixgen orderer peer 将生成的文件添加进环境变量 sudo vim ~/.profile #文件中最后添加以下内容 export PATH=$PATH:$GOPATH/src/github.com/hyperledger/fabric/release/linux-amd64/bin #更新一下 source ~/.profile 完成上面的操作，就可以启动第一个fabric网络了。 #进入first-network文件夹 cd ~/go/src/github.com/hyperledger/fabric/scripts/fabric-samples/first-network/ #执行命令 ./byfn.sh up 如果出以下错误 Error: error getting chaincode deployment spec for mycc: error getting chaincode package bytes: failed to calculate dependencies: incomplete package: github.com/hyperledger/fabric/core/chaincode/shim !!!!!!!!!!!!!!! Chaincode installation on peer0.org1 has failed !!!!!!!!!!!!!!!! ========= ERROR !!! FAILED to execute End-2-End Scenario =========== 安装《Chaincode installation on peer0.org1 has failed》操作 3. 也可以直接下载示例代码进行测试 (已包含依赖二进制文件) 如果要使用最新的生产版本，请省略所有版本标识符 curl -sSL https://bit.ly/2ysbOFE | bash -s 如果要特定版本，请为Fabric，Fabric-ca和第三方Docker映像传递版本标识符。下面的命令演示了如何下载最新的生产版本 -Fabric v2.1.1和Fabric CA v1.4.7 cd ~ # 需要特殊姿势进入 # <fabric_version> <fabric-ca_version> <thirdparty_version> curl -sSL https://bit.ly/2ysbOFE | bash -s -- 2.1.1 1.4.7 0.4.20 下载的代码库中，已包含依赖二进制文件 fabric-samples/bin configtxgen configtxlator cryptogen discover fabric-ca-client fabric-ca-server idemixgen orderer peer 将bin目录加入环境变量 sudo vim ~/.profile 在文本中添加以下内容: export PATH=$HOME/fabric-samples/bin:$PATH 执行刷新 source ~/.profile 参考 https://help.aliyun.com/document_detail/60742.html https://ifican.top/2019/11/23/blog/fabric/Fabric%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/
背景 最近考虑把EOS加上Fabric类似的隐私频道，这样可以满足一些特殊场景。 就是只有允许的人的才能看到解密的数据，这样既能满足区块链的特性，又能满足隐私的需求。 所以抽时间研究下Fabric实现技术细节，先从部署开始把 1. 基础环境 OS：Centos 7 x64 HyperLedger Fabric: v1.1(稍后适配v2.x) 2. 设置YUM国内源 2.1 备份原配置 sudo cp /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak 2.2 设置阿里YUM源 sudo wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo 2.3 清理缓存并生成新的缓存 sudo yum clean all sudo yum makecache 2.4 更新 YUM库 sudo yum update 3. Docker安装 一个完整的Docker由以下几个部分组成： • Docker Client 客户端。 • Docker Daemon 守护进程 • Docker Image 镜像 • Docker Container 容器 3.1 卸载旧版本 sudo yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-selinux \ docker-engine-selinux \ docker-engine 3.2 在线安装Docke CE yum-utils 提供的 yum-config-manager device-mapper-persistent-data 和 lvm2 是设备/存储驱动程序所需要的基础应用。 sudo yum install -y yum-utils \ device-mapper-persistent-data \ lvm2 使用下面的命令来设置稳定存储库 sudo yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo 可以选择性地启用 edge 和测试存储库，这些存储库包含 Docker 中，在默认情况下是禁 用的.具体执行命令如下 sudo yum-config-manager --enable docker-ce-edge sudo yum-config-manager --enable docker-ce-test 也可以通过使用禁用标志来运行 yum-config-manager命令，以禁用 edge 或测试存储库， 要重新启用它可以使用 enable 标志 下面的命令禁用 edge 存储库. sudo yum-config-manager --disable docker-ce-edge 最后， 可执行如下命令安装最新版本的 Docker CE sudo yum install docker-ce 还能通如下命令安装指定版本的 Docker CE sudo yum install docker-ce-<VERSION STRING> 至此，Docker 已经安装完成了，Docker 服务是没有启动的，操作系统里的 docker 组被创建，但是没有用户在这个组里。 使用下面的命令将你的用户添加到 docker 的用户组： sudo usermod -aG docker $(yourname) 执行查询 Docker 版本号 看是否安装成功 docker --version 然后使用下面的命令可以运行hello-world程序，因为Docker中还没有hello-world程序的镜像，所以会先pull（下载）下来然后运行。 sudo docker run hello-world 3.3 Docker启动及常用命令 Docker CE 安装完成后，需要启动它并设置为开机启动 Docker 启动命令如下 # 开启 Docker sudo service docker start # 关闭 Docker sudo service docker stop # 重启 Docker sudo service docker restart 也可以使用systemctl命令进行操作 # 开启 Docker sudo systemctl start docker # 关闭 Docker sudo systemctl stop docker # 重启 Docker sudo systemctl restart docker Docker 开机自启动命令如下 chkconfig docker on 或者使用 sudo systemctl enable docker 3.3.1 杀死所有正在运行的容器 docker kill $(docker ps -a -q) 3.3.2 删除所有己经停止的容器 docker rm $(docker ps -a -q) 3.3.3 删除所有镜像 docker rmi $(docker images -q) 3.3.4 强制删除所有镜像 docker rmi -f $(docker images -q) 4. Docker-Compose安装 Compose 是定义和运行多容器 Docker 应用程序的工具，可以使用 YAML 文件来配置应用 服务。然后 通过单个命令可以从配置中 建井启动所有服务。 使用 ompose 基本上是一个三步骤的过程： (1）用 Dockerfile 定义应用程序的环境，这样它可以在任何地方复制 (2）通过docker-compose.yml 在服务中定义所启动的各个应用，这些应用将在相互隔离的 环境中同时运行。 (3）运行 docker-compose up ，启动 Compose 并运行整个应用程序 4.1 安装额外依赖包 sudo yum install epel-release 4.2 安装 python-pip sudo yum install -y python3-pip 4.3 安装 Docker Compose sudo pip3 install docker-compose 4.4 验证安装 docker-compose version 4.5 如果需要删除docker-conpose sudo pip3 uninstall docker-compose 5. 安装Go 5.1 下载Go代码 先去Golang官网查看最新的版本和下载链接 下载并解压安装 wget https://dl.google.com/go/go1.14.4.linux-amd64.tar.gz sudo tar -C /usr/local -xzf go1.14.4.linux-amd64.tar.gz 或者，使用apt安装 sudo apt install golang-go 5.2 配置Go环境变量 编辑环境变量配置文件 sudo vi /etc/profile 文件最后，添加以下内容 export GOROOT=/usr/local/go export GOPATH=/home/Surou(替换你的账户名)/goProject export GOBIN=$GOPATH/bin export PATH=$PATH:$GOROOT/bin export PATH=$PATH:$GOPATH/bin 编辑保存并退出vi后，然后刷新环境变量，使修改立即生效 source /etc/profile 看Go版本，测试安装好正确 go version 6. Fabric环境部署 6.1 Fabric原码安装 cd $GOPATH go get github.com/hyperledger/fabric 如果没有git先安装下 sudo yum install git 切换代码分支,此文章测试v1.1.0版本，后面再针对v2.x做最新的支持 cd $GOPATH/src/github.com/hyperledger/fabric git checkout -b release-1.1 git branch --set-upstream-to=origin/release-1.1 release-1.1 git reset --hard origin/release-1.1 6.2 下载Fabric镜像 获取运行 Fabric 需的镜像获取有多种方式，如果仅仅是测试 Fabric 集群方案，直接进入 fabric/examples/e2e_cli 目录下，运行./download-dockerimages.sh脚本文件即可下载该工程必要 的镜像文件。 进入cli目录 cd fabric/examples/e2e_cli 运行脚本文件即可下载该工程必要的镜像文件 chmod +x ./download-dockerimages.sh ./download-dockerimages.sh // 可能因开梯子失败 Fabric/Peer 运行所需镜像如下 hyperledger/fab ic-tools hyperledger/fabric-peer hyperledger/fabric-couchdb hyperrledger/fabric-ca hyperledger/fabric-ccenv hyperledger/fabric-baseos fabric-tools 是本地客户端镜像，主要用来执行 Peer 点中的相关操作，如频道 智能合约等。 fabric-peer是Fabric 中网络节点镜像，从 1.0 本开始， Fabric的Peer 不再提交数据，全部由客户端完成，但 Peer 依然会对数据进行提交前的验证和背书。 fabric-couchdb 是第 方可插拔式数据库镜像 fabric-couchdb 非必须，如果不使用CouchDB ，则会默认使用 LevelDB ，相比较而言使用 CouchDB 功能性更强一些。 fabric-ca 是服务器本地 CA Server ，可以执行 fabric-ca-client 中的相关操作，实现登陆、注册及吊销等方法。 当然， Fabric 整个网络的运行不能缺少排序服务， Fabricl.O 之后新增了背书机 ，客户端在通过节点背书及合约等一系列验证后 将交易请求发送至排序服务器，排序服务在接收到客户端提交的交易后，会进行数据排序并广播同步至各个 Peer 节点， Fabric/Orderer 运行所需镜 如下： hyperledger/fabric-orderer 如果在使用中已经有了部署生产环境的计划，则需要将共识由 Solo 改为 Kafka ，而 Kafka集群部署所需要的镜像如下： hyperledger/fabric-kafka hyperledger/fabric-zookeeper 通过上述步骤，可以将这些必要的镜像由 Docker 务全部下载至本地， 并最终使用Docker Compose 来启动对应的镜像服务 7. End-2-End 案例 End-2-End HyperLedger Fabric 源码中提供的 Demo ，在1.0版本中，它运行的是Solo 共识，需要 个排序服务和两个组织（每个组织包含两个节点〉组网，入门而言较为简单。而从1.1版本开始，它改成了 Kafka 共识，利用三个 Zookeeper 和四个 Kafka 组成的两个 外围集群，排序服务与节点服务的启动样本与 1.0 版本相同。 7.1 平台特定文件 HyperLedger Fabric 网络 平台部署需要一些特定的二进制文件 ，如 cryptogen,configtxgen,configtxlator,peer 等。这些二进制文件用于辅助生成证书、密钥以及各项配置文件等。 编译Fabric源代码 # 编译依赖gcc 如果没有的话，需要提前安装 sudo yum install gcc # 源码根目录执行 make release 等待编译完成后，会在源码根目录下创建目录/release/linux-amd64/bin，并生成以下文件 configtxgen configtxlator cryptogen get-docker-images.sh orderer peer 将上面的目录添加到环境变量 编辑环境变量配置文件 sudo vi /etc/profile 文件最后，添加以下内容 export PATH=$PATH:$GOPATH/src/github.com/hyperledger/fabric/release/linux-amd64/bin 编辑保存并退出vi后，然后刷新环境变量，使修改立即生效 source /etc/profile 参考文档 https://medium.com/@techgeek628/how-to-install-hyperledger-fabric-on-ubuntu-92d777dcf6a7 https://zhuanlan.zhihu.com/p/44205356 https://juejin.im/post/5da2c97e6fb9a04ddb3b7bc4 《HyperLedger Fabric开发实战-快速掌握区块链技术》 https://medium.com/@tharindusandaruwan40/how-to-setup-hyperledger-fabric-and-work-around-first-network-in-your-windows-machine-part1-78bd0b75595c https://chainhero.io/2017/07/tutorial-build-blockchain-app/ https://github.com/hyperledger/fabric-samples
fabric配置讲解 在 fabric 源码 sampleconfig 目录的两个配置文件，core.yaml，orderer.yaml Peer 配置剖析 core.yaml ############################################################################### # # 日志部分 # ############################################################################### logging: ## 日志级别有： critical、 error、 warning、 notice、 info、 debug 级别由大到小， 级别越小输出越详细 level: info ## 全局的默认日志级别 ## 各个模块日志级别， 覆盖全局配置 cauthdsl: warning gossip: warning grpc: error ledger: info msp: warning policies: warning peer: gossip: warning # 日志的输出格式 format: '%{color}%{time:2006-01-02 15:04:05.000 MST} [%{module}] %{shortfunc} -> %{level:.4s} %{id:03x}%{color:reset} %{message}' ############################################################################### # # peer部分 # ############################################################################### peer: id: jdoe ## Peer节点ID networkId: dev ## 网络ID listenAddress: 0.0.0.0:7051 ## 节点监听的本地网络接口地址 chaincodeAddress: 0.0.0.0:7052 ## 链码容器连接时的监听地址 如未指定, 则使用listenAddress的IP地址和7052端口 address: 0.0.0.0:7051 ## 节点对外的服务地址 （对外的地址） addressAutoDetect: false ## 是否自动探测服务地址 (默认 关闭， 如果启用TLS时，最好关闭) gomaxprocs: -1 ## Go的进程限制数 runtime.GOMAXPROCS(n) 默认 -1 keepalive: ## 客户端和peer间的网络心跳连接配置 minInterval: 60s ## 最小的心跳间隔时间 client: ## 该节点和客户端 的交互配置 interval: 60s ## 和客户端 的心跳间隔 必须 interval >= minInterval timeout: 20s ## 和客户端 间的网络连接超时时间 deliveryClient: ## 交付客户端用于与订购节点通信的心跳 interval: 60s timeout: 20s gossip: ## 节点间通信的gossip 协议的P2P通信 【主要包含了 启动 及 连接】 bootstrap: 127.0.0.1:7051 ## 启动节点后 向哪些节点发起gossip连接，以加入网络，且节点相互间都是同一个组织的 useLeaderElection: true ## 是否启动动态选举 组织的Leader 节点 与 orgLeader 互斥 orgLeader: false ## 是否指定本节点为 组织Leader 节点 与 useLeaderElection 互斥 endpoint: ## 本节点在组织内的gossip id maxBlockCountToStore: 100 ## 保存到内存的区块个数上限 maxPropagationBurstLatency: 10ms ## 保存消息的最大时间，超过则触发转发给其他节点 maxPropagationBurstSize: 10 ## 保存的最大消息个数，超过则触发转发给其他节点 propagateIterations: 1 ## 消息转发的次数 propagatePeerNum: 3 ## 推送消息给指定个数的节点 pullInterval: 4s ## 拉取消息的时间间隔 (second) 必须大于 digestWaitTime + responseWaitTime pullPeerNum: 3 ## 从指定个数的节点拉取消息 requestStateInfoInterval: 4s ## 从节点拉取状态信息(StateInfo) 消息间隔 (second) publishStateInfoInterval: 4s ## 向其他节点推动状态信息消息的间隔 (second) stateInfoRetentionInterval: ## 状态信息消息的超时时间 (second) publishCertPeriod: 10s ## 启动后在心跳消息中包括证书的等待时间 skipBlockVerification: false ## 是否不对区块消息进行校验，默认为false dialTimeout: 3s ## gRPC 连接拨号的超时 (second) connTimeout: 2s ## 建立连接的超时 (second) recvBuffSize: 20 ## 收取消息的缓冲大小 sendBuffSize: 200 ## 发送消息的缓冲大小 digestWaitTime: 1s ## 处理摘要数据的等待时间 (second) 可以大于 requestWaitTime requestWaitTime: 1500ms ## 处理nonce 数据的等待时间 (milliseconds) 可以大于 digestWaitTime responseWaitTime: 2s ## 终止拉取数据处理的等待时间 (second) aliveTimeInterval: 5s ## 定期发送Alive 心跳消息的时间间隔 (second) aliveExpirationTimeout: 25s ## Alive 心跳消息的超时时间 (second) reconnectInterval: 25s ## 断线后重连的时间间隔 (second) externalEndpoint: ## 节点被组织外节点感知时的地址，公布给其他组织的地址和端口, 如果不指定, 其他组织将无法知道本peer的存在 election: ## Leader 节点的选举配置 startupGracePeriod: 15s ## leader节点选举等待的时间 (second) membershipSampleInterval: 1s ## 测试peer稳定性的时间间隔 (second) leaderAliveThreshold: 10s ## pear 尝试进行选举的等待超时 (second) leaderElectionDuration: 5s ## pear 宣布自己为Leader节点的等待时间 (second) pvtData: pullRetryThreshold: 60s transientstoreMaxBlockRetention: 1000 pushAckTimeout: 3s btlPullMargin: 10 reconcileBatchSize: 10 reconcileSleepInterval: 5m events: ## 事件配置 （在1.3版本后配置去除） address: 0.0.0.0:7053 ## 本地服务监听地址 (默认在所有网络接口上进心监听，端口 7053) buffersize: 100 ## 最大缓冲消息数，超过则向缓冲中发送事件消息会被阻塞 timeout: 10ms ## 事件发送超时时间, 如果事件缓存已满, timeout < 0, 事件被丢弃; timeout > 0, 阻塞直到超时丢弃, timeout = 0, 阻塞直到发送出去 timewindow: 15m ## 允许peer和 客户端 时间不一致的最大时间差 keepalive: ## 客户端到peer间的事件心跳 minInterval: 60s sendTimeout: 60s ## 在GRPC流上向客户端发送事件的超时时间 tls: ## tls配置 enabled: false ## 是否开启 TLS，默认不开启TLS clientAuthRequired: false ## 客户端连接到peer是否需要使用加密 cert: ## 证书密钥的位置, 各peer应该填写各自相应的路径 file: tls/server.crt ## 本服务的身份验证证书，公开可见，访问者通过该证书进行验证 key: file: tls/server.key ## 本服务的签名私钥 rootcert: file: tls/ca.crt ## 信任的根CA整数位置 clientRootCAs: ## 用于验证客户端证书的根证书颁发机构的集合 files: - tls/ca.crt clientKey: ## 当TLS密钥用于制作客户端连接。如果不设置，将使用而不是peer.tls.key.file file: clientCert: ## 在进行客户端连接时用于TLS的X.509证书。 如果未设置，将使用peer.tls.cert.file file: serverhostoverride: ## 是否制定进行TLS握手时的主机名称 authentication: ## 身份验证包含与验证客户端消息相关的配置参数 timewindow: 15m ## 客户端请求消息中指定的当前服务器时间与客户端时间之间的可接受差异 fileSystemPath: /var/hyperledger/production ## peer数据存储位置(包括账本,状态数据库等) BCCSP: ## 加密库配置 与Orderer 配置一样 Default: SW ## 使用软件加密方式 (默认 SW) SW: Hash: SHA2 ## Hash 算法类型，目前仅支持SHA2 Security: 256 FileKeyStore: ## 本地私钥文件路径，默认指向 <mspConfigPath>/keystore KeyStore: # Settings for the PKCS#11 crypto provider (i.e. when DEFAULT: PKCS11) PKCS11: ## 设置 PKCS#11 加密算法 (默认PKCS11) Library: ## 本地PKCS11依赖库 Label: ## token的标识 Pin: ## 使用Pin Hash: Security: FileKeyStore: KeyStore: mspConfigPath: msp ## msp 的本地路径 localMspId: SampleOrg ## Peer 所关联的MSP 的ID client: ## cli 公共客户端配置选项 connTimeout: 3s ## 连接超时时间 deliveryclient: ## 交付服务配置 reconnectTotalTimeThreshold: 3600s ## 交付服务交付失败后尝试重连的时间 connTimeout: 3s ## 交付服务和 orderer节点的连接超时时间 reConnectBackoffThreshold: 3600s ## 设置连续重试之间的最大延迟 localMspType: bccsp ## 本地MSP类型 （默认为 BCCSP） profile: ## 是否启用Go自带的profiling 支持进行调试 enabled: false listenAddress: 0.0.0.0:6060 adminService: ## admin服务用于管理操作，例如控制日志模块严重性等。只有对等管理员才能使用该服务 handlers: authFilters: - name: DefaultAuth - name: ExpirationCheck ## 此筛选器检查身份x509证书过期 decorators: - name: DefaultDecorator endorsers: escc: name: DefaultEndorsement library: validators: vscc: name: DefaultValidation library: validatorPoolSize: ## 处理交易验证的并发数, 默认是CPU的核数 discovery: ## 客户端使用发现服务来查询有关peers的信息，例如 - 哪些peer已加入某个channel，最新的channel配置是什么，最重要的是 - 给定chaincode和channel，哪些可能的peer满足认可 policy enabled: true authCacheEnabled: true authCacheMaxSize: 1000 authCachePurgeRetentionRatio: 0.75 orgMembersAllowedAccess: false ############################################################################### # # vm环境配置，目前主要支持 Docker容器 # ############################################################################### vm: endpoint: unix:///var/run/docker.sock ## Docker Daemon 地址，默认是本地 套接字 docker: tls: ## Docker Daemon 启用TLS时的相关证书配置, 包括信任的根CA证书、服务身份证书、签名私钥等等 enabled: false ca: file: docker/ca.crt cert: file: docker/tls.crt key: file: docker/tls.key attachStdout: false ## 是否启用绑定到标准输出，启用后 链码容器 的输出消息会绑定到标准输出，方便进行调试 hostConfig: ## Docker 相关的主机配置，包括网络配置、日志、内存等等，这些配置在启动链码容器时进行使用 NetworkMode: host Dns: # - 192.168.0.1 LogConfig: Type: json-file Config: max-size: "50m" max-file: "5" Memory: 2147483648 ############################################################################### # # 链码相关配置 # ############################################################################### chaincode: id: ## 记录链码相关信息，包括路径、名称、版本等等，该信息会以标签形式写到链码容器 path: name: builder: $(DOCKER_NS)/fabric-ccenv:latest ## 通用的本地编译环境，是一个Docker 镜像 pull: false ## golang: ## Go语言的链码部署生成镜像的基础Docker镜像 runtime: $(BASE_DOCKER_NS)/fabric-baseos:$(ARCH)-$(BASE_VERSION) dynamicLink: false car: ## car格式的链码部署生成镜像的基础Docker 镜像 runtime: $(BASE_DOCKER_NS)/fabric-baseos:$(ARCH)-$(BASE_VERSION) java: ## java语言的基础镜像 Dockerfile: | from $(DOCKER_NS)/fabric-javaenv:$(ARCH)-1.1.0 node: ## node.js的基础镜像 runtime: $(BASE_DOCKER_NS)/fabric-baseimage:$(ARCH)-$(BASE_VERSION) startuptimeout: 300s ## 启动链码容器超时，等待超时时间后还没收到链码段的注册消息，则认为启动失败 executetimeout: 30s ## invoke 和 initialize 命令执行超时时间 deploytimeout: ## 部署链码的命令执行超时时间 mode: net ## 执行链码的模式，dev: 允许本地直接运行链码，方便调试； net: 意味着在容器中运行链码 keepalive: 0 ## Peer 和链码之间的心跳超市时间， <= 0 意味着关闭 system: ## 系统链码的相关配置 (系统链码白名单 ??) cscc: enable lscc: enable escc: enable vscc: enable qscc: enable systemPlugins: ## 系统链码插件 logging: ## 链码容器日志相关配置 level: info shim: warning format: '%{color}%{time:2006-01-02 15:04:05.000 MST} [%{module}] %{shortfunc} -> %{level:.4s} %{id:03x}%{color:reset} %{message}' ############################################################################### # # 账本相关配置 # ############################################################################### ledger: blockchain: state: ## 状态DB的相关配置(包括 golevelDB、couchDB)、DN连接、查询最大返回记录数等 stateDatabase: goleveldb ## stateDB的底层DB配置 (默认golevelDB) couchDBConfig: ## 如果启用couchdb，配置连接信息 (goleveldb 不需要配置这些) couchDBAddress: 127.0.0.1:5984 username: password: maxRetries: 3 ## 运行时出错重试数 maxRetriesOnStartup: 10 ## 启动时出错的重试数 requestTimeout: 35s ## 请求超时时间 queryLimit: 10000 ## 每个查询最大返回数 maxBatchUpdateSize: 1000 ## 批量更新最大记录数 warmIndexesAfterNBlocks: 1 history: enableHistoryDatabase: true ## 是否启用历史数据库，默认开启 ############################################################################### # # 服务度量监控配置 # ############################################################################### metrics: enabled: false ## 是否开启监控服务 reporter: statsd interval: 1s statsdReporter: address: 0.0.0.0:8125 flushInterval: 2s flushBytes: 1432 promReporter: ## prometheus 普罗米修斯服务监听地址 Orderer 配置剖析 orderer.yaml ################################################################################ # # Orderer的配置 # ################################################################################ General: LedgerType: file ## 账本类型，支持ram、json、file 三种类型【建议用file】，其中ram保存在内存中；json、file保存在本地文件中 (通常为 /var/hyperledger/production/orderer 下) ListenAddress: 127.0.0.1 ## 服务监听地址，一般需要制定为服务的特定网络接口地址 或者全网(0.0.0.0) ListenPort: 7050 ## 服务监听端口 默认7050 TLS: ## 启用TLS 时的相关配置 (grpc 传输) Enabled: false PrivateKey: tls/server.key ## Orderer 签名私钥 Certificate: tls/server.crt ## Orderer 身份证书 RootCAs: - tls/ca.crt ## 根证书 ClientAuthRequired: false ## 是否对客户端也进行认证 ClientRootCAs: Keepalive: ## 设置GRPC 服务心跳检查 ServerMinInterval: 60s ## 客户端和 orderer 的 最小心跳间隔 ServerInterval: 7200s ## 客户端和 orderer 的心跳间隔时间 ServerTimeout: 20s ## 客户端和 Orderer 的超时时间 LogLevel: info ## 日志等级 ## 日志输出格式 LogFormat: '%{color}%{time:2006-01-02 15:04:05.000 MST} [%{module}] %{shortfunc} -> %{level:.4s} %{id:03x}%{color:reset} %{message}' GenesisMethod: provisional ## 创世块的提供方式 (系统通道初始区块的提供方式，支持 provisional 或者 file；前者根据GenesisProfile 指定默认的 $FABRIC_CFG_PATH/config.yaml 文件中的profile生成；后者使用GenesisFile 指定现成的初始区块文件) GenesisProfile: SampleInsecureSolo ## 创世块使用的Profile；GenesisMethod: provisional 才有效 GenesisFile: genesisblock ## 使用现成创世块文件时，文件的路径 [创世块的位置] GenesisMethod: file 才有效 LocalMSPDir: msp ## 本地MSP文件的路径 【orderer节点所需的安全认证文件的位置】 LocalMSPID: SampleOrg ## Orderer所关联的MSP的ID MSP管理器用于注册安全认证文件的ID, 此ID必须与配置系统通道和创世区块时(configtx.yaml的OrdererGenesis部分)指定的组织中的某一个组织的ID一致 Profile: ## 为Go pprof性能优化工具启用一个HTTP服务以便作性能分析(https://golang.org/pkg/net/http/pprof) Enabled: false ## 不启用 Address: 0.0.0.0:6060 ## Go pprof的HTTP服务监听的地址和端口 BCCSP: ## 加密库配置 具体参照Peer 配置 Default: SW SW: Hash: SHA2 Security: 256 FileKeyStore: KeyStore: Authentication: TimeWindow: 15m ################################################################################ # # 基于文件账本配置 (file和json两种类型) # ################################################################################ FileLedger: Location: /var/hyperledger/production/orderer ## 指定存放文件的位置，一般为 /var/hyperledger/production/orderer, 该目录下的 chains目录存放各个chain的区块，index目录存放 索引文件 (如果这项不指定, 每次节点重启都将使用一个新的临时位置) Prefix: hyperledger-fabric-ordererledger ## 如果不指定Location，则在临时目录下创建账本时目录的名称 ################################################################################ # # 基于内存账本配置 # ################################################################################ RAMLedger: HistorySize: 1000 ## 内存账本所支持存储的区块的数量, 如果内存中存储的区块达到上限, 继续追加区块会导致最旧的区块被丢弃 ################################################################################ # # kafka 集群配置 # ################################################################################ Kafka: # kafka是一种基于发布/订阅模式的分布式消息系统 # fabric网络中, orderer节点集群组成kafka集群, 客户端是kafka集群的Producer(消息生产者), peer是kafka集群的Consumer(消息消费者) # kafka集群使用ZooKeeper(分布式应用协调服务)管理集群节点, 选举leader. Retry: ## 连接时的充实操作 kafka 会利用 sarama 客户端为chennel创建一个producer 负责向kafka 写数据，一个comsumer负责kafka读数据 ShortInterval: 5s ## 操作失败后的快速重试间隔时间 ShortTotal: 10m ## 快速重试阶段最对重试多久 LongInterval: 5m ## 快速充实阶段仍然失败后进入 慢重试阶段，慢重试的时间间隔 LongTotal: 12h ## 慢重试最多重试多久 # https://godoc.org/github.com/Shopify/sarama#Config NetworkTimeouts: ## Sarama 网络超时时间 DialTimeout: 10s ReadTimeout: 10s WriteTimeout: 10s Metadata: ## kafka集群leader 选举中的metadata 请求参数 RetryBackoff: 250ms ## leader选举过程中元数据请求失败的重试间隔 RetryMax: 3 ## 最大重试次数 Producer: ## 发送消息到kafka集群时的超时 RetryBackoff: 100ms ## 向kafka集群发送消息失败后的重试间隔 RetryMax: 3 ## 最大重试次数 Consumer: ## 从kafka集群接收消息时的超时 RetryBackoff: 2s ## 从kafka集群拉取消息失败后的重试间隔 Verbose: false ## 是否开启kafka的客户端的调试日志 (orderer与kafka集群交互是否生成日) TLS: ## 与kafka集群的连接启用TLS时的相关配置 Enabled: false ## 是否开启TLS，默认不开启 PrivateKey: ## Orderer 身份签名私钥 # File: ## 私钥文件路径 Certificate: ## kafka的身份证书 # File: ## 证书文件路径 RootCAs: ## 验证kafka证书时的根证书 # File: ## 根证书文件路径 Version: ## kafka的版本 ################################################################################ # # Orderer节点的调试参数 # ################################################################################ Debug: BroadcastTraceDir: ## 该orderer节点的广播服务请求保存的位置 DeliverTraceDir: ## 该orderer节点的传递服务请求保存的位置 ## 以下配置是1.4最新的配置 ################################################################################ # # 操作配置 # ################################################################################ Operations: # 操作服务地址端口 ListenAddress: 127.0.0.1:8443 # TLS 配置 TLS: Enabled: false Certificate: PrivateKey: ClientAuthRequired: false RootCAs: [] ################################################################################ # # 度量配置 # ################################################################################ Metrics: # 度量提供程序是 prometheus或disabled Provider: disabled # statsd 配置 Statsd: # 网络协议 Network: udp # 服务地址 Address: 127.0.0.1:8125 # 将本地缓存的计数器和仪表推送到 statsd 的时间间隔;时间被立即推送 WriteInterval: 30s # 前缀预先添加到所有发出的 statsd 指标 Prefix: ################################################################################ # # 共识配置 # ################################################################################ Consensus: # 这里允许的键值对取决于共识插件。对于 etcd/raft， # 我们使用以下选项: # WALDir 指定存储 etcd/raft 的Write Ahead Logs的位置。每个channel都有自己的以channelID命名的子目录 WALDir: /var/hyperledger/production/orderer/etcdraft/wal # SnapDir 指定存储 etcd/raft 快照的位置。每个channel都有自己的以channelID命名的子目录 SnapDir: /var/hyperledger/production/orderer/etcdraft/snapshot 搭建网络核心crypto-config.yaml 配置 crypto-config.yaml 文件 # --------------------------------------------------------------------------- # "OrdererOrgs" # --------------------------------------------------------------------------- OrdererOrgs: ## 定义Orderer组织 - Name: Orderer ## 名称 Domain: example.com ## 组织的命名域 # --------------------------------------------------------------------------- # "Specs" - 有关完整说明，请参阅下面的PeerOrgs # --------------------------------------------------------------------------- Specs: - Hostname: orderer # --------------------------------------------------------------------------- # "PeerOrgs" # --------------------------------------------------------------------------- PeerOrgs: - Name: Org1 ## 名称 Domain: org1.example.com ## 组织的命名域 EnableNodeOUs: true ## 如果设置了EnableNodeOUs，就在msp下生成config.yaml文件 Template: ## 允许定义从模板顺序创建的1个或多个主机。 默认情况下，这看起来像是从0到Count-1的“peer”。 您可以覆盖节点数（Count），起始索引（Start）或用于构造名称的模板（Hostname）。 Count: 1 ## 表示生成几个Peer # Start: 5 # Hostname: {{.Prefix}}{{.Index}} # default Users: Count: 1 ## 表示生成普通User数量 - Name: Org2 Domain: org2.example.com EnableNodeOUs: true Template: Count: 1 Users: Count: 1 通道及锚节点的配置 configtx.yaml 配置剖析 configtx.yaml 文件 ################################################################################ # # Organizations部分 # 【注意】：本文件中 &KEY 均为 *KEY 所引用； xx：&KEY 均为 <<: *KEY 所引用 ################################################################################ Organizations: ## 定义Orderer组织 - &OrdererOrg Name: OrdererOrg ## Orderer的组织的名称 ID: OrdererMSP ## Orderer 组织的ID （ID是引用组织的关键） MSPDir: crypto-config/ordererOrganizations/example.com/msp ## Orderer的 MSP 证书目录路径 AdminPrincipal: Role.ADMIN ## 【可选项】 组织管理员所需要的身份，可选项: Role.ADMIN 和 Role.MEMBER ## 定义Peer组织1 - &Org1 Name: Org1MSP ## 组织名称 ID: Org1MSP ## 组织ID MSPDir: crypto-config/peerOrganizations/org1.example.com/msp ## Peer的MSP 证书目录路径 AnchorPeers: ## 定义组织锚节点 用于跨组织 Gossip 通信 - Host: peer0.org1.example.com ## 锚节点的主机名 Port: 7051 ## 锚节点的端口号 ## 定义Peer组织 2 - &Org2 Name: Org2MSP ID: Org2MSP MSPDir: crypto-config/peerOrganizations/org2.example.com/msp AnchorPeers: - Host: peer0.org2.example.com Port: 7051 ################################################################################ # 本节定义了 fabric 网络的功能. ################################################################################ Capabilities: ## 通道功能适用于orderers and the peers，并且必须得到两者的支持。 将功能的值设置为true. Global: &ChannelCapabilities ## V1.1 的 Global是一个行为标记，已被确定为运行v1.0.x的所有orderers和peers的行为，但其修改会导致不兼容。 用户应将此标志设置为true. V1_1: true ## Orderer功能仅适用于orderers，可以安全地操纵，而无需担心升级peers。 将功能的值设置为true Orderer: &OrdererCapabilities ## Orderer 的V1.1是行为的一个标记，已经确定为运行v1.0.x的所有orderers 都需要，但其修改会导致不兼容。 用户应将此标志设置为true V1_1: true ## 应用程序功能仅适用于Peer 网络，可以安全地操作，而无需担心升级或更新orderers。 将功能的值设置为true Application: &ApplicationCapabilities ## V1.2 for Application是一个行为标记，已被确定为运行v1.0.x的所有peers所需的行为，但其修改会导致不兼容。 用户应将此标志设置为true V1_2: true ################################################################################ # # 应用通道相关配置，主要包括 参与应用网络的可用组织信息 # ################################################################################ Application: &ApplicationDefaults ## 自定义被引用的地址 Organizations: ## 加入通道的组织信息 ################################################################################ # # Orderer 系统通道相关配置，包括 Orderer 服务配置和参与Orderer 服务的可用组织 # Orderer 默认是 solo 的 且不包含任何组织 【主要被 Profiles 部分引用】 ################################################################################ Orderer: &OrdererDefaults ## 自定义被引用的地址 OrdererType: solo ## Orderer 类型，包含 solo 和 kafka 集群 Addresses: ## 服务地址 - orderer.example.com:7050 BatchTimeout: 2s ## 区块打包的最大超时时间 (到了该时间就打包区块) BatchSize: ## 区块打包的最大包含交易数 MaxMessageCount: 10 ## 一个区块里最大的交易数 AbsoluteMaxBytes: 98 MB ## 一个区块的最大字节数， 任何时候都不能超过 PreferredMaxBytes: 512 KB ## 一个区块的建议字节数，如果一个交易消息的大小超过了这个值, 就会被放入另外一个更大的区块中 MaxChannels: 0 ## 【可选项】 表示Orderer 允许的最大通道数， 默认 0 表示没有最大通道数 Kafka: Brokers: ## kafka的 brokens 服务地址 允许有多个 - 127.0.0.1:9092 Organizations: ## 参与维护 Orderer 的组织，默认为空 ################################################################################ # # Profile # # - 一系列通道配置模板，包括Orderer 系统通道模板 和 应用通道类型模板 # ################################################################################ Profiles: ## Orderer的 系统通道模板 必须包括 Orderer、 Consortiums 两部分 TwoOrgsOrdererGenesis: ## Orderer 系统的通道及创世块配置。通道为默认配置，添加一个OrdererOrg 组织， 联盟为默认的 SampleConsortium 联盟，添加了两个组织 【该名称可以自定义 ？？】 Capabilities: <<: *ChannelCapabilities Orderer: ## 指定Orderer系统通道自身的配置信息 <<: *OrdererDefaults ## 引用 Orderer 部分的配置 &OrdererDefaults Organizations: - *OrdererOrg ## 属于Orderer 的通道组织 该处引用了 【 &OrdererOrg 】位置内容 Capabilities: <<: *OrdererCapabilities Consortiums: ## Orderer 所服务的联盟列表 SampleConsortium: ## 创建更多应用通道时的联盟 引用 TwoOrgsChannel 所示 Organizations: - *Org1 - *Org2 ## 应用通道模板 必须包括 Application、 Consortium 两部分 TwoOrgsChannel: ## 应用通道配置。默认配置的应用通道，添加了两个组织。联盟为SampleConsortium Consortium: SampleConsortium ## 通道所关联的联盟名称 Application: ## 指定属于某应用通道的信息，主要包括 属于通道的组织信息 <<: *ApplicationDefaults Organizations: ## 初始 加入应用通道的组织 - *Org1 - *Org2 Capabilities: <<: *ApplicationCapabilities 转载自：https://gitee.com/jonluo/blockchain/tree/master/hyperledger-fabric
Hyperledger Fabric 超级账本 Hyperledger Fabric 称为联盟链，是分布式账本技术（DLT），采用模块化架构来提供高度机密性，伸缩性，灵活性和可扩展性。 它旨在支持不同组件的可插拔实现，并适应整个经济生态系统中存在的复杂性和复杂性。 Hyperledger Fabric 架构 Blockchain区块链架构设计之一：成员管理 Blockchain区块链架构设计之二：分布式账本技术对比 Blockchain区块链架构设计之三：Hyperledger Fabric介绍 Blockchain区块链架构设计之四：Fabric多通道和下一代账本设计 Blockchain区块链架构设计之五：让DLT产生协作，对Corda和GSL的思考 Blockchain区块链架构设计之六：Fabric 1.0账本设计（1） Blockchain区块链架构设计之七：Fabric 1.0 Endorse背书策略 Blockchain区块链架构设计之八：Fabric 1.0交易流程示例 Blockchain区块链架构设计之九：Hyperledger Burrow介绍Hyperledger开发环境 前提安装条件 Git Golang Node.js and NPM Docker and Docker Compose (Docker版本17.06.2-ce或更高版本,Docker Compose版本1.14.0或更高版本) 克隆 hyperledger/fabric-samples git clone https://github.com/hyperledger/fabric-samples.git 切换到fabric-samples文件夹下 cd fabric-samples 将指定版本的Hyperledger Fabric平台特定二进制文件和配置文件分别安装到fabric-samples存储库的根目录中bin文件夹和config文件夹,和下载指定版本的Hyperledger Fabric docker镜像 ./scripts/bootstrap.sh [version] [ca version] [thirdparty_version] (默认版本为 1.2.0, 1.2.0 和 0.4.10 ) 构建第一个网络 cd first-network 生成网络工件： ./byfn.sh generate 启动网络: ./byfn.sh up 终止容器，删除加密材料和四个工件，并从Docker Registry中删除链上代码镜像： ./byfn.sh down (这一步一般在重新启动新的联盟链使用) 到此，第一个联盟链搭建成功，因为是自动化脚本构建的，接下来分析细节，手动构建细节： ./byfn.sh generate 执行后的日志如图： 对应日志中的 1，以获取生成将用于crypto-config.yaml文件中定义的网络配置的证书，对应手工配置： ../bin/cryptogen generate --config=./crypto-config.yaml 对应输出日志： org1.example.com org2.example.com 证书和密钥（即MSP材料）将输出到 first-network 目录中的 crypto-config 文件夹 对应日志中的 2，告诉 configtxgen 工具在哪里查找配置文件 configtx.yaml 并调用 configtxgen 工具来创建 orderer 创世区块，对应手工配置：export FABRIC_CFG_PATH=$PWD && ../bin/configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block 对应输出类似日志： 2018-08-23 10:36:13.825 CST [common/tools/configtxgen] main -> WARN 001 Omitting the channel ID for configtxgen is deprecated. Explicitly passing the channel ID will be required in the future, defaulting to 'testchainid'. 2018-08-23 10:36:13.825 CST [common/tools/configtxgen] main -> INFO 002 Loading configuration 2018-08-23 10:36:13.831 CST [common/tools/configtxgen/encoder] NewChannelGroup -> WARN 003 Default policy emission is deprecated, please include policy specificiations for the channel group in configtx.yaml 2018-08-23 10:36:13.832 CST [common/tools/configtxgen/encoder] NewOrdererGroup -> WARN 004 Default policy emission is deprecated, please include policy specificiations for the orderer group in configtx.yaml 2018-08-23 10:36:13.832 CST [common/tools/configtxgen/encoder] NewOrdererOrgGroup -> WARN 005 Default policy emission is deprecated, please include policy specificiations for the orderer org group OrdererOrg in configtx.yaml 2018-08-23 10:36:13.832 CST [msp] getMspConfig -> INFO 006 Loading NodeOUs 2018-08-23 10:36:13.832 CST [common/tools/configtxgen/encoder] NewOrdererOrgGroup -> WARN 007 Default policy emission is deprecated, please include policy specificiations for the orderer org group Org1MSP in configtx.yaml 2018-08-23 10:36:13.832 CST [msp] getMspConfig -> INFO 008 Loading NodeOUs 2018-08-23 10:36:13.832 CST [common/tools/configtxgen/encoder] NewOrdererOrgGroup -> WARN 009 Default policy emission is deprecated, please include policy specificiations for the orderer org group Org2MSP in configtx.yaml 2018-08-23 10:36:13.832 CST [common/tools/configtxgen] doOutputBlock -> INFO 00a Generating genesis block 2018-08-23 10:36:13.833 CST [common/tools/configtxgen] doOutputBlock -> INFO 00b Writing genesis block 创世区块 genesis.block 将输出到 first-network 目录中的 channel-artifacts 文件夹 对应日志中的 3，创建通道配置文件，对应手工配置：export CHANNEL_NAME=mychannel && ../bin/configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME 对应输出类似日志： 2018-08-23 10:55:33.393 CST [common/tools/configtxgen] main -> INFO 001 Loading configuration 2018-08-23 10:55:33.399 CST [common/tools/configtxgen] doOutputChannelCreateTx -> INFO 002 Generating new channel configtx 2018-08-23 10:55:33.399 CST [common/tools/configtxgen/encoder] NewApplicationGroup -> WARN 003 Default policy emission is deprecated, please include policy specificiations for the application group in configtx.yaml 2018-08-23 10:55:33.399 CST [msp] getMspConfig -> INFO 004 Loading NodeOUs 2018-08-23 10:55:33.399 CST [common/tools/configtxgen/encoder] NewApplicationOrgGroup -> WARN 005 Default policy emission is deprecated, please include policy specificiations for the application org group Org1MSP in configtx.yaml 2018-08-23 10:55:33.400 CST [msp] getMspConfig -> INFO 006 Loading NodeOUs 2018-08-23 10:55:33.400 CST [common/tools/configtxgen/encoder] NewApplicationOrgGroup -> WARN 007 Default policy emission is deprecated, please include policy specificiations for the application org group Org2MSP in configtx.yaml 2018-08-23 10:55:33.401 CST [common/tools/configtxgen] doOutputChannelCreateTx -> INFO 008 Writing new channel tx 通道配置文件 channel.tx 将输出到 first-network 目录中的 channel-artifacts 文件夹 对应日志中的 4，构建的通道上为Org1组织锚节点配置文件，对应手工配置：../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP 对应输出类似日志： 2018-08-23 11:07:49.817 CST [common/tools/configtxgen] main -> INFO 001 Loading configuration 2018-08-23 11:07:49.823 CST [common/tools/configtxgen] doOutputAnchorPeersUpdate -> INFO 002 Generating anchor peer update 2018-08-23 11:07:49.823 CST [common/tools/configtxgen] doOutputAnchorPeersUpdate -> INFO 003 Writing anchor peer update 通道上为Org1定义锚对等节点配置文件 Org1MSPanchors.tx 将输出到 first-network 目录中的 channel-artifacts 文件夹 对应日志中的 5，构建的通道上为Org2组织锚节点配置文件，对应手工配置：../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org2MSP 对应输出类似日志： 2018-08-23 11:10:02.486 CST [common/tools/configtxgen] main -> INFO 001 Loading configuration 2018-08-23 11:10:02.493 CST [common/tools/configtxgen] doOutputAnchorPeersUpdate -> INFO 002 Generating anchor peer update 2018-08-23 11:10:02.493 CST [common/tools/configtxgen] doOutputAnchorPeersUpdate -> INFO 003 Writing anchor peer upda 通道上为Org2定义锚对等节点配置文件 Org2MSPanchors.tx 将输出到 first-network 目录中的 channel-artifacts 文件夹 ./byfn.sh up 执行后的日志可以分为两部分： 第一部分 Creating network "net_byfn" with the default driver Creating volume "net_orderer.example.com" with default driver Creating volume "net_peer0.org1.example.com" with default driver Creating volume "net_peer1.org1.example.com" with default driver Creating volume "net_peer0.org2.example.com" with default driver Creating volume "net_peer1.org2.example.com" with default driver Creating peer0.org2.example.com ... done Creating orderer.example.com ... done Creating peer1.org1.example.com ... done Creating peer1.org2.example.com ... done Creating peer0.org1.example.com ... done Creating cli ... done 这部分其实是利用 docker-compose 启动容器编排，具体命令为： docker-compose -f docker-compose-cli.yaml up -d 第二部分 ____ _____ _ ____ _____ / ___| |_ _| / \ | _ \ |_ _| \___ \ | | / _ \ | |_) | | | ___) | | | / ___ \ | _ < | | |____/ |_| /_/ \_\ |_| \_\ |_| Build your first network (BYFN) end-to-end test Channel name : mychannel Creating channel... + peer channel create -o orderer.example.com:7050 -c mychannel -f ./channel-artifacts/channel.tx --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem + res=0 + set +x 2018-08-23 04:18:50.971 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized 2018-08-23 04:18:50.985 UTC [cli/common] readBlock -> INFO 002 Got status: &{NOT_FOUND} 2018-08-23 04:18:50.987 UTC [channelCmd] InitCmdFactory -> INFO 003 Endorser and orderer connections initialized 2018-08-23 04:18:51.193 UTC [cli/common] readBlock -> INFO 004 Received block: 0 ===================== Channel 'mychannel' created ===================== Having all peers join the channel... + peer channel join -b mychannel.block + res=0 + set +x 2018-08-23 04:18:51.282 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized 2018-08-23 04:18:51.386 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel ===================== peer0.org1 joined channel 'mychannel' ===================== + peer channel join -b mychannel.block + res=0 + set +x 2018-08-23 04:18:54.468 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized 2018-08-23 04:18:54.577 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel ===================== peer1.org1 joined channel 'mychannel' ===================== + peer channel join -b mychannel.block + res=0 + set +x 2018-08-23 04:18:57.680 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized 2018-08-23 04:18:57.790 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel ===================== peer0.org2 joined channel 'mychannel' ===================== + peer channel join -b mychannel.block + res=0 + set +x 2018-08-23 04:19:00.881 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized 2018-08-23 04:19:00.991 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel ===================== peer1.org2 joined channel 'mychannel' ===================== Updating anchor peers for org1... + peer channel update -o orderer.example.com:7050 -c mychannel -f ./channel-artifacts/Org1MSPanchors.tx --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem + res=0 + set +x 2018-08-23 04:19:04.082 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized 2018-08-23 04:19:04.089 UTC [channelCmd] update -> INFO 002 Successfully submitted channel update ===================== Anchor peers updated for org 'Org1MSP' on channel 'mychannel' ===================== Updating anchor peers for org2... + peer channel update -o orderer.example.com:7050 -c mychannel -f ./channel-artifacts/Org2MSPanchors.tx --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem + res=0 + set +x 2018-08-23 04:19:07.175 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized 2018-08-23 04:19:07.183 UTC [channelCmd] update -> INFO 002 Successfully submitted channel update ===================== Anchor peers updated for org 'Org2MSP' on channel 'mychannel' ===================== Installing chaincode on peer0.org1... + peer chaincode install -n mycc -v 1.0 -l golang -p github.com/chaincode/chaincode_example02/go/ + res=0 + set +x 2018-08-23 04:19:10.273 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc 2018-08-23 04:19:10.273 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc 2018-08-23 04:19:10.401 UTC [chaincodeCmd] install -> INFO 003 Installed remotely response:<status:200 payload:"OK" > ===================== Chaincode is installed on peer0.org1 ===================== Install chaincode on peer0.org2... + peer chaincode install -n mycc -v 1.0 -l golang -p github.com/chaincode/chaincode_example02/go/ + res=0 + set +x 2018-08-23 04:19:10.461 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc 2018-08-23 04:19:10.461 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc 2018-08-23 04:19:10.573 UTC [chaincodeCmd] install -> INFO 003 Installed remotely response:<status:200 payload:"OK" > ===================== Chaincode is installed on peer0.org2 ===================== Instantiating chaincode on peer0.org2... + peer chaincode instantiate -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n mycc -l golang -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P 'AND ('\''Org1MSP.peer'\'','\''Org2MSP.peer'\'')' + res=0 + set +x 2018-08-23 04:19:10.634 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc 2018-08-23 04:19:10.634 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc ===================== Chaincode is instantiated on peer0.org2 on channel 'mychannel' ===================== Querying chaincode on peer0.org1... ===================== Querying on peer0.org1 on channel 'mychannel'... ===================== Attempting to Query peer0.org1 ...3 secs + peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}' + res=0 + set +x 100 ===================== Query successful on peer0.org1 on channel 'mychannel' ===================== Sending invoke transaction on peer0.org1 peer0.org2... + peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n mycc --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"Args":["invoke","a","b","10"]}' + res=0 + set +x 2018-08-23 04:19:31.656 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200 ===================== Invoke transaction successful on peer0.org1 peer0.org2 on channel 'mychannel' ===================== Installing chaincode on peer1.org2... + peer chaincode install -n mycc -v 1.0 -l golang -p github.com/chaincode/chaincode_example02/go/ + res=0 + set +x 2018-08-23 04:19:31.708 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc 2018-08-23 04:19:31.708 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc 2018-08-23 04:19:31.815 UTC [chaincodeCmd] install -> INFO 003 Installed remotely response:<status:200 payload:"OK" > ===================== Chaincode is installed on peer1.org2 ===================== Querying chaincode on peer1.org2... ===================== Querying on peer1.org2 on channel 'mychannel'... ===================== + peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}' Attempting to Query peer1.org2 ...3 secs + res=0 + set +x 90 ===================== Query successful on peer1.org2 on channel 'mychannel' ===================== ========= All GOOD, BYFN execution completed =========== _____ _ _ ____ | ____| | \ | | | _ \ | _| | \| | | | | | | |___ | |\ | | |_| | |_____| |_| \_| |____/ 这部分其实是利用 docker exec 命令 进入 cli 容器中执行 scripts/script.sh 脚本，其参数为 mychannel 3 golang 10 false，具体命令为： docker exec cli scripts/script.sh mychannel 3 golang 10 false 接下来，继续细分 docker exec cli scripts/script.sh mychannel 3 golang 10 false 这个命令等同于以下操作： 首先进入 cli 容器： docker exec -it cli bash 接下来在容器里操作，配置环境变量: export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp export CORE_PEER_ADDRESS=peer0.org1.example.com:7051 export CORE_PEER_LOCALMSPID="Org1MSP" export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt 创建 mychannel 通道(相当于通过创世区块创建区块链，每个通道相当于每条独立的区块链)： export CHANNEL_NAME=mychannel peer channel create -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/channel.tx --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem 输出日志： 2018-08-23 06:56:14.257 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized 2018-08-23 06:56:14.273 UTC [cli/common] readBlock -> INFO 002 Got status: &{NOT_FOUND} 2018-08-23 06:56:14.274 UTC [channelCmd] InitCmdFactory -> INFO 003 Endorser and orderer connections initialized 2018-08-23 06:56:14.480 UTC [cli/common] readBlock -> INFO 004 Received block: 0 节点加入 mychannel 通道(相当于节点加入区块链网络)： 加入通道需要用到环境变量的值，默认为 peer0.org1 节点加入通道 peer channel join -b mychannel.block 输出日志： 2018-08-23 07:10:09.620 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized 2018-08-23 07:10:09.729 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel 要其他节点也加入 mychannel 通道，需要修改环境变量的值，也很简单，举个例子,如果 peer1.org2 节点加入通道，只要把所有环境变量值出现 org1 替换成 org2 ，并把 CORE_PEER_ADDRESS值中的 peer0 替换成 peer1 ，如下： CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp CORE_PEER_ADDRESS=peer1.org2.example.com:7051 CORE_PEER_LOCALMSPID="Org2MSP" CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt 修改后继续执行：peer channel join -b mychannel.block，同理完成 peer0.org2，peer1.org1，peer1.org2 加入 mychannel 通道 更新通道的锚节点，实质上是在通道的创世块之上添加了额外的配置信息(所谓锚节点就是某联盟在通道中公开链接的一个或多个节点) 更新通道中 Org1 组织的锚节点为 peer0.org1.example.com： 首先确保环境变量是 peer0.org1 的信息： CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp CORE_PEER_ADDRESS=peer0.org1.example.com:7051 CORE_PEER_LOCALMSPID="Org1MSP" 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 然后更新 peer channel update -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/Org1MSPanchors.tx --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem 更新通道中 Org2 组织的锚节点为 peer0.org2.example.com： 首先确保环境变量是 peer0.org2 的信息： CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp CORE_PEER_ADDRESS=peer0.org2.example.com:7051 CORE_PEER_LOCALMSPID="Org2MSP" CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt 然后更新 peer channel update -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/Org2MSPanchors.tx --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem 安装和实例化Chaincode 安装 golang版 Chaincode ，安装到的节点为环境变量的配置节点: peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/chaincode_example02/go/ 日志输出： 2018-08-23 11:25:20.439 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc 2018-08-23 11:25:20.439 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc 2018-08-23 11:25:20.831 UTC [chaincodeCmd] install -> INFO 003 Installed remotely response:<status:200 payload:"OK" > 接下来，在通道上实例化链码。这将初始化通道上的链代码，设置链代码的认可策略，并为目标节点启动链代码容器： peer chaincode instantiate -o orderer.example.com:7050 --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C $CHANNEL_NAME -n mycc -v 1.0 -c '{"Args":["init","a", "100", "b","200"]}' -P "AND ('Org1MSP.peer','Org2MSP.peer')" 日志输出： 2018-08-23 11:31:33.050 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc 2018-08-23 11:31:33.050 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc 查询以确保链代码已正确实例化并填充状态数据库 peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}' 日志输出： 100 调用，a取10给b peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C $CHANNEL_NAME -n mycc --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"Args":["invoke","a","b","10"]}' 输出 INFO 001 Chaincode invoke successful. result: status:200 查询结果得到： a：90，b:210，成功结束 联盟链新增组织 Org3 ：./eyfn.sh up 手动构建脚本细节 切换目录：cd org3-artifacts 为Org3生成加密材料../../bin/cryptogen generate --config=./org3-crypto.yaml 生成Org3的配置材料export FABRIC_CFG_PATH=$PWD && ../../bin/configtxgen -printOrg Org3MSP > ../channel-artifacts/org3.json 将 Orderer 的MSP材料复制到 Org3 的crypto-config目录cd ../ && cp -r crypto-config/ordererOrganizations org3-artifacts/crypto-config/ 进入cli容器docker exec -it cli bash 导出环境变量export ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem && export CHANNEL_NAME=mychannel 将旧版本通道配置块保存到 config_block.pb peer channel fetch config config_block.pb -o orderer.example.com:7050 -c $CHANNEL_NAME --tls --cafile $ORDERER_CA 使用 configtxlator 工具将通道配置块解码为JSON格式（可读取和修改），并必须删除与更改无关的所有标头，元数据，创建者签名configtxlator proto_decode --input config_block.pb --type common.Block | jq .data.data[0].payload.data.config > config.json 花一点时间在选择的文本编辑器（或浏览器）中打开此文件。值得研究，因为它揭示了底层配置结构和可以进行的其他类型的通道更新 使用 jq 工具将Org3配置定义 org3.json 附加到通道的应用程序组字段，并命名输出 modified_config.json jq -s '.[0] * {"channel_group":{"groups":{"Application":{"groups": {"Org3MSP":.[1]}}}}}' config.json ./channel-artifacts/org3.json > modified_config.json 将 config.json 转回二进制文件 config.pbconfigtxlator proto_encode --input config.json --type common.Config --output config.pb 将 modified_config.json 转二进制文件 modified_config.pbconfigtxlator proto_encode --input modified_config.json --type common.Config --output modified_config.pb 用 configtxlator 用来计算这两个配置二进制文件之间的增量。输出一个名为的新二进制文件 org3_update.pbconfigtxlator compute_update --channel_id $CHANNEL_NAME --original config.pb --updated modified_config.pb --output org3_update.pb 将 org3_update.pb 解码为可编辑的JSON格式 org3_update.jsonconfigtxlator proto_decode --input org3_update.pb --type common.ConfigUpdate | jq . > org3_update.json 包装信封消息为 org3_update_in_envelope.jsonecho '{"payload":{"header":{"channel_header":{"channel_id":"mychannel", "type":2}},"data":{"config_update":'$(cat org3_update.json)'}}}' | jq . > org3_update_in_envelope.json 将 org3_update_in_envelope.json 转最终二进制文件 org3_update_in_envelope.pbconfigtxlator proto_encode --input org3_update_in_envelope.json --type common.Envelope --output org3_update_in_envelope.pb Org1 签名配置peer channel signconfigtx -f org3_update_in_envelope.pb 导出 Org2 环境变量: export CORE_PEER_LOCALMSPID="Org2MSP" export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp export CORE_PEER_ADDRESS=peer0.org2.example.com:7051 Org2管理员签名并提交更新 peer channel update -f org3_update_in_envelope.pb -c $CHANNEL_NAME -o orderer.example.com:7050 --tls --cafile $ORDERER_CA 配置领导者选举，利用动态领导者选举:CORE_PEER_GOSSIP_USELEADERELECTION=true CORE_PEER_GOSSIP_ORGLEADER=false 将 Org3 加入通道 打开一个新的终端，从 first-network 启动 Org3 docker compose docker-compose -f docker-compose-org3.yaml up -d 进入 Org3cli 容器docker exec -it Org3cli bash 导出环境变量export ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem && export CHANNEL_NAME=mychannel 加入通道peer channel join -b mychannel.block 升级和调用Chaincode 到从Org3 CLI中peer chaincode install -n mycc -v 2.0 -p github.com/chaincode/chaincode_example02/go/ 到从CLI中 安装 peer chaincode install -n mycc -v 2.0 -p github.com/chaincode/chaincode_example02/go/ 升级 peer chaincode upgrade -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -v 2.0 -c '{"Args":["init","a","90","b","210"]}' -P "OR ('Org1MSP.peer','Org2MSP.peer','Org3MSP.peer')" 到从Org3 CLI中，查询即可peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}' 完成 如果使用过该 eyfn.sh 脚本，则需要关闭网络。这可以通过：./eyfn.sh down 通过 hyperledger fabric-ca 搭建生产环境的联盟链 利用 fabric-samples/fabric-ca 进行搭建 cd fabric-ca 首先下载镜像： ./bootstrap.sh 运行：./start.sh 完成搭建 接下来分析细节，仔细分析start.sh脚本文件 #!/bin/bash set -e SDIR=$(dirname "$0") # 引入环境变量 source ${SDIR}/scripts/env.sh cd ${SDIR} # 删除docker容器 dockerContainers=$(docker ps -a | awk '$2~/hyperledger/ {print $1}') if [ "$dockerContainers" != "" ]; then log "Deleting existing docker containers ..." docker rm -f $dockerContainers > /dev/null fi # 删除链码docker镜像 chaincodeImages=`docker images | grep "^dev-peer" | awk '{print $3}'` if [ "$chaincodeImages" != "" ]; then log "Removing chaincode docker images ..." docker rmi -f $chaincodeImages > /dev/null fi # 准备一个空文件夹 DDIR=${SDIR}/${DATA} if [ -d ${DDIR} ]; then log "Cleaning up the data directory from previous run at $DDIR" rm -rf ${SDIR}/data fi mkdir -p ${DDIR}/logs # 创建docker-compose.yml文件 ${SDIR}/makeDocker.sh # 根据生成的docker-compose.yml文件启动docker容器编排 log "Creating docker containers ..." docker-compose up -d # 等待名为 setup 容器完成 dowait "the 'setup' container to finish registering identities, creating the genesis block and other artifacts" 90 $SDIR/$SETUP_LOGFILE $SDIR/$SETUP_SUCCESS_FILE # 等待名为 run 容器启动，然后打印它的结束日志 dowait "the docker 'run' container to start" 60 ${SDIR}/${SETUP_LOGFILE} ${SDIR}/${RUN_SUMFILE} tail -f ${SDIR}/${RUN_SUMFILE}& TAIL_PID=$! # 等待名为 run 容器完成，然后结束 while true; do if [ -f ${SDIR}/${RUN_SUCCESS_FILE} ]; then kill -9 $TAIL_PID exit 0 elif [ -f ${SDIR}/${RUN_FAIL_FILE} ]; then kill -9 $TAIL_PID exit 1 else sleep 1 fi done 相关资料 Hyperledger白皮书 Hyperledger模块和关键概念 Hyperledger fabric 1.2 文档 Fabric Samples 有必要深入研究 转载自：https://gitee.com/jonluo/blockchain/blob/master/hyperledger-fabric/README.md