智能合约,是一个抽象的概念,智能合约的历史可以追溯到 1990s 年代。它是由尼克萨博(Nick Szabo)提出的理念,几乎与互联网同龄。

我们这里所说的智能合约只狭义的指区块链中。它能够部署和运行在区块链环境中,由一段代码描述相关的业务逻辑。部署后的智能合约在区块链中无法修改,智能合约的执行完全由代码决定,不受人为因素的干扰。一般来说,参与方通过智能合约各自权利和义务触发合约的条件以及结果,一旦该智能合约在区块链环境中运行就可以得出客观准确的结果。

什么是ChainCode

  ChainCode(链码)是智能合约在Fabric区块链网络的实现形式。分为用户链码系统链码,通常指的是用户链码。链码是访问账本基本方法,一般是用Go等高级语言编写的、实现规定接口的代码。上层应用可以通过调用链码初始化和管理账本的状态。只要有适当的权限链码之间也可以互相调用

  链码被部署在Fabric网络节点上,运行在隔离沙盒(目前为Docker容器)中,并通过gRPC协议与相应的Peer节点进行交互,以操作分布式账本中的数据。

  启动Fabric网络后,可以通过命令行或SDK进行链码操作,验证网络运行是否正常。

  它扮演的角色如下图所示:

应用程序通过向区块链网络发送交易来调用智能合约,从而操作账本中的状态。

ChainCode的运行方式

  在Fabric中交易的处理过程,客户端将提案首先发送到背书节点,背书节点检提案的合法性。如果合法的话,背书节点将通过交易所属的链码临时执行一个交易,并执行背书节点在本地持有的状态副本。

  Chaincode应该仅仅被安装于chaincode所有者的背书节点上,链码运行在节点上的沙盒(Docker容器)中,并通过gRPC协议与相应的Peer节点进行交互,以使该chaincode逻辑对整个网络的其他成员保密。

  请务必在一条channel上每一个要运行你chaincode的背书节点上安装你的chaincode,其他没有chaincode的成员将无权成为chaincode影响下的交易的认证节点(endorser)。也就是说,他们不能执行chaincode。不过,他们仍可以验证交易并提交到账本上

  ChainCode要在区块链网络中运行,需要经过链码安装链码实例化两个步骤。

  多次安装,一次实例化
  
在一个区块链子链中,该网络是由“1账本+1通道+N个peer节点”组成。如果我们要手动来搭建Fabric网络的话,即通过命令行的形式来进行ChainCode的安装与实例化。我们需要多次install,一次instance。也就是说,对于整个Fabric网络来说,假设有X个背书节点,那么,我们需要给每个背书节点安装ChainCode,但是在整个网络搭建过程中只需要instance ChainCode一次。因为install 针对的是背书节点,instance 针对的是通道。

  install 链码的对象是背书节点,主要目的是方便背书节点对运行链码,对交易进行模拟。

  instance 链码的对象是channel,主要目的是为了将安装过的链码在指定通道上进行实例化调用,在节点上创建容器启动,并执行初始化操作。实例化的过程中,需要指定背书策略,来确定通道上哪些节点执行的交易才能添加到账本中。

  安装的过程其实就是对指定的代码进行编译打包,并把打包好的文件发送到Peer,等待接下来的实例化。下面链码的生命周期就是指这个过程。

  实例化链上代码主要是在Peer所在的机器上对前面安装好的链上代码进行包装,生成对应Channel的Docker镜像和Docker容器。并且在实例化时我们可以指定背书策略。

  • Chaincode运行在一个受保护的Docker容器当中,与背书节点的运行互相隔离。
  • Chaincode可通过应用提交的交易对账本状态初始化并进行管理。

ChainCode的生命周期

Hyperledger Fabric API提供了四个管理chaincode生命周期的命令:

  • package
  • install
  • Instantiate
  • Upgrade

在未来的版本中,正考虑添加stop和start交易的指令,以便能方便地停止与重启chaincode,而不用非要真正卸载它才行。在一个区块链网络中,将打包、安装、实例化和升级chaincode的过程作为一种可操作的chaincode生命周期函数进行调用。

在这里,我们简单讨论package,signpackage,install,instantiate,upgrade,stop&start这几个生命周期。具体如下图所示:

1)Packaging | 打包

在区块链中,将链码安装到Peer节点,与我们安装普通程序不一样。Fabric对链码的安装有严格的验证和安全机制。

安装好的链码,谁有资格实例化?又该使用什么样的背书策略来调用ChainCode呢?

这一切,都需要在安装之前规定好。我们把这些附加信息+ChainCode源码统称为ChainCode包。

