首页> 中国专利> 一种链码测试种子生成方法、系统、设备及存储介质

一种链码测试种子生成方法、系统、设备及存储介质

摘要

本发明提供一种链码测试种子生成方法、系统、设备及存储介质:方法包括获取链码程序中目标函数的相关信息,并为该目标函数生成一个测试文件;将目标函数的全排列种子组中的种子依次执行测试文件,得到每个种子产生的覆盖率;选择覆盖率最高的种子作为初始种子;将初始种子中的整型数字分别进行可设置固定时长的优化处理,确定最终种子;保存链码程序中所有目标函数的最终种子,输出链码测试种子。该方法可以给不同的链码生成高覆盖率的种子输入,有了能产生较高覆盖率的种子输入,就可以提高漏洞检测的准确性,降低漏报率。另外,格式良好的种子输入,也可以帮助模糊测试更快地发现程序中的一些未知漏洞。

著录项

  • 公开/公告号CN113190441A

    专利类型发明专利

  • 公开/公告日2021-07-30

    原文格式PDF

  • 申请/专利号CN202110454744.0

  • 发明设计人 王晨旭;刘琛;杨子江;

    申请日2021-04-26

  • 分类号G06F11/36(20060101);G06F21/56(20130101);G06F21/57(20130101);

  • 代理机构11703 北京中巡通大知识产权代理有限公司;

  • 代理人张弘

  • 地址 710077 陕西省西安市高新区天谷八路软件新城云汇谷156号B2座11层

  • 入库时间 2023-06-19 12:02:28

说明书

技术领域

本发明涉及区块链技术领域,特别涉及一种链码测试种子生成方法、系统、设备及存储介质。

背景技术

区块链是一种采用包括密码学,共识算法等技术的分布式系统。采用区块链可以对金融、供应链等多领域提供去中心化、透明、可追溯的信息平台。在区块链上的智能合约可以进一步满足用户的自定义需求,例如投票、众筹和金融交易等。智能合约本质上是一种在区块链上自动执行的电脑程序,根据区块链平台的不同,基于不同的理论和不同的程序语言实现。例如以太坊(Ethereum)上的智能合约(smart contract)和Hyperledger Fabric上的链码(chaincode)。

Hyperledger Fabric是由Linux基金会提出并维护的区块链平台,专注于私有性和安全性。其支持的智能合约又称为链码(chaincode)。该种技术被众多大型公司采用,因此链码的安全性要求也逐渐提高。

对于链码安全性的提高随之带来了对链码安全的检测技术的更高要求。当前已有技术分别是基于静态分析,或者静态分析与模糊测试相结合的方法来分析链码的安全漏洞。静态分析不实际运行程序,因此不需要为程序提供种子输入,然而模糊测试或者其他动态测试方法则需要程序的种子输入,以实际将程序运行起来,这样能够检测到程序中与输入相关的漏洞。

静态分析有如下缺点:1.安全漏洞误报率高:静态分析会报告出更多在实际运行中不存在的错误;2.无法实际证明安全漏洞在实际中存在:静态分析报告的安全漏洞必须依靠实际运行程序来进行证明;3.无法证明与实际链码输入有关的安全漏洞:由于静态分析不实际运行链码,因此无法分析与实际输入有关的安全漏洞;4.静态程序分析还面临着路径爆炸问题,可能会分析到代码实际运行过程中根本不可能执行到的路径。

针对以上缺点,出现了第二种漏洞检测方法:通过模糊测试,对链码进行安全漏洞挖掘,在模糊测试过程中,会产生多个链码输入并以每个链码输入对链码进行模拟运行,分析链码的运行安全漏洞,并根据链码运行的结果,结合静态分析来分析链码的静态安全漏洞。此时,静态分析只分析链码模拟运行过程中执行到的部分(同时避免了路径爆炸),即只能对模糊测试过程中产生的输入所能覆盖到的代码进行检测。

