您的位置:首页 > 区块链 >

实现基于Horn子句的检查引擎 能提高SMTChecker的证明能力

2019-08-07 14:12:40 来源: 区块网

SMTChecker当前模型检查引擎是安全但还不是很完整的。这意味着报告为安全的断言和其他验证目标应该是安全的 - 除非SMTChecker或后端解算器中

SMTChecker当前模型检查引擎是安全但还不是很完整的。这意味着报告为安全的断言和其他验证目标应该是安全的 - 除非SMTChecker或后端解算器中存在bug-但是误报可能是虚假的抽象。

当前引擎给出的反例中的两个主要误报源是:

· 循环以有界的方式处理(只考虑一次迭代)。

· 函数在各自的环境中单独分析。

因此在SMTChecker分析时,依赖于程序逻辑循环或在不同函数中使用状态变量的智能合约可能会导致误报。

为了提高SMTChecker的证明能力并减少误报,我们最近实现了一个基于Horn子句系统的新模型检查引擎,能够推理循环和状态变量之间的关系。请注意,智能合约的生命周期也可以建模为以下循环,其中每个循环迭代都是一个事务:

constructor(...);

while(true)

random_public_function(...);

新引擎的目标是自动推断循环和状态不变量,同时尝试证明安全属性,消除了前面写的额外假设的需要。

我们可以通过分析前一篇文章中的相同合同立即看到结果,而无需额外的假设:

pragma experimental SMTChecker;

contract C {

uint sum;

uint count;

function () external payable {

require(msg.value > 0);

// Avoid overflow.

require(sum + msg.value >= sum);

require(count + 1 > count);

sum += msg.value;

++count;

}

function average() public returns (uint) {

require(count > 0);

uint avg = sum / count;

assert(avg > 0);

return avg;

}

}

SMTChecker现在试图证明断言考虑整个合同和无限数量的交易,而不是仅执行一次函数平均。它自动学习合约不变量(count> 0)=>((sum / count)> 0),它保存在每个函数的开头和结尾,并且能够证明所需的属性。我的笔记本电脑上的支票需要0.16秒。

如果我们用uint avg = count / sum替换除法,这显然打破了断言,我们得到以下反例:

(and

(function_average_68_0 2 1 0 0)

(interface_C_69_0 2 1)

(fallback_42_0 0 0 2)

(interface_C_69_0 0 0)

)

这是多事务自下而上路径的内部表示,导致断言失败的地方

(interface_C_69 )是合约的空闲状态,以下数字分别是状态变量sum和count的当前值。(fallback_42_0 )是对回退函数的调用。

(function_average_60_8 )是对函数平均值的调用。

在合约构造之后,sum和count都是0.第一个事务使用msg.value = 2调用回退函数,这导致sum = 2和count = 1.第二个事务调用函数average,其中(count / sum)= 0。检查需要0.14秒。

除了合约不变量之外,引擎还尝试总结while和for循环内部的函数。它可以很快证明关于循环行为的简单属性,但问题也很容易变得太难。记住,这是一个不可判定的问题:)

function f(uint x) public pure {

uint y;

require(x > 0);

while (y < x)

++y;

assert(y == x);

}

上述断言在0.05s内得到证实。

function f() public pure {

uint x = 10;

uint y;

while (y < x)

{

++y;

x = 0;

while (x < 10)

++x;

assert(x == 10);

}

assert(y == x);

}

上面的断言涉及一个更复杂的结构和嵌套的循环,并在0.375中得到证明。

uint[] a;

function f(uint n) public {

uint i;

while (i < n)

{

a[i] = i;

++i;

}

require(n > 1);

assert(a[n-1] > a[n-2]);

}

即使上面的代码也使用数组,断言只涉及数组的两个元素,检查只需0.16秒。

function max(uint n, uint[] memory _a) public pure returns (uint) {

require(n > 0);

uint i;

uint m;

while (i < n) {

if (_a[i] > m)

m = _a[i];

++i;

}

i = 0;

while (i < n) {

assert(m >= _a[i]);

++i;

}

return m;

}

上面的函数计算并返回数组的最大值。数组的长度作为参数给出,因为.length尚不支持。这种检查要复杂得多,因为它检查计算出的最大值是否确实大于或等于无界数组的所有元素。

编辑:在写这篇文章时,这个断言序列在1小时超时后无法证明。调整一些量化求解器参数后,检查在0.13秒后成功!

如果我们将断言更改为断言(m> _a [i]),则给定的反例是数组[0,0]。

另一个与状态机更相似的例子是以下Crowdsale架构:

pragma experimental SMTChecker;

