实战Fabric 2.0 链码操作

简介:

Hyperledger Fabric 2.0最近已经发布,其中最引人关注的一点是链码操作。官方文档虽然对此提供了详细的说明,但本文将通过与Hyperledger Fabric前一个版本中链码操作的对比,来帮助你更好的理解新版本中链码操作的不同之处以及幕后的一些技术细节。

Hyperledger Fabric区块链开发教程:Node.js | Java | Golang

1、链码操作:Fabric 1.4 vs Fabric 2.0

我们将首先快速介绍在HF 1.4和HF 2.0中的整个链码操作过程。

链码操作指的是在Hyperledger fabric网络通道上部署链码的操作,这样区块链之外的应用可以调用或查询链码方法。在链码开发完成并测试后,首先需要将Fabric链码安装到指定的peer节点。在这个阶段链码还不能使用,直到链码被提交(Fabric 2.0中的术语)到通道中或在通道上实例化(Fabric 1.4中的术语),这样链码就可以被授权用户访问了。

下面是两个版本的Hyperledger Fabric中链码操作流程的对比图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fjdBW7zx-1582514440641)(fabric-2.0-chaincode-operation/compare.png)]

在Hyperledger Fabric 1.4中,链码操作过程包含以下步骤:打包、安装、实例化。如果链码属于多个参与方,那么就需要打包这一环节。如果不存在多方属主的问题,那么直接安装链码就可以(其中隐含了打包环节)。在Fabric链码安装时需要指定要安装链码的目标节点。

在这个阶段,安装好的Fabric链码还不能使用,因为它还没有在通道上实例化。当Fabric链码包被安装在指定的节点上之后,我们就可以执行链码实例化操作,从而让链码在通道上可用。技术上来说,链码实例化实际上就是调用LSCC系统链码的方法来初始化通道上的一个链码。

Fabric链码实例化之后就可以使用了,可以接受通道上的调用或查询请求。

下面我们看在Hyperledger Fabric 2.0中的链码操作步骤有何区别。

宽泛地来讲,在Fabric 2.0中链码操作基本遵循同样的流程,但是在命令和某些后台处理中做了一些调整。整体的流程可以分为四个步骤:打包、安装、机构审批、链码提交。大致可以认为前两个环节对应于Fabric 1.4中的链码安装,后面两个环节对应于Fabric 1.4中的链码实例化,但是实例化(instantiation)这个词不再用了。

链码打包这一步是创建一个打包文件(tar格式),其中包含Fabric链码以及一些元数据。虽然不同的机构可以分别进行打包处理,更常见是由一个机构打包然后分发给其他机构以便确保所有的机构使用相同的链码。

安装步骤是将打包的Fabric链码文件安装在指定的peer节点上。和之前的版本一样,只有需要接受链码调用的节点才需要安装链码。在这个节点,Fabric链码还不可用,因为还没有提交到通道中。链码安装的结果是得到一个包标识符,其格式为<label>.<hash>

机构审批是在Hyperledger Fabric 2.0中增加的步骤。在之前的版本中我们可以让一个机构实例化链码。在Fabric 2.0中,需要机构显式地审批链码。需要多少机构审批则是由生命周期背书策略来决定,默认情况下设置为需要大多数机构(超过半数)。如果Fabric网络中包含两个机构,那么就需要这两个机构同时批准。在审批过程中需要排序节点的参与,因为每次审批都会生成一个新的区块,这意味着所有的peer节点都了解审批的状态。

当审批环节完成后,我们就需要指定要在哪个通道上部署链码。这需要提交一些信息,例如背书策略、是否需要执行Init代码等等。在这里也有些与Fabric 1.4不同的地方:在Fabric 1.4中,当链码实例化时会自动调用链码的Init方法,然而在Fabric 2.0中,需要在提交链码后显式地调用Init方法。

在批准机构达到指定数量后,链码就可以提交了。我们现在就进入了最后一个步骤:链码提交。