代码覆盖(Code coverage)是软件测试中的一种度量,描述程序中源代码被测试的比例和程度,所得比例称为代码覆盖率。虽然覆盖率达到100%,也不一定能够检测出所有漏洞。但是如果代码没有被执行到,若其中包含漏洞,则一定不会被检测出来。覆盖率越低,那么没有被执行到的代码包含潜在漏洞的可能性就越大。因此,结合上面对Fabric链码漏洞检测方法的描述,代码覆盖率在智能合约漏洞检测方面也起着至关重要的作用,覆盖率的高低可以直接表现出漏洞检测的完全程度。

发明内容

本文基于强化学习,提出了一种链码测试种子生成方法、系统、设备及存储介质,具体是一种为Hyperledger Fabric链码自动生成高覆盖率种子输入的方法,也可以看作是对链码进行模糊测试时对模糊测试流程中“生成种子输入”这一步骤的优化。该方法可以自动为给定链码生成高覆盖率的测试种子组,比较人工编写测试用例节省时间及相关资源。

为达到上述目的,本发明采用了以下技术方案:

一种链码测试种子生成方法,包括以下步骤:

获取链码程序中目标函数的相关信息,并为该目标函数生成一个测试文件;

将目标函数的全排列种子组中的种子依次执行测试文件,得到每个种子产生的覆盖率;选择覆盖率最高的种子作为初始种子;

将初始种子中的整型数字分别进行可设置固定时长的优化处理,确定最终种子;

保存链码程序中所有目标函数的最终种子,输出链码测试种子。

作为本发明的进一步改进,链码程序中目标函数的相关信息采用抽象语法树方法或正则表达式获得。

作为本发明的进一步改进,所述全排列种子组是指每次尝试使用若干个(如1~6个)参数,且每个参数的取值有两种情况,一是数字,二是非数字的字符串,依次对这两种情况进行排列组合得到全排列种子组。

作为本发明的进一步改进,选出覆盖率最高的种子作为初始种子时,如果有几个种子都产生最高的覆盖率,则选择其中含数字的数量最少的种子作为初始种子;

所述初始种子在格式上要求符合当前函数的参数格式。

作为本发明的进一步改进,将初始种子中的整型数字分别进行可设置固定时长的优化处理具体是:

只对初始种子中的数字依次进行可设置固定时长的优化处理,更新整型参数的值,使得相应的初始种子的覆盖率提高;如果初始种子中没有数字,则初始种子作为最终种子。

作为本发明的进一步改进,将初始种子中的整型数字分别进行可设置固定时长的优化处理,采用Double Q-Learning算法、Deep Q-Learning算法或Q-Learning算法。

作为本发明的进一步改进,还包括验证步骤:

使用每个目标函数的最终种子,分别运行对应的单元测试文件,得出这组种子产生的总覆盖率;如果总覆盖率值不满足要求,调整优化处理的参数重新获取最终种子。

将初始种子交给FCQ-learning模块进行优化,从而得到最终种子。

一种链码测试种子生成系统,包括:

测试文件生成单元,用于获取链码程序中目标函数的相关信息,并为该目标函数生成一个测试文件;

初始种子选择单元,用于将目标函数的全排列种子组中的种子依次执行测试文件,得到每个种子产生的覆盖率;选择覆盖率最高的种子作为初始种子;

最终种子确定单元,用于将初始种子中的整型数字分别进行可设置固定时长的优化处理,确定最终种子;

测试种子输出单元,用于保存链码程序中所有目标函数的最终种子,输出链码测试种子。

一种电子设备,包括存储器、处理器以及存储在所述存储器中并可在所述处理器上运行的计算机程序,所述处理器执行所述计算机程序时实现所述链码测试种子生成方法的步骤。

一种计算机可读存储介质,所述计算机可读存储介质存储有计算机程序,所述计算机程序被处理器执行时实现所述链码测试种子生成方法的步骤。

本发明的有益效果体现在:

本发明针对Hyperledger Fabric区块链平台上智能合约(链码,chaincode),以覆盖率为结果选择,得到每个种子产生的覆盖率;选择覆盖率最高的种子作为初始种子;并通过优化处理得到最终种子,生成高覆盖率输入的方法。该方法可以给不同的链码生成高覆盖率的种子输入,有了能产生较高覆盖率的种子输入,就可以提高漏洞检测的准确性,降低漏报率。另外,格式良好的种子输入,也可以帮助模糊测试更快地发现程序中的一些未知漏洞。本发明是针对链码的、从函数级别生成测试种子的方法。自动为给定链码生成高覆盖率的测试种子组,比较人工编写测试用例节省时间及相关资源。

