一种执行智能合约的方法、区块链节点、存储介质转让专利

申请号 : CN202010901427.4

文献号 : CN111770116B

文献日 :

基本信息:

PDF:

法律信息:

相似专利:

发明人 : 闫莺魏长征郭学鹏

申请人 : 支付宝(杭州)信息技术有限公司

摘要 :

本说明书提供一种执行智能合约的方法、区块链节点、存储介质。一种执行智能合约的方法实施例包括:区块链节点接收创建智能合约的请求,所述请求中包括所述智能合约的字节码;所述区块链节点完成所述智能合约的部署后,开始将所述智能合约的字节码通过全局编译方式编译为第一机器码并存储;所述区块链节点执行所述部署的智能合约时,如果本地存储有所述智能合约的第一机器码,则执行所述第一机器码。通过本说明书的实施例,在全局编译尚未完成的情况下,对所述智能合约的字节码进行局部编译并执行,从而可以在全局编译的同时保证区块链业务请求的正常处理。

权利要求 :

1.一种执行智能合约的方法,包括:

区块链节点接收创建智能合约的请求,所述请求中包括所述智能合约的字节码;

所述区块链节点完成所述智能合约的部署后,开始将所述智能合约的字节码通过全局编译方式编译为第一机器码并存储;

所述区块链节点执行部署的智能合约时,如果本地没有存储所述智能合约的第一机器码,则对所述智能合约的字节码通过局部编译方式编译得到第二机器码并存储,执行所述第二机器码。

2.如权利要求1所述的方法,所述区块链节点完成所述智能合约的部署后,开始将所述智能合约的字节码通过全局编译方式编译为第一机器码,具体包括:所述区块链节点完成创建所述智能合约后开始对所述智能合约的字节码进行全局编译;或,区块链节点完成创建所述智能合约后,利用相对空闲的时间段对所述智能合约的字节码进行全局编译。

3.如权利要求1所述的方法,所述将所述智能合约的字节码通过全局编译方式编译为第一机器码,包括:对所述智能合约的字节码进行全局编译的过程中进行优化编译得到第一机器码。

4.如权利要求1所述的方法,所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第一机器码,对所述智能合约的字节码进行局部编译,具体包括:所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第一机器码,所述区块链节点还查询当前对所述智能合约的字节码的全局编译情况,如果正处于全局编译中,则对所述智能合约的字节码进行局部编译;

或,

所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第一机器码,所述区块链节点还查询当前对所述智能合约的字节码的全局编译情况,如果尚未开始全局编译,则启动全局编译,并对所述智能合约的字节码进行局部编译。

5.如权利要求1或3所述的方法,所述区块链节点对所述智能合约的字节码进行局部编译,包括:所述区块链节点对所述智能合约中对应所调用函数的字节码进行局部编译。

6.如权利要求1或4所述的方法,所述对所述智能合约的字节码进行局部编译得到第二机器码并存储,包括:对所述智能合约的字节码进行翻译和/或执行的过程中识别热点的第二机器码,对热点的第二机器码进行存储以供后续调用;

和/或,

对所述智能合约的字节码进行翻译和/或执行的过程中进行优化编译得到第二机器码并存储。

7.如权利要求1所述的方法,所述区块链节点执行所述部署的智能合约时,如果本地存储有所述智能合约的第一机器码,则执行所述第一机器码。

8.如权利要求7所述的方法,所述区块链节点执行第一机器码,包括:所述区块链节点执行存储的所述智能合约中对应所调用函数的第一机器码。

9.如权利要求1、3、7、8中任一项所述的方法,所述存储为缓存。

10.如权利要求1-4、7、8中任一项所述的方法,所述全局编译方式包括AoT或JIT,所述局部编译方式包括JIT。

11.一种执行智能合约的方法,包括:

区块链节点完成所述智能合约的部署后,开始将所述智能合约的字节码通过全局编译方式编译为第一机器码并存储;

所述区块链节点执行部署的智能合约时,如果本地没有存储所述智能合约的第一机器码,则对所述智能合约的字节码通过局部编译方式编译得到第二机器码并存储,执行所述第二机器码。

12.如权利要求11所述的方法,所述区块链节点完成所述智能合约的部署后,开始将所述智能合约的字节码通过全局编译方式编译为第一机器码,具体包括:所述区块链节点完成创建所述智能合约后开始对所述智能合约的字节码进行全局编译;或,区块链节点完成创建所述智能合约后,利用相对空闲的时间段对所述智能合约的字节码进行全局编译。

13.如权利要求11所述的方法,所述将所述智能合约的字节码通过全局编译方式编译为第一机器码,包括:对所述智能合约的字节码进行全局编译的过程中进行优化编译得到第一机器码。

14.如权利要求11所述的方法,所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第一机器码,对所述智能合约的字节码进行局部编译,具体包括:所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第一机器码,所述区块链节点还查询当前对所述智能合约的字节码的全局编译情况,如果正处于全局编译中,则对所述智能合约的字节码进行局部编译;

或,

所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第一机器码,所述区块链节点还查询当前对所述智能合约的字节码的全局编译情况,如果尚未开始全局编译,则启动全局编译,并对所述智能合约的字节码进行局部编译。

15.如权利要求11或13所述的方法,所述区块链节点对所述智能合约的字节码进行局部编译,包括:所述区块链节点对所述智能合约中对应所调用函数的字节码进行局部编译。

16.如权利要求11或14所述的方法,所述对所述智能合约的字节码进行局部编译得到第二机器码并存储,包括:对所述智能合约的字节码进行翻译和/或执行的过程中识别热点的第二机器码,对热点的第二机器码进行存储以供后续调用;

和/或,

对所述智能合约的字节码进行翻译和/或执行的过程中进行优化编译得到第二机器码并存储。

17.如权利要求11所述的方法,所述区块链节点执行所述部署的智能合约时,如果本地存储有所述智能合约的第一机器码,则执行所述第一机器码。

18.如权利要求17所述的方法,所述区块链节点执行第一机器码,包括:所述区块链节点执行存储的所述智能合约中对应所调用函数的第一机器码。

19.如权利要求11、13、17、18中任一项所述的方法,所述存储为缓存。

20.如权利要求11-14、17、18中任一项所述的方法,所述全局编译方式包括AoT或JIT,所述局部编译方式包括JIT。

21.一种执行智能合约的区块链节点,包括:

处理器,

存储器,存储有程序,其中在所述处理器执行所述程序时,执行上述权利要求1-10或

11-20中任一项所述的方法。

22.一种存储介质,用于存储程序,其中所述程序在被处理器执行时进行上述权利要求

1-10或11-20中任一项的操作。

说明书 :

一种执行智能合约的方法、区块链节点、存储介质

技术领域

[0001] 本说明书实施例属于区块链技术领域,尤其涉及一种执行智能合约的方法、区块链节点、存储介质。

背景技术

[0002] 区块链(Blockchain)是分布式数据存储、点对点传输、共识机制、加密算法等计算机技术的新型应用模式。区块链2.0时代中出现了智能合约,将区块链的应用范围提升到了一个新高度。有了智能合约,区块链能做不再是单一的转账交易,而是还可以调用一段代码,而这段代码可以由用户自定义。

发明内容

[0003] 本说明书在于提供一种执行智能合约的方法、区块链节点、存储介质,通过以下方式实现:
[0004] 一种执行智能合约的方法,包括:
[0005] 区块链节点接收创建智能合约的请求,所述请求中包括所述智能合约的字节码;
[0006] 所述区块链节点完成所述智能合约的部署后,开始将所述智能合约的字节码通过全局编译方式编译为第一机器码并存储;
[0007] 所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第一机器码,则对所述智能合约的字节码通过局部编译方式编译得到第二机器码并存储,执行所述第二机器码。
[0008] 一种执行智能合约的方法,包括:
[0009] 区块链节点完成所述智能合约的部署后,开始将所述智能合约的字节码通过全局编译方式编译为第一机器码并存储;
[0010] 所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第一机器码,则对所述智能合约的字节码通过局部编译方式编译得到第二机器码并存储,执行所述第二机器码。
[0011] 一种执行智能合约的区块链节点,执行上述任一项所述的方法。
[0012] 一种执行智能合约的区块链节点,包括:
[0013] 处理器,
[0014] 存储器,存储有程序,其中在所述处理器执行所述程序时,执行上述任一项所述的方法。
[0015] 一种存储介质,用于存储程序,其中所述程序在被执行时进行上述任一项的操作。
[0016] 通过本说明书的实施例,在区块链上部署智能合约的字节码后,开始对智能合约的机器码进行全局编译;如果接收到调用所述智能合约的请求,在本地没有存储所述智能合约的机器码的情况下,即全局编译尚未完成的情况下,对所述智能合约的字节码进行局部编译执行。从而可以在全局编译的同时保证区块链业务请求的正常处理。
[0017] 一种执行智能合约的方法,包括:
[0018] 区块链节点接收创建智能合约的请求,所述请求中包括所述智能合约的字节码;
[0019] 所述区块链节点完成所述智能合约的部署后,开始将所述智能合约的字节码通过全局编译方式编译为第一机器码并存储;
[0020] 所述区块链节点执行所述部署的智能合约时,如果本地存储有所述智能合约的第一机器码,则执行所述第一机器码。
[0021] 一种执行智能合约的方法,包括:
[0022] 区块链节点部署所述智能合约的字节码后,开始将所述智能合约的字节码通过全局编译为第一机器码并存储;
[0023] 所述区块链节点执行所述部署的智能合约时,如果本地存储有所述智能合约的第一机器码,则执行所述机器码。
[0024] 一种执行智能合约的区块链节点,执行上述任一项所述的方法。
[0025] 一种执行智能合约的区块链节点,包括:
[0026] 处理器,
[0027] 存储器,存储有程序,其中在所述处理器执行所述程序时,执行上述任一项所述的方法。
[0028] 一种存储介质,用于存储程序,其中所述程序在被执行时进行上述任一项的操作。
[0029] 通过本说明书的实施例,在区块链上部署智能合约的字节码后,开始对智能合约的机器码进行全局编译;如果接收到调用所述智能合约的请求,在本地存储有对所述智能合约进行全局编译得到的第一机器码的情况下,即全局编译完成的情况下,执行所述第一机器码,从而可以快速处理区块链的业务请求。
[0030] 一种执行智能合约的方法,包括:
[0031] 区块链节点接收创建智能合约的请求,所述请求中包括所述智能合约的字节码;
[0032] 所述区块链节点完成所述智能合约的部署后,开始将所述智能合约的字节码通过全局编译方式编译为第一机器码并存储;
[0033] 所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第一机器码,则对所述智能合约的字节码进行解释执行。
[0034] 一种执行智能合约的方法,包括:
[0035] 区块链节点完成所述智能合约的部署后,开始将所述智能合约的字节码通过全局编译方式编译为第一机器码并存储;
[0036] 所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第一机器码,则对所述智能合约的字节码进行解释执行。
[0037] 一种执行智能合约的区块链节点,执行上述任一项所述的方法。
[0038] 一种执行智能合约的区块链节点,包括:
[0039] 处理器,
[0040] 存储器,存储有程序,其中在所述处理器执行所述程序时,执行上述任一项所述的方法。
[0041] 一种存储介质,用于存储程序,其中所述程序在被执行时进行上述任一项的操作。
[0042] 通过本说明书的实施例,在区块链上部署智能合约的字节码后,开始对智能合约的机器码进行全局编译;如果接收到调用所述智能合约的请求,在本地没有存储针对所述智能合约进行全局编译得到的第一机器码的情况下,即全局编译尚未完成的情况下,对所述智能合约的字节码进行编译执行。从而可以在全局编译的同时保证区块链业务请求的正常处理。
[0043] 一种执行智能合约的方法,包括:
[0044] 区块链节点接收创建智能合约的请求,所述请求中包括所述智能合约的字节码;
[0045] 所述区块链节点完成所述智能合约的部署后,开始将所述智能合约的字节码通过局部编译方式编译为第二机器码并存储;
[0046] 所述区块链节点执行所述部署的智能合约时,如果本地存储有所述智能合约的第二机器码,则执行所述第二机器码。
[0047] 一种执行智能合约的方法,包括:
[0048] 区块链节点部署所述智能合约的字节码后,开始将所述智能合约的字节码通过局部编译方式编译为第二机器码并存储;
[0049] 所述区块链节点执行所述部署的智能合约时,如果本地存储有所述智能合约的第二机器码,则执行所述机器码。
[0050] 一种执行智能合约的区块链节点,执行上述任一项所述的方法。
[0051] 一种执行智能合约的区块链节点,包括:
[0052] 处理器,
[0053] 存储器,存储有程序,其中在所述处理器执行所述程序时,执行上述任一项所述的方法。
[0054] 一种存储介质,用于存储程序,其中所述程序在被执行时进行上述任一项的操作。
[0055] 通过本说明书的实施例,在区块链上部署智能合约的字节码后,开始对智能合约的机器码进行局部编译;如果接收到调用所述智能合约的请求,在本地存储有所述智能合约的第二机器码的情况下,即局部编译完成的情况下,执行所述第二机器码,从而可以快速处理区块链的业务请求。
[0056] 一种执行智能合约的方法,包括:
[0057] 区块链节点接收创建智能合约的请求,所述请求中包括所述智能合约的字节码;
[0058] 所述区块链节点完成所述智能合约的部署后,开始将所述智能合约的字节码通过局部编译方式编译为第二机器码并存储;
[0059] 所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第二机器码,则对所述智能合约的字节码进行解释执行。
[0060] 一种执行智能合约的方法,包括:
[0061] 区块链节点完成所述智能合约的部署后,开始将所述智能合约的字节码通过局部编译方式编译为第二机器码并存储;
[0062] 所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第二机器码,则对所述智能合约的字节码进行解释执行。
[0063] 一种执行智能合约的区块链节点,执行上述任一项所述的方法。
[0064] 一种执行智能合约的区块链节点,包括:
[0065] 处理器,
[0066] 存储器,存储有程序,其中在所述处理器执行所述程序时,执行上述任一项所述的方法。
[0067] 一种存储介质,用于存储程序,其中所述程序在被执行时进行上述任一项的操作。
[0068] 通过本说明书的实施例,在区块链上部署智能合约的字节码后,开始对智能合约的机器码进行全局部译;如果接收到调用所述智能合约的请求,在本地没有存储针对所述智能合约进行局部编译得到的第二机器码的情况下,即局部编译尚未完成的情况下,对所述智能合约的字节码进行编译执行。从而可以在局部编译的同时保证区块链业务请求的正常处理。