链码提交可以由任何机构发起。该流程首先需要批准机构的背书,然后交易提交到排序服务并生成新的区块,最后所有的对等节点在账本中提交该区块。

现在链码就可以使用了。

2、First Network和SACC链码简介

出于完整性考虑,下面给出关于First Network和SACC链码的一些信息,这些内容都来自fabric-samples仓库。

First Network是一个双机构设置,每个机构中包含两个peer节点。通道mychannel创建后加入所有的4个peer节点。在byfn.sh中完整的实现了First Network的部署,并包含一些可选的参数。在下面的演示中,我们不使用默认的链码(在Fabric 1.4中式chaincode_example02,在Fabric 2.0中式abstore),而是使用SACC链码。

SACC式Simple Asset ChainCode的缩写,表示简单资产链码。它在账本中模拟一个键/值存储。当初次部署后,需要一个初始的键/值对。SACC链码定义了两个方法:Set()Get(),分别用来设置或读取某个键的值。

好了,现在我们可以开始演示Fabric 1.4和Fabric 2.0中链码操作的不同了。

3、Fabric 1.4.4链码操作演示

我们首先以无链码方式(使用-n选项)启动First Network,然后我们再加载SACC链码以便聚焦链码的生命周期。

下面是演示步骤:

  • 无链码方式启动First Network
  • 在指定的peer节点上安装SACC链码
  • 在mychannel通道上实例化SACC链码并查询结果
  • 调用set()设置新值并从另一个peer节点查询结果

STEP 1:首先启动First Network:

cd fabric-samples/first-network
./byfn.sh up -n

上面的命令会启动First Network、创建通道mychannel并将所有的peer节点加入该通道。注意在Fabric 1.4.4中,First Network使用solo排序服务实现,只有一个排序节点。另外,我们看到有4个对等节点在运行,以及一个CLI用于链码操作。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AIgCiAK7-1582514440643)(fabric-2.0-chaincode-operation/first-network-1.4.4.png)]

现在我们可以开始链码部署操作。

STEP 2:在指定peer节点上安装链码

这里我们跳过打包环节,直接在目标节点peer.org1和peer0.org2上安装链码,因为在这个演示中我们只需要这两个节点进行链码调用和查询。

# peer0.org1
docker exec cli peer chaincode install -n mycc -v 1 \
  -p github.com/chaincode/sacc
  
# peer0.org2  
docker exec \
  -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:9051 -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 \
  cli peer chaincode install -n mycc -v 1 -p github.com/chaincode/sacc

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kOzPUU3j-1582514440643)(fabric-2.0-chaincode-operation/install-1.4.4.png)]

STEP 3:在通道mychannel上实例化链码并查询

注意在sacc链码中有Init()代码。当我们实例化链码时,我们需要提供Init()所需的参数:

docker exec cli 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 mychannel -n mycc -v 1 -c '{"Args":["name","kc"]}' \
  -P "AND ('Org1MSP.peer','Org2MSP.peer')"

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SrpebQJT-1582514440643)(fabric-2.0-chaincode-operation/instantiate-1.4.4.png)]

如果现在看看peer节点的日志,我们可以看到出了新区块#3。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O4qTT6dv-1582514440644)(fabric-2.0-chaincode-operation/block-3-1.4.4.png)]

在链码实例化之后,我们可以查询:

docker exec cli peer chaincode query -C mychannel -n mycc -c '{"Args":["get","name"]}'

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MyDp34sY-1582514440645)(fabric-2.0-chaincode-operation/query-1.4.4.png)]

STEP 4:调用set()设置新值并从另一个节点查询

出于演示目的,我们在peer0.org1上调用set(),然后在peer0.org2上调用get(),以此说明链码是否工作正常。

# peer0.org1
docker exec cli peer chaincode invoke -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 \
  --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:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt \
  -C mychannel -n mycc -c '{"Args":["set","name","Peter"]}'
  
  # peer0.org2