进一步,引入抽象语法树技术获取代码中的信息,比使用正则表达式具有更高的准确度和效率。

进一步,本发明对强化学习中的Q-Learning算法做出适当修改,并将其应用到种子生成方法中。

进一步,可以根据覆盖率值判断本次生成输入的优良与否。如果覆盖率够高,可以降低漏洞检测工具如afuzzer的漏报率。

附图说明

图1为示例链码程序示意图一;

图2为示例链码程序示意图二;

图3为链码生成高覆盖率种子的总流程;

图4为链码片段示例;

图5为Go语言单元测试示意图;

图6为本发明优选实施例的FCQ-learning模块的算法流程;

图7为FCQ-learning算法举例示意图;

图8为一种链码测试种子生成系统结构示意图;

图9为电子设备结构示意图;

图10为本发明链码测试种子生成方法示意图。

具体实施方式

本发明基于强化学习和模糊测试,提出了一种为Hyperledger Fabric链码自动生成高覆盖率种子输入的方法,也可以看作是对链码进行模糊测试时对模糊测试流程中“生成种子输入”这一步骤的优化。

其中,模糊测试流程一般分为以下四个主要步骤:

1.寻找Fuzz target(即要对什么程序、函数进行模糊测试);

2.编写/生成测试用例(种子输入);

3.将生成的种子输入提供给程序,然后运行程序,直到发现错误或者crash情况(不断对种子进行变异,不停地运行程序);

4.重现crash/分析结果/锁定漏洞原因和位置。

名词解释:

单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。对于单元测试中单元的含义,一般来说,要根据实际情况去判定其具体含义,如C语言中单元指一个函数,Java里单元指一个类,图形化的软件中可以指一个窗口或一个菜单等。总的来说,单元就是人为规定的最小的被测功能模块。单元测试是在软件开发过程中要进行的最低级别的测试活动,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试。

为了方便描述本文的方法,下面引入一个示例链码程序(此处不需要关注链码中每条语句是否具有实际意义):

图1和图2为示例链码程序示意图。

可以看到,该链码的包名(package name)为sacc,其中主要包括Init()、Invoke()方法和set()、get()方法。与以太坊上的智能合约不同,以太坊上的智能合约中每个函数都可以通过其函数名被交易调用。而根据Fabric链码编写规范,链码中只有Init()和Invoke()两个方法是暴露给用户的接口,可以由用户调用。链码中的其他方法都是在用户发起一笔交易时,作为Invoke()的参数被间接调用的。(当然除了set()和get()外还可以定义其他任意的方法,但这些方法并不要求全部都由Invoke()间接调用,为了实现更复杂的逻辑,它们之间也可以相互调用)。

因此,这里本申请重点关注Invoke()接口中调用到的函数,再加上对Init()接口做一些特殊处理,而且main()函数的书写格式基本是固定的(对其进行单元测试意义不大)。总体来说,本文方法所生成的测试种子组可以从函数级别覆盖整个链码程序的测试要求。

由于智能合约中的每个函数都可以通过链码中的Init()初始化函数和Invoke()功能调用函数被间接调用(主要是Invoke),因此,针对一个Fabric链码程序,本发明从函数级别为一个链码里的每个函数分别生成测试种子。具体说明如下:

如图10所示,本发明第一个目的是提供一种链码测试种子生成方法,包括以下步骤:

获取链码程序中目标函数的相关信息,并为该目标函数生成一个测试文件;

将目标函数的全排列种子组中的种子依次执行测试文件,得到每个种子产生的覆盖率;选择覆盖率最高的种子作为初始种子;

将初始种子中的整型数字分别进行可设置固定时长的优化处理,确定最终种子;

保存链码程序中所有目标函数的最终种子,输出链码测试种子。

该方法可以给不同的链码生成高覆盖率的种子输入,有了能产生较高覆盖率的种子输入,就可以提高漏洞检测的准确性,降低漏报率。另外,格式良好的种子输入,也可以帮助模糊测试更快地发现程序中的一些未知漏洞。

