摘录自以太坊白皮书,文中前部分从技术角度解析比特币区块链的原理,我只是划重点把比特币部分知识点摘抄下来。
作为状态转换系统的比特币
从技术角度讲,比特币账本可以被认为是一个状态转换系统,该系统包括所有现存的比特币所有权状态和“状态转换函数”。状态转换函数以当前状态和交易为输入,输出新的状态。例如,在标准的银行系统中,状态就是一个资产负债表,一个从A账户向B账户转账X美元的请求是一笔交易,状态转换函数将从A账户中减去X美元,向B账户增加X美元。如果A账户的余额小于X美元,状态转换函数就会返回错误提示。所以我们可以如下定义状态转换函数:
1 | APPLY(S,TX) > S' or ERROR |
在上面提到的银行系统中,状态转换函数如下:
1 | APPLY({ Alice: $50, Bob: $50 },"send $20 from Alice to Bob") = { Alice: $30,Bob: $70 } |
但是:
1 | APPLY({ Alice: $50, Bob: $50 },"send $70 from Alice to Bob") = ERROR |
比特币系统的“状态”是所有已经被挖出的、没有花费的比特币(技术上称为“未花费的交易输出,unspent transaction outputs 或UTXO”)的集合。每个UTXO都有一个面值和所有者(由20个字节的本质上是密码学公钥的地址所定义)。一笔交易包括一个或多个输入和一个或多个输出。每个输入包含一个对现有UTXO的引用和由与所有者地址相对应的私钥创建的密码学签名。每个输出包含一个新的加入到状态中的UTXO。
在比特币系统中,状态转换函数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自己,也就是找零。
挖矿
比特币的去中心化共识进程要求网络中的节点不断尝试将交易打包成“区块”。网络被设计为大约每十分钟产生一个区块,每个区块包含一个时间戳、一个随机数、一个对上一个区块的引用(即哈希)和上一区块生成以来发生的所有交易列表。这样随着时间流逝就创建出了一个持续增长的区块链,它不断地更新,从而能够代表比特币账本的最新状态。
依照这个范式,检查一个区块是否有效的算法如下:
- 检查区块引用的上一个区块是否存在且有效。
- 检查区块的时间戳是否晚于以前的区块的时间戳,而且早于未来2小时。
- 检查区块的工作量证明是否有效。
- 将上一个区块的最终状态赋于S[0]。
- 假设TX是区块的交易列表,包含n笔交易。对于属于0……n-1的所有i,进行状态转换S[i+1] = APPLY(S[i],TX[i])。如果任何一笔交易i在状态转换中出错,退出程序,返回错误。
- 返回正确,状态S[n]是这一区块的最终状态。
区块验证算法的有趣部分是“工作量证明”概念:对每个区块进行SHA256哈希处理,将得到的哈希视为长度为256比特的数值,该数值必须小于不断动态调整的目标数值,本书写作时目标数值大约是2^190。工作量证明的目的是使区块的创建变得困难,从而阻止女巫攻击者恶意重新生成区块链。因为SHA256是完全不可预测的伪随机函数,创建有效区块的唯一方法就是简单地不断试错,不断地增加随机数的数值,查看新的哈希数值是否小于目标数值。如果当前的目标数值是2^192,就意味着平均需要尝试2^64次才能生成有效的区块。一般而言,比特币网络每隔2016个区块重新设定目标数值,保证平均每十分钟生成一个区块。为了对矿工的计算工作进行奖励,每一个成功生成区块的矿工有权在区块中包含一笔凭空发给他们自己25BTC的交易。另外,如果交易的输入大于输出,差额部分就作为“交易费用”付给矿工。顺便提一下,对矿工的奖励是比特币发行的唯一机制,创世状态中并没有比特币。
默克尔树
默克尔树是一种二叉树,由一组叶节点、一组中间节点和一个根节点构成。最下面的大量的叶节点包含基础数据,每个中间节点是它的两个子节点的哈希,根节点也是由它的两个子节点的哈希,代表了默克尔树的顶部。默克尔树的目的是允许区块的数据可以零散地传送:节点可以从一个源下载区块头,从另外的源下载与其有关的树的其它部分,而依然能够确认所有的数据都是正确的。之所以如此是因为哈希向上的扩散:如果一个恶意用户尝试在树的下部加入一个伪造的交易,所引起的改动将导致树的上层节点的改动,以及更上层节点的改动,最终导致根节点的改动以及区块哈希的改动,这样协议就会将其记录为一个完全不同的区块(几乎可以肯定是带着不正确的工作量证明的)。