contract SimpleCrowdsale {

enum State { INIT, STARTED, FINISHED }

State state = State.INIT;

uint weiRaised;

uint cap;

function setCap(uint _cap) public {

require(state == State.INIT);

require(_cap > 0);

cap = _cap;

state = State.STARTED;

}

function () external payable {

require(state == State.STARTED);

require(msg.value > 0);

uint newWeiRaised = weiRaised + msg.value;

// Avoid overflow.

require(newWeiRaised > weiRaised);

// Would need to return the difference to the sender or revert.

if (newWeiRaised > cap)

newWeiRaised = cap;

weiRaised = newWeiRaised;

}

function finalize() public {

require(state == State.STARTED);

assert(weiRaised <= cap);

state = State.FINISHED;

}

}

当state为INIT时,函数setCap只能调用一次。 当state为STARTED时,后备函数接受多个存款(在此模拟中不发出令牌)。 Crowdsale可以在函数finalize中最终确定,它确保不会破坏cap。

分析自动学习不变的weiRaised <= cap,证明了断言。 检查需要0.09秒。

如果我们将正确的断言更改为断言(weiRaised

(and

(function_finalize_107_0 1 1 1)

(interface_SimpleCrowdsale_108_0 1 1 1)

(fallback_85_0 1 0 1 0)

(interface_SimpleCrowdsale_108_0 1 0 1)

(function_setCap_42_0 0 0 0 1)

(interface_SimpleCrowdsale_108_0 0 0 0)

)

这种自下而上的内部表示遵循与第一个示例中所示格式相同的格式。 所有状态变量都从0开始。第一个tx调用setCap(1),它导致state = State.START和cap = 1.第二个tx用msg.value = 1调用回退函数,它将weiRaised修改为1.最后, 第三个tx调用finalize并且断言失败。 检查需要0.08秒。

这些初步实验表明新引擎可能能够合理地快速地自动证明涉及多tx行为的复杂属性。(链三丰)

关键词: Horn子句 检查引擎 SMTChecker

精选 导读

募资55亿港元万物云启动招股 预计9月29日登陆港交所主板

万科9月19日早间公告,万物云当日启动招股,预计发行价介乎每股47 1港元至52 7港元,预计9月29日登陆港交所主板。按发行1 167亿股计算,万

发布时间: 2022-09-20 10:39
管理   2022-09-20

公募基金二季度持股情况曝光 隐形重仓股多为高端制造业

随着半年报披露收官,公募基金二季度持股情况曝光。截至今年二季度末,公募基金全市场基金总数为9794只,资产净值为269454 75亿元,同比上

发布时间: 2022-09-02 10:45
资讯   2022-09-02

又有上市公司宣布变卖房产 上市公司粉饰财报动作不断

再有上市公司宣布变卖房产。四川长虹25日称,拟以1 66亿元的转让底价挂牌出售31套房产。今年以来,A股公司出售房产不断。根据记者不完全统

发布时间: 2022-08-26 09:44
资讯   2022-08-26

16天12连板大港股份回复深交所关注函 股份继续冲高

回复交易所关注函后,大港股份继续冲高。8月11日大港股份高开,随后震荡走高,接近收盘时触及涨停,报20 2元 股。值得一提的是,在7月21日

发布时间: 2022-08-12 09:56
资讯   2022-08-12

万家基金再添第二大股东 中泰证券拟受让11%基金股权

7月13日,中泰证券发布公告,拟受让齐河众鑫投资有限公司(以下简称齐河众鑫)所持有的万家基金11%的股权,交易双方共同确定本次交易的标的资

发布时间: 2022-07-14 09:39
管理   2022-07-14

央行连续7日每天30亿元逆回购 对债市影响如何?

央行12日再次开展了30亿元逆回购操作,中标利率2 10%。这已是央行连续7日每天仅进行30亿元的逆回购缩量投放,创下去年1月以来的最低操作规

发布时间: 2022-07-13 09:38
资讯   2022-07-13

美元指数创近20年新高 黄金期货创出逾9个月新低

由于对美联储激进加息的担忧,美元指数11日大涨近1%创出近20年新高。受此影响,欧美股市、大宗商品均走弱,而黄金期货创出逾9个月新低。美

发布时间: 2022-07-13 09:36
资讯   2022-07-13

美股三大股指全线下跌 纳斯达克跌幅创下记录以来最大跌幅

今年上半年,美股持续回落。数据显示,道琼斯指数上半年下跌15 3%,纳斯达克综合指数下跌29 5%,标普500指数下跌20 6%。其中,纳斯达克连续

发布时间: 2022-07-04 09:51
推荐   2022-07-04

融资客热情回升 两市融资余额月内增加超344亿元

近期A股走强,沪指6月以来上涨4%,融资客热情明显回升。数据显示,截至6月16日,两市融资余额1 479万亿元,月内增加344 67亿元,最近一个半

发布时间: 2022-06-20 09:41
资讯   2022-06-20

4个交易日净买入超百亿元 北向资金持续流入A股市场

北向资金净流入态势延续。继6月15日净买入133 59亿元后,北向资金6月16日净买入44 52亿元。自5月27日至今,除6月13日以外,北向资金累计净

发布时间: 2022-06-17 09:37
推荐   2022-06-17