作为优选实施例,链码程序中目标函数的相关信息采用抽象语法树方法获得。

也可以考虑使用正则表达式获取关键信息。本发明引入抽象语法树技术获取代码中的信息,比使用正则表达式具有更高的准确度和效率。

将目标函数的全排列种子组中的种子依次执行测试文件具体是:

将目标函数的全排列种子组中的种子进行排列形成全排列种子组,用全排列种子组中的种子依次执行测试文件;全排列种子组是指每次尝试使用1~6个参数,且每个参数的取值有两种情况,一是数字,二是非数字的字符串,依次对这两种情况进行排列组合得到全排列种子组。

选出覆盖率最高的种子作为初始种子时,如果有几个种子都产生最高的覆盖率,则选择其中含数字的数量最少的种子作为初始种子;所述初始种子在格式上要求符合当前函数的参数格式。

将初始种子中的整型数字分别进行可设置固定时长的优化处理具体是:

只对初始种子中的数字依次进行可设置固定时长的优化处理,通过为整型参数找到一个合适的值,提高初始种子产生的覆盖率;如果初始种子中没有数字,则初始种子作为最终种子。

本发明自动为给定链码生成高覆盖率的测试种子组,比较人工编写测试用例节省时间及相关资源。在Hyperledger Fabric平台上不存在其他生成高覆盖率种子的工具。

本发明针对Hyperledger fabric区块链平台上的go语言链码,结合Fabric链码编写规范和单元测试,为链码程序生成高覆盖率的优良测试种子。(根据覆盖率对种子输入是否优良进行评判)。

因此,如图10所示,本发明还包括验证步骤:

使用每个目标函数函数的最终种子,运行对应的单元测试文件,得出这组种子产生的总覆盖率;如果对总覆盖率值不满意,可以调整参数重新获取最终种子。

将初始种子交给FCQ-learning模块进行优化,从而得到最终种子。

以下结合具体实施例和附图对本发明的方法过程进行详细说明。

实施例1

1)如图3所示,本发明首先通过采用抽象语法树技术,获取到链码程序中某个目标函数的一些相关信息,然后为该函数生成一个测试文件。该测试文件是可以接收参数的、可运行的,通过go test及其子命令运行测试文件可以获取传递进来的参数所产生的覆盖率信息和覆盖率值。需要注意的一点:通过观察上述示例链码,可以发现,我们无法从函数头得知Invoke调用一个函数时需要传递的参数的个数以及类型。因此,通过观察收集到的链码,我们每次尝试使用1~6个参数(注意:这里的参数个数是可以人为设置的,所以如果有特殊需要,可以进行修改),且每个参数的取值有两种情况,一是数字,二是字符串(但是在调用链码时,数字和字符串都是以字符串形式传递的)。通过多次传递不同个数及形式的参数,可以选出一个初始种子,初始种子在格式上基本是符合当前函数的参数格式的。最后,再借助强化学习中的Q-Learning算法,对初始种子中的整型数字分别进行可设置固定时长的处理。通过为整型参数找到一个合适的值,来进一步提高测试种子产生的覆盖率,最终得到一个覆盖率较高的测试种子。

2)最后一步,同时使用为每个函数生成的最终测试种子,运行其对应的单元测试文件,得出这组种子产生的总覆盖率。如果对总覆盖率值不满意,可以将强化学习部分处理时间延长。

3)针对基于Go语言实现的链码程序,自动生成高代码覆盖率的测试种子。

4)下文结构如下:1.对Go语言实现的链码结构进行说明;2.单元测试文件示例及说明;3.为链码生成高覆盖率测试种子的总流程及关键细节说明;3.FCQ-learning算法的介绍说明

5)1.Go语言实现的链码结构:

6)链码(chaincode)是执行在Hyperledger fabric平台上的智能合约程序。支持使用Go,node.js或java编程语言实现。编译后的chaincode可以在Hyperledger fabric上执行。通过执行链码,可以产生交易(transaction)来初始化或者更新区块链账本(ledger)。本部分通过下面的链码片段来对链码的结构进行简要叙述。

