最近针对区块链的“币圈”进行了一个小范围的资料阅读与研究,学习总结了一些安全方面的知识。通过对“币圈”发生的一些重大安全事件的研究,我也接触了许多“激励层”方面的知识。希望将内容简单的总结于此。
通过这几个月的对区块链知识的学习,我提炼前人的话简单的对区块链进行总结——简单来说区块链为“去中心化”+“Token机制”的结合。而去中心化我们在这里先不谈,我们就主要讨论下这个Token机制(激励机制)中蕴含的思想。
下面,我将从比特币、以太币入手,并引出与激励层相关的安全攻击—Race To Empty。
区块链本质是分布式共识与价值激励相结合的产物,它一个方面通过密码学等数学运算来提供各个节点的共识;另一个方面通过激励机制保证了区块链生态圈的平衡发展。大家都知道,区块链的核心理念就是去中心化(即所有节点遵循同一种共识,并对任何事情达成一致性看法)。而通过对区块链的了解中我们也发现区块链的各个节点就如同社会中的个人一样,只有在有“人”存在的条件下,整个社区才会有可能欣欣向荣。而如何提高整个社会的运作效率、如何让人们更乐意去工作去付出是我们要考虑的事情。对于社会来说,金钱(虽然俗气但是确实最好的方法)是push人们实现价值的最好动力。在区块链这个小的社区中也是如此,它借鉴了人类社会的发展模式,通过提供一些奖励使各个节点更努力的去工作(下面会根据不同货币进行相关讲解)。
在去中心化系统中,共识节点本身是有机会获得相应的奖励,各个节点消耗自身资源参与数据验证和记账的根本目的是使自己的利益最大化。为保证去中心化系统的安全有效的良性运转,我们必须引入符合经济模型的激励机制,使各方能跨越组织信任边界,建立一种无界、协同的发展生产关系,并使更多节点加入进来共同维持系统的正常运转。
对此,区块链的设计理念中引入了数字通证(Token)作为激励。由于没有中心节点,所以账本的维护就成为了各个节点有义务所作的工作,而我们对于记账的节点可以进行相应的币值奖励,以此来推动生态的平稳发展。
密码共识机制是比特币赖以实现去中心化的那套技术和协议,也就是所谓“区块链”,实际的区块链仅仅是这个机制中的一项次要技术。比特币和以太坊是依据密码共识机制设计的去中心化的密码共识平台。token是这些密码共识平台的产品,是通过比特币或以太坊等公链提供的协议、脚本、节点、软件等设计、创建、发行和流通的信用凭证。比特币或以太坊平台的密码共识机制尽管没有改变token的信用本质,但让整个发行和流通过程变得公开透明,从而更加可信。离开了通过密码共识机制建立的去中心化平台,token就跟游戏金币、Q币、商城积分等没什么差别了。
借助于以太坊和比特币发行的token为什么就比传统token有这么大的影响力呢?关键在于,这些token一经发行就可以在完全开放的比特币和以太坊平台上,通过近乎完全自由的比特币和以太币进行交易,并且很容易进入中心化的交易平台进行大规模撮合交易。也就是说,token借助于它所依附的较成熟的密码货币系统,获得了传统token难以获得的巨大流动性。
从技术细节上看,token跟传统token的一个重要差别在于,新的token利用非对称密码技术的公私钥确认权属。公钥在密码共识系统中记录token数量及其转移方向,用户持有的私钥确定对应公钥的token的归属,并对转移进行签名授权,而不需要依赖第三方来见证和确认,可以说是“去中介”。不过,离开了“共识”(即分布式共识),单纯的“密码”应用无法让token获得上述自由发行便利和强大的流动性。“密码共识”才是token的基础(比特币或以太坊)的基础。
详细可参看对token的解读
比特币、以太币以及其他各种虚拟代币(token),正是区块链具备激励功能的体现。中本聪所设计的区块链是试验之作,本身并无商业价值,为了引起关注、发展联结点,同时激励参与者不断通过“挖矿”式计算来创建新的区块,共同维护链条的延展存续,他必须要给予为此而做出努力的人以“报酬”。所以,在每一次“挖矿”成功并得到确认之后,新的区块形成,而公认胜出的“挖矿”者则获得token,并被记入公共账本。中本聪将这种本质上属于一段计算机程序的奖励命名为“比特币(Bitcoin)”,这种命名暗合了现实社会中人们关于货币的各种意念,从而使区块链被误认为是一种造钱的计算机程序,比特币因此而风靡于世,并且还催生出一波虚拟货币热潮。
比特币系统是典型的通过经济激励机制实现自我驱动的系统。其可靠性依靠了整个系统中所有节点的共同算力,由此,比特币系统不需要任何中心机构维持其信用而只需要技术手段就可以创建共识。
首先,我们可以总结为挖矿节点收取的手续费。通过打包交易所产生的激励为一个区块中包含的所有交易费用。具体来说,比特币交易的手续费不取决于交易金额,而是按照用户交易的每千字节收取0.0001BTC(比特币)的价格。除此之外,为了防止通货膨胀,比特币的发行量每4年减半,总量为2100万枚。当达到数额时(预计为2140年),矿工便不能够通过获得系统的记账奖励来获得比特币,而是只能通过系统中的手续费来生存。
而除了发币激励之外,系统还存在交易规则。首先矿工会优先处理高优先级的交易。区块中前50kb是保留给高优先级交易的。那么怎么评判优先级的高低呢?其通过币的新旧、交易字节数、交易币数量总和决定(有点像操作系统中进程的管理算法)。具体计算公式为:priority = sum(input_value_in_units * input_age) / size_in_bytes
。如何值大于0.576则为高优先级。简单来说,随着新区块的产生,留在内存池中未被打包的交易年龄越来也大,最终优先级会提高。之后会按照矿工费用排序交易。由高到底排序。
与所有基于区块链技术的去中心化系统一样,以太坊也有一套自己的激励机制,用以鼓励矿工花费计算资源进行挖矿,而这一机制就是以太币。
以太坊最小货币单位是wei,以太币与其兑换率为1Ether = 10^18wei。每个区块被挖出,那么相应矿工会获得一定的奖励,而奖励由两个部分组成:
①矿工在获得记账权后可以获得5个以太币的奖励。
②除了上面的静态奖励,我们还有动态奖励。首先记账的区块中所有的交易费用归矿工所有,除此之外,矿工还可以从每个叔区块中获得额外的1/32以太币的奖励。
那么以太币与比特币的区别又是什么呢?下面我们来看一看“叔区块”的概念。
在这里,叔区块是指那些没有在最长的那条链上,而是分叉链上挖出的有效区块。由于各个节点是各自独立的工作,就有可能出现两个独立的矿工先后发现了两个不同的满足要求的区块,被称为临时分叉。以太坊采用这种机制而分散中心挖矿的现象(即最大矿池垄断区块生产,导致单个矿工总是落后矿池的区块信息的情况)。采用这种机制,即使单个分散节点没有大矿池挖矿速度快,那他们也会有相应的奖励。
例如下图,区块二先挖到2,而区块一速度慢一些。但是当区块3生成的时候,3中会将黄色与红色两个都记录下来(黄色为叔块)。
更例如下:
如上图说是,当打包102的时候,发现还有个黄色的101也指向自己(102)的爷爷(100),那么黄色的101就是一个叔块(当然这个是最高级别的叔块,如果打包102的时候还没有黄色的101,打包103的时候才发现黄色的101,那么黄色的101也是会当做区块打包到103内,区别是黄色101区块的生产者获得奖励不同)
而我们为什么要有叔块的概念呢?
比特币里面是没有叔块概念的,叔块是以太坊中引进的,至于为什么要引进叔块的概念,是与以太坊的缩短出块时间有关。比特币平均出块时间间隔为10分钟,出现叔块的情况概率比较小,当时中本聪设定的这种情况的叔块是做无用功,不会有任何奖励。但是以太坊为了缩短出块时间到10s出头,那么叔块产生的概率就比较高了,如果类似比特币的设计,会有很多矿工因为生产了叔块而获取不到任何奖励,矿工的积极性会降低,不利于以太坊生态发展,所以V神引入了叔块的概念,这种情况下矿工打包叔块进区块,叔块生产者和打包叔块的矿工都会有一定的奖励。
具体的叔块的介绍我们参考以太坊叔块相关(包括叔块的特性、奖励金额等)
叙述完了上述的以太坊激励机制,那我们现在可以想象一下,因为以太坊赋予用户使用solidity来编写自己的智能合约。倘若某天恶意用户部署无限循环的运行合约,那么我们系统就要承担巨大的流量。那么如何解决这个问题呢?于是我们引入了gas机制。
如果我们让程序的每条指令都要消耗一点儿“资源”,“资源”用光了,无论程序执行完没有,都会被强行终止,这样无论是不是死循环都没关系了。这样是不是就使用一种外力来制约恶意节点了。
具体来说,部署只能合约每一步需要支付1Gas,停止合约不需要支付,创建合约需要100Gas而合约交易需要支付500Gas。因此,Gas就相当于部署和执行只能合约所需的燃料,没有燃料就无法使用只能合约。
在以太坊中,每种操作所需要的Gas由以太坊的设计者决定以确保系统的正常运行。但是每个合约所需要的费用不是完全固定的,不同的用户有不同的需求,有的希望交易能够快速确认(优先级概念),有的希望用较少的以太币执行合约。因此“Gas的价格”与“以太币”有相应的兑换率。Gas价格可由用户自行定义,价格定的越高,交易被确认的越快。这样以Gas来与以太币挂钩作为一种激励,给与用户DIY的权利,并维护了以太坊生态的平稳进行。
对于复杂的运算,需要消耗的Gas越多,只要给程序加上一个消耗Gas的上限,就可以防止程序出现死循环而不能停止的情况了。同时,以太坊还给每个区块包含的程序消耗的总Gas设定了上限,以免区块中包含的程序过多,影响一些性能比较弱的节点。每个区块能消耗的Gas上限也是可以调整的,由矿工们进行投票决定。每个程序需要为Gas支付的以太币可以用如下公式计算:Gas花费 = 消耗的Gas数量 x Gas的价格
Gas机制降低了以太坊的恶意情况产生,不过仍然还是会存在恶意攻击绕过了gas机制并带来了严重后果的情况。之后我会针对激励层机制来分析相关恶意事件,下面就先简单的介绍下区块链中的Race-to-empty攻击类型
对于Race-To-Empty攻击,我们从字面简单分析。
race简单来看是一种快速的动作
,而 to empty意思是导致为空
。而我对这种攻击的理解是——用一种攻击方法,通过多次快速的调用某个代码致使被攻击者的账户中有用资产为空的情况。
这里我们简单的引出相关攻击手法。我们引用一个简单的例子来说明。(尽量简洁易理解)
function getBalance(address user) constant returns(uint) {
return userBalances[user];
}
function addToBalance() {
userBalances[msg.sender] += msg.amount;
}
function withdrawBalance() {
amountToWithdraw = userBalances[msg.sender];
if (!(msg.sender.call.value(amountToWithdraw)())) { throw; }
userBalances[msg.sender] = 0;
}
我们可以暂时规定msg.sender.call.value()
函数被调用的时候,系统会默认执行一个默认函数Function。我们将其定义如下:
function () {
vulnerableContract v;
uint times;
if (times == 0 && attackModeIsOn) {
times = 1;
v.withdraw();
} else { times = 0; }
}
由上面的内容我们可以有所发现,当withdrawBalance ()
方法被执行的时候,我们里面会执行msg.sender.call.value(amountToWithdraw)())
,此时我们会默认执行function ()
方法。加入我们function方法中定义了withdraw()方法(即我进行了回调)。此时就类似于递归的感觉了,这也是攻击成功的原因之一。
函数入栈情况如下:
withdraw run 1st
attacker function run 1st
withdraw run 2rd
attacker function run 2rd
.........(后面会无限执行这两个方法,这也就是为什么叫race的原因)
大家了解了这个攻击手段后,我会在之后的文章中介绍有关此攻击的具体例子。
在此,感谢参考文献race-to-empty
3 https://vessenes.com/more-ethereum-attacks-race-to-empty-is-the-real-deal/
4 https://blog.csdn.net/cherisegege/article/details/80146273
本稿为原创稿件,转载请标明出处。谢谢。