比特币开发者指南--区块链

来源:互联网 发布:淘宝分销商招募书 编辑:程序博客网 时间:2024/06/07 04:46

名词

Block Chain:区块链

UTXO: Unspent Transaction Output,未花费的交易输出

Genesis Block: 块0,创世块

SPV: Simplified Payment Verification,简单支付验证

BIP: Bitcoin Improvement Proposal,比特币改进提案

Proof Of Work: 工作量证明


区块链

区块链提供了比特币的公共帐本,这是一个有序有时间戳的交易(transaction)记录。该系统用于防止重复花费(双花 double spending)和修改先前的交易记录。

Bitcoin 网络中的每个完整节点独立地存储仅包含由节点验证过的区块链。当多个节点在其块链中都具有相同的块时,它们被认为达成了共识。这些节点遵循维持共识的验证规则被称为共识规则。本节将介绍Bitcoin Core使用的许多共识规则。

 

区块链概述

上图显示了区块链的简化版本。一个或多个新交易的块被收集到一个区块的交易数据部分中。每个交易数据的副本将被哈希, 这些哈希值两两配对,再被hash,直到得到最顶层的一个hash值,这就是一棵merkle树的根。

merkle树根存储在这个区块标头中。每个块还存储着先前块的标头的哈希值,这样块将链接在一起。这样可以确保事务无法修改,而不修改记录该事务的块以及所有后续块。

交易记录也被链接在一起。比特币钱包软件给人的感觉是从钱包发送或接收多少聪(satoshi,单位)的比特币,但实际上比特币真的是在交易中流转。每个交易花费先前在一个或多个较早的交易中接收到的多少聪的比特币,因此一个交易的输入是先前交易的输出。

单个交易可以创建多个输出,就像发送到多个地址时的情况一样,但是特定交易的每个输出只能是在区块链中用作输入一次。任何后续的引用都禁止重复花费 - 尝试花费相同的多少聪的比特币两次。

输出绑定到交易标识符(TXID)上,这是验证过的交易的哈希值。

因为特定交易的 输出 只允许花费一次,那所有包含在区块链上的交易输出可以归类为未花费的交易输出(UTXOs)或已花费的交易输出。要想付款有效,只能使用未花费的交易输出UTXOs作为输入。

先不讲比特币交易(后面会详述),若一个交易的输出超过交易的输入,这个交易将会被拒绝--但是若是输入超出输出,这个差值可以作为交易费奖励给创建这个区块的Bitcoin矿工。例如,在上图中,每个交易相比它相关的交易输入花费了10000聪,实际上就是支付了10000聪的交易费。

 

工作量证明

区块链是有由网络中对等的节点共同维护的,所以Bitcoin要求每个区块需要一定工作量投入确保想篡改历史区块的不诚实节点比想在区块链上创建新区块的诚实节点需要付出更大代价。

链接区块在一起使得在不修改所有后面的区块情况下不可能修改此区块中包含的交易。结果,修改特定区块的成本随着添加到区块链中的每个新区块而增加,放大了工作量证明的效果。

Bitcoin中使用的工作量证明利用了密码散列的显式随机特性。一个好的加密哈希算法将任意数据转换成看似随机的数字。如果以任何方式修改数据并且重新得到哈希值,则会产生一个新的看似随机的数字,因此无法修改数据以使哈希数值可被预测。

为了证明你做了一些额外的工作来创建一个区块,你必须创建一个不超过某个值的区块头的散列。例如,如果最大可能的哈希值为2256-1,则可以证明您通过产生哈希值来两两组合最多尝试次数小于2255

在上面给出的例子中,平均每个其他尝试都会产生一个成功的哈希。您甚至可以估计给定哈希尝试将生成低于目标阈值的数字的概率。比特币假设一个线性概率,它使得目标阈值越低,平均需要更多的哈希尝试。

新的块会被添加到块链,仅当它们的哈希难度至少与共识协议所期望的难度值相当。每2016 个块,比特币网络会使用存储在每个块头中的时间戳来计算生成上一个2016个块的第一个区块和最后一个区块之间经过的秒数。这个理想值为1209600秒(两周)。

如果生成2016个块需要不到两周的时间,则预期的难度值将按比例增加(高达300%),当以相同的速率检查散列情况下以便接下来的2016块应该恰好需要两个星期来生成。

如果生成块需要两个多星期,因为相同的原因,预期的难度值会按比例降低(75%)。