图4为链码片段示例。以图4中链码片段示例,任何链码在实现的时候都需要至少实现Init和Invoke两个程序接口。当链码进行初始化交易时会执行Init方法,而当其进行执行交易时会执行Invoke方法。这两个方法归属于给定的链码对象,在此链码片段中指图中ChaincodeAsset结构体。

此外,链码需要调用shim接口中的ChaincodeStubInterface方法(图4中shim.ChaincodeStubInterface)来与账本或者其他区块链上的链码进行交互,在图链码片段中指Init与Invoke方法的输入参数stub。

单元测试文件示例及说明:

这里的单元测试,指的是对链码中某个函数的测试,即以函数为最小单位进行的测试。

Go语言单元测试需要遵守一下几点要求,否则就无法进行测试:

1.需要导入testing包;

2.单元测试文件以_test.go结尾;

3.测试用例的函数必须以Test开头,可选的后缀名必须以大写字母开头

以示例链码中的set()方法为例,本发明为其生成的单元测试文件set_test.go内容如下:

图5为Go语言单元测试示意图。

此处第01行的包名为sacc,其必须与链码的包名相同。并且,如果测试不是在go语言工作目录下的src文件夹下进行的,则测试文件包名不仅必须与链码包名相同,且必须都为main。

第09、10行是为了对fabric中提供的MockStub类进行实例化,得到一个stub变量。

MockStub主要提供两个函数来模拟背书节点对链码的调用:MockInit()和MockInvoke(),分别调用Init和Invoke接口。接收的参数均为类型为string的uuid(随便设置即可),以及一个二维byte数组(用于测试的参数)。

第12~16行是对Init函数的一个处理,是通过观察收集的链码及经验所得,这5种情况基本上涵盖了我们已知的Init函数的所有调用格式。

显而易见,第17行则是为了调用set函数,通过提供的参数对set函数进行测试。通过改变这一行的内容来对不同的函数进行测试、对同一个函数使用不同格式的参数进行测试。

以下为链码生成高覆盖率测试种子的总流程及关键细节说明:

实施例2

结合图3,本部分将展示本发明的总流程和部分关键技术细节。FCQ-learning算法将在下一部分(第4部分)给出。

本发明方法中生成的测试文件中利用了Hyperledger Fabric官方开发套件(SDK)提供的模拟测试接口(MockAPI)。当给测试文件提供合适的测试用例之后,可以对链码进行模拟运行,此运行过程是严格模拟真实链上运行环境的,可以完成链码功能验证以及覆盖率统计。

给定一个链码文件,首先,本发明借助抽象语法树技术,从链码程序中提取所需的信息(如包名、结构体名、函数名等),然后,下面的第(1)、(2)、(3)步骤对于Invoke中调用的函数可以是并行的:

(1)为每个Invoke接口中调用的函数单独生成一个类似前述set_test.go文件的测试文件;

(2)使用由经验所得的“全排列种子组”中的种子,依次执行测试文件,同时可以得到每个种子产生的覆盖率。因为通过观察收集到的链码程序,发现其中函数的参数都不超过6个,所以这里的全排列种子组便为:{[“a”],[“0”],[“a”,“a”],[“a”,“0”],[“0”,“a”],[“0”,“0”],……,[“a”,“a”,“a”,“a”,“a”,“a”],……,[“0”,“0”,“0”,“0”,“0”,“0”]},共126个。就使用这126个种子执行测试文件,选出覆盖率最高的那个作为初始种子。如果有几个种子都可以产生最高的覆盖率,则选择其中”0”的数量最少的,这样可以减少由初始种子获得最终种子的负担;(如对于示例链码中的set()函数,选出来的处置种子就会是[“a”,“0”])

(3)将初始种子交给FCQ-learning模块进行优化,从而得到最终种子。因为区块链可以看作是分布式的数据库,对于Hyperledger Fabric底层使用的LevelDB数据库,支持key-value类型数据的存储,种子中的字符串“a”一般都是作为“键”,而整型变量“0”一般都是作为“值”。因为改变“键”不会影响覆盖率的值,而改变“值”则可以对覆盖率产生影响,所以FCQ-learning借助Q-Learning算法,只对初始种子中的“0”依次进行处理——如果初始种子中没有“0”,则FCQ-learning步骤可省略,初始种子作为最终种子返回;

