网站首页 > 要闻 > | 资讯详情
系统了解以太坊(二)挖矿和默克尔树
无限idea
2018-01-29 14:29

如果我们拥有可信任的中心化服务机构,状态转换系统可以很容易地实现,可以简单地将上述功能准确编码。然而,我们想把比特币系统建成为去中心化的货币系统,为了确保每个人都同意交易的顺序,我们需要将状态转换系统与一个共识系统结合起来。比特币的去中心化共识进程要求网络中的节点不断尝试将交易打包成“区块”。网络被设计为大约每十分钟产生一个区块,每个区块包含一个时间戳、一个随机数、一个对上一个区块的引用(即哈希)和上一区块生成以来发生的所有交易列表。这样随着时间流逝就创建出了一个持续增长的区块链,它不断地更新,从而能够代表比特币账本的最新状态。

依照这个范式,检查一个区块是否有效的算法如下:

检查区块引用的上一个区块是否存在且有效。

检查区块的时间戳是否晚于以前的区块的时间戳,而且早于未来2小时[2]。

检查区块的工作量证明是否有效。

将上一个区块的最终状态赋于S[0]。

假设TX是区块的交易列表,包含n笔交易。对于属于0……n-1的所有i,进行状态转换S[i+1] = APPLY(S[i],TX[i])。如果任何一笔交易i在状态转换中出错,退出程序,返回错误。

返回正确,状态S[n]是这一区块的最终状态。

本质上,区块中的每笔交易必须提供一个正确的状态转换,要注意的是,“状态”并不是编码到区块的。它纯粹只是被校验节点记住的抽象概念,对于任意区块都可以从创世状态开始,按顺序加上每一个区块的每一笔交易,(妥妥地)计算出当前的状态。另外,需要注意矿工将交易收录进区块的顺序。如果一个区块中有A、B两笔交易,B花费的是A创建的UTXO,如果A在B以前,这个区块是有效的,否则,这个区块是无效的。

区块验证算法的有趣部分是“工作量证明”概念:对每个区块进行SHA256哈希处理,将得到的哈希视为长度为256比特的数值,该数值必须小于不断动态调整的目标数值,本书写作时目标数值大约是2^190。工作量证明的目的是使区块的创建变得困难,从而阻止女巫攻击者恶意重新生成区块链。因为SHA256是完全不可预测的伪随机函数,创建有效区块的唯一方法就是简单地不断试错,不断地增加随机数的数值,查看新的哈希数值是否小于目标数值。如果当前的目标数值是2^192,就意味着平均需要尝试2^64次才能生成有效的区块。一般而言,比特币网络每隔2016个区块重新设定目标数值,保证平均每十分钟生成一个区块。为了对矿工的计算工作进行奖励,每一个成功生成区块的矿工有权在区块中包含一笔凭空发给他们自己25BTC的交易。另外,如果交易的输入大于输出,差额部分就作为“交易费用”付给矿工。顺便提一下,对矿工的奖励是比特币发行的唯一机制,创世状态中并没有比特币。

为了更好地理解挖矿的目的,让我们分析比特币网络出现恶意攻击者时会发生什么。因为比特币的密码学基础是非常安全的,所以攻击者会选择攻击没有被密码学直接保护的部分:交易顺序。攻击者的策略非常简单:

向卖家发送100BTC购买商品(尤其是无需邮寄的电子商品)。

等待直至商品发出。

创建另一笔交易,将相同的100BTC发送给自己的账户。

使比特币网络相信发送给自己账户的交易是最先发出的。

一旦步骤(1)发生,几分钟后矿工将把这笔交易打包到区块,假设是第270000个区块。大约一个小时以后,在此区块后面将会有五个区块,每个区块间接地指向这笔交易,从而确认这笔交易。这时卖家收到货款,并向买家发货。因为我们假设这是数字商品,攻击者可以即时收到货。现在,攻击者创建另一笔交易,将相同的100BTC发送到自己的账户。如果攻击者只是向全网广播这一消息,这一笔交易不会被处理。矿工会运行状态转换函数APPLY(S,TX),发现这笔交易将花费已经不在状态中的UTXO。所以,攻击者会对区块链进行分叉,将第269999个区块作为父区块重新生成第270000个区块,在此区块中用新的交易取代旧的交易。因为区块数据是不同的,这要求重新进行工作量证明。另外,因为攻击者生成的新的第270000个区块有不同的哈希,所以原来的第270001到第270005的区块不指向它,因此原有的区块链和攻击者的新区块是完全分离的。在发生区块链分叉时,区块链长的分支被认为是诚实的区块链,合法的的矿工将会沿着原有的第270005区块后挖矿,只有攻击者一人在新的第270000区块后挖矿。攻击者为了使得他的区块链最长,他需要拥有比除了他以外的全网更多的算力来追赶(即51%攻击)。

默克尔树

左:仅提供默克尔树(Merkle tree)上的少量节点已经足够给出分支的合法证明。

右:任何对于默克尔树的任何部分进行改变的尝试都会最终导致链上某处的不一致。

比特币系统的一个重要的可扩展特性是:它的区块存储在多层次的数据结构中。一个区块的哈希实际上只是区块头的哈希,区块头是包含时间戳、随机数、上个区块哈希和存储了所有的区块交易的默克尔树的根哈希的长度大约为200字节的一段数据。

默克尔树是一种二叉树,由一组叶节点、一组中间节点和一个根节点构成。最下面的大量的叶节点包含基础数据,每个中间节点是它的两个子节点的哈希,根节点也是由它的两个子节点的哈希,代表了默克尔树的顶部。默克尔树的目的是允许区块的数据可以零散地传送:节点可以从一个源下载区块头,从另外的源下载与其有关的树的其它部分,而依然能够确认所有的数据都是正确的。之所以如此是因为哈希向上的扩散:如果一个恶意用户尝试在树的下部加入一个伪造的交易,所引起的改动将导致树的上层节点的改动,以及更上层节点的改动,最终导致根节点的改动以及区块哈希的改动,这样协议就会将其记录为一个完全不同的区块(几乎可以肯定是带着不正确的工作量证明的)。

默克尔树协议对比特币的长期持续性可以说是至关重要的。在2014年4月,比特币网络中的一个全节点-存储和处理所有区块的全部数据的节点-需要占用15GB的内存空间,而且还以每个月超过1GB的速度增长。目前,这一存储空间对台式计算机来说尚可接受,但是手机已经负载不了如此巨大的数据了。未来只有商业机构和爱好者才会充当完整节点。简化支付确认(SPV)协议允许另一种节点存在,这样的节点被成为“轻节点”,它下载区块头,使用区块头确认工作量证明,然后只下载与其交易相关的默克尔树“分支”。这使得轻节点只要下载整个区块链的一小部分就可以安全地确定任何一笔比特币交易的状态和账户的当前余额。

    栏目排行
    全站排行