环境搭建
Docker 安装
1 | curl -fsSl <https://get.docker.com/> | sh |
Docker-compose 安装
1 | yum -y install epel-release && yum -y install python-pip && pip install docker-compose |
Go安装
1 | wget https://dl.google.com/go/go1.11.5.linux-amd64.tar.gz |
下载Fabric组件
bootstrap.sh
文件可以通过网络下载
1 | curl -sSL https://raw.githubusercontent.com/hyperledger/fabric/master/scripts/bootstrap.sh | bash 1.4.0 -s # 下载Fabric二进制文件 Image 以及示例文件 |
Fabric-sdk-go下载
github地址: https://github.com/hyperledger/fabric-sdk-go.git
sdk 编译, 最好在外网进行编译,用VPN容易超时
1 | make pupulate |
网络配置
创建目录结构
创建一个目录用来存储Fabric的所有配置文件
1 | mkdir -p /opt/prod/Fabric/network # 存储Fabric所有配置文件 |
生成MSP
创建MSP配置信息
编辑MSP配置文件 crypto-config.yaml
1 | # 排序节点配置 |
Template.Count 指定了所要生成的节点数量
Users.Count 指定了需要生成的初始化用户数量。
生成MSP文件系统
1 | cryptogen generate --config=./crypto-config.yaml |
将会生成一个名为crypto-config的目录,里面存储了order 和peer 的MSP文件系统;
使用该cryptogen
工具为各种网络实体生成加密材料(x509证书和签名密钥)。这些证书代表身份,它们允许在我们的实体进行通信和交易时进行签名/验证身份验证。
Cryptogen使用文件 - crypto-config.yaml
包含网络拓扑,并允许我们为组织和属于这些组织的组件生成一组证书和密钥。每个组织都配置了一个唯一的根证书(ca-cert
),它将特定组件(同行和订购者)绑定到该组织。
MSP文件系统的目录结构如下:
1 | . ## Orderer 组织配置 |
生成Order创世区块
在 Orderer 节点上维护的有个 system chain, 这个创世区块实际上是这个 system chain 的创世区块。在 Fabric 的上下文中,chain,channel 基本上可以通用,下面有时会称 system chain 为 system channel。
创建system chain的创世区块
创建创世区块的配置文件 configtx.yaml
1 | ## 一些列组织的定义,【被其他 部分引用】 |
在这个文件里有两个 Profile, 一个是 OneOrgOrdererGenesis, 一个是 OneOrgChannel。
一个 Profile 代表了一组配置, 里面包含了通道相关配置,Orderer 节点相关配置,联盟成员相关配置。通道相关配置确定了系统通道的一些权限策略,Orderer 节点配置确定了 Orderer 节点的类型(是 solo 还是 kafaka),Orderer 节点的访问地址,还有出块时间,区块大小,区块内允许包含的交易数量等。联盟配置确定了联盟的名称和联盟所包含的组织,对组织来说这里最为关键的是组织的 MSP ID 和路径,这些信息都会被包含到 system chain 中。
生成创世区块
1 | configtxgen -profile OneOrgOrdererGenesis -channelID order-channel -outputBlock ./channel-artifacts/genesis.block |
这个命令需要指定一个 channelID,注意这里的 channelID 为系统链(system chain)的 channelID。
生成通道配置区块
现在来创建创世区块交易,通过交易将创世块上传到channel上
生成channel配置事务
通过下面的命令,可以生成这样的一个交易。
1 | export CHANNEL_NAME=mychannel && configtxgen -profile OneOrgChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME |
该命令会读取和生成 Orderer 相同的配置文件,只是使用了 “OneOrgChannel” 这个 Profile,确定了通道的权限策略,创建通道的联盟和组织信息。
只是创建了通道,而不创建锚节点的化,通道区块数据就无法跨组织传播,所以一般还要通过下面的命令创建用来更新锚节点的交易。
为每个组织生成锚节点配置事务
1 | export CHANNEL_NAME=mychannel && configtxgen -profile OneOrgChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP |
上面的命令生成了为每个组织生成锚节点的交易。
启动网络
接下来,就可以通过orderer命令或 docker 容器来启动网络了,orderer 启动的时候会查找一个名为 orderer.yaml 的配置文件。这个配置文件不是必须的,在找不到这个配置文件时,orderer 命令会使用默认配置。我们也可以通过环境变量或命令行参数的方式去对每个配置项进行覆盖。
配置各节点启动参数
配置 yaml_config/docker-compose.yml 文件
1 | # Copyright IBM Corp. All Rights Reserved. |
启动网络节点
1 | docker-compose -f docker-compose.yml up -d ca.example.com orderer.example.com peer0.org1.example.com couchdb |
注意: 如果启动ca, 之一要修改yaml文件中对应的ca私钥地址
运行Channel(示例为一个组织)
这个阶段把网络启动后,还是啥事都做不了,节点之间也没有通信。
因为还没有生成peer节点互相通信的channel,也没有将节点加入到channel中
创建channel
创建了一个channel的创世块,逻辑上就等于是创建了一个channel
1 | docker exec -e "CORE_PEER_LOCALMSPID=Org1MSP" -e "CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/users/Admin@org1.example.com/msp" peer0.org1.example.com peer channel create -o orderer.example.com:7050 -c mychannel -f /etc/hyperledger/configtx/channel.tx |
该命令是,通过Org1向order节点发送事务,order节点验证通过后,会生成mychannel的创世块
将组织加入到channel
将组织加入到channel
1 | docker exec -e "CORE_PEER_LOCALMSPID=Org1MSP" -e "CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/users/Admin@org1.example.com/msp" peer0.org1.example.com peer channel join -b mychannel.block |
更新锚节点
1 | docker exec -e "CORE_PEER_LOCALMSPID=Org1MSP" -e "CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/users/Admin@org1.example.com/msp" peer0.org1.example.com peer channel update -o orderer.example.com:7050 -c mychannel -f /etc/hyperledger/configtx/Org1MSPanchors.tx |
目前为止一个基本的网络就已经搭建好了。下面再介绍一些怎么更新我们的网络组织和channel成员
chain code 安装和使用
chaincode 安装
将即将安装节点配置到环境变量中
1
2
3
4CORE_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安装chaincode
1
peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/chaincode_example02/go/
将chaincode实例化
一个channel只需要实例化一次
1
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')"
chaincode使用
查询
1
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
调用
1
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"]}'
创建新组织并添加到channel
生成组织的证书和密钥
创建一个目录: org3-artifacts, 用来存储生成org3最终配置和事务的配置文件和中间产物等;
该阶段操作都在org3-artifacts目录下进行
加密资料准备
生成组织的MSP文件
创建一个新org的org3-crypto.yaml文件用来生成新组织的MSP资料
org3-crypto.yaml文件内容
1
2
3
4
5
6
7
8
9
10
11PeerOrgs:
# ---------------------------------------------------------------------------
# Org3
# ---------------------------------------------------------------------------
- Name: Org3
Domain: org3.example.com
EnableNodeOUs: true
Template:
Count: 2
Users:
Count: 11
cryptogen generate --config=./org3-crypto.yaml
导出MSP数据
configtx.yaml文件内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17Organizations:
-
# DefaultOrg defines the organization which is used in the sampleconfig
# of the fabric.git development environment
Name: Org3MSP
# ID to load the MSP definition as
ID: Org3MSP
MSPDir: crypto-config/peerOrganizations/org3.example.com/msp
AnchorPeers:
# AnchorPeers defines the location of peers which can be used
# for cross org gossip communication. Note, this value is only
# encoded in the genesis block in the Application section context
- Host: peer0.org3.example.com
Port: 110511
export FABRIC_CFG_PATH=$PWD && configtxgen -printOrg Org3MSP > ../artifacts/org3.json
上面的命令创建一个JSON文件 -
org3.json
并将其输出到artifacts
。此文件包含Org3的策略定义,以及以base 64格式呈现的三个重要证书:管理员用户证书(稍后将充当Org3的管理员),CA根证书和TLS根目录证书移动order MSP数据到当前目录下
将Orderer Org的MSP材料移植到Org3
crypto-config
目录中。特别是,我们关注的是Orderer的TLS根证书,它将允许Org3实体与网络订购节点之间的安全通信。1
cd ../ && cp -r crypto-config/ordererOrganizations org3-artifacts/crypto-config/
生成配置文件
进入cli应用
1
docker exec -it cli bash
设置环境变量
接下来急需要使用order管理员的身份获取mychannel的区块文件
1
2export 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获取channel的配置信息
1
peer channel fetch config config_block.pb -o orderer.example.com:7050 -c $CHANNEL_NAME --tls --cafile $ORDERER_CA
将配置转化为Json
1
configtxlator proto_decode --input config_block.pb --type common.Block | jq .data.data[0].payload.data.config > config.json
这给我们留下了一个精简的JSON对象 -
config.json
它将作为我们的配置更新的基线。
获得添加组织后的配置文件
将组织的配置json文件添加到channel的应用的分组字段,并输出到modified_config.json
1
jq -s '.[0] * {"channel_group":{"groups":{"Application":{"groups": {"Org3MSP":.[1]}}}}}' config.json ./channel-artifacts/org3.json > modified_config.json
现在,在CLI容器中,我们有两个感兴趣的JSON文件 -
config.json
和modified_config.json
。初始文件仅包含Org1和Org2材料,而“modified”文件包含所有三个Orgs。此时,只需重新编码这两个JSON文件并计算增量即可。将config.json翻译回到config.pb
1
configtxlator proto_encode --input config.json --type common.Config --output config.pb
将modified_config.json 编码成modified_config.pb:
1
configtxlator proto_encode --input modified_config.json --type common.Config --output modified_config.pb
计算两个pb文件的增量
因为之前的组织MSP材料已经存在于通道的区块中,因此只需要计算和使用两个文件的增量
1
configtxlator compute_update --channel_id $CHANNEL_NAME --original config.pb --updated modified_config.pb --output org3_update.pb
将增量内容解码为json格式
1
configtxlator proto_decode --input org3_update.pb --type common.ConfigUpdate | jq . > org3_update.json
封装消息
1
echo '{"payload":{"header":{"channel_header":{"channel_id":"mychannel", "type":2}},"data":{"config_update":'$(cat org3_update.json)'}}}' | jq . > org3_update_in_envelope.json
将最终的json文件转化为pb格式
1
configtxlator proto_encode --input org3_update_in_envelope.json --type common.Envelope --output org3_update_in_envelope.pb
签名并提交配置更新
对更新做签名
在将配置写入分类帐之前,我们需要来自必需管理员用户的签名。
我们的渠道应用程序组的修改策略(mod_policy)设置为默认值“MAJORITY”,这意味着我们需要大多数现有组织管理员对其进行签名。
首先,让我们将此更新原型作为Org1管理员签名。请记住,CLI容器是使用Org1 MSP材质引导的,因此我们只需要发出 命令:
peer channel signconfigtx
1
peer channel signconfigtx -f org3_update_in_envelope.pb
最后一步是切换CLI容器的标识以反映Org2 Admin用户。我们通过导出特定于Org2 MSP的四个环境变量来实现此目的。
配置Org2环境变量:
1
2
3
4
5
6
7
8
9# you can issue all of these commands at once
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签署
1
peer channel signconfigtx -f org3_update_in_envelope.pb
发送更新请求
1
peer channel update -f org3_update_in_envelope.pb -c $CHANNEL_NAME -o orderer.example.com:7050 --tls --cafile $ORDERER_CA
如果您的更新已成功提交,您应该会看到类似于以下内容的消息摘要指示:
1
2018-02-24 18:56:33.499 UTC [msp/identity] Sign -> DEBU 00f Sign: digest: 3207B24E40DE2FAB87A2E42BC004FEAA1E6FDCA42977CB78C64F05A88E556ABA
您还将看到我们的配置事务的提交:
1
2018-02-24 18:56:33.499 UTC [channelCmd] update -> INFO 010 Successfully submitted channel update
成功的频道更新呼叫向频道上的所有对等体返回新块 - 块5。如果您还记得,块0-2是初始通道配置,而块3和4是
mycc
链代码的实例
将新的节点组织加入到channel
配置领导者的选举
新的对等体不能利用gossip,因为它们无法验证其他对等体从其自己的组织转发的块,直到它们获得将该组织添加到该channel的配置事务。
因此,新添加的对等体必须具有以下配置之一,以便它们从订购服务接收块:
要使用静态领导模式,请将对等方配置为组织领导者:
1
2CORE_PEER_GOSSIP_USELEADERELECTION=false
CORE_PEER_GOSSIP_ORGLEADER=true注意
对于添加到通道的所有新对等方,此配置必须相同。
要利用动态领导者选举,配置对等方使用领导者选举:
1
2CORE_PEER_GOSSIP_USELEADERELECTION=true
CORE_PEER_GOSSIP_ORGLEADER=false注意
由于新添加的组织的对等方将无法形成成员资格视图,因此该选项将类似于静态配置,因为每个对等方将开始宣称自己是领导者。但是,一旦他们更新了将组织添加到渠道的配置事务,组织中将只有一个活跃的领导者。因此,如果您最终希望组织的同行使用领导者选举,建议使用此选项
将Org3 peer加入channel
打开org3 peer
此时,通道配置已更新为包含我们的新组织
Org3
- 意味着与其关联的对等方现在可以加入mychannel
。首先,让我们为Org3对等体和Org3特定的CLI启动容器。
打开一个新的终端并从
first-network
启动Org3 docker compose:compose文件内容:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92version: '2'
volumes:
peer0.org3.example.com:
peer1.org3.example.com:
networks:
byfn:
services:
peer0.org3.example.com:
container_name: peer0.org3.example.com
extends:
file: base/peer-base.yaml
service: peer-base
environment:
- CORE_PEER_ID=peer0.org3.example.com
- CORE_PEER_ADDRESS=peer0.org3.example.com:11051
- CORE_PEER_LISTENADDRESS=0.0.0.0:11051
- CORE_PEER_CHAINCODEADDRESS=peer0.org3.example.com:11052
- CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:11052
- CORE_PEER_GOSSIP_BOOTSTRAP=peer1.org3.example.com:12051
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org3.example.com:11051
- CORE_PEER_LOCALMSPID=Org3MSP
volumes:
- /var/run/:/host/var/run/
- ./org3-artifacts/crypto-config/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/msp:/etc/hyperledger/fabric/msp
- ./org3-artifacts/crypto-config/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls:/etc/hyperledger/fabric/tls
- peer0.org3.example.com:/var/hyperledger/production
ports:
- 11051:11051
networks:
- byfn
peer1.org3.example.com:
container_name: peer1.org3.example.com
extends:
file: base/peer-base.yaml
service: peer-base
environment:
- CORE_PEER_ID=peer1.org3.example.com
- CORE_PEER_ADDRESS=peer1.org3.example.com:12051
- CORE_PEER_LISTENADDRESS=0.0.0.0:12051
- CORE_PEER_CHAINCODEADDRESS=peer1.org3.example.com:12052
- CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:12052
- CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org3.example.com:11051
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org3.example.com:12051
- CORE_PEER_LOCALMSPID=Org3MSP
volumes:
- /var/run/:/host/var/run/
- ./org3-artifacts/crypto-config/peerOrganizations/org3.example.com/peers/peer1.org3.example.com/msp:/etc/hyperledger/fabric/msp
- ./org3-artifacts/crypto-config/peerOrganizations/org3.example.com/peers/peer1.org3.example.com/tls:/etc/hyperledger/fabric/tls
- peer1.org3.example.com:/var/hyperledger/production
ports:
- 12051:12051
networks:
- byfn
Org3cli:
container_name: Org3cli
image: hyperledger/fabric-tools:$IMAGE_TAG
tty: true
stdin_open: true
environment:
- GOPATH=/opt/gopath
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
- FABRIC_LOGGING_SPEC=INFO
#- FABRIC_LOGGING_SPEC=DEBUG
- CORE_PEER_ID=Org3cli
- CORE_PEER_ADDRESS=peer0.org3.example.com:11051
- CORE_PEER_LOCALMSPID=Org3MSP
- CORE_PEER_TLS_ENABLED=true
- CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/server.crt
- CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/server.key
- CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt
- CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/users/Admin@org3.example.com/msp
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
command: /bin/bash
volumes:
- /var/run/:/host/var/run/
- ./../chaincode/:/opt/gopath/src/github.com/chaincode
- ./org3-artifacts/crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/
- ./crypto-config/peerOrganizations/org1.example.com:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com
- ./crypto-config/peerOrganizations/org2.example.com:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com
- ./scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/
depends_on:
- peer0.org3.example.com
- peer1.org3.example.com
networks:
- byfn1
docker-compose -f docker-compose-org3.yaml up -d
此新组合文件已配置为跨越我们的初始网络,因此两个对等方和CLI容器将能够使用现有对等方和订购节点进行解析。现在运行三个新容器,执行特定于Org3的CLI容器:
1
docker exec -it Org3cli bash
就像我们使用初始CLI容器一样,导出两个关键环境变量:
设置环境变量
就像我们使用初始CLI容器一样,导出两个关键环境变量:
ORDERER_CA
和CHANNEL_NAME
:1
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
检查以确保已正确设置变量:
1
echo $ORDERER_CA && echo $CHANNEL_NAME
将节点加入到channel
1
peer channel join -b mychannel.block
将第二个节点加入到channel
1
2export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/peers/peer1.org3.example.com/tls/ca.crtexport CORE_PEER_ADDRESS=peer1.org3.example.com:7051
peer channel join -b mychannel.block
升级chaincode并更改认可策略
更新chaincode的认可策略,添加org3到认可策略中
在org3 cli安装chaincode:
1
peer chaincode install -n mycc -v 2.0 -p github.com/chaincode/chaincode_example02/go/
在org1 和 org2 的 cli上安装新版本chaincode
peer0.org2上安装
1
peer chaincode install -n mycc -v 2.0 -p github.com/chaincode/chaincode_example02/go/
跳到peer0.org1
1
2
3
4
5
6
7
8
9export 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
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
peer chaincode install -n mycc -v 2.0 -p github.com/chaincode/chaincode_example02/go/更新认可策略
1
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')"