(注意:Bitcoin Core实现中的一个时间戳错误导致每2016 块更新难度值仅从2015 块,产生轻微的偏移。)

因为每个块头必须哈希到低于目标阈值的值,并且因为每个块链接到前一个快,平均需要扩散一个更改过的区块的哈希算力与整个Bitcoin网络在初始块的创建时间和当前时间之间所消耗的一样多。只有您获得了大部分网络的哈希功能,您才可以根据交易历史可靠地执行这种51%的攻击(尽管如此,应该注意的是,即使小于50哈希强度的百分比仍然有很好的机会进行这种攻击)。

块头提供了几个易于修改的字段,例如专用的nonce字段,因此获取新的哈希不需要等待新的交易到来。此外,只有80字节的块头被散列以用于工作证明,因此在块中包含大量的事务数据不会减慢哈希的额外I/O和添加附加事务数据只需要重新计算merkle树中的祖先散列。


块高和分叉

任何算出块头的hash值低于目标阈值的Bitcoin矿工可以将整个块添加到块链上(假设块有效)。这些块通常由它们的块高度 定位的 - 即它们与第一个比特币块之间的块数量(块0,最通常称为创世块)。例如,块 2016是可以首先调整难度值的地方。

多个区块可能有相同的区块高度,当2个或多个矿工在大致相同时间内产生合适新区块的时候这很常见。这在块链中产生了一个明显的分叉,如上图所示。

当矿工同时在区块链尾部产生新区块,每个节点独立选择接受哪个区块。在没有其他考虑的情况下,如下所述,节点通常使用他们看到的第一个块。

最终,一个矿工产生另一个块,它只附加在一个竞争同时开采的块中。这使得叉的那侧比另一侧更强。假设一个分叉仅包含有效区块,正常节点通常紧接着最难的链来增长,抛弃那些属于短分叉的过期区块。(过期块有时也称为孤儿或孤儿块,但是这些术语也用于没有已知父块的真孤儿块)

如果不同的矿工工作在相反的目的,例如一些矿工努力扩展块链,同时其他矿工正在尝试发起51%的攻击来修改交易历史,则长期分叉是可能的。

由于在区块链 的分叉中,多个块可以具有相同的高度 ,区块高度不应该被用作全局唯一标识符。反而,块通常由它们的块头的哈希引用(通常以字节顺序颠倒,十六进制形式)。

 

交易数据

每个块必须包含一个或多个交易。这些交易中的第一个必须是一个币基交易,也称为生成交易,它应该收集并花费块奖励(包括块补贴以及由块中包含的交易支付的任何交易费用)。

币基交易的未花费的交易输出UTXO有一个特殊的条件,它至少需要100个块产生之后才能使用(用作输入)。这暂时阻止矿工花费从一个分叉链上以后可能被淘汰的区块(因此币基交易也被删除)上花费交易费和区块奖励。

区块不需要包括任何非币基交易,但是矿工几乎总是包含额外的交易,以便于获得他们的交易费。

包括币基交易在内的所有交易都以二进制原始交易格式编码入块。

原始交易格式被散列为交易标识符(txid)。通过这些txid,merkle树是通过将每个txid与另一个txid配对,然后将它们组合在一起构成的。如果有奇数个txids,那么没有合作伙伴的txid会使用自己的副本进行散列。

所产生的哈希本身每个都与另一个哈希配对,并且散列在一起。没有伙伴的哈希求自身的hash值。该过程重复,直到只剩下一个散列,这就是merkle根。

例如,如果交易仅是加入(不是求哈希),那么一个五个交易的merkle树将如下图所示:

根据在简单支付验证(SPV)子节的讨论, merkle树允许从一个完全分片的块头和一系列中间hash值得到的merkle根来验证区块中的一个交易。完整的分片不需要都被信任:伪造块头是昂贵的,中间哈希值不能被伪造或者会验证失败。

例如,为了验证事务D被添加到区块,SPV客户端除了merkle根之外只需要C,AB和EEEE散列的副本;客户不需要知道任何其他交易。如果这个块中的五个交易都处于最大值,下载整个块将需要超过500,000个字节,但是下载三个散列加上块头只需要140个字节。

注意:如果在相同的块中找到相同的txids,则可能merkle树可能与块,其中一些或所有重复项由于如何不平衡而被删除merkle树被实现(复制孤岛哈希)。由于使用相同的txids的单独事务是不切实际的,所以这不会对诚实软件造成负担,但是必须检查块的无效状态是否为缓存;否则,删除重复项的有效块可以具有相同的merkle根和块哈希,但被缓存的无效结果拒绝,结果在安全漏洞中,如CVE-2012-2459。

 

