本次搭建的fabric网络是从fabric-samples 的test-network里摘出来的,主要是为了提高可读性以及在启动网络过程中更好的理解fabric v2.*版本的新特性,对新手应该比较友好。
在整理过程中对节点的配置进行了分割和拓展,增加了两个orderer节点,为org1增加了一个peer节点。
官方文档:https://hyperledger-fabric.readthedocs.io/en/release-2.3/whatsnew.html#what-s-new-in-hyperledger-fabric-v2-3
如果第一次搭建fabric网络,需要在服务器/虚拟机上安装docker和go,且没必要下载fabric源码[说得谁会一上来就看源码似的]。
配置文件较多,就直接上传资源了,需要的话可以下载或者私信,配置文件地址:https://download.csdn.net/download/weixin_43562234/18622072
生成证书
// 清理环境
// 部署前须删除服务器上可能影响fabric部署的容器、镜像、容器挂载卷、证书、通道创始区块等
docker ps -a
docker stop $(docker ps -aq)
docker rm $(dcokier ps -aq)
docker volume ls
docker volume rm <容器挂载卷名称>
docker images
docker rmi <镜像名称>
// 本实例证书在organizations目录下, 通道创始区块在channel-artifacts下, system-genesis-block下的genesis.block目录也删掉[这个目录在启动容器后会自动生成,这个目录下什么都没有,目测没什么卵用,但是test-network的配置文件中有,所以就留着了]
环境变量
export PATH=/home/adder/fabric/bin/bin_v2.3.1:$PATH
export IMAGE_TAG=2.3.1
export COMPOSE_PROJECT_NAME=net
peer节点
cryptogen generate --config=./organizations/cryptogen/crypto-config-org1.yaml --output="organizations"
cryptogen generate --config=./organizations/cryptogen/crypto-config-org2.yaml --output="organizations"
orderer节点
cryptogen generate --config=./organizations/cryptogen/crypto-config-orderer.yaml --output="organizations"
启动节点
docker-compose -f orderer0.yaml up -d
docker-compose -f orderer1.yaml up -d
docker-compose -f orderer2.yaml up -d
docker-compose -f peer0org1.yaml up -d
docker-compose -f peer1org1.yaml up -d
docker-compose -f peer0org2.yaml up -d
docker-compose -f cli0.yaml up -d
docker-compose -f cli1.yaml up -d
docker-compose -f cli2.yaml up -d
生成通道创始区块
configtxgen -profile TwoOrgsApplicationGenesis -outputBlock ./channel-artifacts/mychannel.block -channelID mychannel
orderer节点加入通道
// orderer0
osnadmin channel join --channelID mychannel --config-block /home/adder/fabric/v2.3.1/raft-multi/channel-artifacts/mychannel.block -o localhost:7053 --ca-file /home/adder/fabric/v2.3.1/raft-multi/organizations/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --client-cert /home/adder/fabric/v2.3.1/raft-multi/organizations/ordererOrganizations/example.com/orderers/orderer0.example.com/tls/server.crt --client-key /home/adder/fabric/v2.3.1/raft-multi/organizations/ordererOrganizations/example.com/orderers/orderer0.example.com/tls/server.key
// orderer1
osnadmin channel join --channelID mychannel --config-block /home/adder/fabric/v2.3.1/raft-multi/channel-artifacts/mychannel.block -o localhost:8053 --ca-file /home/adder/fabric/v2.3.1/raft-multi/organizations/ordererOrganizations/example.com/orderers/orderer1.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --client-cert /home/adder/fabric/v2.3.1/raft-multi/organizations/ordererOrganizations/example.com/orderers/orderer1.example.com/tls/server.crt --client-key /home/adder/fabric/v2.3.1/raft-multi/organizations/ordererOrganizations/example.com/orderers/orderer1.example.com/tls/server.key
// orderer2
osnadmin channel join --channelID mychannel --config-block /home/adder/fabric/v2.3.1/raft-multi/channel-artifacts/mychannel.block -o localhost:9053 --ca-file /home/adder/fabric/v2.3.1/raft-multi/organizations/ordererOrganizations/example.com/orderers/orderer2.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --client-cert /home/adder/fabric/v2.3.1/raft-multi/organizations/ordererOrganizations/example.com/orderers/orderer2.example.com/tls/server.crt --client-key /home/adder/fabric/v2.3.1/raft-multi/organizations/ordererOrganizations/example.com/orderers/orderer2.example.com/tls/server.key
peer0org1节点加入通道
docker exec -it cli0 sh
peer channel join -b ./channel-artifacts/mychannel.block
peer1org1节点加入通道
docker exec -it cli1 sh
peer channel join -b ./channel-artifacts/mychannel.block
peer0org2节点加入通道
docker exec -it cli2 sh
peer channel join -b ./channel-artifacts/mychannel.block
设置锚节点
// 组织org1
// 进入cli0
docker exec -it cli0 sh
// 获取通道配置信息
peer channel fetch config config_block.pb -o orderer0.example.com:7050 --ordererTLSHostnameOverride orderer0.example.com -c mychannel --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
// 解码配置为json
configtxlator proto_decode --input config_block.pb --type common.Block | jq .data.data[0].payload.data.config > Org1MSPconfig.json
// 添加锚节点配置
jq '.channel_group.groups.Application.groups.Org1MSP.values += {"AnchorPeers":{"mod_policy": "Admins","value":{"anchor_peers": [{"host": "peer0.org1.example.com","port": 7051}]},"version": "0"}}' Org1MSPconfig.json > Org1MSPmodified_config.json
// 原配置块
configtxlator proto_encode --input Org1MSPconfig.json --type common.Config >original_config.pb
// 修改后的配置块
configtxlator proto_encode --input Org1MSPmodified_config.json --type common.Config >modified_config.pb
// 计算原配置和修改后配置的差异,生成升级配置块
configtxlator compute_update --channel_id mychannel --original original_config.pb --updated modified_config.pb >config_update.pb
// 解码生成配置更新json文件
configtxlator proto_decode --input config_update.pb --type common.ConfigUpdate >config_update.json
// 补全配置,生成配置更新交易封装json文件
echo '{"payload":{"header":{"channel_header":{"channel_id":"mychannel", "type":2}},"data":{"config_update":'$(cat config_update.json)'}}}' | jq . >config_update_in_envelope.json
// 将配置更新交易封装json文件编译生成锚节点配置上下文文件
configtxlator proto_encode --input config_update_in_envelope.json --type common.Envelope >Org1MSPanchors.tx
// 提交配置更新交易
peer channel update -o orderer0.example.com:7050 --ordererTLSHostnameOverride orderer0.example.com -c mychannel -f Org1MSPanchors.tx --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
// 组织org2
// 进入cli2
docker exec -it cli2 sh
// 获取通道配置信息
peer channel fetch config config_block.pb -o orderer0.example.com:7050 --ordererTLSHostnameOverride orderer0.example.com -c mychannel --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
// 解码配置块为json
configtxlator proto_decode --input config_block.pb --type common.Block | jq .data.data[0].payload.data.config > Org2MSPconfig.json
// 添加锚节点配置
jq '.channel_group.groups.Application.groups.Org2MSP.values += {"AnchorPeers":{"mod_policy": "Admins","value":{"anchor_peers": [{"host": "peer0.org2.example.com","port": 9051}]},"version": "0"}}' Org2MSPconfig.json > Org2MSPmodified_config.json
// 原配置块
configtxlator proto_encode --input Org2MSPconfig.json --type common.Config >original_config.pb
// 修改后的配置块
configtxlator proto_encode --input Org2MSPmodified_config.json --type common.Config >modified_config.pb
// 计算原配置和修改后配置的差异,生成升级配置块
configtxlator compute_update --channel_id mychannel --original original_config.pb --updated modified_config.pb >config_update.pb
// 解码生成配置更新json文件
configtxlator proto_decode --input config_update.pb --type common.ConfigUpdate >config_update.json
// 补全配置,生成配置更新交易封装json文件
echo '{"payload":{"header":{"channel_header":{"channel_id":"mychannel", "type":2}},"data":{"config_update":'$(cat config_update.json)'}}}' | jq . >config_update_in_envelope.json
// 将配置更新交易封装json文件编译生成锚节点配置上下文文件
configtxlator proto_encode --input config_update_in_envelope.json --type common.Envelope >Org2MSPanchors.tx
// 提交配置更新交易
peer channel update -o orderer0.example.com:7050 --ordererTLSHostnameOverride orderer0.example.com -c mychannel -f Org2MSPanchors.tx --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
解决智能合约依赖问题
// 进入链码项目根目录,执行以下命令
// go
GO111MODULE=on go mod vendor
// java链码
./gradlew installDist
// nodejs链码
npm install
npm run build
打包链码
docker exec -it cli0 sh
cd chaincode
peer lifecycle chaincode package basic.tar.gz --path /opt/gopath/src/github.com/hyperledger/fabric/peer/chaincode/chaincode-go --lang golang --label basic_1.0
节点安装链码
// peer0org1
peer lifecycle chaincode install basic.tar.gz
// 查询已安装的链码
peer lifecycle chaincode queryinstalled
// peer1org1
docker exec -it cli1 sh
cd chaincode
peer lifecycle chaincode install basic.tar.gz
// 查询已安装的链码
peer lifecycle chaincode queryinstalled
// peer0org2
docker exec -it cli2 sh
cd chaincode
peer lifecycle chaincode install basic.tar.gz
// 查询已安装的链码
peer lifecycle chaincode queryinstalled
// 组织批准chaincode定义 org1
// peer0org1
docker exec -it cli0 sh
peer lifecycle chaincode approveformyorg -o orderer0.example.com:7050 --ordererTLSHostnameOverride orderer0.example.com --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --channelID mychannel --name basic --version 1.0 --package-id basic_1.0:4ec191e793b27e953ff2ede5a8bcc63152cecb1e4c3f301a26e22692c61967ad --sequence 1
// 检查链码定义是否准备好被提交
// peer0org1
peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name basic --version 1.0 --sequence 1 --output json
// peer0org2
peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name basic --version 1.0 --sequence 1 --output json
// 节点批准chaincode定义 org2
docker exec -it cli2 sh
peer lifecycle chaincode approveformyorg -o orderer0.example.com:7050 --ordererTLSHostnameOverride orderer0.example.com --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --channelID mychannel --name basic --version 1.0 --package-id basic_1.0:4ec191e793b27e953ff2ede5a8bcc63152cecb1e4c3f301a26e22692c61967ad --sequence 1
// 检查chaincode定义是否准备好被提交
// peer0org1
peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name basic --version 1.0 --sequence 1 --output json
// peer0org2
peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name basic --version 1.0 --sequence 1 --output json
通道内的组织提交链码定义
peer lifecycle chaincode commit -o orderer0.example.com:7050 --ordererTLSHostnameOverride orderer0.example.com --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --channelID mychannel --name basic --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt --version 1.0 --sequence 1
//--------------------------------------------------------------------------
// [验证]可否两个组织分步commit chaincode definition,还是说一个通道内所有安装并批准chiacode definition的节点只需要commit一次就可以
peer lifecycle chaincode commit -o orderer0.example.com:7050 --ordererTLSHostnameOverride orderer0.example.com --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --channelID mychannel --name basic --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --version 1.0 --sequence 1
// 报错
2021-05-12 02:40:09.725 UTC [chaincodeCmd] ClientWait -> INFO 001 txid [90dbeae67e09e02ac43b9943d8afb4fc23f5a4b020c9a15e2121f895c8138559] committed with status (ENDORSEMENT_POLICY_FAILURE) at peer0.org2.example.com:9051
Error: transaction invalidated with status (ENDORSEMENT_POLICY_FAILURE)
// 分析
chiancode definition的commit受背书策略的影响, 所以一个组织不能单独commit chaincode definition
//--------------------------------------------------------------------------
// peer0org1上检查channel上已提交的链码定义
peer lifecycle chaincode querycommitted --channelID mychannel --name basic
// peer0org2上检查channel上已提交的链码定义
peer lifecycle chaincode querycommitted --channelID mychannel --name basic
// 初始化数据
peer chaincode invoke -o orderer0.example.com:7050 --ordererTLSHostnameOverride orderer0.example.com --tls --cafile "/opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n basic --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles "/opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles "/opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" -c '{"function":"InitLedger","Args":[]}'
// 查询
peer chaincode query -C mychannel -n basic -c '{"Args":["GetAllAssets"]}'
// 交易
peer chaincode invoke -o orderer0.example.com:7050 --ordererTLSHostnameOverride orderer0.example.com --tls --cafile "/opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n basic --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles "/opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles "/opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" -c '{"function":"TransferAsset","Args":["asset6","Christopher"]}'
peer chaincode invoke -o orderer0.example.com:7050 --ordererTLSHostnameOverride orderer0.example.com --tls --cafile "/opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n basic --peerAddresses peer1.org1.example.com:8051 --tlsRootCertFiles "/opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt" --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles "/opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" -c '{"function":"TransferAsset","Args":["asset6","adder"]}'
// 通道内有两个组织,提交交易时只需要两个组织各提供一个节点进行背书即可
// 查询
peer chaincode query -C mychannel -n basic -c '{"Args":["ReadAsset","asset6"]}'
peer chaincode invoke -o orderer.example.com:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "/opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n basic --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles "/opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" -c '{"function":"TransferAsset","Args":["asset6","adder1"]}'
// 交易返回状态码200,但是查询无结果
// peer节点报错
2021-05-11 08:03:25.295 UTC [vscc] Validate -> ERRO 083 VSCC error: stateBasedValidator.Validate failed, err validation of endorsement policy for chaincode basic in tx 10:0 failed: implicit policy evaluation failed - 1 sub-policies were satisfied, but this policy requires 2 of the 'Endorsement' sub-policies to be satisfied
2021-05-11 08:03:25.295 UTC [committer.txvalidator] validateTx -> ERRO 084 Dispatch for transaction txId = 88b59c46ce4087cf89aa69dba364cd911242fd59082a2fa4596087cb7685ef99 returned error: validation of endorsement policy for chaincode basic in tx 10:0 failed: implicit policy evaluation failed - 1 sub-policies were satisfied, but this policy requires 2 of the 'Endorsement' sub-policies to be satisfied
// 错误原因
背书策略要求多于一半的组织【同一组织上的任意节点】背书,交易才能通过