如何搭建一个多通道Fabric网络
这篇文章主要为大家展示了"如何搭建一个多通道Fabric网络",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"如何搭建一个多通道Fabric网络"这篇文章吧。
1、Hyperledger Fabric多通道网络实验环境概述
我们将构造一个包含3个机构的Hyperledger Fabric网络:Org1、Org2和Org3,每个机构中包含一个节点Peer0。网络包含两个通道:由Org1、Org2和Org3组成的ChannelAll,以及由Org1和Org2组成的Channel12,因此这个Fabric网络是多通道的配置。在这两个Fabric通道上我们将部署同样的链码,即Fabrc-Samples中提供的Simple Asset链码:
2、Hyperledger Fabric多通道网络实验环境搭建
Step 1:在Hyperledger官方提供的fabric-samples目录下克隆本教程提供的示例代码:
cd fabric-samplesgit clone https://github.com/kctam/3org2ch_143.gitcd 3org2ch_143
Step 2:为参与Fabric通道的机构生成所需的密码学资料
../bin/cryptogen generate --config=./crypto-config.yaml
Step 3:生成Fabric通道素材
mkdir channel-artifacts && export FABRIC_CFG_PATH=$PWD../bin/configtxgen -profile OrdererGenesis \ -outputBlock ./channel-artifacts/genesis.blockexport CHANNEL_ONE_NAME=channelallexport CHANNEL_ONE_PROFILE=ChannelAllexport CHANNEL_TWO_NAME=channel12export CHANNEL_TWO_PROFILE=Channel12../bin/configtxgen -profile ${CHANNEL_ONE_PROFILE} \ -outputCreateChannelTx ./channel-artifacts/${CHANNEL_ONE_NAME}.tx \ -channelID $CHANNEL_ONE_NAME../bin/configtxgen -profile ${CHANNEL_TWO_PROFILE} \ -outputCreateChannelTx ./channel-artifacts/${CHANNEL_TWO_NAME}.tx \ -channelID $CHANNEL_TWO_NAME../bin/configtxgen -profile ${CHANNEL_ONE_PROFILE} \ -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors_${CHANNEL_ONE_NAME}.tx \ -channelID $CHANNEL_ONE_NAME -asOrg Org1MSP../bin/configtxgen -profile ${CHANNEL_ONE_PROFILE} \ -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors_${CHANNEL_ONE_NAME}.tx \ -channelID $CHANNEL_ONE_NAME -asOrg Org2MSP../bin/configtxgen -profile ${CHANNEL_ONE_PROFILE} \ -outputAnchorPeersUpdate ./channel-artifacts/Org3MSPanchors_${CHANNEL_ONE_NAME}.tx \ -channelID $CHANNEL_ONE_NAME -asOrg Org3MSP../bin/configtxgen -profile ${CHANNEL_TWO_PROFILE} \ -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors_${CHANNEL_TWO_NAME}.tx \ -channelID $CHANNEL_TWO_NAME -asOrg Org1MSP../bin/configtxgen -profile ${CHANNEL_TWO_PROFILE} \ -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors_${CHANNEL_TWO_NAME}.tx \ -channelID $CHANNEL_TWO_NAME -asOrg Org2MSP
Step 4:启动所有的容器,最后应当看到有5个容器
docker-compose up -ddocker ps
Step 5:为了便于演示,开启3个终端,并设置排序节点的CA
Org1
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
Org2
docker exec -e "CORE_PEER_LOCALMSPID=Org2MSP" \ -e "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" \ -e "CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp" \ -e "CORE_PEER_ADDRESS=peer0.org2.example.com:7051" \ -it cli bashexport 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
Org3
docker exec -e "CORE_PEER_LOCALMSPID=Org3MSP" \ -e "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" \ -e "CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/users/Admin@org3.example.com/msp" \ -e "CORE_PEER_ADDRESS=peer0.org3.example.com:7051" \ -it cli bashexport 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
Step 5:在Fabric网络中创建多通道,并将各peer节点分别加入多个通道
首先创建channelall通道,并将3个机构的节点都加入该通道:
Org1
peer channel create -o orderer.example.com:7050 -c channelall \ -f /opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts/channelall.tx \ --tls --cafile $ORDERER_CApeer channel join -b channelall.block --tls --cafile $ORDERER_CApeer channel update -o orderer.example.com:7050 -c channelall \ -f /opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts/Org1MSPanchors_channelall.tx \ --tls --cafile $ORDERER_CA
Org2
peer channel join -b channelall.block --tls --cafile $ORDERER_CApeer channel update -o orderer.example.com:7050 -c channelall \ -f /opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts/Org2MSPanchors_channelall.tx \ --tls --cafile $ORDERER_CA
Org3
peer channel join -b channelall.block --tls --cafile $ORDERER_CApeer channel update -o orderer.example.com:7050 -c channelall \ -f /opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts/Org3MSPanchors_channelall.tx \ --tls --cafile $ORDERER_CA
然后创建channel12,并将Org1和Org2都加入该通道:
Org1
peer channel create -o orderer.example.com:7050 -c channel12 \ -f /opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts/channel12.tx \ --tls --cafile $ORDERER_CApeer channel join -b channel12.block --tls --cafile $ORDERER_CApeer channel update -o orderer.example.com:7050 -c channel12 \ -f /opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts/Org1MSPanchors_channel12.tx \ --tls --cafile $ORDERER_CA
Org2
peer channel join -b channel12.block --tls --cafile $ORDERER_CApeer channel update -o orderer.example.com:7050 -c channel12 \ -f /opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts/Org2MSPanchors_channel12.tx \ --tls --cafile $ORDERER_CA
Step 6:检查各节点已经加入的Fabric通道
在各节点对应的终端中使用如下命令查看当前节点加入的通道:
peer channel list
你应当可以看到org1和org2分别加入了两个通道,而org3则只加入了一个通道。
如果一切顺利,现在你就有了一个包含3个机构的多通道Fabric网络,可以用于测试 任何链码了。
Step 7:在测试完毕后记得清理实验环境,命令如下:
docker-compose down -vdocker rm $(docker ps -aq)docker rmi $(docker images dev-* -q)
3、Fabric多通道安装Simple Asset链码(SACC)
现在我们的Fabric多通道实验网络已经起来了,可以开始部署链码了。
我们使用fabric-samples内置的SACC链码,其内容如下:
/* * Copyright IBM Corp All Rights Reserved * * SPDX-License-Identifier: Apache-2.0 */package mainimport ( "fmt" "github.com/hyperledger/fabric/core/chaincode/shim" "github.com/hyperledger/fabric/protos/peer")// SimpleAsset implements a simple chaincode to manage an assettype SimpleAsset struct {}// Init is called during chaincode instantiation to initialize any// data. Note that chaincode upgrade also calls this function to reset// or to migrate data.func (t *SimpleAsset) Init(stub shim.ChaincodeStubInterface) peer.Response { // Get the args from the transaction proposal args := stub.GetStringArgs() if len(args) != 2 { return shim.Error("Incorrect arguments. Expecting a key and a value") } // Set up any variables or assets here by calling stub.PutState() // We store the key and the value on the ledger err := stub.PutState(args[0], []byte(args[1])) if err != nil { return shim.Error(fmt.Sprintf("Failed to create asset: %s", args[0])) } return shim.Success(nil)}// Invoke is called per transaction on the chaincode. Each transaction is// either a 'get' or a 'set' on the asset created by Init function. The Set// method may create a new asset by specifying a new key-value pair.func (t *SimpleAsset) Invoke(stub shim.ChaincodeStubInterface) peer.Response { // Extract the function and args from the transaction proposal fn, args := stub.GetFunctionAndParameters() var result string var err error if fn == "set" { result, err = set(stub, args) } else { // assume 'get' even if fn is nil result, err = get(stub, args) } if err != nil { return shim.Error(err.Error()) } // Return the result as success payload return shim.Success([]byte(result))}// Set stores the asset (both key and value) on the ledger. If the key exists,// it will override the value with the new onefunc set(stub shim.ChaincodeStubInterface, args []string) (string, error) { if len(args) != 2 { return "", fmt.Errorf("Incorrect arguments. Expecting a key and a value") } err := stub.PutState(args[0], []byte(args[1])) if err != nil { return "", fmt.Errorf("Failed to set asset: %s", args[0]) } return args[1], nil}// Get returns the value of the specified asset keyfunc get(stub shim.ChaincodeStubInterface, args []string) (string, error) { if len(args) != 1 { return "", fmt.Errorf("Incorrect arguments. Expecting a key") } value, err := stub.GetState(args[0]) if err != nil { return "", fmt.Errorf("Failed to get asset: %s with error: %s", args[0], err) } if value == nil { return "", fmt.Errorf("Asset not found: %s", args[0]) } return string(value), nil}// main function starts up the chaincode in the container during instantiatefunc main() { if err := shim.Start(new(SimpleAsset)); err != nil { fmt.Printf("Error starting SimpleAsset chaincode: %s", err) }}
Fabric Samples提供的SACC链码的逻辑很简单:
当链码实例化时就会执行
Init()
函数,该函数需要两个参数,分别对应键和值将传入Init()函数的键/值对使用PutState方法保存到账本中
在链码实例化之后,对交易的处理是由
Invoke()
函数来负责的。 该函数的参数 包括一个方法名以及若干参数。如果调用Invoke()函数时方法名为set,那么就需要传入两个参数,分别表示要 设置的键和值
如果调用Invoke()函数时方法名为get,那么就需要一个参数,表示要读取的键
通过链码安装操作,就可以在各节点上启动链码。注意在链码实例化之前还不可用。
在各节点对应的终端中使用如下命令安装链码:
peer chaincode install -n sacc -p github.com/chaincode/sacc -v 1.0
我们应当可以看到如下的输出结果:
现在所有的节点上都安装了SACC链码,我们可以实例化这个链码了。
4、Fabric多通道实验1:ChannelAll通道上Fabric链码的实例化与访问
首先我们看包含所有三个机构的ChannelAll通道。
在Org1对应的终端中,在ChannelAll通道上实例化链码:
peer chaincode instantiate -o orderer.example.com:7050 --tls \ --cafile $ORDERER_CA -C channelall -c '{"Args":["a", "100"]}' \ -n sacc -v 1.0 -P "OR('Org1MSP.peer', 'Org2MSP.peer', 'Org3MSP.peer')"
我们设置了初始的键/值对为a/100。此外我们设置了背书策略:OR
表示只需要3个机构中的任何一个背书即可。
现在让我们在通道ChannelAll上查询键a
的值。
进入Org1对应的终端,运行如下命令:
peer chaincode query -C channelall -n sacc -c '{"Args":["get","a"]}'
结果如下:
现在在Org2对应的终端中运行如下命令:
peer chaincode query -C channelall -n sacc -c '{"Args":["get","a"]}'
结果如下:
现在在Org3对应的终端中运行如下命令:
peer chaincode query -C channelall -n sacc -c '{"Args":["get","a"]}'
结果如下:
现在我们可以看到在三个节点上得到了相同的值,它们共享同一个账本。
5、Fabric多通道实验2:在Channel12通道上SACC链码的实例化与交互
现在让我们在通道Channel12上实例化这个SACC链码。
在Org1对应的终端中,运行如下命令:
peer chaincode instantiate -o orderer.example.com:7050 \ --tls --cafile $ORDERER_CA -C channel12 \ -c '{"Args":["b", "200"]}' -n sacc -v 1.0 \ -P "OR('Org1MSP.peer', 'Org2MSP.peer')"
这次我们将初始的键/值对设置为b/200
,背书策略为任一机构完成背书即可。
还是从Org1开始:
peer chaincode query -C channel12 -n sacc -c '{"Args":["get","b"]}'
结果如下:
然后进入Org2对应的终端:
peer chaincode query -C channel12 -n sacc -c '{"Args":["get","b"]}'
结果如下:
如果我们在Org3对应的终端运行同样的命令,就会看到提示禁止访问。这是 因为Org3没有加入通道Channel12:
peer chaincode query -C channel12 -n sacc -c '{"Args":["get","b"]}'
结果如下:
如果我们尝试在通道Channel12上读取键a
的值,会发现提示没有定义a
。 在Hyperledger Fabric中,每个通道都有自己的账本,不同通道的状态是不共享的。
在Org1和Org2的终端中运行如下命令:
peer chaincode query -C channel12 -n sacc -c '{"Args":["get","a"]}'
结果如下:
以上是"如何搭建一个多通道Fabric网络"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!