一般而言,ChainCode包由以下三个部分组成:

  • chaincode本身,其由ChaincodeDeploymentSpec(Chaincode部署规范)来定义。ChaincodeDeploymentSpec,以下简称CDS。CDS是根据代码及一些其他属性(名称,版本等)来定义chaincode。
  • 一个可选的实例化策略,该策略可被背书策略描述。
  • 一组表示chaincode所有权的签名。

打包的过程,就是将这三部分信息打包成一个整体。一般来说,打包chaincode有两种方式:

  • 第一种是当你想要让chaincode有多个所有者的时候,此时就需要让chaincode包被多个所有者签名。这种情况下需要我们创建一个被签名的chaincode包(SignedCDS),这个包依次被每个所有者签名。
  • 另一种就比较简单了,让chaincode有一个所有者的时候,此时只要被一个人签名即可。

要创建一个签名过的chaincode包,请用下面的指令:

peer chaincode package -n mycc -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02 -v  -s -S -i "AND('OrgA.admin')" ccpack.out
  • -s:选项创建了一个可被多个所有者签名的包,而非简单地创建一个CDS。如果使用-s,那么当其他所有者要签名的时候,-S也必须同时使用。否则,该过程将创建一个仅包含实例化策略的签名chaincode包(SignedCDS)。
  • -S选项可以使在core.yaml文件中被localMspid相关属性值定义好的MSP对包进行签名。该选项是可选的。不过,如果我们创建了一个没有签名的包,那么它就不能被任何其他所有者用signpackage指令进行签名。
  • -i选项也是可选的,它允许我们为chaincode指定实例化策略。实例化策略与背书策略格式相同,它指明谁可以实例化chaincode。

2)signpackage | 签名并打包

一个在创建时就被签名的chaincode包可以交给其他所有者进行检查与签名。具体的工作流程支持通道外对chaincode包签名。

ChaincodeDeploymentSpec可以选择被全部所有者签名并创建一个SignedChaincodeDeploymentSpec(SignedCDS),SignedCDS包含三个部分:

  • CDS包含chaincode的源码、名称与版本
  • 一个chaincode实例化策略,其表示为背书策略
  • chaincode所有者的列表,由Endorsement定义

一个chaincode所有者可以对一个之前创建好的带签名的包进行签名,具体使用如下指令:

peer chaincode signpackage ccpack.out signedccpack.out

指令中的ccpack.out和signedccpack.out分别是输入与输出包。

signedccpack.out则包含一个用本地MSP对包进行的附加签名。

3)install | 安装

install的过程会将chaincode的源码以一种被称ChaincodeDeploymentSpec(CDS)的规定格式打包,并把它安装在一个将要运行该chaincode的peer节点上。

在Fabric网络中,我们需要在一个channel上每一个要运行你chaincode的背书节点上安装你的chaincode。

Chaincode应该仅仅被安装于chaincode所有者的背书节点上,以使该chaincode逻辑对整个网络的其他成员保密。其他没有chaincode的成员将无权成为chaincode影响下的交易的认证节点(endorser)。对于认证节点来说,他们不能执行chaincode。不过,他们仍可以验证交易并提交到账本上。

下面安装chaincode,使用CLI安装一个存放在sacc目录下的chaincode时,命令如下

peer chaincode install -n asset_mgmt -v 1.0 -p sacc

-n:name 对链码进行命令

-v: version 指定chaincode的版本

-p: path 指明chainCode的路径

在CLI内部会为sacc创建SignedChaincodeDeploymentSpec,并将其发送到本地peer节点。这些节点会调用LSCC上的Install方法。

4)instantiate | 实例化chaincode

实例化ChainCode过程会调用生命周期系统chaincode(LSCC)在一个channel上创建并初始化一段chaincode。实例化过程,会生成对应Channel的Docker镜像和Docker容器。并且在实例化时我们可以指定背书策略。

当然,一个实例化交易的创建者必须符合在SignedCDS中chaincode的实例化策略,且必须充当channel的写入器(这会成为channel创建配置的一部分),这对于channel的安全至关重要。

使用CLI去实例化 名为mycc 的chaincode,指令具体如下:

peer chaincode instantiate -n mycc -v 1.0 -c '{"Args":["john","0"]}' -P "OR ('Org1.member','Org2.member')"

-n 实例化链码的名称

-c --ctor,链码的具体执行参数,为json格式

-P --Policy 指定实例化策略

5)upgrade | 升级chaincode

一段chaincode可以通过更改它的版本(SignedCDS的一部分)来随时进行更新。至于SignedCDS的其他部分,比如所有者及实例化策略,都是可选的。不过,chaincode的名称必须一致,否则它会被当做完全不同的另一段chaincode。

