最新文档 https://www.ibm.com/developerworks/cloud/library/cl-add-an-organization-to-your-hyperledger-fabric-blockchain/index.html
首先有两个问题:
1.在fabric网络运行一段时间后,如何新建应用通道,并让新的组织加入新的应用通道
2.在fabric网络运行一段时间后,如何让新的组织加入原有的应用通道
问题分析:
1.创建新的应用通道需要发送应用通道配置到系统通道(orderer)取回应用通道创世区块(包含有应用通道各组织证书),所以必须先修改或更新系统通道配置区块,加入新添加的组织,才能在orderer创建新通道,返回新通道的创世区块,然后发送该应用通道创世区块到新组织,让新组织加入新应用通道
2.待确认
1)先修改或更新系统链的配置区块,在其中加入新增组织的msp信息(问题1解决)
2)利用新的通道配置(包含新增组织)向系统链取得原有应用链新的配置区块
3)广播新的配置区块到应用通道各节点
4)发送应用通道创世区块给新的组织节点,让它们加入该通道,然后同步区块数据
问题1实验步骤
1.我们选用fabric提供的first-network例子
$git clone https://github.com/hyperledger/fabric-samples.git
$cdfabric-samples/first-network
2.修改crypto-config.yaml,提前注册Org3和Org4
./byfn.sh -m generate
生成各种网络实体的所有证书和密钥,用于引导排序服务的起源块,以及配置通道所需的配置事务集合
其中系统链创世区块只包含Org1和Org2得msp信息,应用通道配置channel.tx中指定mychannel的包含组织Org1和Org2
在crypto-config中生成了Org1、Org2、Org3和Org4四个组织的msp信息
3.修改base/docker-compose-base.yaml,添加Org3和Org4基础容器配置
4.创建mychannel2的通道配置
mkdir channel2-artifacts;mkdir blocks
修改configtx.yaml(也可以创建新的“configtx”文件),用于创建mychannel2通道配置
configtxgen -profile TwoNewOrgsChannel -outputCreateChannelTx ./channel2-artifacts/channel.tx -channelID mychannel2
在channel2-artifacts内生成channel2的通道配置
修改docker-compose-cli.yaml
5../byfn.sh -m up 开启网络
此时fabric网络已经开启,在系统通道中创建了一个应用通道mychannel,Org1、Org2通道已经加入该应用通道,Org3、Org4的peer节点已经开启,但未加入任何通道,接下来我们创建新应用通道mychannel2,然后让Org3、Org4组织加入该通道
6.接下来我们更新fabric系统链的配置区块,加入Org3、Org4的msp信息
1)开启configtxlator服务,服务监听在本地任意ip地址和7059端口
无论配置交易文件和初始区块文件都是二进制格式,无法直接编辑。
configtxlator工具将这些配置文件在二进制格式和方便阅读的json格式之间进行转换。
英文文档:https://github.com/hyperledger/fabric/tree/master/examples/configtxupdate
中文文档:https://github.com/qiushaoxi/doc_translation/blob/master/Reconfiguring%20with%20configtxlator.rst
configtxlator工具是一个restful服务程序,采用如下命令启动服务:
configtxlator start --hostname="0.0.0.0" --port 7059
2)获取系统通道testchainid配置区块:
docker exec -it cli /bin/bash 进入cli
mkdir blocks;cd blocks
修改环境变量(一定要找到script脚本中peer channel fetch的例子为参考)
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
export CORE_PEER_LOCALMSPID="OrdererMSP"
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp
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
peer channel fetch config testchainid.pb -o orderer.example.com:7050 -c "testchainid" --tls --cafile $ORDERER_CA
获取到了testchainid.pb到cli容器
3)将testchainid.pb转变为json格式文件
将二进制格式数据解码为json格式
在cli容器外,cd blocks
转换系统通道配置区块
curl -X POST --data-binary @testchainid.pb http://127.0.0.1:7059/protolator/decode/common.Block > ./testchainid.json
得到testchainid.json
4)利用jq工具提取要修改配置域并修改
可能需要安装jq 连接 http://blog.csdn.net/shashayangzhou/article/details/52974196
查看json文件推荐使用vscode
通过vscode查看testchainid.json文件
我们需要在"groups"里添加"Org3MSP"、"Org4MSP"。
jq .data.data[0].payload.data.config testchainid.json >testchainid_config.json
得到testchainid.json的config域为testchainid_config.json文件
修改testchainid_config.json文件在"groups"里添加"Org3MSP"、"Org4MSP",另存为testchainid_config_new.json
cd crypto-config/peerOrganizations/org3(4).example.com/msp
admincerts、cacerts、tlscacerts将这三个证书分别用base64编码后,替换testchainid_config.json组织中对应的位置
base64 admincerts/[email protected] | xargs echo | sed 's/ //g'
5)将两个配置文件编码为二进制格式
curl -X POST --data-binary @testchainid_config.jsonhttp://127.0.0.1:7059/protolator/encode/common.Config> ./testchainid_config.pb
curl -X POST --data-binary @testchainid_config_new.jsonhttp://127.0.0.1:7059/protolator/encode/common.Config> ./testchainid_config_new.pb
6)计算更新量信息为common.ConfigUpdate结构的二进制文件,再生成json格式文件。
curl -X POST -F original=@testchainid_config.pb-F updated=@testchainid_config_new.pbhttp://127.0.0.1:7059/configtxlator/compute/update-from-configs -F channel=testchainid> config_update.pb
curl -X POST --data-binary @config_update.pb http://127.0.0.1:7059/protolator/decode/common.ConfigUpdate > ./config_update.json
7)对common.ConfigUpdate结构数据进行补全,封装为common.Envelope
echo '{"payload":{"header":{"channel_header":{"channel_id":"testchainid", "type":2}},"data":{"config_update":'$(cat config_update.json)'}}}' > config_update_envelope.json
8)编码config_update_envelope.json为二进制交易配置文件config_update_envelope.tx
curl -X POST--data-binary @config_update_envelope.json http://127.0.0.1:7059/protolator/encode/common.Envelope> ./config_update_envelope.tx
9)发送配置交易
docker exec -it cli /bin/bash
export CORE_PEER_LOCALMSPID="OrdererMSP"
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/users/[email protected]/msp
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
peer channel update -o orderer.example.com:7050 -ctestchainid -f ./blocks/config_update_envelope.tx --tls --cafile $ORDERER_CA
这样就在系统链上增加了Org3MSP、Org4MSP
7.创建第二个应用通道mychannel2
export CORE_PEER_LOCALMSPID="Org3MSP"
export 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
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/users/[email protected]/msp
peer channel create -o orderer.example.com:7050 -c mychannel2 -f ./channel2-artifacts/channel.tx --tls true --cafile $ORDERER_CA
在cli本地获得mychannel2.block
8.让Org3和Org4加入mychannel2,然后安装和初始化智能合约
加入Org3.peer0
export CORE_PEER_LOCALMSPID="Org3MSP"
export 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
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/users/[email protected]/msp
export CORE_PEER_ADDRESS=peer0.org3.example.com:7051
peer channel join -b mychannel2.block
peer chaincode install -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02
一个应用通道能安装任意个不同名智能合约,一个智能合约只能被初始化一次
peer chaincode instantiate -o orderer.example.com:7050 --tls true --cafile $ORDERER_CA -C mychannel2 -n mycc -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P "OR ('Org3MSP.member','Org4MSP.member')"
加入Org3.peer1
export CORE_PEER_LOCALMSPID="Org3MSP"
export 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.crt
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/users/[email protected]/msp
export CORE_PEER_ADDRESS=peer1.org3.example.com:7051
peer channel join -b mychannel2.block
peer chaincode install -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02
加入Org4.peer0
export CORE_PEER_LOCALMSPID="Org4MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org4.example.com/peers/peer0.org4.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org4.example.com/users/[email protected]/msp
export CORE_PEER_ADDRESS=peer0.org4.example.com:7051
peer channel join -b mychannel2.block
peer chaincode install -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02
加入Org4.peer1
export CORE_PEER_LOCALMSPID="Org4MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org4.example.com/peers/peer1.org4.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org4.example.com/users/[email protected]/msp
export CORE_PEER_ADDRESS=peer1.org4.example.com:7051
peer channel join -b mychannel2.block
peer chaincode install -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02
9.查询、转账验证
查询a
peer chaincode query -C mychannel2 -n mycc -c '{"Args":["query","a"]}'
Query Result: 100
a转10到b
peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile $ORDERER_CA -C mychannel2 -n mycc -c '{"Args":["invoke","a","b","10"]}'
chaincodeInvokeOrQuery -> INFO 00a Chaincode invoke successful. result: status:200
查询b
peer chaincode query -C mychannel2 -n mycc -c '{"Args":["query","b"]}'
Query Result: 210
至此,第一个问题已经解决并完成验证
问题2实验步骤
在问题1的基础上,在问题1完成后,我们创建了一个fabric网络,这个网络中有一个系统通道testchainid,有两个应用通道,mychannel中加入了Org1、Org2,Org1、Org2是在系统链创建时注册的到系统链,mychannel2中加入了Org3、Org4,Org3、Org4是在系统链创建后添加注册到系统链的。
现在我们让Org3加入mychannel应用通道
1.获取mychannel配置区块
docker exec -it cli /bin/bash 进入cli
cd blocks
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
export CORE_PEER_LOCALMSPID="OrdererMSP"
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp
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
peer channel fetch config mychannel.pb -o orderer.example.com:7050 -c "mychannel" --tls --cafile $ORDERER_CA
获取到了mychannel.pb到cli容器
2.将mychannel.pb转变为json格式文件
在cli容器外,cd blocks
转换mychannel通道配置区块
curl -X POST --data-binary @mychannel.pb http://127.0.0.1:7059/protolator/decode/common.Block > ./mychannel.json
得到mychannel.json
3.利用jq工具提取要修改配置域并修改
通过vscode查看mychannel.json文件
我们需要在"groups"里添加"Org3MSP"。
jq .data.data[0].payload.data.config mychannel.json > mychannel_config.json
得到mychannel.json的config域为mychannel_config.json文件
修改mychannel_config.json文件在"groups"里添加"Org3MSP",另存为mychannel_config_new.json
cd crypto-config/peerOrganizations/org3.example.com/msp
admincerts、cacerts、tlscacerts将这三个证书分别用base64编码后,替换mychannel_config.json组织中对应的位置
base64 admincerts/[email protected] | xargs echo | sed 's/ //g'
4.将两个配置文件编码为二进制格式
curl -X POST --data-binary @mychannel_config.json http://127.0.0.1:7059/protolator/encode/common.Config> ./mychannel_config.pb
curl -X POST --data-binary @mychannel_config_new.json http://127.0.0.1:7059/protolator/encode/common.Config > ./mychannel_config_new.pb
5.计算mychannel更新量信息为common.ConfigUpdate结构的二进制文件,再生成json格式文件。
curl -X POST -F original=@mychannel_config.pb -F updated=@mychannel_config_new.pb http://127.0.0.1:7059/configtxlator/compute/update-from-configs -F channel=mychannel>mychannel_config_update.pb
curl -X POST --data-binary @mychannel_config_update.pb http://127.0.0.1:7059/protolator/decode/common.ConfigUpdate > ./mychannel_config_update.json
6.对common.ConfigUpdate结构数据进行补全,封装为common.Envelope
echo '{"payload":{"header":{"channel_header":{"channel_id":"mychannel", "type":2}},"data":{"config_update":'$(cat mychannel_config_update.json)'}}}' > mychannel_config_update_envelope.json
7.编码mychannel_config_update_envelope.json为二进制交易配置文件mychannel_config_update_envelope.tx curl -X POST --data-binary @mychannel_config_update_envelope.json http://127.0.0.1:7059/protolator/encode/common.Envelope > ./mychannel_config_update_envelope.tx
8.发送mychannel配置交易
docker exec -it cli /bin/bash
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/msp/tlscacerts/tlsca.org1.example.com-cert.pem
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/[email protected]/msp
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
peer channel update -o orderer.example.com:7050 -c mychannel -f ./blocks/mychannel_config_update_envelope.tx --tls true --cafile $ORDERER_CA
报错 The identity is a member of a different MSP (expected Org1MSP, got Org2MSP)
改为使用Org1MSP相关的几个环境变量,报错The identity is a member of a different MSP (expected Org2MSP, got Org1MSP),最终确认问题为目前加入新的组织到应用通道内需要通道内全部组织(Org1、Org2)签名,需要修改策略,待解决,通过在一开始设置mychannel的组织为Org1,先绕过这个问题
这样就在mychannel的配置上增加了Org3MSP
9.让Org3加入mychannel,然后安装和初始化智能合约
加入Org3.peer0
export CORE_PEER_LOCALMSPID="Org3MSP"
export 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
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/users/[email protected]/msp
export CORE_PEER_ADDRESS=peer0.org3.example.com:7051
peer channel join -b mychannel.block
peer chaincode install -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02
加入Org3.peer1
export CORE_PEER_LOCALMSPID="Org3MSP"
export 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.crt
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/users/[email protected]/msp
export CORE_PEER_ADDRESS=peer1.org3.example.com:7051
peer channel join -b mychannel.block
peer chaincode install -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02
10.向Org3.peer0查询a
export CORE_PEER_LOCALMSPID="Org3MSP"
export 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
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/users/[email protected]/msp
export CORE_PEER_ADDRESS=peer0.org3.example.com:7051
peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'
Query Result: 90
11.a转10到b
peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile $ORDERER_CA -C mychannel -n mycc -c '{"Args":["invoke","a","b","10"]}'
chaincodeInvokeOrQuery -> INFO 00a Chaincode invoke successful. result: status:200
12.再查询a
peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'
Query Result:90
原因是在初始化智能合约时已经指定了智能合约有效的签名策略:
peer chaincode instantiate -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -v 1.0 -c '{"Args":["init","a","100","b","200"]}'-P "OR ('Org1MSP.member','Org2MSP.member')"
一笔交易在org1或org2签名时有效,如果我们在一开始修改命令:
peer chaincode instantiate -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P "OR ('Org1MSP.member','Org2MSP.member','Org3MSP.member)"
此时Org3组织还未加入mychannel,经过一系列操作,再次执行
peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'
Query Result: 90
a转10到b
peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile $ORDERER_CA -C mychannel -n mycc -c '{"Args":["invoke","a","b","10"]}'
chaincodeInvokeOrQuery -> INFO 00a Chaincode invoke successful. result: status:200
peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'
Query Result: 80
通过修改策略或更新智能合约去解决问题,待解决