这个官方样例
Building Your First Network
我运行了可能有5遍了,今天才真正明白是怎么回事,这里记录一下。运行这个样例之前务必要先弄明白Docker。
另外后面有两个扩展部分
Adding an Org to a Channel
和Using Private Data in Fabric
,官方文档是分开讲的,由于都是用这个网络,我这里就放到一起了,认真实践之后会有很大收获。
UPDATE:20180805
一直对msp和证书相关的东西很迷,昨天仔细去看了下,又有了新的收获,发现之前理解的还是不够,在此更新一下这篇博客。
首先先用现成的脚本执行一次,确保环境安装正确。
./byfn.sh up
如果最后输出如下,说明运行成功。
===================== All GOOD, BYFN execution completed =====================
_____ _ _ ____
| ____| | \ | | | _ \
| _| | \| | | | | |
| |___ | |\ | | |_| |
|_____| |_| \_| |____/
然后一定不要忘记清理运行环境。
./byfn.sh down
编写组织架构文件crypto-config.yaml
,其中配置了排序服务节点和组织节点。
简要说明一下
- Name: Org2
Domain: org2.example.com
EnableNodeOUs: true
Template:
Count: 2 //表明一个Org有几个peer
Users:
Count: 1 //表明一个Org有几个User
使用cryptogen工具根据架构文件生成相关的证书,放到crypto-config
目录下。
../bin/cryptogen generate --config=./crypto-config.yaml
这里我们有必要看一下这个目录(这里只列出了子目录ordererOrganizations下的):
这里从上到下一共有三个msp文件夹:
再说一下ca文件夹,这就是这个Org的CA,里面有证书和私钥。
而tlsca文件夹,是tls通信要用的CA,里面也是证书和私钥。
每一个order或者peer或者user都有自己的msp,如果要tls通信还要有tls,我们在docker配置文件docker-compose-cli.yaml
中可以看到里面配置peer和order的时候环境变量里的msp和tls都是这两个文件夹。admin是这个组织的管理者。
用到configtxgen工具,生成的配置文件都在channel-artifacts
目录下,这里一共会有四个。
要告诉工具去哪里找configtx.yaml
文件。
export FABRIC_CFG_PATH=$PWD
生成orderer genesis block
../bin/configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block
用来启动order服务
生成通道配置文件
先指定通道名称:export CHANNEL_NAME=mychannel
../bin/configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME
通道建立时该文件会被广播到order
为Org定义anchor peer
../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP
../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org2MSP
指定了Org的anchor peer
这里需要用到Docker-Compose模板文件docker-compose-cli.yaml
,里面定义了需要用到的容器,去看代码发现里面其实是扩展了base
目录下的另外两个模板文件,感觉就像是继承一样。
启动网络:docker-compose -f docker-compose-cli.yaml up -d
同时用先前生成的genesis.block
引导启动了order服务
其中容器CLI的定义如下(截取部分):
cli:
container_name: cli
image: hyperledger/fabric-tools:$IMAGE_TAG
tty: true
stdin_open: true
environment:
- GOPATH=/opt/gopath
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
#- CORE_LOGGING_LEVEL=DEBUG
- CORE_LOGGING_LEVEL=INFO
- CORE_PEER_ID=cli
- CORE_PEER_ADDRESS=peer0.org1.example.com:7051
- CORE_PEER_LOCALMSPID=Org1MSP
- CORE_PEER_TLS_ENABLED=true
- CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt
- CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.key
- CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
- CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
上面的环境变量部分指定是在peer0.org1.example.com节点操作chaincode
还要说明一下,我们是通过CLI容器对其它容器进行配置。
进入CLI容器的命令:docker exec -it cli bash
声明通道名:export CHANNEL_NAME=mychannel
创建通道
将channel.tx
发送至order节点
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
-o 指定排序节点,-c指定通道名字,-f指定通道配置文件,–tls允许tls通信,–cafile指定排序节点根证书目录(也就是上图中的第一个msp目录)以允许tls握手
这一步会生成mychannel.block
,里面包含了channel.tx
中的通道配置信息,直接在当前命令行输入ls
就可看到,后面加入peer节点是需要用到。
将peer加入通道
加入peer0.org1.example.com节点
peer channel join -b mychannel.block
加入peer0.org2.example.com节点,这里要先声明环境变量
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 join -b mychannel.block
更新anchor peer
将对应的文件发给order节点。
本质上是更新通道配置信息,并没有修改genesis.block,而是添加到后面。
更新Org1的anchor peerpeer0.org1.example.com
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的anchor peerpeer0.org2.example.com
先设置环境变量
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/chaincode_example02/go/
目录下现成的智能合约,当然也可以自己写。
可以在docker-compose-cli.yaml
中peer0的volumes配置部分看到./../chaincode/:/opt/gopath/src/github.com/chaincode
,这里就是把上面说的那个目录映射到peer0中的目录下。不过这里映射的目录有一点疑惑,下面install
的时候的路径也很迷,既不是相对当前目录的路径,也不是绝对路径,而是相对/opt/gopath/src/
的路径=_=
安装智能合约
在peer0.org1.example.com
上安装
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 chaincode install -n mycc -v 1.0 -p github.com/chaincode/chaincode_example02/go/
在peer0.org2.example.com
上安装
当然还是要设置环境变量
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 chaincode install -n mycc -v 1.0 -p github.com/chaincode/chaincode_example02/go/
注意这里如果不在
peer0.org2.example.com
上安装智能合约,后面转账(invoke)时会报错
实例化智能合约
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')"
-o指定排序节点,–tls允许tls通信,–cafile指定排序节点根证书目录,-C指定通道名字,-n指定智能合约名字,-v指定智能合约版本,-c为调用智能合约传递参数
查询和转账
查询:peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
转账: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"]}'
可以看到这里转账用到的证书是第一个msp下tlscacerts文件夹下的pem格式的证书,以及后面两个peer目录下tls文件夹下的ca.crt证书。应该就是tls通信需要。
这里如果转账之后立即查询,可能会发现账本未更新,结果与预期不符,等一下再去查询结果又对了,应该是查询只需要在本地peer上进行比较快,而转账需要其它节点参与以及共识机制,要慢。
查看交易日志
打开一个新的终端:docker logs dev-peer0.org2.example.com-mycc-1.0
看这里也可以发现只有和自己有关的交易日志才会记录下来,比如说peer0.org1的查询只在docker logs dev-peer0.org1.example.com-mycc-1.0
中可以看到,而转账在两个中都可以看到。
可以用CouchDB替换默认的goleveldb数据库,支持丰富的查询。
如果上面的部分都已经理解透彻了,强烈建议看一下这部分内容,虽然比较麻烦,不过看完了相信会有很大收获。
官方文档
这里说一下大概步骤:
1. 先生成Org3需要的证书
2. 计算出需要更新的网络,这一步比较繁琐,需要pb文件和json文件来回转换
3. 更新网络
4. 将Org3相关的加入网络
5. 安装智能合约
6. 更新智能合约
7. 就可以查询转账了
官方文档
collection vs. private channel:
智能合约的不同之处在于要对数据分别处理,而且实例化智能合约的时候要用--collections-config
参数执行collection definiton
的目录。
另外collection definiton
中有个blockToLive
参数,用来指定私有数据的存活时间,以Block为单位,过期会被销毁。