以太坊白皮书
以太坊的目标
以太坊的目标就是提供一个带有内置的成熟的
图灵完备语言
的区块链,用这种语言可以创建合约来编码任意状态转换功能,用户只要简单地用几行代码来实现逻辑,就能够创建以上提及的所有系统以及许多我们还想象不到的的其它系统。
历史
因为货币是一个先申请应用,交易的顺序至关重要,所以去中心化的货币需要找到实现去中心化共识的方法。
中本聪的创新是引入这样一个理念:将一个非常简单的基于节点的去中心化共识协议与
工作量证明(POW)机制
结合在一起。节点通过工作量证明机制获得参与到系统的权利,每十分钟将交易打包到“区块”中,从而创建出不断增长的区块链。拥有大量算力的节点有更大的影响力,但获得比整个网络更多的算力比创建一百万个节点困难得多。尽管比特币区块链模型非常简陋,但是实践证明它已经足够好用了,在未来五年,它将成为全世界两百个以上的货币和协议的基石。
UTXO :unspent transaction outputs ,未花费的交易输出
在比特币系统中,状态转换函数
APPLY(S,TX)->S’
大体上可以如下定义:
-
交易的每个输入:
-
如果引用的UTXO不存在于现在的状态中(
S
),返回错误提示
-
如果签名与UTXO所有者的签名不一致,返回错误提示
-
-
如果所有的UTXO输入面值总额小于所有的UTXO输出面值总额,返回错误提示
-
返回新状态
S’
,新状态
S
中移除了所有的输入UTXO,增加了所有的输出UTXO。
第一步的第一部分防止交易的发送者花费不存在的比特币,第二部分防止交易的发送者花费其他人的比特币。第二步确保价值守恒。比特币的支付协议如下。假设Alice想给Bob发送11.7BTC。事实上,Alice不可能正好有11.7BTC。假设,她能得到的最小数额比特币的方式是:6+4+2=12。所以,她可以创建一笔有3个输入,2个输出的交易。第一个输出的面值是11.7BTC,所有者是Bob(Bob的比特币地址),第二个输出的面值是0.3BTC,所有者是Alice自己,也就是找零。
挖矿
[图片上传中...(image-690ef9-1512553916325-1)]
比特币的去中心化共识进程要求网络中的节点不断尝试将交易打包成“区块”。网络被设计为大约每十分钟产生一个区块,每个区块包含一个时间戳、一个随机数、一个对上一个区块的引用(即哈希)和上一区块生成以来发生的所有交易列表。这样,随着时间流逝就创建出了一个持续增长的区块链,它不断更新,从而代表账本的最新状态。
依照上面的范式, 检查一个区块是否有效的算法如下:
-
检查区块引用的上一个区块是否存在且有效
-
检查区块的时间戳是否晚于以前的区块的时间戳,而且早于未来2小时
-
检查区块的工作量证明是否有效
-
将上一个区块的最终状态赋值于
-
建设TX是区块的交易列表,包含N笔交易,都满满足与状态转换:
, 如果任一
不满足上面的等式,则抛出一个error。
-
如果上面 step 5 全部满足,则
为区块练得最终状态
区块链中的每一个区块,都是可以从创世块中通过交易顺序按照状态转换计算出当前的状态的。通俗的说一点,就是对于任意区块,从创世区块开始,加上链上的(按照循序)每一笔交易,计算出当前状态。假设:现在有A和B两个交易,B交易花费了A的UTXO, 如果A交易在B交易之前。那么这个交易就是有效的。否则就是无效的。
工作量证明(挖矿):
对每个区块进行SHA256 哈希处理,生成一个哈希视长为256bit 的哈希值。这个哈希值必须小于不断调整的目标数值。工作量证明的目的是使区块的创建变得困难,从而阻止女巫攻击者恶意重新生成区块链。因为SHA256是完全不可预测的伪随机函数,创建有效区块的唯一方法就是简单地不断试错,不断地增加随机数的数值,查看新的哈希数值是否小于目标数值。如果当前的目标数值是
那就意味着要尝试
次才能生成有效的区块。一般而言,比特币网络每隔2016个区块重新设定目标数值,保证平均每十分钟生成一个区块。为了对矿工的计算工作进行奖励,每一个成功生成区块的矿工有权在区块中包含一笔凭空发给他们自己25BTC的交易。
另外,如果交易的输入大于输出,差额部分就作为“交易费用”付给矿工。顺便提一下,对矿工的奖励是比特币发行的唯一机制,创世状态中并没有比特币
案例
为了更好地理解挖矿的目的,让我们分析比特币网络出现恶意攻击者时会发生什么。因为比特币的密码学基础是非常安全的,所以攻击者会选择攻击没有被密码学直接保护的部分:交易顺序。攻击者的策略非常简单:
-
向卖家发送100BTC购买商品(尤其是无需邮寄的电子商品)。
-
等待直至商品发出。
-
创建另一笔交易,将相同的100BTC发送给自己的账户。
-
使比特币网络相信发送给自己账户的交易是最先发出的。
一旦步骤(1)发生,几分钟后矿工将把这笔交易打包到区块,假设是第270000个区块。大约一个小时以后,在此区块后面将会有五个区块,每个区块间接地指向这笔交易,从而确认这笔交易。这时卖家收到货款,并向买家发货。因为我们假设这是数字商品,攻击者可以即时收到货。现在,攻击者创建另一笔交易,将相同的100BTC发送到自己的账户。如果攻击者只是向全网广播这一消息,这一笔交易不会被处理。矿工会运行状态转换函数
APPLY(S,TX)
,发现这笔交易将花费已经不在状态中的UTXO。所以,攻击者会对区块链进行分叉,将第269999个区块作为父区块重新生成第270000个区块,在此区块中用新的交易取代旧的交易。因为区块数据是不同的,这要求重新进行工作量证明。另外,因为攻击者生成的新的第270000个区块有不同的哈希,所以原来的第270001到第270005的区块不指向它,因此原有的区块链和攻击者的新区块是完全分离的。在发生区块链分叉时,区块链长的分支被认为是诚实的区块链,合法的的矿工将会沿着原有的第270005区块后挖矿,只有攻击者一人在新的第270000区块后挖矿。攻击者为了使得他的区块链最长,他需要拥有比除了他以外的全网更多的算力来追赶(即51%攻击)。
默克尔树
[图片上传中...(image-28622d-1512553916325-0)]
默克尔树在数据结构上讲是一个二叉树,默克尔树包括根节点中间节点和叶子节点。其中,根节点和中间节点每个节点的值是两个子节点的Hash值。私用默克尔树的目的在于区块可以零散的传播,节点可以从一个源下载区块头,从另外的源下载与其有关的树的其它部分,而依然能够确认所有的数据都是正确的。之所以如此是因为哈希向上的扩散:如果一个恶意用户尝试在树的下部加入一个伪造的交易,所引起的改动将导致树的上层节点的改动,以及更上层节点的改动,最终导致根节点的改动以及区块哈希的改动,这样协议就会将其记录为一个完全不同的区块(几乎可以肯定是带着不正确的工作量证明的)。
比特币存在的缺陷:
-
缺少图灵完备性 : 这就是说,尽管比特币脚本语言可以支持多种计算,但是它不能支持所有的计算。最主要的缺失是循环语句。不支持循环语句的目的是避免交易确认时出现无限循环。理论上,对于脚本程序员来说,这是可以克服的障碍,因为任何循环都可以用多次重复if 语句的方式来模拟,但是这样做会导致脚本空间利用上的低效率,例如,实施一个替代的椭圆曲线签名算法可能将需要256次重复的乘法,而每次都需要单独编码。
-
价值盲(Value-blindness)
。UTXO脚本不能为账户的取款额度提供精细的的控制。例如,预言机合约(oracle contract)的一个强大应用是对冲合约,A和B各自向对冲合约中发送价值1000美元的比特币,30天以后,脚本向A发送价值1000美元的比特币,向B发送剩余的比特币。虽然实现对冲合约需要一个预言机(oracle)决定一比特币值多少美元,但是与现在完全中心化的解决方案相比,这一机制已经在减少信任和基础设施方面有了巨大的进步。然而,因为UTXO是不可分割的,为实现此合约,唯一的方法是非常低效地采用许多有不同面值的UTXO(例如对应于最大为30的每个k,有一个
的UTXO)并使预言机挑出正确的UTXO发送给A和B。
-
缺少状态
– UTXO只能是已花费或者未花费状态,这就没有给需要任何其它内部状态的多阶段合约或者脚本留出生存空间。这使得实现多阶段期权合约、去中心化的交换要约或者两阶段加密承诺协议(对确保计算奖励非常必要)非常困难。这也意味着UTXO只能用于建立简单的、一次性的合约,而不是例如去中心化组织这样的有着更加复杂的状态的合约,使得元协议难以实现。二元状态与价值盲结合在一起意味着另一个重要的应用-取款限额-是不可能实现的。
-
区块链盲(Blockchain-blindness)
- UTXO看不到区块链的数据,例如随机数和上一个区块的哈希。这一缺陷剥夺了脚本语言所拥有的基于随机性的潜在价值,严重地限制了博彩等其它领域应用。
以太坊
以太坊账户
在以太坊系统中,状态是由被称为“账户”(每个账户由一个20字节的地址)的对象和在两个账户之间转移价值和信息的状态转换构成的。以太坊的账户包含四个部分:
-
nonce
用来保证每个交易只被处理一次
-
账户的以太币余额
-
账户的智能合约,如果有的话
-
账户的存储,默认为空
消息和交易
交易指的即为从外部账户过来的包含有消息的数据包,一个“交易”的组成包括
-
消息的接受者
-
发送者的签名
-
从发送者转到接收者的以太币数量
-
其他可选的数据列
-
要发送的数据和两个被称为STARTGAS和GASPRICE的数值
STARTGAS
: 代表交易执行最多被允许的次数
GASPRICE
: 发送者到交易者每个交易执行步奏的价格
对于第4条中的可选数据列,智能合约代码是可以访问这些数据的。举例来说,如果要在区块链上进行一个域名注册服务,数据要包含有要注册的域名和IP两条数据。
对于Gas price 来说,每一个交易步奏被收费1 gas或更高, 传输的交易数据中每 1 字节收费5gas
以太坊的状态转换函数:
APPLY(S,TX) -> S'
,可以定义如下:
-
检查交易的格式是否正确(即有正确数值)、签名是否有效和随机数是否与发送者账户的随机数匹配。如否,返回错误。
-
计算交易费用:
fee=STARTGAS * GASPRICE
,并从签名中确定发送者的地址。从发送者的账户中减去交易费用和增加发送者的随机数。如果账户余额不足,返回错误。
-
设定初值
GAS = STARTGAS
,并根据交易中的字节数减去一定量的瓦斯值。
-
从发送者的账户转移价值到接收者账户。如果接收账户还不存在,创建此账户。如果接收账户是一个合约,运行合约的代码,直到代码运行结束或者瓦斯用完。
-
如果因为发送者账户没有足够的钱或者代码执行耗尽瓦斯导致价值转移失败,恢复原来的状态,但是还需要支付交易费用,交易费用加至矿工账户。
-
否则,将所有剩余的瓦斯归还给发送者,消耗掉的瓦斯作为交易费用发送给矿工。 例如,假设合约的代码如下:
网友评论