Hyperledger Fabric 2.2 学习笔记:测试网络test-network

写在前面

  最近被Hyperledger Fabric折磨,归根结底还是因为自己太菜了qwq。学习路漫漫,笔记不能少。下面的步骤均是基于已经成功搭建了Fabric2.2环境,并且拉取fabric-samples文件夹了。

一、启动测试网络

  打开终端进入test-network目录下。我的具体目录是: /workspace/fabric-samples/test-network,因此有命令:

cd /workspace/fabric-samples/test-network

  在使用./network.sh命令前,可以先查看选项说明。

./network.sh -h

  要是不想看问题也不大,跟着我走就好。(๑>ڡ<)☆

  下面正式开始!

  首先启动网络。注意下面这个命令只是启动网络并没有创建通道。

./network.sh up

  启动网络后,接着创建通道。由于这里并没有指定通道的名字,此时默认为mychannel.

./network.sh createChannel

  其实上述两步可以用一条命令实现,那就是:

./network.sh up createChannel

  之后,将bin目录中二进制文件添加到 CLI 路径。

export PATH=${PWD}/../bin:$PATH

  设置FABRIC_CFG_PATH为指向fabric-samples中的core.yaml文件。

export FABRIC_CFG_PATH=$PWD/../config/

 

二、安装链码

  根据官方文档可以知道,Fabric链码生命周期需要组织同意定义一个链码的参数,比如说名称、版本以及链码背书策略。通道成员通过以下四步达成共识。不是通道上的每一个组织都需要完成每一步。

  1.打包链码。这一步可以被一个或者每一个组织完成。

  2.安装链码在你的peer节点上。每一个用链码的组织都需要完成。

  3.为你的组织批准链码定义。使用链码的每一个组织都需要完成这一步。链码能够在通道上运行之前,链码定义需要被足够多的组织批准来满足通道的生命周期背书(LifecycleEndorsement)策略(默认为大多数组织)。

  4.提交链码定义到链上。一旦通道所需数量的组织已经同意,提交交易需要被提交。提交者首先从已同意组织中的足够的peer节点中收集背书,然后通过提交链码声明。

  显然,下面要进行的第一步是打包链码。链码需要被打包成一个tar文件。

 

  1.打包链码

  下面使用peer lifecycle chaincode package命令创建链码包

peer lifecycle chaincode package fabcar.tar.gz --path ../chaincode/fabcar/go/ --lang golang --label fabcar_1

  说明:① 命令中--path指的是 将指定目录(../chaincode/fabcar/go/)的源码打包成fabcar.tar.gz.

      ② --label 后面是标签,当日后链码包升级的时候,可以设置不同的标签。

 

  2.安装链码

  此时网络有两个组织,所以需要先后在Org1、Org2的peer节点上安装链码。

  (1)Org1 peer节点安装链码

export CORE_PEER_TLS_ENABLED=true export CORE_PEER_LOCALMSPID=Org1MSP export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/[email protected]/msp export CORE_PEER_ADDRESS=localhost:7051 peer lifecycle chaincode install fabcar.tar.gz

  当看到status:200即为成功。具体成功返回如下:

2022-04-20 10:03:14.293 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 001 Installed remotely: response:<status:200 payload:\nIfabcar_1:762e0fe3dbeee0f7b08fb6200adeb4a3a20f649a00f168c0b3c2257e53b6e506\022\010fabcar_1 > 2022-04-20 10:03:14.294 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 002 Chaincode code package identifier: fabcar_1:762e0fe3dbeee0f7b08fb6200adeb4a3a20f649a00f168c0b3c2257e53b6e506

  但过程总是曲折的,显然我没有那么顺利成功。在安转链码的时候,我得到如下返回:

Error: chaincode install failed with status: 500 - failed to invoke backing implementation of 'InstallChaincode': could not build chaincode: docker build failed: docker image build failed: docker build failed: Error returned from build: 1 go: github.com/hyperledger/[email protected]: Get https://proxy.golang.org/github.com/hyperledger /fabric-contract-api-go/@v/v1.1.0.mod: dial tcp: lookup proxy.golang.org on 172.20.10.1:53: read udp 172.17.0.2:53395 ->172.20.10.1:53: i/o timeout “

  解决方案如下:

  到../chaincode/fabcar/go/目录下打开终端执行命令。

go env -w GOPROXY=https://goproxy.io,direct go env -w GO111MODULE=on go mod vendor

  之后重新执行peer lifecycle chaincode install fabcar.tar.gz即可成功。

  (2)Org2 peer节点安装链码

export CORE_PEER_LOCALMSPID=Org2MSP export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/[email protected]/msp export CORE_PEER_ADDRESS=localhost:9051 peer lifecycle chaincode install fabcar.tar.gz

 

  3.批准链码定义

  下面需要把链码发布到通道上去。首先查询链码包ID

peer lifecycle chaincode queryinstalled

  得到返回如下:

Installed chaincodes on peer: Package ID: fabcar_1:762e0fe3dbeee0f7b08fb6200adeb4a3a20f649a00f168c0b3c2257e53b6e506, Label: fabcar_1

  因此我的包ID为:

fabcar_1:762e0fe3dbeee0f7b08fb6200adeb4a3a20f649a00f168c0b3c2257e53b6e506.

  通过链码时,我们将使用包ID,因此,将包ID保存为环境变量。将返回的包ID粘贴到下面的命令中。

export CC_PACKAGE_ID=

  在这里就是:

export CC_PACKAGE_ID=fabcar_1:762e0fe3dbeee0f7b08fb6200adeb4a3a20f649a00f168c0b3c2257e53b6e506

  之后,Org2通过链码定义

peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name fabcar --version 1.0 --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --waitForEvent

  返回如下即为成功。

2022-04-20 10:20:59.307 CST [chaincodeCmd] ClientWait -> INFO 001 txid [f688ddff60056af56e96784d253695e9fbb056e5244058fb30b2d05977214c1c] committed with status (VALID) at localhost:9051

  设置以下环境变量以Org1管理员身份运行:
  Org1通过链码定义

export CORE_PEER_LOCALMSPID=Org1MSP export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/[email protected]/msp export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt export CORE_PEER_ADDRESS=localhost:7051 peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name fabcar --version 1.0 --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --waitForEvent

  返回:

2022-04-20 10:25:23.828 CST [chaincodeCmd] ClientWait -> INFO 001 txid [9178a978646d4b010a61677488532af88b7393ba898341168fc627c0953a9884] committed with status (VALID) at localhost:7051

  使用 peer lifecycle chaincode checkcommitreadiness 命令来检查通道成员是否已批准相同的链码定义:

peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name fabcar --version 1.0 --sequence 1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --output json

  返回:

{     approvals: {         Org1MSP: true,         Org2MSP: true     } }

  返回的结果说明这两个节点批准了这个链码的定义。

 

  4.将链码提交到通道

  使用 peer lifecycle chaincode commit 命令将链码定义提交到通道。commit命令还需要由组织管理员提交。

peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name fabcar --version 1.0 --sequence 1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt

  返回:

2022-04-20 10:45:05.973 CST [chaincodeCmd] ClientWait -> INFO 001 txid [c93e2e79e2da09f04654d30630959d9e80d2576aefdf4be16e3b281d48a011a4] committed with status (VALID) at localhost:7051 2022-04-20 10:45:06.019 CST [chaincodeCmd] ClientWait -> INFO 002 txid [c93e2e79e2da09f04654d30630959d9e80d2576aefdf4be16e3b281d48a011a4] committed with status (VALID) at localhost:9051


  使用 peer lifecycle chaincode querycommitted 命令来确认链码定义已经提交给通道。

peer lifecycle chaincode querycommitted --channelID mychannel --name fabcar --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

  返回:

Committed chaincode definition for chaincode 'fabcar' on channel 'mychannel': Version: 1.0, Sequence: 1, Endorsement Plugin: escc, Validation Plugin: vscc, Approvals: [Org1MSP: true, Org2MSP: true]

  看到此返回信息后可以知道我们提交的链码已经提交到通道myChannel中。

 

三、调用链码

  ① 调用链码

peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n fabcar  --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{function:initLedger,Args:[]}'

  返回如下即为成功。

2022-04-20 15:49:24.590 CST [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200

  显然,我并没有一下就成功。我得到如下返回:

Error: endorsement failure during invoke. response: status:500 message:error in simulation:failed to execute transaction 5e72e85cea510ecc198412f2f7df406b8fbcff8adf97d052d6b165413ed85854: could not launch chaincode fabcar_1:762e0fe3dbeee0f7b08fb6200adeb4a3a20f649a00f168c0b3c2257e53b6e506:error starting container: error starting container: API error (404): network _test not found

  错误原因:

  fabric-samples/test-network/docker/docker-compose-test-net.yaml的配置文件中有一个

- CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=${COMPOSE_PROJECT_NAME}_test

  ${COMPOSE_PROJECT_NAME}在智能合约启动时,此值获取到的会是空值,从而导致标题的错误提示。这个也被官方收录进issue中,并在fabric-samples的main分支中已经改为固定值,如下:

- CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=fabric_test

 

  需要注意的是使用docker-compse启动时,创建的network名字会在前边加上当前docker-compse文件的目录名字。所以如果我们在使用老版本的fabric-sample时,自己可修改${COMPOSE_PROJECT_NAME}值为当前你存放compose文件的文件夹名称。
  查看创建的docker network可以使用docker network ls查看。
  此时查看到名字是:docker_test
因此将文件中的
- CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=${COMPOSE_PROJECT_NAME}_test
改为
- CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=docker_test
  注意文件有两处需要改。

 

 

  ②调用链码

peer chaincode query --channelID mychannel --name fabcar -c '{Args:[queryAllCars]}'

 

  得到返回:

[{Key:CAR0,Record:{make:Toyota,model:Prius,colour:blue,owner:Tomoko}},{Key:CAR1,Record:{make:Ford,model:Mustang,colour:red,owner:Brad}},{Key:CAR10,Record:{make:VW,model:Polo,colour:Grey,owner:Archie}},{Key:CAR2,Record:{make:Hyundai,model:Tucson,colour:green,owner:Jin Soo}},{Key:CAR3,Record:{make:Volkswagen,model:Passat,colour:yellow,owner:Max}},{Key:CAR4,Record:{make:Tesla,model:S,colour:black,owner:Adriana}},{Key:CAR5,Record:{make:Peugeot,model:205,colour:purple,owner:Michel}},{Key:CAR6,Record:{make:Chery,model:S22L,colour:white,owner:Aarav}},{Key:CAR7,Record:{make:Fiat,model:Punto,colour:violet,owner:Pari}},{Key:CAR8,Record:{make:Tata,model:Nano,colour:indigo,owner:Valeria}},{Key:CAR9,Record:{make:Holden,model:Barina,colour:brown,owner:Shotaro}}]

 

  到这测试网络也就跑通了。(๑╹◡╹)ノ

 

 

参考

[1] Hyperledger Fabric2中文文档-链码部署

[2] Error starting container: API error (404): {“message“:“network _byfn not found“}

[3] error starting container: API error (404): network fabric_test not found“

[4] hyperledger-fabric【1】运行测试网络