共识规则更改

为了维护共识,所有全部节点使用相同的共识规则验证块。然而,有时共识规则要被改变以引入新功能或阻止网络被滥用。当新规则实施时,可能会有一段时间,当未升级的节点遵循旧规则并且升级节点遵循新规则时,导致两种可能的方式打破共识:

遵循新共识规则的块被升级后节点接受,但被未升级的节点拒绝。例如,在块中使用新的交易功能:升级节点了解该功能并接受该功能,但未升级的节点拒绝因为它违反了旧的规则。

违反新的共识规则的块被升级后节点拒绝,但被未升级的节点接受。例如,在块中使用了滥用交易功能:升级后节点拒绝它,因为它违反了新规则,但未升级的节点接受它,因为它遵循旧的规则。

第一种情况,被未升级的节点拒绝,那些从其他未升级节点获取区块链数据的挖矿软件拒绝和那些从升级过的节点获取数据的挖矿软件在同一条链上创建。这将创建永久性发散的链 - 一个用于未升级的节点,一个链接用于升级节点-- 这被称为硬分叉。


第二种情况,被升级后的节点拒绝,如果升级后的节点控制着主要的hash速率则可能阻止区块链永久发散。这是因为,在这种情况下,未升级节点和升级过的节点一样接受相同的快,所以升级后的节点可以创建一个更强的链,也被未升级节点所接受。这被称为软分叉。

虽然一个分叉实际上是区块链上发散,共识规则的改变经常被描述为它们潜在地创建一个硬分叉或者软分叉。例如,“将块的大小增加到1 MB以上需要一个硬分叉。在这个例子中,一个实际的块链 分叉不是必需的 - 但这是一个可能的结果。

共识规则的改变可能会以各种方式激活更改。在Bitcoin的前两年,中本聪同过发布立刻强制使用新规则的向后兼容的客户端改变执行了几次软分叉。已经通过标记日激活了多个软叉,例如BIP30,其中新规则开始在预设时间或块高度强制执行。通过标记日激活的分叉被称为用户激活软分叉,因为他们取决于足够多的用户节点在标记日之后强制使用新规则。

稍后软分叉等待多数哈希速率(通常为75%或95%)来显示他们对执行新共识规则准备就绪。一旦信令阈值已经通过,所有节点将开始执行新规则。这样的分叉被称为矿工活动软分叉(MASF),因为它们依赖于矿工进行激活。

资源: BIP16,BIP30和BIP34被实现为可能导致软分叉。BIP50描述了一个意外的硬分叉和一个蓄意的硬分叉可以通过临时降级升级后节点的能力来解决。来自Gavin Andresen的文档概述了如何实施未来的规则更改。

 

检测分叉

未升级的节点可以在两种类型的分叉中使用和分发不正确的信息,从而出现可能导致财务损失的几种情况。特别地,未升级的节点可以中继和接受被升级的节点认为无效的交易,因此永远不会成为普遍认可的最佳区块链的一部分。未升级的节点可能拒绝中继那些已经或者即将添加到最佳区块链里面的区块或者交易,因此它们提供不完整的信息。

比特币核心包括通过查看块链 工作证明检测硬分叉。如果一个未升级的节点接收到的区块链头显示至少比最佳链的工作量多6个区块,这个节点就会在getinfo RPC里报一个错误,并在设置的情况下执行-alertnotify命令。这会提醒操作者未升级的节点不能切换到可能的最佳区块链。

完整节点也可以检查区块和交易的版本号。如果当前几个区块中的区块或者交易的版本号比这个节点使用的版本号高,可以假设它没有使用当前的共识规则。Bitcoin Core 0.10.0如果设置了会通过getinfo RPC和-alertnotify命令报告此情况。

无论哪种情况,区块和交易数据都不能被信任如果它们来自于一个明显不使用当前共识规则的节点。

连接到全节点的SPV客户端通过连接多个全节点,确保他们在同一个链上具有相同的块高,或者根据账户传输时延和过期与否增减几个区块,能够测到一个可能的硬分叉。如果存在分歧,客户端可以使用较弱的链从节点断开连接。

SPV客户端还应该监控块和交易的版本号增加,以确保它们用当前的共识规则处理接收到的交易。