附图说明

[0069] 为了更清楚地说明本说明书实施例的技术方案,下面将对实施例描述中所需要使用的附图作简单地介绍,显而易见地,下面描述中的附图仅仅是本说明书中记载的一些实施例,对于本领域普通技术人员来讲,在不付出创造性劳动性的前提下,还可以根据这些附图获得其他的附图。
[0070] 图1为一个实施例中编译执行和解释执行的原理示意图;
[0071] 图2为一个实施例中解释执行和JIT的原理示意图;
[0072] 图3为一个实施例的创建智能合约的图示过程;
[0073] 图4为一个实施例的调用智能合约的图示过程;
[0074] 图5为一个实施例中创建智能合约和调用智能合约的示意图;
[0075] 图6为一个实施例中的执行智能合约的流程图;
[0076] 图7为一个实施例中的区块链节点的模块结构图;
[0077] 图8为一个实施例中的创建智能合约和调用智能合约的示意图;
[0078] 图9为一个实施例中的创建智能合约和调用智能合约过程中包含虚拟机执行过程的示意图;
[0079] 图10为一个实施例中的执行智能合约的流程图;
[0080] 图11为一个实施例中的执行智能合约的流程图;
[0081] 图12为一个实施例中的执行智能合约的流程图;
[0082] 图13为一个实施例中的执行智能合约的流程图。

具体实施方式