在升级之前,chaincode的新版本必须安装在需要它的背书节点上。升级是一个类似于实例化交易的交易,它会将新版本的chaincode与channel绑定。其他与旧版本绑定的channel则仍旧运行旧版本的chaincode。换句话说,升级交易只会一次影响一个提交它的channel。

6)stop&star | 停止与启动

注意,停止与启动生命周期交易的功能还没实现。不过,你可以通过移除chaincode容器以及从每个背书节点删除SignedCDS包来停止chaincode。具体而言,就是删除所有主机或虚拟机上peer节点运行于其中的chaincode的容器,随后从每个背书节点删除SignedCDS。

chainCode的状态总结

在上述的过程中,ChainCode的状态有以下几种。这里做一个小总结:

CDS-ChainCodeSpec 包含链码源码,名称,版本等信息

SignedCDS-SignedChaincodeDeploymentSpec ,包含 CDS、一个chaincode实例化策略,其表示为背书策略、chaincode所有者的列表,由Endorsement定义。

ChainCode的种类

在Fabric中,链码可以分为两种,系统chaincode用户chaincode

1)系统ChainCode

系统链码则负责Fabric节点自身的处理逻辑,包括系统配置、背书、校验等工作。这些处理过程最初通过硬编码(Hard-Coded)的方式固化在系统中。Fabric通过系统链码的形式来实现,运行在Peer主进程内,兼顾了逻辑实现和管理的灵活性,以及通信的性能。

例如:一个系统chaincode只能通过peer节点的二进制文件升级。同时,系统chaincode只能以一组编译好的特定的参数进行注册,且不具有背书策略相关功能。

以下是系统chaincode的表格:

Fabric五大类型系统链码。系统链码目前仅支持Go语言,在Peer节点启动时会自动完成注册和部署,以进程内逻辑形式跟主进程进行交互。

2)用户chaincode

用户链码对应用开发者来说十分重要,它提供了基于区块链分布式账本的状态处理逻辑,基于它可以开发出多种复杂的应用。

在超级账本Fabric项目中,用户可以使用Go语言来开发链码,未来还将支持包括Java、JavaScript在内的多种高级语言。

用户链码相关的代码都在core/chaincode路径下。其中core/chaincode/shim包中的代码主要是供链码容器侧调用使用,其他代码主要是Peer侧使用。

3)两者的比较

相同点

系统chaincode与用户chaincode两种的编程模型相同,

不同点

系统chaincode运行于peer节点内 而 用户chaincode运行在一个隔离的容器中。因此,系统chaincode在节点内构建且不遵循上文描述的chaincode生命周期。安装,实例化,升级这三项操作不适用于系统chaincode。

链码的工作流程

我们知道,在Fabric中,链码运行在节点上的沙盒(Docker容器)中,被调用时的基本工作流程如上图所示。

  • 首先,用户通过客户端(SDK或CLI),向Fabric的背书节点(endorser)发出调用链码交易提案(proposal)
  • 然后,节点对提案进行包括ACL权限检查在内的各种检验,通过后则创建模拟执行这一交易的环境。
  • 接着,背书节点链码容器之间通过gRPC消息来交互,模拟执行交易并给出背书结论。
  • 最后,客户端收到足够的背书节点的支持后,便可以将这笔交易发送给排序节点(orderer)进行排序,并最终写入区块链。

链码容器的shim节点与链码交互中间层当链码的代码逻辑需要读写账本时,链码会通过shim层发送相应操作类型的ChaincodeMessage给节点,节点本地操作账本后返回响应消息。在上面的流程中,出现了一个重要的部分,shim层。这里需要再次强调一下,链码容器的shim层是节点与链码交互的中间层。

《区块链核心技术与应用》

《区块链开发实战》

