BTC开发者指南翻译-区块链(Block Chain)

翻译原文在 这里 区块链(Block Chain) ​ 区块链提供了比特币的公共账本(ledger),一个有序的(ordered)、带有时间戳的(timestamped)交易记录。该系统用于防止双重支付(double spending)和修改以前的交易记录 介绍(Introdution) ​ 比特币网络中的每个完整节点独立存储一个区块链,其中仅包含由该节点验证的区块。当多个节点在其区块链中都拥有相同的区块时,则认为它们已达成共识(consensus)。这些节点为维持共识而遵循的验证规则称为共识规则(consensus rules)。本节描述了 Bitcoin Core 使用的许多共识规则。 ​ 上图显示了区块链的简化版本。一个或多个新交易的区块被收集到区块的交易数据部分。每笔交易的副本都会被哈希(hashed),然后将哈希配对、哈希、再次配对、再哈希,直到剩下一个哈希,即默克尔树(merkle tree)的默克尔根(merkle root)。 默克尔根存储在区块头(block header)中。每个区块还存储前一个区块头的哈希值,将这些区块链接在一起。这确保在不修改记录它的块和所有后续块的情况下无法修改。 ​ 交易也被链接(chained)在一起。比特币钱包软件给人的印象是聪(satoshis)是从钱包发送到钱包,但比特币确实在交易之间移动。每笔交易都会花费先前在一个或多个早期交易中收到的聪,因此一笔交易的输入是前一笔交易的输出。 ​ 单个交易可以创建多个输出(multiple outputs),就像发送到多个地址时的情况一样,但特定交易的每个输出在区块链中只能用作输入一次(once)。任何后续引用都是被禁止的双花(double spend)——试图两次花费相同的聪。 ​ 输出与交易标识符 (TXID) 相关联,交易标识符是已签名交易的哈希值。 ​ 由于特定交易的每个输出只能花费一次(spent once),因此区块链中包含的所有交易的输出可以归类为未花费的交易输出(UTXO)或已花费的交易输出。要使付款有效(valid),它必须仅使用 UTXO 作为输入。 ​ 忽略 coinbase 交易(稍后描述),如果交易的输出值超过其输入值,则该交易将被拒绝(rejected)——但如果输入值超过输出值,则任何价值差异都可能被比特币认作交易费创建包含该交易的区块的矿工。例如,在上图中,每笔交易的花费比从其组合输入中收到的少 10,000 satoshis,实际上支付了 10,000 satoshi 交易费。 工作量证明(Proof of Work) ​ 区块链是由网络上的匿名节点(anonymous peers)协作维护的,因此比特币要求每个区块都证明在其创建上投入了大量工作(invested in its creation),以确保想要修改过去区块的不可信节点必须比只修改过去区块的诚实节点更努力地工作想要向区块链添加新区块。 ​ 将区块链接在一起(Chaining blocks together)使得在不修改所有后续区块的情况下修改任何区块中包含的交易是不可能的。因此,随着区块链中每增加一个新区块,修改特定区块的成本就会增加(increases),从而放大了工作量证明的效果。 ​ 比特币中使用的工作量证明(pow)利用了加密哈希(cryptographic hashes)的明显随机性。一个好的加密散列算法将任意数据转换为看似随机的数字。如果以任何方式修改数据并重新运行散列,则会产生一个新的看似随机的数字,因此无法修改数据以使哈希可预测(predictable)。 ​ 为了证明你做了一些额外的工作来创建一个块,你必须创建一个不超过某个值的块头的哈希值。例如,如果最大可能的哈希值为 2^256 − 1,您可以通过生成小于 2^255 的哈希值来证明您尝试了多达两种组合。 ​ 在上面给出的示例中,您将平均每隔一次尝试就产生一个成功的散列。您甚至可以估计给定哈希尝试生成低于目标阈值的数字的概率。比特币假设一个线性概率,它使目标阈值越低,需要尝试的哈希尝试(平均)越多。 ​ 只有当新区块的哈希值至少与共识协议预期的难度值(difficulty value)一样具有挑战性时,才会将新区块添加到区块链中。每 2,016 个区块,网络使用存储在每个区块头中的时间戳来计算最后 2,016 个区块的第一个和最后一个生成之间经过的秒数。理想值是 1,209,600 秒(两周)。 如果生成 2,016 个区块的时间少于两周,则预期难度值会按比例增加(increased)(最多增加 300%),因此,如果以相同的速度检查哈希值,接下来的 2,016 个区块应该正好需要两周的时间来生成。 如果生成区块的时间超过两周,出于同样的原因,预期难度值会按比例降低(最多 75%)。 (注意:比特币核心实现中的一个逐一错误(an off-by-one error)导致使用仅 2,015 个块的时间戳每 2,016 个块更新一次难度,造成轻微的偏差。) ​ 因为每个区块头必须散列到低于目标阈值(target threshold)的值,并且因为每个区块都链接到它之前的区块,所以传播修改后的区块需要(平均)与整个比特币网络在两个区块之间消耗的哈希算力(hashing power)一样多。创建原始块的时间和当前时间。只有当你获得了网络的大部分哈希算力时,你才能可靠地对交易历史执行 51% 的攻击(尽管应该注意,即使不到 50% 的哈希算力仍然有很好的机会执行此类攻击)。 ​ 区块头(block header)提供了几个易于修改的字段,例如专用的 nonce 字段,因此获取新的哈希不需要等待新的交易。此外,只有 80 字节的区块头被哈希用于工作量证明,因此在一个区块中包含大量交易数据不会因额外的 I/O 而减慢哈希(slow down hashing),而添加额外的交易数据只需要重新计算祖先在默克尔树中哈希。 区块高度和分叉(Block Height And Forking) ​ 任何成功将区块头哈希到低于目标阈值的值的比特币矿工(miner)都可以将整个区块添加到区块链中(假设该区块是有效的)。这些块通常通过它们的块高度来寻址(addressed by their block height)——它们与第一个比特币块(块 0,最常称为创世块(genesis block))之间的块数。例如,块 2016 是首先调整难度的地方。 ​ 常见和不常见的区块链分叉 ​ 多个区块都可以具有相同的区块高度(same block height),这在两个或多个矿工大致同时生产一个区块时很常见。这会在区块链中创建一个明显的分叉,如上图所示。 ​ 当矿工在区块链末端同时(simultaneous)产生区块时,每个节点单独选择接受哪个区块。在没有其他考虑的情况下,如下所述,节点通常使用它们看到的第一个块。 ​ 最终,矿工产生另一个块,该块仅附加到一个同时开采的竞争块(the competing simultaneously-mined blocks)上。这使得前叉的那一侧比另一侧更坚固。假设一个分叉只包含有效块,普通节点总是遵循最困难的链来重新创建并丢弃属于较短分叉的陈旧块(stale blocks)。 (陈旧块有时也称为孤块(orphan blocks)),但这些术语也用于没有已知父块的真正孤块。) ​ 如果不同的矿工出于不同目的而工作,那么长期分叉是可能的,例如一些矿工在努力扩展区块链的同时,其他矿工正在尝试进行 51% 攻击以修改交易历史记录。 ​ 由于在区块链分叉过程中多个区块可以具有相同的高度(same height),因此不应将区块高度用作全局唯一标识符。相反,块通常由其标头的哈希值引用(通常字节倒序,并以十六进制表示) 交易数据(Transaction Data) ​ 每个区块必须包含一个或多个交易(one or more transactions)。这些交易中的第一个必须是 coinbase 交易,也称为generation交易,它应该收集和花费区块奖励(包括区块补贴(block subsidy)和该区块中包含的交易支付的任何交易费用)。 ​ coinbase 交易的 UTXO 有一个特殊条件,即它至少在100 个块内不能被花费(用作输入)。这暂时阻止了矿工在区块链分叉后花费交易费用和区块奖励,该区块可能稍后被确定为陈旧块(因此 coinbase 交易被破坏)。 ​ 区块不需要包含任何非 coinbase 交易,但矿工几乎总是包含额外的交易以收取他们的交易费用(transaction fees)。 ​ 所有交易,包括 coinbase 交易,都以二进制原始交易格式(binary raw transaction format)编码到块中。 ​ 原始交易格式经过哈希处理以创建交易标识符 (txid)。从这些 txid 中,通过将每个 txid 与另一个 txid 配对(pairing),然后将它们哈希在一起来构建默克尔树。如果有奇数(odd)个 txid,则没有配对(without a partner)的 txid 会与其自身的副本(copy of itself)一起哈希。 ​ 将得到的哈希值再一一配对进行哈希。任何没有配对的将与自己进行哈希。重复这个过程,直到只剩下一个哈希值,即默克尔根(merkle root)。 ​ 例如,如果交易只是连接(未哈希),拥有5个交易的默克尔树将如下图所示: ABCDEEEE .......Merkle root / \ ABCD EEEE / \ / AB CD EE .......E 与自己配对 / \ / \ / A B C D E .........5个交易 ​ 正如在简化支付验证 (SPV) 小节中讨论的那样,默克尔树允许客户端通过从区块头获取默克尔根和来自完整对等方的中间哈希列表来自行验证交易是否包含在区块中。全节点不需要被信任(trusted):伪造区块头(fake blocker headers)的成本很高,中间哈希不能伪造,否则验证将失败(verification will fail)。 ​ 例如,要验证交易 D 是否已添加到区块中,除了默克尔根之外,SPV 客户端只需要 C、AB 和 EEEE 哈希的副本(copy);客户端不需要知道任何其他交易的任何信息。如果这个区块中的五个交易都是最大上限(maximum size),下载整个区块将需要超过 500,000 字节——但下载三个哈希加上区块头只需要 140 字节。 注意:如果在同一个区块中发现相同的 txid,由于实现不平衡的默克尔树(复制单独的哈希),默克尔树可能会与删除了部分或全部重复项的区块发生碰撞(collide)。由于使用相同的 txid 进行单独的交易是不切实际的,这不会给诚实的软件带来负担,但必须检查是否要缓存块(cached)的无效状态(invalid status);否则,消除重复的有效块可能具有相同的默克尔根和块哈希,但会被缓存的无效结果拒绝,从而导致安全漏洞,例如 CVE-2012-2459 共识规则的变更(Consensus Rule Changes) ​ 为了保持共识(maintain consensus),所有全节点使用相同的共识规则验证块。但是,有时会更改共识规则以引入新功能(new features)或防止网络滥用(prevent network abuse)。当新规则实施时,可能会有一段时间未升级的节点遵循旧规则,升级的节点遵循新规则,从而产生两种可能的共识破坏方式: 遵循新共识规则的区块被升级的节点接受(accepted),但被未升级的节点拒绝(rejected)。例如,在一个区块中使用了一个新的交易特性:升级的节点理解该特性并接受它,但未升级的节点拒绝它,因为它违反了旧规则(old rules)。 违反新共识规则的区块被升级的节点拒绝,但被未升级的节点接受。例如,在一个区块中使用了一个滥用交易特征:升级的节点因为它违反了新规则而拒绝它,但未升级的节点因为它遵循旧规则而接受它。 在第一种情况下,被未升级节点拒绝,从那些未升级节点获取区块链数据的挖矿软件拒绝建立在与从升级节点获取数据的挖矿软件相同的链上。这会创建永久分叉的链(permanently divergent chins)——一个用于未升级的节点,一个用于升级的节点——称为硬分叉(hard fork)。 ​ 在第二种情况下,被升级的节点拒绝,如果升级的节点控制了大部分哈希率,则可以防止区块链永久分叉(permanently diverging)。这是因为,在这种情况下,未升级节点将接受所有与升级节点相同的区块作为有效区块,因此升级节点可以构建一条健壮(stronger)的链,未升级节点将接受该区块链作为最佳有效区块链。这称为软分叉(soft fork)。 ​ 尽管分叉是区块链中的实在分歧,但共识规则的变化通常被描述为它们可能会创建硬分叉或软分叉。例如,“将块大小增加到 1 MB 以上需要硬分叉。”在这个例子中,链的分叉并不是一定需要,但这是一个可能的结果。 ​ 可以以各种方式激活共识规则更改。在比特币的头两年,中本聪通过在立即开始执行新规则的客户端中发布向后兼容的更改来执行几次软分叉。多个软分叉如 BIP30 已通过标志日激活,新规则在预设时间或区块高度开始执行。这种通过标志日激活的分叉被称为用户激活软分叉(User Activated Soft Forks-UASF),因为它们依赖于在标志日之后有足够的用户(节点)来执行新规则。 ​ 后来的软分叉等待大多数哈希率(hash rate)(通常为 75% 或 95%)来表示他们已准备好执行新的共识规则。一旦超过阈值,所有节点将开始执行新规则。这种分叉被称为矿工激活软分叉(Miner Activated Soft Forks-MASF),因为它们依赖于矿工进行激活。 ​ 资源:BIP16、BIP30 和 [BIP34] 已作为可能导致软分叉的更改实施。 BIP50 描述了通过临时降级升级节点的功能解决的意外硬分叉,以及临时降级被删除时的故意硬分叉。 Gavin Andresen 的一份文件概述了如何实施未来的规则变更。 检测分叉(Detecting Forks) ​ 未升级的节点可能会在两种类型的分叉期间使用和分发不正确的信息,从而产生多种可能导致经济损失的情况。特别是,未升级的节点可能会中继和接受升级节点认为无效的交易,因此永远不会成为公认的最佳区块链的一部分。未升级的节点也可能拒绝中继已经或即将添加到最佳区块链的区块或交易,从而提供不完整的信息。 ​ Bitcoin Core 包含通过查看区块链工作量证明来检测硬分叉的代码。如果未升级的节点收到区块链标头,表明比它认为有效的最佳链至少多出六个区块的工作量证明,则该节点会在“getnetworkinfo”RPC 结果中报告警告,并在设置时运行 -alertnotify 命令。这警告操作员未升级的节点无法切换到可能是最好的区块链。 ​ 全节点还可以检查区块(block)和交易版本号(transaction version numbers)。如果在最近几个区块中看到的区块或交易版本号高于节点使用的版本号,则可以假设它没有使用当前的共识规则。 Bitcoin Core 通过“getnetworkinfo”RPC 和 -alertnotify 命令(如果设置)报告这种情况。 ​ 在任何一种情况下,如果区块和交易数据来自显然没有使用当前共识规则的节点,则不应依赖这些数据。 ​ 连接到完整节点的 SPV 客户端可以通过连接到多个完整节点并确保它们都在具有相同块高度的同一链上,加上或减去几个块以解决传输延迟和陈旧块,从而检测可能的硬分叉。如果出现分歧(divergence),客户端可以与具有较弱链(weak chains)的节点断开连接。 ​ SPV 客户端还应监控区块和交易版本号的增加,以确保他们处理收到的交易并使用当前的共识规则创建新交易。

BTC开发者指南翻译

BTC开发者指南 Bitcoin Developer Guide

BTC网络

P2P 网络架构

git大文件上传

在操作git上传大文件时,提示上传的文件不能超过100M,超过100M的文件需要使用一个工具:lfs, 工具网站在 这里, 源码在这里

Scons的使用

什么是Scons?