docker exec -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:9051 \
  -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 \
  cli peer chaincode query -C mychannel -n mycc -c '{"Args":["get","name"]}'

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lngcTaU5-1582514440646)(fabric-2.0-chaincode-operation/invoke-1.4.4.png)]

4、Fabric 2.0链码操作演示

类似的,在Fairc 2.0.0中,我们也先以无链码方式启动First Network,然后再启动SACC链码以便聚焦链码的生命周期。

下面是演示步骤:

  • 无链码方式启动First Network
  • 打包SACC链码
  • 在指定peer节点上安装SACC链码包
  • 机构审批链码
  • 在mychannel通道上提交链码
  • 调用SACC链码的Init方法
  • 调用SACC链码的set方法并从另一个peer节点查询结果

STEP 1:以无链码方式启动First Network:

cd fabric-samples/first-network
./byfn.sh up -n

现在First Network已经启动,通道mychannel已经创建并且所有peer节点已经加入mychannel通道。注意在Fabric 2.0.0中,First Network使用Raft作为排序服务,所有5个排序节点都在运行。在这个演示中,我们只使用orderer.example.com,不过使用其他排序节点也是一样的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3mctKhpi-1582514440646)(fabric-2.0-chaincode-operation/first-network-2.0.0.png)]

STEP 2:打包SACC链码

首先我们处理依赖问题:

cd fabric-sample/chaincode/sacc
GO111MODULE=on go mod vendor
cd fabric-sample/first-network

然后打包链码:

docker exec cli peer lifecycle chaincode package sacc.tar.gz \
  --path github.com/hyperledger/fabric-samples/chaincode/sacc/ \
  --label sacc_1

在CLI容器内可以看到生成了新的文件sacc.tar.gz:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ILhcIYQG-1582514440647)(fabric-2.0-chaincode-operation/package-2.0.0.png)]

STEP 3:在指定peer节点上安装SACC链码包

现在我们在peer0.org1和peer0.org2上安装SACC练马报,因为在这个演示中我们只需要使用这两个节点进行链码调用和查询。

# peer0.org1
docker exec cli peer lifecycle chaincode install sacc.tar.gz

# peer0.org2
docker exec \
  -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:9051 \
  -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 \
  cli peer lifecycle chaincode install sacc.tar.gz

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rpaQxLUY-1582514440648)(fabric-2.0-chaincode-operation/install-2.0.0.png)]

我们会收到链码包的标识符,在下面的链码审批阶段会用到。我们收到的链码标识符为:sacc_1:bf57…6399

我们可以使用peer lifecycle chaincode queryinstalled命令随时检查节点上的链码安装情况,如果我们需要找出链码包的标识ID,这个命令会很有用。

# peer0.org1
docker exec cli peer lifecycle chaincode queryinstalled

# peer0.org2
docker exec \
  -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:9051 \
  -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 \
  cli peer lifecycle chaincode queryinstalled

STEP 4:审批链码

根据默认策略,需要超过半数的机构审批链码后才能向通道提交链码,具体可参考configtx.yaml中的Application/Policies/LifecycleEndorsement部分。目前的设置中包含两个机构,因此需要两个机构同时批准链码。

首先是Org1批准链码:

docker exec cli peer lifecycle chaincode approveformyorg \
  --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 \
  --channelID mychannel --name mycc --version 1 \
  --init-required --sequence 1 --waitForEvent --package-id ${PACKAGE_ID}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BCEueFc7-1582514440649)(fabric-2.0-chaincode-operation/org1-approval-2.0.0.png)]

如果我们现在看下peer节点的日志,可以看到出了新块#3。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aJmGdp8r-1582514440649)(fabric-2.0-chaincode-operation/block-3-2.0.0.png)]

类似的,我们让Org2批准链码:

docker exec \
  -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:9051 \
  -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 \
  cli peer lifecycle chaincode approveformyorg \
  --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 \
  --channelID mychannel --name mycc --version 1 --init-required \
  --sequence 1 --waitForEvent --package-id ${PACKAGE_ID}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gq0FaafK-1582514440650)(fabric-2.0-chaincode-operation/org2-approval-2.0.0.png)]