[0083] 为了使本技术领域的人员更好地理解本说明书中的技术方案,下面将结合本说明书实施例中的附图,对本说明书实施例中的技术方案进行清楚、完整地描述,显然,所描述的实施例仅仅是本说明书一部分实施例,而不是全部的实施例。基于本说明书中的实施例,本领域普通技术人员在没有作出创造性劳动前提下所获得的所有其他实施例,都应当属于本说明书保护的范围。
[0084] 区块链1.0时代通常是指在2009年到2014年之间,以比特币为代表的区块链应用发展阶段,它们主要致力于解决货币和支付手段的去中心化问题。从2014年开始,开发者们越来越注重于解决比特币在技术和扩展性方面的不足。2013年底,Vitalik Buterin发布了以太坊白皮书《以太坊:下一代智能合约和去中心化应用平台》,将智能合约引入区块链,打开了区块链在货币领域以外的应用,从而开启了区块链2.0时代。
[0085] 智能合约是一种基于规定触发规则的,可自动执行的计算机合约,也可以看作是传统合约的数字版本。智能合约这一概念最早由跨领域法律学者、密码学研究工作者尼克·萨博(Nick Szabo)在1994年提出。这项技术曾一度因为缺乏可编程数字系统和相关技术而没有被用于实际产业中,直到区块链技术和以太坊的出现为其提供了可靠的执行环境。由于区块链技术采用的块链式账本,产生的数据不可篡改或者删除,且整个账本将不断新增账本数据,从而保证了历史数据的可追溯;同时,去中心化的运行机制避免了中心化因素的影响。基于区块链技术的智能合约不仅可以发挥智能合约在成本、效率方面的优势,而且可以避免恶意行为对合约正常执行的干扰。将智能合约以数字化的形式写入区块链中,由区块链技术的特性保障存储、读取、执行整个过程透明可跟踪、不可篡改。
[0086] 智能合约本质上是一段可由计算机执行的程序。智能合约与现在广泛使用的计算机程序一样,可以通过高级语言(例如C语言、C++语言等)编写而成。由高级语言编写好的智能合约的程序代码,一般可以通过“编译器”转换为计算机的CPU可以识别和运行的“机器码”,进而可以由CPU执行这样的机器码(或者称为“微处理器指令”)。这种方式一般称为“编译执行”。
[0087] 编译执行一般不具有跨平台的可扩展性。由于存在不同厂商、不同品牌和不同代的CPU,而这些不同的CPU支持的指令集很多情况下是不同的,如x86指令集,ARM指令集等,且同一厂商同一品牌但不同代的CPU(如不同代的Intel CPU)支持的指令集也不完全相同,因此,用同样的高级语言编写的同样的程序代码,在不同CPU上被编译器转换出来的机器码可能不同。具体的,编译器在转换高级语言编写的程序代码到机器码的过程中,会结合具体的CPU指令集的特点(如向量指令集等)进行优化以提升程序执行的速度,而此类优化往往与具体的CPU硬件相关。这样,同样的机器码,一个在x86上可以运行,但另一个在ARM上就可能无法运行;甚至同样是x86平台,随着时间的推移,指令集也不断丰富和扩展,这就导致不同代的x86平台运行的机器码也有不同。而且,由于执行机器码需要由操作系统内核对CPU进行调度,因此即使是同样的硬件,在不同操作系统下支持运行的机器码也可能不同。
[0088] 不同于编译执行,还存在一种“解释执行”的程序运行方式。比如Java语言,将Java源代码通过Java的编译器编译成标准的字节码(bytecode),这里编译器不针对任何实际的硬件处理器的指令集,而是定义了一套抽象的标准指令集。编译成的标准字节码一般无法在硬件CPU上直接运行,因此引入了一个虚拟机,即JVM,JVM运行在特定的硬件处理器上,用以解释和执行编译后的标准字节码。
[0089] JVM是Java Virtual Machine(Java虚拟机)的缩写,是一种虚构出来的计算机,往往通过在实际的计算机上仿真模拟各种计算机功能来实现。JVM屏蔽了与具体的硬件平台、操作系统等相关的信息,使Java程序只需要是生成的可在Java虚拟机上运行的标准字节码,就可以在多种平台上不加修改地运行。
[0090] Java语言的一个非常重要的特点就是与平台的无关性。而使用Java虚拟机是实现这一特点的关键。一般的高级语言如果要在不同的平台上运行,至少需要编译成不同的目标代码。而引入Java语言虚拟机后,Java语言在不同平台上运行时不需要重新编译。Java语言使用Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。Java虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行。这就是Java的能够“一次编译,到处运行”的原因。
[0091] JVM运行在特定的硬件处理器上,负责针对所运行的特定处理器而进行字节码的解释和执行,并向上屏蔽这些底层的差异,呈现给开发者以标准的开发规范。JVM在执行字节码时,实际上最终还是把字节码解释成具体平台上的机器指令执行。具体的,JVM接收到输入的字节码后,逐句解释其中的每一条指令,并翻译成适合当前机器的机器码来运行,这些过程例如由称为Interpreter的解释器进行解释和执行。这样一来,编写Java程序的开发者不需要考虑编写后的程序代码将运行在哪种硬件平台上。JVM本身的开发是由Java组织的专业开发人员完成,以将JVM适配到不同的处理器架构上。迄今为止,主流的处理器架构只有有限的几种,如X86, ARM, RISC-V,MIPS。专业的开发人员将JVM分别移植到支持这几种特定硬件的平台后,Java程序理论上就可以在所有的机器上运行了。JVM的移植工作通常由Java开发组织专业的人员提供的,这就极大减轻了Java应用开发者的负担。
[0092] 解释执行带来了跨平台可移植性,但由于bytecode的执行经历了JVM中间翻译的过程,因此执行效率不如上述编译执行效率高,这种效率的差异有时甚至可达几十倍。
[0093] 图1示出了编译执行和解释执行的共同点和不同点。不论是解释执行还是编译执行,也不论是物理机还是虚拟机,对于应用程序,机器都不可能如人那样阅读、理解,然后就获得了执行能力。大部分的程序代码到物理机的目标代码或虚拟机能执行的指令集之前,都需要经过图1中的各个步骤。图1中从顶部到左边的那条分支就是传统编译原理中程序代码到目标机器代码的生成过程,从顶部到右边的那条分支是解释执行的过程。如今,基于物理机、Java虚拟机,或者非Java的其他高级语言虚拟机(High-Level Language Virtual Machine, HLLVM)的语言,大多都会遵循这种基于现代经典编译原理的思路,在执行前先对程序源码进行词法分析和语法分析处理,把源码转化为抽象语法树(Abstract Syntax Tree,AST)。对于一门具体语言的实现来说,词法分析、语法分析以至后面的优化器和目标代码生成器都可以选择独立于执行引擎,形成一个完整意义的编译器去实现,这类代表是C/C++语言。也可以选择把其中一部分步骤(如生成抽象语法树之前的步骤)实现为一个半独立的编译器,这类代表是Java语言。又或者把这些步骤和执行引擎全部集中封装在一个封闭的黑匣子之中,如大多数的JavaScript执行器。
[0094]  为了尽可能的兼顾跨平台可移植性和高性能,即时编译器(Just-In-Time Compiler,JIT)的概念被提出。JIT的核心思想是“如何高效避免解释指令的重复工作”。计算机程序中存在大量重复执行的代码,比如某些计算“函数”在一个程序执行过程中可能被循环调用了很多次。如果是解释执行,则循环过程的每次执行都要对这个函数进行字节码到机器码的翻译。然而实际情况是,这个函数在几十次的翻译中产生的机器码都是完全一样的。很自然的,在第一次翻译后,将翻译好的函数的机器码缓存下来,后续再次执行的过程中,不需要再次翻译,而是直接使用缓存好的代码,这样可以提高执行效率。
[0095] 相反的,有些函数在程序运行周期过程中只执行了一次(比如启动初始化),那么这类函数就不需要缓存,直接解释执行一次即可。因此JIT技术中一个核心的模块就是“热点分析”,即通过程序执行过程中分析出哪些代码执行了多次,从而对其翻译后的机器码进行缓存。对于执行次数较少的操作,不需要进行缓存。这样可以在执行效率和内存开销上达到最佳平衡。
[0096] 此外,JIT技术中的另一个核心的模块是编译优化。直接翻译的机器码,没有结合上下文进行优化,仅仅是将高频的机器码缓存下来,性能提升有限。如果要获得更好的性能,可以对编译器进行进一步的优化。编译优化的方式,一般需要相对更多的时间来实现。
[0097] JIT的工作原理例如图2中所示。Java源代码经过Java编译器编译后生成一段Java字节码,经过热点分析后被分发到两个执行路径上(JIT Compiler和Interpreter)。被判断为热点(高频执行)的代码经JIT compiler中进行编译得到机器码,缓存并执行,一般是由CPU在操作系统(Operating System,OS)的控制下执行。低频的进入解释器(Interpreter),翻译成机器码后由CPU在OS的控制下执行。
[0098] 由于程序代码本身的前后关联性,编译过程往往存在较大的优化空间。优化后的机器码,执行效率会远高于直接翻译的机器码。如果要获得更好的性能,编译器的优化是必须的。JIT compiler编译的过程可能比较耗时。特别是JIT Compiler在第一次编译字节码的过程可能耗时很长,甚至不如解释执行。那么,对于某些java程序,如果热点不是很突出,即整体的执行频度都不是很高,而整体执行流程又很长的,JIT就很难发挥出编译执行的优势。
[0099] 此外,还有一种想法被提出,就是AoT (Ahead of Time)。AoT相当于一种预编译执行的方法。在程序运行前针对目标执行环境对字节码进行一次编译,得到机器码,再将机器码部署到目标机器上执行,例如图8所示的过程。AoT的运行效率可以达到编译执行的效果,但在AoT时需要明确知道目标系统的硬件、指令集架构和系统等,确保编译后代码可以运行。而且,一般来说同样功能的指令,用机器码表达所需的语句量会大于字节码,更大于高级语言编写的代码,这样,同样内容的程序,很可能机器码的大小>字节码的大小>高级语言代码的大小。在明确知道目标系统的硬件、指令集架构和系统等情形的前提下,可以通过AoT将字节码编译为机器码。同时,不同类别的目标系统的机器码是不同的,因此,为了各种目标系统上都可以有对应的正确执行的机器码,可能需要将不同版本的机器码都提供。这样,机器码的总大小一般会大于字节码或是高级语言代码。
[0100] 例如,Android在5.0版本以前采用Dalvik虚拟机,而在5.0版本以后采用了ART虚拟机。Dalvik是采用JIT编译器去解释字节码,而ART则是AoT机制。ART方式在应用安装时就预编译字节码(Android App的安装过程实际上是安装程序的字节码)到机器码。在移除解释代码这一过程后,Android上的应用程序执行更有效率,启动更快。
[0101] 区块链中作为一个去中心化的分布式系统,需要保持分布式一致性。具体的,分布式系统中的一组节点,每个节点都内置了状态机。每个状态机需要从相同的初始状态起,按相同的顺序执行相同的指令,保持每一次状态的改变都相同,从而保证最终达到一致的状态。而参与到同一区块链网络的各个节点设备很难都是同样的硬件配置和软件环境。因此,在区块链2.0中的代表以太坊中,为了保证各个节点上执行智能合约的过程和结果是相同的,采用了类似于JVM的虚拟机——以太坊虚拟机(Ethereum Virtual Machine,EVM)。通过EVM可以屏蔽各个节点硬件配置和软件环境的差异性。这样,开发者可以开发一套智能合约的代码,并将该智能合约的代码在开发者本地编译后将编译得到的字节码(bytecode)上传到区块链。各个节点以相同的初始状态通过相同的EVM解释执行相同的字节码后,能够得到相同的最终结果和相同的中间结果,并可以屏蔽不同节点底层的硬件和环境差异。这样,去中心化的区块链技术的出现,才使得早在1994年就提出的智能合约得以实现,并且,由于去中心化的实现必然面临不同执行机器的硬件和运行环境差异,进一步以解释执行的方式对智能合约处理,以保证在去中心的多种不同硬件和运行环境的机器上能够得到相同的执行结果。
[0102] EVM是一个图灵完备的虚拟机,这意味着可以通过它实现各种复杂的逻辑,这也是以太坊作为区块链2.0的代表相对于区块链1.0的最大改进之一。用户在以太坊中发布和调用智能合约可以在EVM上运行。如前所述,EVM直接运行的是字节码,部署在区块链上的智能合约可以是字节码的形式。
[0103] 例如图3所示,Bob将一个包含创建智能合约信息的交易发送到以太坊网络后,节点1的EVM可以执行这个交易并生成对应的合约实例。交易的data字段保存的可以是字节码,交易的to字段可以为一个空的地址。节点间通过共识机制达成一致后,这个合约成功创建,后续用户可以调用这个合约。
[0104] 合约创建后,区块链上出现一个与该智能合约对应的合约账户,并拥有一个特定的地址,合约代码和账户存储可以保存在该合约账户中。智能合约的行为由合约代码控制,而智能合约的账户存储则保存了合约的状态。换句话说,智能合约使得区块链上产生包含合约代码和账户存储的虚拟账户。
[0105] 前述提到,包含创建智能合约的交易的data字段保存的可以是该智能合约的字节码。字节码由一连串的字节组成,每一字节可以表明一个操作。基于开发效率、可读性等多方面考虑,开发者可以不直接书写字节码,而是选择一门高级语言编写智能合约代码。高级语言编写的智能合约代码,经过编译器编译,生成字节码,进而该字节码可以部署到区块链上。以太坊支持的高级语言很多,如Solidity、Serpent、LLL语言等。
[0106] 以Solidity语言为例,用其编写的合约与面向对象编程语言中的类(Class)很相似,在一个合约中可以声明多种成员,包括状态变量、函数、函数修改器、事件等。状态变量是永久存储在智能合约的账户存储中的值,用于保存合约的状态。
[0107] 如下是以Solidity语言编写的一个简单的智能合约的代码示例1:
[0108] Contract Example{
[0109]        int balance;
[0110]        function C( ){
[0111]               balance + = 1;
[0112] }
[0113] function getblance( ) returns(int){
[0114] return balance ;
[0115] }
[0116] }
[0117] 一般的,这个合约部署在区块链后,“balance”这个状态变量可以是在合约中新定义的一种资产类型。function C()这个函数可以定义balance的变化操作,function getbalance() returns(int) 这个函数可以定义取当前balance的值并返回的操作。
[0118] 此外,如图4所示,仍以以太坊为例,Bob将一个包含调用智能合约信息的交易发送到以太坊网络后,节点1的EVM可以执行这个交易并生成对应的合约实例。图中2中交易的from字段是发起调用智能合约的账户的地址,to字段中的“0x69a70d2…”代表了被调用的智能合约的地址,value字段在以太坊中是以太币的值,交易的data字段保存的调用智能合约的方法和参数。调用智能合约后,balance的值可能改变。后续,某个客户端可以通过某一区块链节点查看balance的当前值。
[0119] 智能合约可以以规定的方式在区块链网络中每个节点独立的执行,所有执行记录和数据都保存在区块链上,所以当这样的交易完成后,区块链上就保存了无法篡改、不会丢失的交易凭证。
[0120] 创建智能合约和调用智能合约的示意图如图5所示。以太坊中要创建一个智能合约,需要经过编写智能合约、变成字节码、部署到区块链等过程。以太坊中调用智能合约,是发起一笔指向智能合约地址的交易(可以通过交易中的to字段指向智能合约的地址),智能合约代码分布式的运行在以太坊网络中每个节点的虚拟机中。
[0121] 创建智能合约的交易发送到区块链上,经过共识之后,区块链各节点可以执行这个交易。具体的,可以是由区块链节点的EVM/WASM来执行这个交易。如前所述,这时区块链上出现一个与该智能合约对应的合约账户(包括例如帐户的标识Identity,合约的hash值Codehash,合约存储的根StorageRoot),并拥有一个特定的地址,合约代码和账户存储可以保存在该合约账户的存储中,如图9所示。智能合约的行为由合约代码控制,而智能合约的账户存储则保存了合约的状态。换句话说,智能合约使得区块链上产生包含合约代码和账户存储的虚拟账户。对于合约部署交易或者合约更新交易,将产生或变更Codehash的值。后续,区块链节点可以接收调用部署的智能合约的交易请求,该交易请求可以包括调用的合约的地址、调用的合约中的函数和输入的参数。一般的,该交易请求经过共识后,区块链各个节点可以各自独立执行指定调用的智能合约。具体的,如图9所示,节点可以根据合约的地址将合约的字节码(Bytecode)从存储载入虚拟机(EVM/WASM)中;进而,由解释器(Interpreter)解释执行,例如包括对调用的合约的字节码进行解析,得到操作码(OPcode),并将这些OPcode存储虚拟机的Memory中,同时还得到调用的函数的地址;经过对执行合约所需要消耗的Gas进行计算且Gas足够后,跳转到Memory的对应地址取得所调用函数的OPcode并开始执行,将所调用到的函数的OPcode所操作的数据进行计算(Data Computation)、推入/推出栈(Stack)等的操作,从而完成数据计算。这个过程中,还可能需要一些合约的上下文(Context)信息,例如区块号、调用合约的发起者的信息之类,这些信息可以从Context中得到(Get操作)。最后,将产生的状态通过调用存储接口以存入存储(Storage)中。需要说明的是,合约创建的过程中,也可能产生对合约中某些函数的解释执行,例如初始化操作的函数,这时也会解析代码、产生跳转指令,存入Memory,在Stack中操作数据等。上述涉及的解释执行过程中,一般来说,对重复执行的函数并不缓存,即使多于多次执行的函数,虚拟机都需要重复进行解析、执行的过程。
[0122] 如同前面提到的JVM的跨平台可移植性的优点和有提升性能的需求,类似的,区块链中的EVM也可以采用JIT和AoT之类的技术来提升智能合约执行时的性能。例如,智能合约部署到区块链上之前,先进行AoT编译,将编译后得到的机器码上链,从而完成合约的部署。完成部署的合约,在区块链上可以具有一个特定的地址。这样,客户端发起的创建合约的交易中,可以包含合约的机器码。例如,可以由客户端在将高级语言编写的智能合约编译为字节码后,在客户端本地进行AoT编译,从而得到机器码。执行链上合约的过程(或称为调用智能合约的过程),例如可以是一个客户端(可以是不同于创建智能合约的客户端)直接调用经过AoT编译后的链上的机器码并执行。这里,调用合约的交易中,一般指向的地址(即to字段所指向的地址)可以是被调用的合约的地址。由于本例子中的AoT编译是在智能合约上链前完成的,因此可以简称为“链下AoT”。链下AoT编译过程可以进行大量代码优化,这样,链上执行合约的效率就可以大大提高。但缺点也很明显,即链下AoT时需要预先获得所部署的目标节点的处理器架构、运行环境等,否则上链的机器码后续很可能将无法在目标节点上执行。同时,为了适配各种不同的目标节点,可能需要AoT编译为多种不同的机器码。这样,经过AoT编译后的机器码大小将远大于原来的智能合约字节码的大小,增大了上链数据量,增加存储开销。
[0123] 本说明书提供一种执行智能合约的方法实施例,如图6所示,包括:
[0124] S601:区块链节点接收创建智能合约的请求,所述请求中包括所述智能合约的字节码。
[0125] 用户可以在用户本地用高级语言编写智能合约。编写好的智能合约可以经过适配高级语言的编译器编译,得到字节码。进而,可以通过客户端将编译得到的智能合约的字节码打包到交易中,发送至区块链网络。交易的格式例如为图3~图5中所示,其中,需要创建的智能合约的字节码可以存放于交易的data字段中。
[0126] 用户也可以是在第一区块链节点上直接用高级语言编写智能合约,则第一区块链节点还可以采用编译器对高级语言编写的智能合约进行编译,生成字节码。这样,在上链前的合约也是字节码。
[0127] S603:所述区块链节点完成所述智能合约的部署后,开始将所述智能合约的字节码通过全局编译方式编译为第一机器码并存储。
[0128] 以太坊及类似原理的公有链、联盟链或者私有链系统中,区块链节点可以针对一批交易发起共识。所述一批交易中,可以包括上述创建智能合约的交易。通过共识后,一般的,各共识节点本地都存有所述待创建的智能合约的字节码。各共识节点本地可以执行所述创建智能合约的交易,创建对应的合约账户;并按照相同的规则给所述合约账户创建一个地址,各共识节点针对同一合约创建的地址是相同的。这样,就完成了合约的部署。
[0129] 所述区块链节点完成创建所述智能合约后,即部署所述智能合约之后,可以开始将所述智能合约的字节码通过全局编译方式编译为第一机器码并存储。全局编译方式包括前述提到的AoT编译和JIT编译。这里的全局指的是针对智能合约的全部字节码的编译。这样,通过AoT或者JIT编译方式,可以将智能合约的字节码全部编译为第一机器码。这里通过全局编译方式得到的智能合约的机器码称为第一机器码。事实上,AoT一般是全局编译,而JIT大多时候是局部编译。但是,JIT也可以像AoT一样对全部的智能合约字节码进行编译。一般来说,全局编译所需的时间要长于局部编译。
[0130] 所述区块链节点完成创建所述智能合约后,可以立即开始对所述智能合约的字节码进行全局编译。这是因为,在部署智能合约之后,可能很快就有发起调用部署的智能合约的业务请求。此外,全局编译需要花费相对较多的系统资源和时间,在区块链节点的业务负荷较重时分配系统资源进行全局编译会影响业务的处理;因此,区块链节点也可以是利用相对空闲的时间段再对所述智能合约的字节码进行全局编译,从而降低或避免对业务处理的影响。
[0131] 区块链各节点针对相同的智能合约字节码在本地进行全局编译,各节点仅需针对自身的处理器架构、运行环境等进行调整,而不需要编译多个不同版本的第一机器码。这样,节点设备上存储的第一机器码的大小得以大大降低,从而可以降低存储开销。
[0132] 优选的,所述存储为缓存,通过缓存到内存,后续可以更快速的作出响应。具体的,所述内存可以是在虚拟机中开辟的一块缓存区域。当然,即使存储到磁盘,很多情形下也可以一定程度的提升响应速度。
[0133] 所述将所述智能合约的字节码通过全局编译方式编译为第一机器码,可以对所述智能合约的字节码进行全局编译的过程中进行优化编译而得到第一机器码。经过编译优化的机器码,执行效率一般会高于直接翻译得到的机器码。具体的,一方面,全局编译所采用的编译器可以带上执行编译的区块链节点的硬件和环境信息,从而使得编译得到的机器码具有硬件+环境的优化,具体可以包括机器代码生成里的优化,包括指令级的优化,寄存器分配和优化等等。另一方面,全局编译引擎可以结合程序代码的前后关联进行编译。全局编译引擎可以分析上下文信息,比如当前函数中执行的分支跳转语句,识别其中哪一句是跳转可能行最大的,从而将这个跳转可能性最大的调整到最前,从而可以在执行时更高概率的首先命中该分支的语句;编译器优化过程还可以通过数据流分析/活跃变量分析进行死代码消除,例如消除不会走到的分支,此外还可以包括对循环语句进行优化,公共字表达式替换等。
[0134] S605:所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第一机器码,则对所述智能合约的字节码进行局部编译方式编译得到第二机器码并缓存,执行所述第二机器码。
[0135] 完成智能合约的部署后,可以提供对该合约的调用。这样,客户端(可能不同于S601中发起创建合约交易的客户端)可以发起对该合约的调用。例如,客户端发起一个交易,其中的to字段中为前述部署的智能合约的地址,data字段可以包括所调用的合约的方法和输入的参数,从而实现对所述部署的智能合约的调用。一般的,包括该调用合约的交易在内的一批交易经过共识后,各共识节点各自分别执行交易。
[0136] 所述区块链节点执行所述部署的智能合约时,可以先查看本地是否存在该被调用的合约的第一机器码。如果本地没有存储所述智能合约的第一机器码,可以不必等待全局编译完成,而对所述部署的智能合约的字节码进行局部编译。如前所述,全局编译的过程相对更费时,局部编译相对更省时,而全局编译之后执行得到的机器码最省时。可以对所述智能合约的字节码进行局部编译的过程中识别热点代码,例如通过JIT引擎的代码计数器来统计执行次数,从而分析出哪些字节码是多次执行的,从而对其翻译后的第二机器码进行缓存。而对于执行次数较少的操作,可以不进行缓存。这样可以在执行效率和内存开销上达到最佳平衡。识别热点代码并缓存的方式,可以使得多次执行字节码的过程中,在除了首次需要翻译外,后续可以直接利用缓存的第二机器码,从而免去再次翻译字节码的过程,从而可以缩减时间。识别执行次数的粒度,可以是函数级别,还可以是代码块级别。一般来说,代码块可能是函数中的一部分,也可能是由若干函数构成。
[0137] 其次,可以在局部编译中进行进一步的优化,结合程序代码的前后关联进行编译,并将优化编译后的第二机器码缓存下来以供后续调用时使用。经过编译优化的机器码,执行效率一般会高于直接翻译得到的机器码。例如,JIT引擎可以带上执行编译的区块链节点的硬件和环境信息,从而使得编译得到的机器码具有硬件+环境的优化,具体可以包括机器代码生成里的优化,包括指令级的优化,寄存器分配和优化等等。再例如,JIT引擎可以分析上下文信息,比如当前函数中执行的分支跳转语句,识别其中哪一句是跳转可能行最大的,从而将这个跳转可能性最大的调整到最前,从而可以在执行时更高概率的首先命中该分支的语句;编译器优化过程还可以通过数据流分析/活跃变量分析进行死代码消除,例如消除不会走到的分支,此外还可以包括对循环语句进行优化,公共字表达式替换等。
[0138] AoT编译尚未完成的情况下,对所述智能合约的字节码进行JIT编译并执行,从而可以在AoT编译的同时保证区块链业务请求的正常处理。
[0139] 这里的JIT编译主要包括热点代码识别。识别热点代码并缓存的方式,可以使得AoT编译时间段内,多次执行字节码的过程中,在除了首次需要翻译外,由于将首次翻译得到的机器码进行了缓存,因此后续可以直接利用缓存的机器码,从而免去再次翻译字节码的过程,从而可以缩减时间。具体的,例如通过JIT引擎的代码计数器来统计执行次数,从而分析出哪些字节码是多次执行的,从而对其翻译后的机器码进行缓存。而对于执行次数较少的操作,可以不进行缓存。这样可以在执行效率和内存开销上达到最佳平衡。识别热点代码并缓存的方式,可以使得多次执行字节码的过程中,在除了首次需要翻译外,后续可以直接利用缓存的机器码,从而免去再次翻译字节码的过程,从而可以缩减时间。识别执行次数的粒度,可以是函数级别,还可以是代码块级别。一般来说,代码块可能是函数中的一部分,也可能是由若干函数构成。
[0140] 其次,可以在JIT编译中进行进一步的优化,结合程序代码的前后关联进行编译,并将优化编译后的机器码缓存下来以供后续调用时使用。经过编译优化的机器码,执行效率一般会高于直接翻译得到的机器码。一方面,JIT引擎可以带上执行编译的区块链节点的硬件和环境信息,从而使得编译得到的机器码具有硬件+环境的优化,具体可以包括机器代码生成里的优化,包括指令级的优化,寄存器分配和优化等等。另一方面,JIT引擎可以分析上下文信息,比如当前函数中执行的分支跳转语句,识别其中哪一句是跳转可能行最大的,从而将这个跳转可能性最大的调整到最前,从而可以在执行时更高概率的首先命中该分支的语句;编译器优化过程还可以通过数据流分析/活跃变量分析进行死代码消除,例如消除不会走到的分支,此外还可以包括对循环语句进行优化,公共字表达式替换等。
[0141] 为了及时对业务请求作出响应,即快速响应发起调用部署的智能合约的业务请求,区块链节点可以首先查询是否存在所述被调用的智能合约的第一机器码,如果有,则说明已经完成了全局编译,如果没有,则说明尚未开始或尚未完成全局编译。如果有第一机器码,如前所述,区块链节点执行所述部署的智能合约时,可以执行所述第一机器码,从而可以大幅提升执行智能合约的速度。如果没有第一机器码,则所述区块链节点还查询当前对所述智能合约字节码的全局编译情况,具体可能包括两种情况:
[0142] 情况一:区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第一机器码,所述区块链节点还查询当前对所述智能合约字节码的全局编译情况,如果正处于全局编译中,则对所述智能合约的字节码进行局部编译。
[0143] 如果本地没有存储所述智能合约的第一机器码,所述区块链节点可以查询当前对所述智能合约字节码的全局编译情况,查询结果可以是正处于全局编译中。对于一些调用所述智能合约的业务请求来说,得到快速的响应是首选,这也是各类区块链系统设法提升每秒交易处理数量(Transaction Per Second,TPS)的目标。对于被调用的智能合约正处于全局编译中的情况,为了快速响应,区块链节点可以不等待全局编译结束,而是对所述智能合约的字节码进行局部编译和执行。
[0144] 情况二:区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第一机器码,所述区块链节点还查询当前对所述智能合约字节码的全局编译情况,如果尚未开始全局编译,则启动全局编译,并对所述智能合约的字节码进行局部编译和执行。
[0145] 类似于情况一,对于被调用的智能合约尚未启动全局编译的情况,为了快速响应,区块链节点可以对所述智能合约的字节码进行局部编译和执行。并且,对于尚未启动全局编译的情况,区块链节点可以启动全局编译。
[0146] 区块链节点对所述智能合约的字节码进行局部编译,可以是采用JIT引擎对所述智能合约中热点的字节码进行翻译,并将翻译后的第二机器码存储(例如缓存)下来以供后续调用时使用。具体的,可以对所述智能合约的字节码进行翻译和/或执行的过程中识别热点代码,即分析出哪些第二机器码是多次执行的,从而对其翻译后的第二机器码进行缓存。而对于执行次数较少的操作,可以不进行缓存。这样可以在执行效率和内存开销上达到最佳平衡。如前所述,识别执行次数的粒度,可以是函数级别,还可以是代码块级别。一般来说,代码块可能是函数中的一部分,也可能是由若干函数构成。其次,可以在局部编译中进行进一步的优化,例如采用JIT引擎结合程序代码的前后关联进行编译,并将优化编译后的第二机器码缓存下来以供后续调用时使用。经过编译优化的机器码,执行效率一般会高于直接翻译得到的机器码。
[0147] 所述区块链节点对所述智能合约完成全局编译后,可以将所述编译后的第一机器码执行所述存储操作。这样,所述区块链节点执行所述部署的智能合约时,如果本地存在该被调用的合约的第一机器码,则说明本地已经完成对该智能合约字节码的AoT编译。进而,区块链节点可以直接执行所述合约中对应所调用的函数的第一机器码,并输入前述data字段指明的输入参数。
[0148] 在存储有智能合约的第一机器码的情况下,由于机器码本身即是CPU(在OS的控制下)可以直接执行的,因此,所述区块链节点可以大幅提升执行智能合约的速度。并且,所述智能合约的第一机器码缓存在内存中的情形,可以更进一步的提升智能合约的执行速度。当然,即使存储在磁盘中,也可以一定程度上提升执行速度。所述区块链节点执行所述第一机器码,具体可以是执行存储的所述合约中对应所调用函数的第一机器码。
[0149] 本说明书中的JIT编译和执行,除了适用EVM,还可以适用WASM(Web Assembly)虚拟机、JSVM(JavaScript Virtual Machine)等,在此不做限制。
[0150] 上述方法实施例的过程,可以一并结合图8作为参考示意。
[0151] 需要说明的是,上述S601中的区块链节点,可能不同于S603和S605中的区块链节点。这是因为,区块链作为分布式的系统,接收交易的节点和发起共识的节点以及执行交易的节点可以是不同的节点,当然也可以是相同的节点。
[0152] 以下介绍本说明书另一执行智能合约的方法实施例,包括:
[0153] 步骤A1:区块链节点部署所述智能合约的字节码后,开始将所述智能合约的字节码通过全局编译方式编译为第一机器码并存储。
[0154] 所述区块链节点完成所述智能合约的部署后,开始将所述智能合约的字节码通过全局编译方式编译为第一机器码,具体包括:
[0155] 所述区块链节点完成创建所述智能合约后开始对所述智能合约的字节码进行全局编译;或,
[0156] 区块链节点完成创建所述智能合约后,利用相对空闲的时间段对所述智能合约的字节码进行全局编译。
[0157] 所述将所述智能合约的字节码通过全局编译方式编译为第一机器码,可以包括:
[0158] 对所述智能合约的字节码进行全局编译的过程中进行优化编译得到第一机器码。
[0159] 步骤A2:所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第一机器码,则对所述智能合约的字节码进行JIT编译得到第二机器码并存储,执行所述第二机器码。
[0160] 所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第一机器码,对所述智能合约的字节码进行局部编译,具体包括:
[0161] 所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第一机器码,所述区块链节点还查询当前对所述智能合约字节码的全局编译情况,如果正处于全局编译中,则对所述智能合约的字节码进行局部编译;
[0162] 或,
[0163] 所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第一机器码,所述区块链节点还查询当前对所述智能合约字节码的全局编译情况,如果尚未开始全局编译,则启动全局编译,并对所述智能合约的字节码进行局部编译。
[0164] 所述区块链节点对所述智能合约的字节码进行局部编译,可以包括:
[0165] 所述区块链节点对所述合约中对应所调用函数的字节码进行局部编译。
[0166] 所述对所述智能合约的字节码进行局部编译得到第二机器码并存储,可以包括:
[0167] 对所述智能合约的字节码进行翻译和/或执行的过程中识别热点的第二机器码,对热点的第二机器码进行存储以供后续调用;
[0168] 和/或,
[0169] 对所述智能合约的字节码进行翻译和/或执行的过程中进行优化编译得到第二机器码并存储。
[0170] 所述区块链节点执行所述部署的智能合约时,如果本地存储有所述智能合约的第一机器码,则执行所述第一机器码。
[0171] 所述区块链节点执行第一机器码,可以包括:
[0172] 所述区块链节点执行存储的所述合约中对应所调用函数的第一机器码。
[0173] 上述存储的具体方式可以为缓存。通过缓存到内存,后续可以更快速的作出响应。当然,即使存储到磁盘,很多情形下也可以一定程度的提升响应速度。
[0174] 所述全局编译方式包括AoT或JIT,所述局部编译方式包括JIT。
[0175] 以下介绍本说明书一种执行智能合约的区块链节点实施例,如图7所示,包括:
[0176] 接收单元71,用于接收创建智能合约的请求,所述请求中包括所述智能合约的字节码;
[0177] 部署单元72,用于根据接收单元71接收到的创建智能合约的请求部署所述智能合约;
[0178] 编译单元73,用于所述部署单元72完成部署后,开始将所述智能合约的字节码通过全局编译方式编译为第一机器码;执行单元75执行所述部署的智能合约时,如果存储单元74没有存储所述智能合约的第一机器码,则对所述智能合约的字节码通过局部编译方式编译得到第二机器码;
[0179] 存储单元74,用于存储编译单元73编译的第一机器码或第二机器码;
[0180] 执行单元75,接收到调用所述部署的智能合约时,如果存储单元74没有存储所述智能合约的第一机器码,则执行所述存储单元74存储的第二机器码。
[0181] 所述部署单元72完成所述智能合约的部署后,编译单元73开始将所述智能合约的字节码通过全局编译方式编译为第一机器码,具体包括:
[0182] 所述部署单元72完成创建所述智能合约后,编译单元73开始对所述智能合约的字节码进行全局编译;或,
[0183] 部署单元72完成创建所述智能合约后,编译单元73利用相对空闲的时间段对所述智能合约的字节码进行全局编译。
[0184] 所述编译单元73将所述智能合约的字节码通过全局编译方式编译为第一机器码,包括:
[0185] 所述编译单元73对所述智能合约的字节码进行全局编译的过程中进行优化编译得到第一机器码。
[0186] 所述执行单元75执行所述部署的智能合约时,如果存储单元74没有存储所述智能合约的第一机器码,编译单元73对所述智能合约的字节码进行局部编译,具体包括:
[0187] 所述执行单元75执行所述部署的智能合约时,如果存储单元74没有存储所述智能合约的第一机器码,所述执行单元75还查询当前对所述智能合约字节码的全局编译情况,如果正处于全局编译中,则编译单元73对所述智能合约的字节码进行局部编译;
[0188] 或,
[0189] 所述执行单元75执行所述部署的智能合约时,如果存储单元74没有存储所述智能合约的第一机器码,所述执行单元75还查询当前对所述智能合约字节码的全局编译情况,如果尚未开始全局编译,则编译单元73启动全局编译,并对所述智能合约的字节码进行局部编译。
[0190] 所述编译单元73对所述智能合约的字节码进行局部编译得到第二机器码,包括:
[0191] 所述编译单元73对所述智能合约的字节码进行翻译和/或执行的过程中识别热点的第二机器码,所述操存储单元74对热点的第二机器码进行存储以供后续调用;
[0192] 和/或,
[0193] 所述编译单元73对所述智能合约的字节码进行翻译和/或执行的过程中进行优化编译得到第二机器码,所述存储单元74对热点的第二机器码进行存储以供后续调用。
[0194] 所述执行单元75执行所述部署的智能合约时,如果存储单元74存储有所述智能合约的第一机器码,则执行单元75执行所述第一机器码。
[0195] 所述执行单元75执行第一机器码,包括:
[0196] 所述执行单元75执行所述存储单元74存储的所述合约中对应所调用函数的第一机器码。
[0197] 所述存储可以为缓存或磁盘存储。
[0198] 所述全局编译方式可以包括AoT或JIT,所述局部编译方式可以包括JIT。
[0199] 此外,执行智能合约的区块链节点,也可以执行上述步骤A1、步骤A2的方法。
[0200] 本说明书还提供一种区块链节点实施例,包括:
[0201] 处理器,
[0202] 存储器,存储有程序,其中在所述处理器执行所述程序时,按照前述的方式执行智能合约。
[0203] 本说明书还提供一种存储介质实施例,用于存储程序,其中所述程序在被执行时,执行前述方法。
[0204] 本说明书提供一种执行智能合约的方法实施例,如图10所示,包括:
[0205] S101:区块链节点接收创建智能合约的请求,所述请求中包括所述智能合约的字节码。
[0206] 用户可以在用户本地用高级语言编写智能合约。编写好的智能合约可以经过适配高级语言的编译器编译,得到字节码。进而,可以通过客户端将编译得到的智能合约的字节码打包到交易中,发送至区块链网络。交易的格式例如为图3~6中所示,其中,需要创建的智能合约的字节码可以存放于交易的data字段中。
[0207] 用户也可以是在第一区块链节点上直接用高级语言编写智能合约,则第一区块链节点还可以采用编译器对高级语言编写的智能合约进行编译,生成字节码。这样,在上链前的合约也是字节码。
[0208] S103:所述区块链节点完成所述智能合约的部署后,开始将所述智能合约的字节码通过全局编译方式编译为第一机器码并存储。
[0209] 所述区块链节点完成创建所述智能合约后,即部署所述智能合约之后,可以开始将所述智能合约的字节码通过全局编译方式编译为第一机器码并存储。所述区块链节点完成创建所述智能合约后,可以立即开始对所述智能合约的字节码进行全局编译。这是因为,在部署智能合约之后,可能很快就有发起调用部署的智能合约的业务请求。此外,全局编译方式需要花费相对较多的系统资源和时间,在区块链节点的业务负荷较重时分配系统资源进行全局编译会影响业务的处理;因此,区块链节点也可以是利用相对空闲的时间段再对所述智能合约的字节码进行全局编译,从而降低或避免对业务处理的影响。
[0210] 区块链各节点针对相同的智能合约字节码在本地进行全局编译,各节点仅需针对自身的处理器架构、运行环境等进行调整,而不需要编译多个不同版本的第一机器码。这样,节点设备上存储的第一机器码的大小得以大大降低,从而可以降低存储开销。
[0211] 优选的,所述存储为缓存,通过缓存到内存,后续可以更快速的作出响应。具体的,所述内存可以是在虚拟机中开辟的一块缓存区域。当然,即使存储到磁盘,很多情形下也可以一定程度的提升响应速度。
[0212] 区块链中的EVM采用全局编译方式来提升智能合约执行时的性能,具体的,可以结合程序代码的前后关联进行编译,并将优化编译后的第一机器码缓存下来以供后续调用时使用。经过编译优化的第一机器码,执行效率一般会高于直接翻译得到的第一机器码。一方面,全局编译引擎可以带上执行编译的区块链节点的硬件和环境信息,从而使得编译得到的第一机器码具有硬件+环境的优化,具体可以包括机器代码生成里的优化,包括指令级的优化,寄存器分配和优化等等。另一方面,全局编译引擎可以分析上下文信息,比如当前函数中执行的分支跳转语句,识别其中哪一句是跳转可能行最大的,从而将这个跳转可能性最大的调整到最前,从而可以在执行时更高概率的首先命中该分支的语句;编译器优化过程还可以通过数据流分析/活跃变量分析进行死代码消除,例如消除不会走到的分支,此外还可以包括对循环语句进行优化,公共字表达式替换等。
[0213] S105:所述区块链节点执行所述部署的智能合约时,如果本地存储有所述智能合约的第一机器码,则执行所述第一机器码。
[0214] 所述区块链节点执行所述部署的智能合约时,可以先查看本地是否存在该被调用的合约的第一机器码。如存在,则说明本地已经完成对该智能合约字节码的全局编译。进而,区块链节点可以直接执行所述合约中对应所调用的函数的第一机器码,并输入前述data字段指明的输入参数。
[0215] 在存储有智能合约的第一机器码的情况下,由于第一机器码本身即是CPU(在OS的控制下)可以直接执行的,因此,所述区块链节点可以大幅提升执行智能合约的速度。并且,所述智能合约的第一机器码缓存在内存中的情形,可以更进一步的提升智能合约的执行速度。当然,即使存储在磁盘中,也可以一定程度上提升执行速度。
[0216] 所述区块链节点执行所述第一机器码,具体可以是执行存储的所述合约中对应所调用函数的第一机器码。
[0217] 此外,所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第一机器码,可以不必等待全局编译的完成,而对所述部署的智能合约的字节码进行解释执行。为了及时对业务请求作出响应,即快速响应发起调用部署的智能合约的业务请求,区块链节点可以首先查询是否存在所述被调用的智能合约的第一机器码,如果有,则说明已经完成了全局编译,如果没有,则说明尚未开始或尚未完成全局编译。如果有第一机器码,如前所述,区块链节点执行所述部署的智能合约时,可以执行所述第一机器码,从而可以大幅提升执行智能合约的速度。如果没有第一机器码,则所述区块链节点还查询当前对所述智能合约字节码的全局编译情况,具体可能包括两种情况:
[0218] 情况一:区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第一机器码,所述区块链节点还查询当前对所述智能合约字节码的全局编译情况,如果正处于全局编译中,则对所述智能合约的字节码进行解释执行。
[0219] 如果本地没有存储所述智能合约的第一机器码,所述区块链节点可以查询当前对所述智能合约字节码的全局编译情况,查询结果可以是正处于全局编译中。对于一些调用所述智能合约的业务请求来说,得到快速的响应是首选,这也是各类区块链系统设法提升TPS的目标。对于被调用的智能合约正处于全局编译中的情况,为了快速响应,区块链节点可以不等待全局编译结束,而是对所述智能合约的字节码进行解释执行。
[0220] 情况二:区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第一机器码,所述区块链节点还查询当前对所述智能合约字节码的全局编译情况,如果尚未开始全局编译,则启动全局编译,并对所述智能合约的字节码进行解释执行。
[0221] 类似于情况一,对于被调用的智能合约尚未启动全局的情况,为了快速响应,区块链节点可以对所述智能合约的字节码进行解释执行。并且,对于尚未启动全局的情况,区块链节点可以启动全局编译。
[0222] 区块链节点对所述智能合约的字节码进行解释执行,可以是采用EVM对所述智能合约的字节码进行逐句翻译,并对翻译后机器码进行逐条执行。除了EVM,还可以是WASM(Web Assembly)虚拟机、JSVM(JavaScript Virtual Machine),后续以EVM作为例子加以说明。
[0223] 此外,区块链中的EVM也可以采用局部编译技术来提升智能合约执行时的性能。例如,区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第一机器码,可以对所述智能合约的字节码进行局部编译并执行。具体的,首先,可以是对所述智能合约的字节码进行逐句翻译,并将翻译后的机器码缓存下来以供后续调用时使用。这里的将翻译后的机器码缓存下来,可以是不加区分的将翻译后的所有机器码缓存下来。其次,可以对所述智能合约的字节码进行翻译和/或执行的过程中识别热点代码,即分析出哪些机器码是多次执行的,从而对其翻译后的机器码进行缓存。而对于执行次数较少的操作,可以不进行缓存。这样可以在执行效率和内存开销上达到最佳平衡。识别热点代码并缓存的方式,可以使得全局编译时间段内,多次执行字节码的过程中,在除了首次需要翻译外,由于将首次翻译得到的机器码进行了缓存,因此后续可以直接利用缓存的机器码,从而免去再次翻译字节码的过程,从而可以缩减时间。
[0224] 所述区块链节点对所述智能合约完成全局编译后,将所述编译后的第一机器码执行所述存储操作。这样,所述区块链节点执行所述部署的智能合约时,如果本地存在该被调用的合约的经全局编译后得到的第一机器码,则说明本地已经完成对该智能合约字节码的全局编译。进而,区块链节点可以直接执行所述合约中对应所调用的函数的经过全局编译得到的第一机器码,并输入前述data字段指明的输入参数。所述全局编译方式可以包括AoT或JIT,所述局部编译方式可以包括JIT。
[0225] 需要说明的是,上述S101中的区块链节点,可能不同于S103和S105中的区块链节点。这是因为,区块链作为分布式的系统,接收交易的节点和发起共识的节点以及执行交易的节点可以是不同的节点,当然也可以是相同的节点。
[0226] 以下介绍本说明书另一执行智能合约的方法实施例,包括:
[0227] 步骤B1:区块链节点部署所述智能合约的字节码后,开始将所述智能合约的字节码通过全局编译为第一机器码并存储;
[0228] 步骤B2:所述区块链节点执行所述部署的智能合约时,如果本地存储有所述智能合约的第一机器码,则执行所述机器码。
[0229] 所述区块链节点部署所述智能合约的字节码后,开始将所述智能合约的字节码通过全局编译方式编译为第一机器码,具体包括:
[0230] 所述区块链节点完成创建所述智能合约后开始对所述智能合约的字节码进行全局编译;或,
[0231] 区块链节点完成创建所述智能合约后,利用相对空闲的时间段对所述智能合约的字节码进行全局编译。
[0232] 所述区块链节点执行所述第一机器码,包括:
[0233] 所述区块链节点执行存储的所述合约中对应所调用函数的第一机器码。
[0234] 所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第一机器码,则对所述智能合约的字节码进行解释执行。
[0235] 所述区块链节点对所述智能合约的字节码进行解释执行,包括:
[0236] 所述区块链节点对所述合约中对应所调用函数的字节码进行解释执行。
[0237] 所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第一机器码,对所述智能合约的字节码进行解释执行,具体包括:
[0238] 所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第一机器码,所述区块链节点还查询当前对所述智能合约字节码的全局编译情况,如果正处于全局编译中,则对所述智能合约的字节码进行解释执行;
[0239] 或,
[0240] 所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第一机器码,所述区块链节点还查询当前对所述智能合约字节码的全局编译情况,如果尚未开始全局编译,则启动全局编译,并对所述智能合约的字节码进行解释执行。
[0241] 所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第一机器码,则对所述智能合约的字节码进行局部编译并执行。
[0242] 所述对智能合约的字节码进行局部编译,包括:
[0243] 对所述智能合约的字节码进行逐句翻译,并将翻译后的机器码缓存下来以供后续调用时使用;
[0244] 或,
[0245] 对所述智能合约的字节码进行翻译和/或执行的过程中识别热点的机器码,对热点的机器码进行编译并缓存以供后续调用。
[0246] 所述识别热点代码的粒度包括函数级别或代码块级别。
[0247] 所述对智能合约的字节码进行局部编译,还包括:对所述智能合约的字节码进行局部翻译的过程中进行优化编译。
[0248] 所述智能合约的第一机器码缓存在内存中的情形,可以更进一步的提升智能合约的执行速度。当然,即使存储在磁盘中,也可以一定程度上提升执行速度。
[0249] 所述全局编译方式包括AoT或JIT,所述局部编译方式包括JIT。
[0250] 本说明书还提出一种执行智能合约的区块链节点,用于执行上述中任一项所述的方法。
[0251] 本说明书还提出一种执行智能合约的区块链节点,包括:
[0252] 处理器,
[0253] 存储器,存储有程序,其中在所述处理器执行所述程序时,执行上述中任一项所述的方法。
[0254] 本说明书还提出一种存储介质,用于存储程序,其中所述程序在被执行时进行上述中任一项的操作。
[0255] 本说明书提供一种执行智能合约的方法实施例,如图11所示,包括:
[0256] S121:区块链节点接收创建智能合约的请求,所述请求中包括所述智能合约的字节码。
[0257] S123:所述区块链节点完成所述智能合约的部署后,开始将所述智能合约的字节码通过全局编译方式编译为第一机器码并存储。
[0258] S121、S123分别与前述S101和S103类似,这里不再赘述。
[0259] S125:所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第一机器码,则对所述智能合约的字节码进行解释执行。
[0260] 所述区块链节点执行所述部署的智能合约时,可以先查看本地是否存在该被调用的合约的第一机器码。如果本地没有存储所述智能合约的第一机器码,可以不必等待全部编译的完成,而对所述部署的智能合约的字节码进行解释执行。全局编译的过程相对更费时,解释执行相对更省时,而全局编译之后执行得到的机器码最省时。全局编译尚未完成的情况下,对所述智能合约的字节码进行解释执行,从而可以在全局编译的同时保证区块链业务请求的正常处理。
[0261] 为了及时对业务请求作出响应,即快速响应发起调用部署的智能合约的业务请求,区块链节点可以首先查询是否存在所述被调用的智能合约的第一机器码,如果有,则说明已经完成了全局编译,如果没有,则说明尚未开始或尚未完成全局编译。如果有第一机器码,如前所述,区块链节点执行所述部署的智能合约时,可以执行所述第一机器码,从而可以大幅提升执行智能合约的速度。如果没有第一机器码,则所述区块链节点还查询当前对所述智能合约字节码的全局编译情况,具体可能包括两种情况:
[0262] 情况一:区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第一机器码,所述区块链节点还查询当前对所述智能合约字节码的全局编译情况,如果正处于全局编译中,则对所述智能合约的字节码进行解释执行。
[0263] 如果本地没有存储所述智能合约的第一机器码,所述区块链节点可以查询当前对所述智能合约字节码的全局编译情况,查询结果可以是正处于全局编译中。对于一些调用所述智能合约的业务请求来说,得到快速的响应是首选,这也是各类区块链系统设法提升TPS的目标。对于被调用的智能合约正处于全局编译中的情况,为了快速响应,区块链节点可以不等待全局编译结束,而是对所述智能合约的字节码进行解释执行。
[0264] 情况二:区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第一机器码,所述区块链节点还查询当前对所述智能合约字节码的全局编译情况,如果尚未开始全局编译,则启动全局编译,并对所述智能合约的字节码进行解释执行。
[0265] 类似于情况一,对于被调用的智能合约尚未启动全局编译的情况,为了快速响应,区块链节点可以对所述智能合约的字节码进行解释执行。并且,对于尚未启动全局编译的情况,区块链节点可以启动全局编译。
[0266] 区块链节点对所述智能合约的字节码进行解释执行,可以是采用EVM对所述智能合约的字节码进行逐句翻译,并对翻译后的机器码进行逐条执行。除了EVM,还可以是WASM(Web Assembly)虚拟机、JSVM(JavaScript Virtual Machine),后续以EVM作为例子加以说明。
[0267] 所述区块链节点对所述智能合约完成全局编译后,可以将所述编译后的第一机器码执行所述存储操作。这样,所述区块链节点执行所述部署的智能合约时,如果本地存在该被调用的合约的第一机器码,则说明本地已经完成对该智能合约字节码的全局编译。进而,区块链节点可以直接执行所述合约中对应所调用的函数的经过全局编译得到的第一机器码,并输入前述data字段指明的输入参数。所述全局编译方式可以包括AoT或JIT。
[0268] 在存储有智能合约的经过全局编译得到的第一机器码的情况下,由于第一机器码本身即是CPU(在OS的控制下)可以直接执行的,因此,所述区块链节点可以大幅提升执行智能合约的速度。并且,所述智能合约的第一机器码缓存在内存中的情形,可以更进一步的提升智能合约的执行速度。当然,即使存储在磁盘中,也可以一定程度上提升执行速度。
[0269] 所述区块链节点执行所述第一机器码,具体可以是执行存储的所述合约中对应所调用函数的第一机器码。
[0270] 以下介绍本说明书另一执行智能合约的方法实施例,包括:
[0271] 步骤C1:区块链节点完成所述智能合约的部署后,开始将所述智能合约的字节码通过全局编译方式编译为第一机器码并存储;
[0272] 步骤C2:所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第一机器码,则对所述智能合约的字节码进行解释执行。
[0273] 所述区块链节点完成所述智能合约的部署后,开始将所述智能合约的字节码通过全局编译方式编译为第一机器码,具体包括:
[0274] 所述区块链节点完成创建所述智能合约后开始对所述智能合约的字节码进行全局编译;或,
[0275] 区块链节点完成创建所述智能合约后,利用相对空闲的时间段对所述智能合约的字节码进行全局编译。
[0276] 所述区块链节点对所述智能合约的字节码进行解释执行,包括:
[0277] 所述区块链节点对所述合约中对应所调用函数的字节码进行解释执行。
[0278] 所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第一机器码,对所述智能合约的字节码进行解释执行,具体包括:
[0279] 所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第一机器码,所述区块链节点还查询当前对所述智能合约字节码的全局编译情况,如果正处于全局编译中,则对所述智能合约的字节码进行解释执行;
[0280] 或,
[0281] 所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第一机器码,所述区块链节点还查询当前对所述智能合约字节码的全局编译情况,如果尚未开始全局编译,则启动全局编译,并对所述智能合约的字节码进行解释执行。
[0282] 如果本地存储有所述智能合约的第一机器码,则执行所述第一机器码。
[0283] 所述区块链节点执行所述第一机器码,包括:
[0284] 所述区块链节点执行存储的所述合约中对应所调用函数的第一机器码。
[0285] 所述智能合约的第一机器码缓存在内存中的情形,可以更进一步的提升智能合约的执行速度。当然,即使存储在磁盘中,也可以一定程度上提升执行速度。
[0286] 所述全局编译方式包括AoT或JIT。
[0287] 本说明书还提供一种执行智能合约的区块链节点,执行上述中任一项所述的方法。
[0288] 本说明书还提供一种执行智能合约的区块链节点,包括:
[0289] 处理器,
[0290] 存储器,存储有程序,其中在所述处理器执行所述程序时,执行上述中任一项所述的方法。
[0291] 本说明书还提供一种存储介质,用于存储程序,其中所述程序在被执行时进行上述中任一项的操作。
[0292] 本说明书提供一种执行智能合约的方法实施例,如图12所示,包括:
[0293] S141:区块链节点接收创建智能合约的请求,所述请求中包括所述智能合约的字节码。
[0294] S141与前述S101类似,这里不再赘述。
[0295] S143:所述区块链节点完成所述智能合约的部署后,开始将所述智能合约的字节码通过局部编译方式编译为第二机器码并存储。
[0296] 所述区块链节点完成创建所述智能合约后,即部署所述智能合约之后,可以开始将所述智能合约的字节码通过局部编译方式编译为第二机器码并存储。局部编译方式例如为JIT。所述区块链节点完成创建所述智能合约后,可以立即开始对所述智能合约的字节码进行JIT编译。这是因为,在部署智能合约之后,可能很快就有发起调用部署的智能合约的业务请求。此外,JIT需要花费相对较多的系统资源和时间,在区块链节点的业务负荷较重时分配系统资源进行JIT会影响业务的处理;因此,区块链节点也可以是利用相对空闲的时间段再对所述智能合约的字节码进行JIT编译,从而降低或避免对业务处理的影响。此外,所述区块链节点完成创建所述智能合约后,也可以是区块链节点接收到调用所述创建的智能合约的交易请求后,对所述智能合约的字节码进行JIT编译。
[0297] 区块链各节点针对相同的智能合约字节码在本地进行JIT编译,各节点仅需针对自身的处理器架构、运行环境等进行调整,而不需要编译多个不同版本的第二机器码。这样,节点设备上存储的第二机器码的大小得以大大降低,从而可以降低存储开销。
[0298] 优选的,所述存储为缓存,通过缓存到内存,后续可以更快速的作出响应。具体的,所述内存可以是在虚拟机中开辟的一块缓存区域。当然,即使存储到磁盘,很多情形下也可以一定程度的提升响应速度。
[0299] 区块链中的EVM采用JIT技术来提升智能合约执行时的性能,具体的,可以包括:
[0300] 首先,可以对所述智能合约的字节码进行翻译和/或执行的过程中识别热点代码,例如通过JIT引擎的代码计数器来统计执行次数,从而分析出哪些字节码是多次执行的,从而对其翻译后的第二机器码进行缓存。而对于执行次数较少的操作,可以不进行缓存。这样可以在执行效率和内存开销上达到最佳平衡。识别热点代码并缓存的方式,可以使得多次执行字节码的过程中,在除了首次需要翻译外,后续可以直接利用缓存的第二机器码,从而免去再次翻译字节码的过程,从而可以缩减时间。识别执行次数的粒度,可以是函数级别,还可以是代码块级别。一般来说,代码块可能是函数中的一部分,也可能是由若干函数构成。
[0301] 其次,可以在JIT编译中进行进一步的优化,结合程序代码的前后关联进行编译,并将优化编译后的第二机器码缓存下来以供后续调用时使用。经过编译优化的第二机器码,执行效率一般会高于直接翻译得到的第二机器码。一方面,JIT引擎可以带上执行编译的区块链节点的硬件和环境信息,从而使得编译得到的第二机器码具有硬件+环境的优化,具体可以包括机器代码生成里的优化,包括指令级的优化,寄存器分配和优化等等。另一方面,JIT引擎可以分析上下文信息,比如当前函数中执行的分支跳转语句,识别其中哪一句是跳转可能行最大的,从而将这个跳转可能性最大的调整到最前,从而可以在执行时更高概率的首先命中该分支的语句;编译器优化过程还可以通过数据流分析/活跃变量分析进行死代码消除,例如消除不会走到的分支,此外还可以包括对循环语句进行优化,公共字表达式替换等。
[0302] S145:所述区块链节点执行所述部署的智能合约时,如果本地存储有所述智能合约的第二机器码,则执行所述第二机器码。
[0303] 所述区块链节点执行所述部署的智能合约时,可以先查看本地是否存在该被调用的合约的第二机器码。如存在,则说明本地已经对该智能合约字节码的进行过JIT编译。进而,区块链节点可以直接执行所述合约中对应所调用的函数/代码块的机器码,并输入前述data字段指明的输入参数。
[0304] 在存储有智能合约的第二机器码的情况下,由于第二机器码本身即是CPU(在OS的控制下)可以直接执行的,因此,所述区块链节点可以大幅提升执行智能合约的速度。并且,所述智能合约的第二机器码缓存在内存中的情形,可以更进一步的提升智能合约的执行速度。当然,即使存储在磁盘中,也可以一定程度上提升执行速度。
[0305] 所述区块链节点执行所述第二机器码,具体可以是执行存储的所述合约中对应所调用函数/代码块的第二机器码。
[0306] 此外,所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第二机器码,可以不必等待JIT编译的完成,而对所述部署的智能合约的字节码进行解释执行。为了及时对业务请求作出响应,即快速响应发起调用部署的智能合约的业务请求,区块链节点可以首先查询是否存在所述被调用的智能合约的第二机器码,如果有,则说明已经完成了JIT编译,如果没有,则说明尚未开始或尚未完成JIT编译。如果有第二机器码,如前所述,区块链节点执行所述部署的智能合约时,可以执行所述第二机器码,从而可以大幅提升执行智能合约的速度。如果没有第二机器码,则所述区块链节点还查询当前对所述智能合约字节码的JIT编译情况,具体可能包括两种情况:
[0307] 情况一:区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第二机器码,所述区块链节点还查询当前对所述智能合约字节码的JIT编译情况,如果正处于JIT编译中,则对所述智能合约的字节码进行解释执行。
[0308] 如果本地没有存储所述智能合约的第二机器码,所述区块链节点可以查询当前对所述智能合约字节码的JIT编译情况,查询结果可以是正处于JIT编译中。对于一些调用所述智能合约的业务请求来说,得到快速的响应是首选,这也是各类区块链系统设法提升每秒交易处理数量(Transaction Per Second,TPS)的目标。对于被调用的智能合约正处于JIT中的情况,为了快速响应,区块链节点可以不等待JIT编译结束,而是对所述智能合约的字节码进行解释执行。
[0309] 情况二:区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第二机器码,所述区块链节点还查询当前对所述智能合约字节码的JIT编译情况,如果尚未开始JIT编译,则启动JIT编译,并对所述智能合约的字节码进行解释执行。
[0310] 类似于情况一,对于被调用的智能合约尚未启动JIT的情况,为了快速响应,区块链节点可以对所述智能合约的字节码进行解释执行。并且,对于尚未启动JIT的情况,区块链节点可以启动JIT编译。
[0311] 区块链节点对所述智能合约的字节码进行解释执行,可以是采用EVM对所述智能合约的字节码进行逐句翻译,并对翻译后第二机器码进行逐条执行。除了EVM,还可以是WASM(Web Assembly)虚拟机、JSVM(JavaScript Virtual Machine)等,这里主要以EVM作为例子加以说明。
[0312] 所述区块链节点对所述智能合约完成JIT编译后,将所述编译后的第二机器码执行所述存储操作。这样,所述区块链节点执行所述部署的智能合约时,如果本地存在该被调用的合约的经JIT编译后得到的第二机器码,则说明本地已经完成对该智能合约字节码的JIT编译。进而,区块链节点可以直接执行所述合约中对应所调用的函数的经过JIT编译得到的第二机器码,并输入前述data字段指明的输入参数。
[0313] 所述智能合约的第二机器码缓存在内存中的情形,可以更进一步的提升智能合约的执行速度。当然,即使存储在磁盘中,也可以一定程度上提升执行速度。
[0314] 以下介绍本说明书另一执行智能合约的方法实施例,包括:
[0315] 步骤D1:区块链节点部署所述智能合约的字节码后,开始将所述智能合约的字节码通过局部编译方式编译为第二机器码并存储。
[0316] 步骤D2:所述区块链节点执行所述部署的智能合约时,如果本地存储有所述智能合约的第二机器码,则执行所述第二机器码。
[0317] 所述区块链节点部署所述智能合约的字节码后,开始将所述智能合约的字节码通过局部编译方式编译为第二机器码,具体包括:
[0318] 所述区块链节点完成创建所述智能合约后开始对所述智能合约的字节码进行局部编译;或,
[0319] 区块链节点完成创建所述智能合约后,利用相对空闲的时间段对所述智能合约的字节码进行局部编译;或,
[0320] 区块链节点接收到调用所述创建的智能合约的交易请求后,对所述智能合约的字节码进行局部编译。
[0321] 所述对智能合约的字节码进行局部编译为第二机器码并存储,包括:
[0322] 对所述智能合约的字节码进行翻译和/或执行的过程中识别热点的字节码进行编译并存储;
[0323] 和/或,
[0324] 对所述智能合约的字节码进行翻译和/或执行的过程中进行优化编译并存储。
[0325] 所述识别热点代码的粒度包括函数级别或代码块级别。
[0326] 所述区块链节点执行所述第二机器码,包括:
[0327] 所述区块链节点执行存储的所述合约中对应所调用函数/代码块的第二机器码。
[0328] 所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第二机器码,则对所述智能合约的字节码进行解释执行。
[0329] 所述区块链节点对所述智能合约的字节码进行解释执行,包括:
[0330] 所述区块链节点对所述合约中对应所调用函数的字节码进行解释执行。
[0331] 所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第二机器码,对所述智能合约的字节码进行解释执行,具体包括:
[0332] 所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第二机器码,所述区块链节点还查询当前对所述智能合约字节码的局部编译情况,如果正处于局部编译中,则对所述智能合约的字节码进行解释执行;
[0333] 或,
[0334] 所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第二机器码,所述区块链节点还查询当前对所述智能合约字节码的局部编译情况,如果尚未开始局部编译,则启动局部编译,并对所述智能合约的字节码进行解释执行。
[0335] 所述存储可以为缓存。
[0336] 所述局部编译方式可以包括JIT。
[0337] 本说明书还提供一种执行智能合约的区块链节点,执行上述任一项所述的方法。
[0338] 本说明书还提供一种执行智能合约的区块链节点,包括:
[0339] 处理器,
[0340] 存储器,存储有程序,其中在所述处理器执行所述程序时,执行上述任一项所述的方法。
[0341] 本说明书还提供一种存储介质,用于存储程序,其中所述程序在被执行时进行上述中任一项的操作。
[0342] 本说明书提供一种执行智能合约的方法实施例,如图13所示,包括:
[0343] S161:区块链节点接收创建智能合约的请求,所述请求中包括所述智能合约的字节码。
[0344] S163:所述区块链节点完成所述智能合约的部署后,开始将所述智能合约的字节码通过局部编译方式编译为第二机器码并存储。
[0345] S161、S163分别与前述S141和S143类似,这里不再赘述。
[0346] S165:所述区块链节点执行所述部署的智能合约时,如果本地没有存储有所述智能合约对应的第二机器码,则对所述智能合约的字节码进行解释执行。
[0347] 所述区块链节点执行所述部署的智能合约时,可以先查看本地是否存在该被调用的合约的第二机器码。如存在,则说明本地已经对该智能合约字节码的进行过局部编译。局部编译方式例如为JIT。进而,区块链节点可以直接执行所述合约中对应所调用的函数/代码块的第二机器码,并输入前述data字段指明的输入参数。
[0348] 在存储有智能合约的第二机器码的情况下,由于第二机器码本身即是CPU(在OS的控制下)可以直接执行的,因此,所述区块链节点可以大幅提升执行智能合约的速度。并且,所述智能合约的第二机器码缓存在内存中的情形,可以更进一步的提升智能合约的执行速度。当然,即使存储在磁盘中,也可以一定程度上提升执行速度。
[0349] 所述区块链节点执行所述第二机器码,具体可以是执行存储的所述合约中对应所调用函数/代码块的第二机器码。
[0350] 此外,所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第二机器码,可以不必等待JIT编译的完成,而对所述部署的智能合约的字节码进行解释执行。为了及时对业务请求作出响应,即快速响应发起调用部署的智能合约的业务请求,区块链节点可以首先查询是否存在所述被调用的智能合约的第二机器码,如果有,则说明已经完成了JIT编译,如果没有,则说明尚未开始或尚未完成JIT编译。如果有第二机器码,如前所述,区块链节点执行所述部署的智能合约时,可以执行所述第二机器码,从而可以大幅提升执行智能合约的速度。如果没有第二机器码,则所述区块链节点还查询当前对所述智能合约字节码的JIT编译情况,具体可能包括两种情况:
[0351] 情况一:区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第二机器码,所述区块链节点还查询当前对所述智能合约字节码的JIT编译情况,如果正处于JIT编译中,则对所述智能合约的字节码进行解释执行。
[0352] 如果本地没有存储所述智能合约的第二机器码,所述区块链节点可以查询当前对所述智能合约字节码的JIT编译情况,查询结果可以是正处于JIT编译中。对于一些调用所述智能合约的业务请求来说,得到快速的响应是首选,这也是各类区块链系统设法提升每秒交易处理数量(Transaction Per Second,TPS)的目标。对于被调用的智能合约正处于JIT中的情况,为了快速响应,区块链节点可以不等待JIT编译结束,而是对所述智能合约的字节码进行解释执行。
[0353] 情况二:区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第二机器码,所述区块链节点还查询当前对所述智能合约字节码的JIT编译情况,如果尚未开始JIT编译,则启动JIT编译,并对所述智能合约的字节码进行解释执行。
[0354] 类似于情况一,对于被调用的智能合约尚未启动JIT的情况,为了快速响应,区块链节点可以对所述智能合约的字节码进行解释执行。并且,对于尚未启动JIT的情况,区块链节点可以启动JIT编译。
[0355] 区块链节点对所述智能合约的字节码进行解释执行,可以是采用EVM对所述智能合约的字节码进行逐句翻译,并对翻译后机器码进行逐条执行。除了EVM,还可以是WASM(Web Assembly)虚拟机、JSVM(JavaScript Virtual Machine)等,这里主要以EVM作为例子加以说明。
[0356] 所述区块链节点对所述智能合约完成JIT编译后,将所述编译后的第二机器码执行所述存储操作。这样,所述区块链节点执行所述部署的智能合约时,如果本地存在该被调用的合约的经JIT编译后得到的第二机器码,则说明本地已经完成对该智能合约字节码的JIT编译。进而,区块链节点可以直接执行所述合约中对应所调用的函数的经过JIT编译得到的第二机器码,并输入前述data字段指明的输入参数。
[0357] 以下介绍本说明书另一执行智能合约的方法实施例,包括:
[0358] 步骤E1:区块链节点完成所述智能合约的部署后,开始将所述智能合约的字节码通过局部编译方式编译为第二机器码并存储。
[0359] 步骤E2:所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第二机器码,则对所述智能合约的字节码进行解释执行。
[0360] 所述区块链节点完成所述智能合约的部署后,开始将所述智能合约的字节码通过局部编译方式编译为第二机器码,具体包括:
[0361] 所述区块链节点完成创建所述智能合约后开始对所述智能合约的字节码进行局部编译;或,
[0362] 区块链节点完成创建所述智能合约后,利用相对空闲的时间段对所述智能合约的字节码进行局部编译;或,
[0363] 区块链节点接收到调用所述创建的智能合约的交易请求后,对所述智能合约的字节码进行局部编译。
[0364] 所述区块链节点对所述智能合约的字节码进行解释执行,包括:
[0365] 所述区块链节点对所述合约中对应所调用函数的字节码进行解释执行。
[0366] 所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第二机器码,对所述智能合约的字节码进行解释执行,具体包括:
[0367] 所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第二机器码,所述区块链节点还查询当前对所述智能合约字节码的局部编译情况,如果正处于局部编译中,则对所述智能合约的字节码进行解释执行;
[0368] 或,
[0369] 所述区块链节点执行所述部署的智能合约时,如果本地没有存储所述智能合约的第二机器码,所述区块链节点还查询当前对所述智能合约字节码的局部编译情况,如果尚未开始局部编译,则启动局部编译,并对所述智能合约的字节码进行解释执行。
[0370] 所述区块链节点执行所述部署的智能合约时,如果本地存储有所述智能合约的第二机器码,则执行所述第二机器码。
[0371] 所述区块链节点执行所述第二机器码,包括:
[0372] 所述区块链节点执行存储的所述合约中对应所调用函数的第二机器码。
[0373] 所述存储可以为缓存。
[0374] 所述局部编译方式包括JIT。
[0375] 本说明书还提供一种执行智能合约的区块链节点,执行上述任一项所述的方法。
[0376] 本说明书还提供一种执行智能合约的区块链节点,包括:
[0377] 处理器,
[0378] 存储器,存储有程序,其中在所述处理器执行所述程序时,执行上述任一项所述的方法。
[0379] 本说明书还提供一种存储介质,用于存储程序,其中所述程序在被执行时进行上述任一项的操作。
[0380] 需要说明的是,常用的全局编译方式是AoT,即一般常用AoT方式对全部代码进行编译;常用的局部编译方式是JIT,即一般常用JIT方式对部分代码进行编译。结合上述实施例,对于上链的智能合约的字节码,即部署在区块链上的智能合约的代码是字节码的形式,采用AoT来将智能合约的全部字节码进行编译,而采用JIT来将智能合约的部分字节码进行编译。此外,也可以采用JIT来对智能合约的全部字节码进行编译,即进行全局编译。全局编译中,可以进行优化编译,如前所述,当然也可以不采用优化编译。而局部编译中,一方面可以采用热点代码缓存,另一方面可以采用优化编译,或者两者都采用。
[0381]  在20世纪90年代,对于一个技术的改进可以很明显地区分是硬件上的改进(例如,对二极管、晶体管、开关等电路结构的改进)还是软件上的改进(对于方法流程的改进)。然而,随着技术的发展,当今的很多方法流程的改进已经可以视为硬件电路结构的直接改进。设计人员几乎都通过将改进的方法流程编程到硬件电路中来得到相应的硬件电路结构。因此,不能说一个方法流程的改进就不能用硬件实体模块来实现。例如,可编程逻辑器件(Programmable Logic Device, PLD)(例如现场可编程门阵列(Field Programmable Gate Array,FPGA))就是这样一种集成电路,其逻辑功能由用户对器件编程来确定。由设计人员自行编程来把一个数字系统“集成”在一片PLD上,而不需要请芯片制造厂商来设计和制作专用的集成电路芯片。而且,如今,取代手工地制作集成电路芯片,这种编程也多半改用“逻辑编译器(logic compiler)”软件来实现,它与程序开发撰写时所用的软件编译器相类似,而要编译之前的原始代码也得用特定的编程语言来撰写,此称之为硬件描述语言(Hardware Description Language,HDL),而HDL也并非仅有一种,而是有许多种,如ABEL(Advanced Boolean Expression Language)、AHDL(Altera Hardware Description Language)、Confluence、CUPL(Cornell University Programming Language)、HDCal、JHDL(Java Hardware Description Language)、Lava、Lola、MyHDL、PALASM、RHDL(Ruby Hardware Description Language)等,目前最普遍使用的是VHDL(Very-High-Speed Integrated Circuit Hardware Description Language)与Verilog。本领域技术人员也应该清楚,只需要将方法流程用上述几种硬件描述语言稍作逻辑编程并编程到集成电路中,就可以很容易得到实现该逻辑方法流程的硬件电路。
[0382] 控制器可以按任何适当的方式实现,例如,控制器可以采取例如微处理器或处理器以及存储可由该(微)处理器执行的计算机可读程序代码(例如软件或固件)的计算机可读介质、逻辑门、开关、专用集成电路(Application Specific Integrated Circuit,ASIC)、可编程逻辑控制器和嵌入微控制器的形式,控制器的例子包括但不限于以下微控制器:ARC 625D、Atmel AT91SAM、Microchip PIC18F26K20 以及Silicone Labs C8051F320,存储器控制器还可以被实现为存储器的控制逻辑的一部分。本领域技术人员也知道,除了以纯计算机可读程序代码方式实现控制器以外,完全可以通过将方法步骤进行逻辑编程来使得控制器以逻辑门、开关、专用集成电路、可编程逻辑控制器和嵌入微控制器等的形式来实现相同功能。因此这种控制器可以被认为是一种硬件部件,而对其内包括的用于实现各种功能的装置也可以视为硬件部件内的结构。或者甚至,可以将用于实现各种功能的装置视为既可以是实现方法的软件模块又可以是硬件部件内的结构。
[0383] 上述实施例阐明的系统、装置、模块或单元,具体可以由计算机芯片或实体实现,或者由具有某种功能的产品来实现。一种典型的实现设备为服务器系统。当然,本说明书不排除随着未来计算机技术的发展,实现上述实施例功能的计算机例如可以为个人计算机、膝上型计算机、车载人机交互设备、蜂窝电话、相机电话、智能电话、个人数字助理、媒体播放器、导航设备、电子邮件设备、游戏控制台、平板计算机、可穿戴设备或者这些设备中的任何设备的组合。
[0384] 虽然本说明书一个或多个实施例提供了如实施例或流程图所述的方法操作步骤,但基于常规或者无创造性的手段可以包括更多或者更少的操作步骤。实施例中列举的步骤顺序仅仅为众多步骤执行顺序中的一种方式,不代表唯一的执行顺序。在实际中的装置或终端产品执行时,可以按照实施例或者附图所示的方法顺序执行或者并行执行(例如并行处理器或者多线程处理的环境,甚至为分布式数据处理环境)。术语“包括”、“包含”或者其任何其他变体意在涵盖非排他性的包含,从而使得包括一系列要素的过程、方法、产品或者设备不仅包括那些要素,而且还包括没有明确列出的其他要素,或者是还包括为这种过程、方法、产品或者设备所固有的要素。在没有更多限制的情况下,并不排除在包括所述要素的过程、方法、产品或者设备中还存在另外的相同或等同要素。例如若使用到第一,第二等词语用来表示名称,而并不表示任何特定的顺序。
[0385] 为了描述的方便,描述以上装置时以功能分为各种模块分别描述。当然,在实施本说明书一个或多个时可以把各模块的功能在同一个或多个软件和/或硬件中实现,也可以将实现同一功能的模块由多个子模块或子单元的组合实现等。以上所描述的装置实施例仅仅是示意性的,例如,所述单元的划分,仅仅为一种逻辑功能划分,实际实现时可以有另外的划分方式,例如多个单元或组件可以结合或者可以集成到另一个系统,或一些特征可以忽略,或不执行。另一点,所显示或讨论的相互之间的耦合或直接耦合或通信连接可以是通过一些接口,装置或单元的间接耦合或通信连接,可以是电性,机械或其它的形式。
[0386] 本发明是参照根据本发明实施例的方法、装置(系统)、和计算机程序产品的流程图和/或方框图来描述的。应理解可由计算机程序指令实现流程图和/或方框图中的每一流程和/或方框、以及流程图和/或方框图中的流程和/或方框的结合。可提供这些计算机程序指令到通用计算机、专用计算机、嵌入式处理机或其他可编程数据处理设备的处理器以产生一个机器,使得通过计算机或其他可编程数据处理设备的处理器执行的指令产生用于实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能的装置。
[0387] 这些计算机程序指令也可存储在能引导计算机或其他可编程数据处理设备以特定方式工作的计算机可读存储器中,使得存储在该计算机可读存储器中的指令产生包括指令装置的制造品,该指令装置实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能。
[0388] 这些计算机程序指令也可装载到计算机或其他可编程数据处理设备上,使得在计算机或其他可编程设备上执行一系列操作步骤以产生计算机实现的处理,从而在计算机或其他可编程设备上执行的指令提供用于实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能的步骤。
[0389] 在一个典型的配置中,计算设备包括一个或多个处理器(CPU)、输入/输出接口、网络接口和内存。
[0390] 内存可能包括计算机可读介质中的非永久性存储器,随机存取存储器(RAM)和/或非易失性内存等形式,如只读存储器(ROM)或闪存(flash RAM)。内存是计算机可读介质的示例。
[0391] 计算机可读介质包括永久性和非永久性、可移动和非可移动媒体可以由任何方法或技术来实现信息存储。信息可以是计算机可读指令、数据结构、程序的模块或其他数据。计算机的存储介质的例子包括,但不限于相变内存(PRAM)、静态随机存取存储器(SRAM)、动态随机存取存储器(DRAM)、其他类型的随机存取存储器(RAM)、只读存储器(ROM)、电可擦除可编程只读存储器(EEPROM)、快闪记忆体或其他内存技术、只读光盘只读存储器(CD-ROM)、数字多功能光盘(DVD)或其他光学存储、磁盒式磁带,磁带磁盘存储、石墨烯存储或其他磁性存储设备或任何其他非传输介质,可用于存储可以被计算设备访问的信息。按照本文中的界定,计算机可读介质不包括暂存电脑可读媒体(transitory media),如调制的数据信号和载波。
[0392] 本领域技术人员应明白,本说明书一个或多个实施例可提供为方法、系统或计算机程序产品。因此,本说明书一个或多个实施例可采用完全硬件实施例、完全软件实施例或结合软件和硬件方面的实施例的形式。而且,本说明书一个或多个实施例可采用在一个或多个其中包含有计算机可用程序代码的计算机可用存储介质(包括但不限于磁盘存储器、CD-ROM、光学存储器等)上实施的计算机程序产品的形式。
[0393] 本说明书一个或多个实施例可以在由计算机执行的计算机可执行指令的一般上下文中描述,例如程序模块。一般地,程序模块包括执行特定任务或实现特定抽象数据类型的例程、程序、对象、组件、数据结构等等。也可以在分布式计算环境中实践本说明书一个或多个实施例,在这些分布式计算环境中,由通过通信网络而被连接的远程处理设备来执行任务。在分布式计算环境中,程序模块可以位于包括存储设备在内的本地和远程计算机存储介质中。
[0394] 本说明书中的各个实施例均采用递进的方式描述,各个实施例之间相同相似的部分互相参见即可,每个实施例重点说明的都是与其他实施例的不同之处。尤其,对于系统实施例而言,由于其基本相似于方法实施例,所以描述的比较简单,相关之处参见方法实施例的部分说明即可。在本说明书的描述中,参考术语“一个实施例”、“一些实施例”、“示例”、“具体示例”、或“一些示例”等的描述意指结合该实施例或示例描述的具体特征、结构、材料或者特点包含于本说明书的至少一个实施例或示例中。在本说明书中,对上述术语的示意性表述不必须针对的是相同的实施例或示例。而且,描述的具体特征、结构、材料或者特点可以在任一个或多个实施例或示例中以合适的方式结合。此外,在不相互矛盾的情况下,本领域的技术人员可以将本说明书中描述的不同实施例或示例以及不同实施例或示例的特征进行结合和组合。
[0395] 以上所述仅为本说明书一个或多个实施例的实施例而已,并不用于限制本说明书一个或多个实施例。对于本领域技术人员来说,本说明书一个或多个实施例可以有各种更改和变化。凡在本说明书的精神和原理之内所作的任何修改、等同替换、改进等,均应包含在权利要求范围之内。