# Chaincode的开发部署及使用 **Published by:** [leaf](https://paragraph.com/@leaf-6/) **Published on:** 2022-12-06 **URL:** https://paragraph.com/@leaf-6/chaincode ## Content 超级账本的开发,首先来了解一下Chaincode的概念,然后介绍如何开发Chaincode,如何将Chaincode部署到Fabric中,以及如何使用Chaincode。 Chaincode,中文一般称为链码,是超级账本中的智能合约,本质上就是一段计算机语言实现的程序。Chaincode是超级账本的重要组成部分,一般用Go语言编写,也支持用Java、JavaScript等计算机语言来进行编写。本书中的Chaincode使用Go语言编写。 那Chaincode是如何运行的呢?Chaincode编写完成后需要进行编译并部署到超级账本上。部署完成后,Chaincode运行在一个受保护的Docker容器当中,与背书结点的运行互相隔离。超级账本通过Chaincode实现对账本数据的读取和修改操作,同时也会把操作的日志保存到超级账本的数据库中。由一个Chaincode创建的状态仅限于该Chaincode有权限访问,不能由另一个Chaincode直接访问。然而,在同一个超级账本中,给定适当的权限,一个Chaincode可以调用另一个Chaincode来访问其创建的状态。 Chaincode的生命周期包括打包、安装、实例化和升级这四个阶段,具体过程会在下面实例中讲解。 开发Chaincode就是实现特定的接口,这个接口包括两个方法——Init()方法和Invoke()方法。这两个方法的作用如下:当Chaincode接收instantiate或upgrade事务时,会调用Init()方法,以便Chaincode可以执行任何必要的初始化,包括应用程序状态的初始化;Invoke()方法是为了响应接收调用事务来处理事务提案。 下面实现一个最简单的Chaincode,这个例子中的作用就是展示如何开发Chaincode以及Chaincode的执行流程。在这个Chaincode中不对数据进行处理,调用方法后直接返回就可以了,所以在编写Init()方法和Invoke()方法的主体功能时返回空值就可以了。代码如下:其中main函数是Go程序执行的入口函数,当在结点部署Chaincode时,就会执行main函数里面的内容。main函数中第1句Err:=shim.Start(new(SampleChaincode))会启动示例的Chaincode,如发生错误会输出启动失败的信息,否则就会输出成功运行的信息。 在上面的示例中实现了Chaincode的3个方法,依次为Init、Query和Invoke。下面依次来了解下这3个方法的作用 ●Init()方法。Init()方法会在Chaincode首次部署实现到区块链时由各个结点调用,此方法可用于实现任何与初始化、引导或设置相关的任务。 ●Query()方法。只要在区块链上执行任何查询操作,就会调用Query()方法。Query()方法不会修改区块链的状态,因此它不会在交易上下文内运行。如果尝试在Query()方法内修改区块链的状态,将出现一个错误。另外,因为此方法仅用于读取区块链的状态,所以对它的调用不会记录在区块链上。 ●Invoke()方法。只要修改区块链的状态,就会调用Invoke()方法,所以所有对区块链进行的更新或删除操作都应封装在Invoke方法内。因为此方法将修改区块链的状态,所以超级账本会自动创建一个交易上下文,以便此方法在其中执行。对此方法的所有调用都会在区块链上记录为交易,这些交易最终被写入区块中。 实现了上述的代码后就可以操作这个Chaincode。Fabric提供了4个命令管理Chaincode,分别是打包(package)、安装(install)、实例化(instantiate)、升级(upgrade)。首先通过package命令打包Chaincode,然后用install命令安装Chaincode,再通过instantiate实例化Chaincode。如果需要升级Chaincode,则需要先安装新版本的Chaincode,再通过upgrade命令对其进行升级。 在未来的版本中,官方也正在考虑添加stop和start命令禁用和重新启用Chaincode,而不必卸载它。在成功安装并实例化了一个Chaincode之后,Chaincode就处于活跃中(正在运行)。在安装完毕后,也可以在任何时间都对Chaincode进行升级,如图Chaincode有两种安装方式,一是直接安装源代码,二是通过package命令打包并签名生成打包文件,然后再通过install命令进行安装生成的打包文件。 以上就是Chaincode的开发和使用过程,最后再花一小节补充说明一下Chaincode的打包过程。 为了方便对Chaincode进行管理和签名认证,通常需要对Chaincode进行打包操作。所以本节专门对Chaincode的打包过程进行详解。 Chaincode包由3部分组成,包括Chaincode代码本身、一个可选的实例化策略和拥有Chaincode实体的一组签名。其中区块链上Chaincode被实例化进行交易的时候,可被Chaincode对应的实例化策略验证。 签名有以下作用。 ●建立Chaincode的所有权 ●对包的内容进行验证。 ●检测包是否篡改。 打包Chaincode有两种方式。第1种方式是当Chaincode有多个所有者的时候,需要让Chaincode包被多个所有者签名。这种情况下需要创建一个需要签名的Chaincode包,这个包依次被每个所有者签名。第2种就比较简单了,在已签名的结点上用install命令进行打包操作即可。 以上就是关于Chaincode的内容,下面开始进入超级账本的实际开发。 第1个实例是构建一个本地的Fabric网络,通过本案例可以学习如何基于超级账本构建一个简单的区块链网络,并与这个网络进行基本的交互操作,例如查询和更新超级账本的区块链数据。 超级账本的本地环境安装一节中已经下载了Fabric Samples的代码,在这些示例代码中一个名为“first-network”的文件夹,整个文件夹是一个完整的Fabric项目示例,实现了一个Fabric网络,这个Fabric网络中包含多个结点,以及一个命令行工具。下面使用这个示例构建第1个Fabric网络。 进入fabric-network的子目录first-network中,可以看到该目录下有一个名为byfn.sh的脚本文件。这个脚本文件中有着很完备的注释说明,执行“./byfn.sh­h”可以看到这个脚本文件的使用说明,包括如何启动和停止等操作Fabric网络的命令,如图下面开始构建这个简单的Fabric网络。使用命令“./byfn.sh -m generate”来生成网络所需的证书和创世区块,命令执行的过程中需要进行一些配置,这里使用默认配置,在命令行工具中输入“Y”确认既可,如图可以看到在这个过程中,先是用cryptogen工具生成各种网络实体的证书和密钥(cryptogen是Fabric项目中提供的用来生成需要的证书的工具),这些证书是身份的代表,它们允许在网络中进行交流和交易时进行签名/验证身份;然后生成一个genesis block(创世区块),用于引导orderer结点进行排序服务;最后生成Channel所需要的交易配置信息并保存到文件中。启动“first network”网络启动网络成功若要关闭这个网络可以使用./byfn.sh -m down命令进行操作,如图所示。 在启动这个Fabric网络后,我们就可以与这个网络的交互。交互的内容包括对网络中管道(channel,是指在Fabric网络中的通道,用来连接网络中的结点和隔离其他非相关的结点)的管理和对Chaincode的操作,从而更深入地认识Fabric网络。与Fabric网络交互的方式是可以通过命令行工具(CLI)调用Fabric API实现。 使用CLI需要先进入CLI容器(一个包含命令行工具CLI的docker容器,可以理解为一个可运行CLI的独立环境),进入容器的命令是“docker exec-it cli bash”,如图关闭网络进入CLI容器进入CLI容器后可以看到容器中的内容并对Fabric网络进行查询和更新操作。在CLI中使用的命令主要分为两种,一种是和channel有关的命令,另外一种是和Chaincode有关的命令。 (1)和channel有关的命令 和channel有关的命令如下。 ●创建channel。 进入CLI容器,可以通过如下命令来创建通道: peer channel create -o orderer.example.com:7050 -c mychannel -f./channel-artifacts/channel.tx --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 其中的参数含义如下。 ●-o orderer.example.com:7050:指定了orderer的服务定义,用作排序服务。 ●-c mychannel:要创建通道的名字。 ●-f./channel-artifacts/channel.tx:指定由configtxgen等工具生成的配置交易文件,用于提交给orderer结点。 ●--tls true:与orderer通信是否启动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:指定orderer结点的TLS证书,该证书为PEM格式。 ●加入channel。 加入channel的命令是peer channel join -b mychannel.block,其中-b是区块路径,这里指向包含创世区块的文件路径。 ●列举所有channel。 列举所有channel的命令是peer channel list。 ●更新channel。 更新channel的命令是peer channel update -o orderer.example.com:7050 -c mychannel -f./channel-artifacts/Org1MSPanchors.tx --tls true --cafile /opt/ gopath/src/github.com/ hyperl-edger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlsc-acerts/tlsca.example.com-cert.pem,参数与创建channel的类似。 (2)和Chaincode有关的命令 和Chaincode有关的命令如下。 ●安装Chaincode:peer chaincode install[flags]。 ●实例化Chaincode:peer chaincode instantiate[flags]。 ●调用Chaincode:peer chaincode invoke。 ●打包Chaincode:peer chaincode package。 ●查询Chaincode:peer chaincode query。 ●对Chaincode进行签名:peer chaincode signpackage。 ●更新Chaincode:peer chaincode upgrade。 其中主要可以使用的参数如下。 ●-C:channel ID。 ●-c:JSON字串的链代码构造函数消息(默认“{}”)。 ●-h:帮助。 ●-l:编写Chaincode的语言,默认“golang”。 ●-n:Chaincode名称。 ●-p:Chaincode路径。 ●-v:Chaincode版本。 ●-o:orderer结点。 下面通过Chaincode命令查询和更新超级账本。查询和更新超级账本在CLI容器中,先使用query对a和b的余额进行查询操作(其中a和b是在使用byfn.sh-m up命令启动网络时自动创建的两个账户),可以看到a有90,而b有210,如图然后从b账户转80到a账户。这个交易将创建一个新的区块并更新区块链。操作命令如图b账户转80到a账户由上图可以看到操作成功,此时在查询a账户和b账户,应该可以看到a账户有170,b账户有130,如图查询更新后a和b余额以上就是通过Chaincode查询和更新超级账本的方法。 ## Publication Information - [leaf](https://paragraph.com/@leaf-6/): Publication homepage - [All Posts](https://paragraph.com/@leaf-6/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@leaf-6): Subscribe to updates