banner
leaf

leaf

It is better to manage the army than to manage the people. And the enemy.

Chaincode的开发部署及使用

超级账本的开发,首先来了解一下 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()方法的主体功能时返回空值就可以了。代码如下:

image

其中 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 进行升级,如图

image

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 网络的命令,如图

image

下面开始构建这个简单的 Fabric 网络。使用命令 “./byfn.sh -m generate” 来生成网络所需的证书和创世区块,命令执行的过程中需要进行一些配置,这里使用默认配置,在命令行工具中输入 “Y” 确认既可,如图

image

可以看到在这个过程中,先是用 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,如图

image

然后从 b 账户转 80 到 a 账户。这个交易将创建一个新的区块并更新区块链。操作命令如图

b 账户转 80 到 a 账户

由上图可以看到操作成功,此时在查询 a 账户和 b 账户,应该可以看到 a 账户有 170,b 账户有 130,如图

查询更新后 a 和 b 余额

以上就是通过 Chaincode 查询和更新超级账本的方法。

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.