(4)获取所有Invoke接口调用的函数的最终种子之后,使用这些种子为每个函数再次生成测试文件,同时执行所有测试文件,即可得到这组种子所产生的总覆盖率。如果这个覆盖率过低或不符合要求,则可以在第三步增加优化时长。

作为具体实施例,本发明给出FCQ-learning模块算法的介绍说明:

下面就是对FCQ-learning算法的详细描述:(FCQ-learning是Fabric ChaincodeQ-Learning的缩写)

图6为FCQ-learning算法流程。结合以下算法和图6进行说明。

需要再说明两点:

(1)算法中奖励R的计算:R=NOW_COV–LAST_COV,其取值可能为正、负或0;

(2)FCQ-learning部分使用到的测试文件格式(仍然以set()方法为例),代码如下:

图7为算法举例示意图,其中*arg就代表FCQ-learning模块每次传进来的不同参数。

当然,本申请的算法还可以尝试使用Double Q-Learning或者Deep Q-Learning等算法替换Q-Learning算法。

如图8所示,本发明的另一目的在于提出一种链码测试种子生成系统,包括:

测试文件生成单元,用于获取链码程序中目标函数的相关信息,并为该目标函数生成一个测试文件;

初始种子选择单元,用于将目标函数所在链码程序中的种子依次执行测试文件,得到每个种子产生的覆盖率;选择覆盖率最高的种子作为初始种子;

最终种子确定单元,用于将初始种子中的整型数字分别进行可设置固定时长的优化处理,确定最终种子;

测试种子输出单元,用于保存链码程序中所有目标函数的最终种子,输出链码测试种子。

如图9所示,本发明第三个目的是提供一种电子设备,包括存储器、处理器以及存储在所述存储器中并可在所述处理器上运行的计算机程序,所述处理器执行所述计算机程序时实现所述链码测试种子生成方法的步骤。

本发明第四个目的是提供一种计算机可读存储介质,所述计算机可读存储介质存储有计算机程序,所述计算机程序被处理器执行时实现所述链码测试种子生成方法的步骤。

本领域内的技术人员应明白,本发明的实施例可提供为方法、系统、或计算机程序产品。因此,本发明可采用完全硬件实施例、完全软件实施例、或结合软件和硬件方面的实施例的形式。而且,本发明可采用在一个或多个其中包含有计算机可用程序代码的计算机可用存储介质(包括但不限于磁盘存储器、CD-ROM、光学存储器等)上实施的计算机程序产品的形式。

本发明是参照根据本发明实施例的方法、设备(系统)、和计算机程序产品的流程图和/或方框图来描述的。应理解可由计算机程序指令实现流程图和/或方框图中的每一流程和/或方框、以及流程图和/或方框图中的流程和/或方框的结合。可提供这些计算机程序指令到通用计算机、专用计算机、嵌入式处理机或其他可编程数据处理设备的处理器以产生一个机器,使得通过计算机或其他可编程数据处理设备的处理器执行的指令产生用于实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能的装置。

这些计算机程序指令也可存储在能引导计算机或其他可编程数据处理设备以特定方式工作的计算机可读存储器中,使得存储在该计算机可读存储器中的指令产生包括指令装置的制造品,该指令装置实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能。

这些计算机程序指令也可装载到计算机或其他可编程数据处理设备上,使得在计算机或其他可编程设备上执行一系列操作步骤以产生计算机实现的处理,从而在计算机或其他可编程设备上执行的指令提供用于实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能的步骤。

最后应当说明的是:以上实施例仅用以说明本发明的技术方案而非对其限制,尽管参照上述实施例对本发明进行了详细的说明,所属领域的普通技术人员应当理解:依然可以对本发明的具体实施方式进行修改或者等同替换,而未脱离本发明精神和范围的任何修改或者等同替换,其均应涵盖在本发明的权利要求保护范围之内。

去获取专利,查看全文>

相似文献

  • 专利
  • 中文文献
  • 外文文献
获取专利

客服邮箱:kefu@zhangqiaokeyan.com

京公网安备:11010802029741号 ICP备案号:京ICP备15016152号-6 六维联合信息科技 (北京) 有限公司©版权所有
  • 客服微信

  • 服务号