不出意外,可以看到出了新块block#4:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iPxLSobv-1582514440651)(fabric-2.0-chaincode-operation/block-4-2.0.0.png)]

注意我们在approval命令中指定了init相关的参数,以便向SACC链码的Init方法传入所需的参数。

可以随时使用如下命令查看链码的提交状态:

docker exec cli peer lifecycle chaincode checkcommitreadiness \
  --channelID mychannel --name mycc --version 1 --sequence 1 --output json

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y6nGgMOy-1582514440652)(fabric-2.0-chaincode-operation/checkcommit.png)]

两个机构都已经批准了链码,现在可以提交了。

STEP 5:向通道mychannel提交链码

链码提交可以在一个peer节点上完成:

docker exec cli peer lifecycle chaincode commit -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 \
  --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:9051 \
  --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt \
  --channelID mychannel --name mycc --version 1 --sequence 1 --init-required

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SFKxp8k6-1582514440652)(fabric-2.0-chaincode-operation/commit-2.0.0.png)]

可以看到出了新块#5:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n04HaOI5-1582514440653)(fabric-2.0-chaincode-operation/block-5-2.0.0.png)]

注意我们在commit命令中已经包含了init所需的参数。

同样,我们可以使用querycommited命令来查看链码的提交状态:

docker exec cli peer lifecycle chaincode querycommitted --channelID mychannel --name mycc

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BWlouWfU-1582514440653)(fabric-2.0-chaincode-operation/commit-2.0.0-2.png)]

在链码提交到通道之后,链码的生命周期就完成了,链码已经可以访问。现在我们回到链码的调用和查询,这和之前的版本是一致的。

STEP 6:调用链码的Init方法

SACC链码的Init方法需要首先调用。

docker exec cli peer chaincode invoke -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 \
  --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:9051 \
  --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt \
  -C mychannel -n mycc --isInit -c '{"Args":["name","kc"]}'

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x6UNX5kl-1582514440654)(fabric-2.0-chaincode-operation/init-2.0.0.png)]

现在可以查询 链码:

docker exec cli peer chaincode query -C mychannel -n mycc -c '{"Args":["get","name"]}'

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RfW001zh-1582514440654)(fabric-2.0-chaincode-operation/query-2.0.0.png)]

STEP 7:调用链码的set()方法并从另一个peer节点查询

和之前一样,我们在peer0.org1上调用链码的set()方法,在peer0.org2上进行查询:

# peer0.org1
docker exec cli peer chaincode invoke \
  -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 \
  --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:9051 \
  --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt \
  -C mychannel -n mycc -c '{"Args":["set","name","Peter"]}'
  
  # peer0.org2
docker exec \
  -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:9051 \
  -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 \
  cli peer chaincode query -C mychannel -n mycc -c '{"Args":["get","name"]}'

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DqctvG5I-1582514440655)(fabric-2.0-chaincode-operation/invoke-2.0.0.png)]

一切正常。


原文链接:Hyperledger Fabric 2.0链码操作详解 — 汇智网

目录
相关文章
|
6月前
|
开发框架 .NET 区块链
Hyperledger fabric部署链码(五)初始化与链码升级
fabric部署chaincode-go(智能合约)系列之五
|
6月前
|
JavaScript 测试技术 Go
Hyperledger fabric部署链码(一)打包链码
fabric部署chaincode-go(智能合约)系列之一
|
6月前
|
JSON 区块链 数据格式
Hyperledger fabric部署链码(四)提交链码定义到channel
fabric部署chaincode-go(智能合约)系列之四
|
6月前
|
测试技术 API 区块链
Hyperledger fabric部署链码(三)批准链码定义
fabric部署chaincode-go(智能合约)系列之三
|
6月前
|
区块链
Hyperledger fabric部署链码(二)安装链码到fabric
fabric部署chaincode-go(智能合约)系列之二
|
自然语言处理 JavaScript 前端开发
|
安全 JavaScript Java