Hyperledger Fabric(4)链码ChainCode的更多相关文章

  1. Hyperledger Fabric 1.2 --- Chaincode Operator 解读和测试(一)

    前言 本文主要目的是用于整理Hyperledger  Fabric中关于chaincode 管理和操作的内容,作者以release-1.2为范本进行讲解. 主要参考链接: https://hyperl ...

  2. Hyperledger Fabric 1.2 --- Chaincode Operator 解读和测试(二)

    本文接上一节是测试部分 搭建一个模拟测试环境 作者将fabric release1.2工程中的 example-e2e进行了改造来进行本次实验: (1)首先我们将examples/e2e_cli/sc ...

  3. hyperledger fabric 中java chaincode 支持离线打包

    联盟链由于其本身的特性,目前应用在一些大型国有企业银行比较多.出于安全考虑,这些企业一般会隔离外网环境.所以在实际生产需求中可能存在需要在一个离线的环境中打包安装chaincode的情况. 本文基于这 ...

  4. Hyperledger Fabric(5)ChainCode的编写步骤

    链码(chaincode) 会对 Fabric应用程序  发送的交易做出响应,执行代码逻辑,与 账本 进行交互. 再复习下他们之间的逻辑关系: Hyperledger Fabric 中,Chainco ...

  5. Hyperledger Fabric Chaincode for Operators——实操智能合约

    什么是Chaincode(智能合约)? chaincode是一个程序,它是使用Go语言编写的,最终在Java等其他编程语言中实现了指定的接口.chaincode运行在一个被背书peer进程独立出来的安 ...

  6. Hyperledger Fabric 踩坑汇总

    搭建基础环境 阿里云安装出现的一些问题解决 1. [signal SIGSEGV: segmentation violation code=0x1 addr=xxx pc=xxx] 类似的错误:原始错 ...

  7. Hyperledger Fabric CouchDB as the State Database

    使用CouchDB作为状态数据库 状态数据库选项 状态数据库包括LevelDB和CouchDB.LevelDB是嵌入在peer进程中的默认键/值状态数据库,CouchDB是一个可选的外部状态数据库.与 ...

  8. Hyperledger Fabric CouchDB as the State Database——使用CouchDB

    使用CouchDB作为状态数据库 状态数据库选项 状态数据库包括LevelDB和CouchDB.LevelDB是嵌入在peer进程中的默认键/值状态数据库,CouchDB是一个可选的外部状态数据库.与 ...

  9. Hyperledger Fabric 第一次安装

    第一次安装fabric有很多坑.记录一下,主要跟版本问题. 参考的是http://www.cnblogs.com/aberic/p/7532114.html 这篇博客. 我用的阿里云centOs 7. ...

随机推荐

  1. C#类型转换类(通用类)

    //     /// 类型转换类     /// 处理数据库获取字段为空的情况     ///     public static class DBConvert     {         #reg ...

  2. 运维之思科篇——NAT基础配置

    一. NAT(网络地址转换) 1. 作用:通过将内部网络的私有IP地址翻译成全球唯一的公网IP地址,使内部网络可以连接到互联网等外部网络上. 2. 优点: 节省公有合法IP地址 处理地址重叠 增强灵活 ...

  3. fiddler过滤指定的请求

    需要过滤的请求如图: 设置过滤: 正则表达式(REGEX:\.(js|css|google|favicon\?.*)+)

  4. C#调用SQL中存储过程并用DataGridView显示执行结果

    //连接数据库 SqlConnection con = new SqlConnection("server=服务器名称;database=数据库名称;user id=登录名;pwd=登录密码 ...

  5. ojdbc15-10.2.0.4.0.jar maven 引用报错 Dependency 'com.oracle:ojdbc15:10.2.0.4.0' not found

    ojdbc15-10.2.0.4.0.jar maven 引用报错 问题现象 在 Maven 工程中引用 ojdbc15-10.2.0.4.0.jar 报错,报错信息:Dependency 'com. ...

  6. azure sql database CPU troubleshooting

    描述 最新我们一个稳定运行快一年的项目突然出现CPU方面的性能问题,该项目使用的azure sql database  P2 500DTU,运维同事监控到CPU使用非常高,客户反馈系统运行也比较卡.看 ...

  7. linux常用命令(20)用SecureCRT来上传和下载文件

    用SSH管理linux服务器时经常需要远程与本地之间交互文件.而直接用SecureCRT自带的上传下载功能无疑是最方便的,SecureCRT下的文件传输协议有ASCII.Xmodem.Zmodem.  ...

  8. charles获取抓包数据

    charles获取抓包数据 第一步:确保手机和电脑处于同一个局域网之下 第二步:进入 charles 的代理设定选项(主导航栏Proxy-----Proxy Setting......)中,允许代理, ...

  9. Spark内核源码解析

    1.spark内核架构常用术语 Application:基于spark程序,包含一个driver program(客户端程序)和多个executeor(线程) Driver Progrom:代表着sp ...

  10. 从 SPIR-V 到 ISPC:将 GPU 计算转化为 CPU 计算

    游戏行业越来越多地趋向于将计算工作转移到图形处理单元 (GPU) 中,导致引擎和/或工作室需要开发大量 GPU 计算着色器来处理不同的计算任务.但有时候在 CPU 上运行这些计算着色器非常方便,不必重 ...