比特币、区块链读书笔记1《精通比特币》第二部分
《精通比特币》作者:Andreas M.Antonopoulos。
本书下载地址:http://zhibimo.com/books/wang-miao/mastering-bitcoin
翻译:薄荷凉幼;陈萌琦;陈姝吉;程鹏;程西园;达文西;吉鸿帆;李丹;李润熙;李凌豪;李昕阳;刘畅;吕新浩;马峰;牛东晓;秦彤;邱頔;邱蒙;戎如香;史磊;汪海波;王宏钢;辛颖;杨兵;尹文东;余龙;张林;张琦张大嫂;张亚超;张泽铭;赵冬帅;赵
余;YANG YANG。
第 5 章 交易
5.1 简介
比特币交易是比特币系统中最重要的部分。根据比特币系统的设计原理,系统中任何其他的部分都是为了确保比特币交易可以被生成、 能在比特币网络中得以传播和通过验证,并最终添加入全球比特币交易总账簿(比特币区块链)。比特币交易的本质是数据结构, 这些数据结构中含有比特币交易参与者价值转移的相关信息。比特币区块链是全球复式记账总账簿,每个比特币交易都是在比特币区块链上的一个公开记录。
在这一章,我们将会剖析比特币交易的多种形式、所包含的信息、如何被创建、如何被验证以及如何成为所有比特币交易永久记录的一部分。
5.2 比特币交易的生命周期
一笔比特币交易的生命周期起始于它被创建的那一刻,也就是诞生(origination)。 随后,比特币交易会被一个或者多个签名加密,这些签名标志着对该交易指向的比特币资金的使用许可。接下来,比特币交易被广播到比特币网络中。在比特币网络中,每一个节点(比特币交易参与者)验证、并将交易在网络中进行广播,直到这笔交易被网络中大多数节点接收。最终,比特币交易被一个挖矿节点验证,并被添加到区块链上一个记录着许多比特币交易的区块中。
一笔比特币交易一旦被记录到区块链上并被足够多的后续区块确认,便成为比特币总账簿的一部分,并被所有比特币交易参与者认可为有效交易。于是,被这笔交易分配到一个新所有者名下的比特币资金可以在新的交易中被使用——这使得所有权链得以延伸且再次开启一个新的比特币交易生命周期。
5.2.1 创建比特币交易
将一笔比特币交易理解成纸质支票或许有助于加深我们对它的理解。与支票相似,一笔比特币交易其实是一个有着货币转移目的的工具,这个工具只有在交易被执行时才会在金融体系中体现, 而且交易发起人并不一定是签署该笔交易的人。
5.2.2 将比特币交易传送至比特币网络
首先,一笔交易需要传递至比特币网络,才能被传播,也才能加入区块链中。本质上,一笔比特币交易只是 300 到 400 字节的数据,而且它们必须被发送到成千上万个比特币节点中的任意一个。只要发送者能使用多于一个比特币节点来确保这笔交易被传播,那么发送者并不需要信任用来传播该笔交易的单一节点。相应地,这些节点不需要信任发送者,也不用建立发送者的“身份档案”。由于这笔交易是经过签名且不含任何机密信息、私钥或密码,因此它可被任何潜在的便利网络公开地传播。信用卡交易包含敏感信息,而且依赖加密网络连接完成信息传输,但比特币交易可在任意网络环境下被发送。只要这笔交易可以到达能将它广播到比特币网络的比特币节点,这笔交易是如何被传输至第一个节点的并不重要。
5.2.3 比特币交易在比特币网络中的传播
一旦一笔比特币交易被发送到任意一个连接至比特币网络的节点,这笔交易将会被该节点验证。如果交易被验证有效,该节点将会将这笔交易传播到这个节点所连接的其他节点;同时,交易发起者会收到一条表示交易成功的返回信息。如果这笔交易被验证为无效, 这个节点会拒绝接受这笔交易且同时返回给交易发起者一条表示交易被拒绝的信息。
比特币网络是一个点对点网络,这意味着每一个比特币节点都连接到一些其他的比特币节点(这些其他的节点是在启动点对点协议时被发现的)。整个比特币网络形成了一个松散地连接、且没有固定拓扑或任何结构的“蛛网”——这使得所有节点的地位都是同等的。比特币交易相关信息(包括交易和区块)被传播——从每一个节点到它连接的其他节点。一笔刚通过验证且并被传递到比特币网络中任意节点的交易会被发送到三到四个相邻节点, 而每一个相邻节点又会将交易发送到三至四个与它们相邻的节点。以此类推,在几秒钟之内,一笔有效的交易就会像指数级扩散的波一样在网络中传播, 直到所有连接到网络的节点都接收到它。
比特币网络被设计为能高效且灵活地传递交易和区块至所有节点的模式,因而比特币网络能抵御入侵。为了避免垃圾信息的滥发、拒绝服务攻击或其他针对比特币系统的恶意攻击, 每一个节点在传播每一笔交易之前均进行独立验证。一个异常交易所能到达的节点不会超过一个。
5.3 交易结构
一笔比特币交易是一个含有输入值和输出值的数据结构,该数据结构植入了将一笔资金从初始点(输入值)转移至目标地址(输出值)的代码信息。比特币交易的输入值和输出值与账号或者身份信息无关。 你应该将它们理解成一种被特定秘密信息锁定的一定数量的比特币。 只有拥有者或知晓这个秘密信息的人可以解锁。
5.4 交易的输出和输入
比特币交易的基本单位是未经使用的一个交易输出,简称 UTXO。UTXO 是不能再分割、 被所有者锁住或记录于区块链中的并被整个网络识别成货币单位的一定量的比特币货币。 比特币网络监测着以百万为单位的所有可用的(未花费的)UTXO。当一个用户接收比特币时,金额被当作 UTXO 记录到区块链里。这样,一个用户的比特币会被当作 UTXO 分散到数百个交易和数百个区块中。实际上,并不存在储存比特币地址或账户余额的地点,只有被所有者锁住的、分散的UTXO。“一个用户的比特币余额”,这个概念是一个通过比特币钱包应用创建的派生之物。比特币钱包通过扫描区块链并聚合所有属于该用户的 UTXO 来计算该用户的余额。
在比特币的世界里既没有账户,也没有余额,只有分散到区块链里的UTXO。一个 UTXO 可以是一“聪”的任意倍。就像美元可以被分割成表示两位小数的“分”一样,比特币可以被分割成表示八位小数的“聪”。尽管 UTXO 可以是任意值,但只要它被创造出来了,就像不能被切成两半的硬币一样不可再分了。如果一个 UTXO 比一笔交易所需量大,它仍会被当作一个整体而消耗掉,但同时会在交易中生成零头。例如,你有20 比特币的 UTXO 并且想支付 1 比特币,那么你的交易必须消耗掉整个20 比特币的 UTXO 并且产生两个输出:一个是支付了1 比特币给接收人,另一个是支付 19 比特币的找零到你的钱包。这样的话,大部分比特币交易都会产生找零。
5.4.1 交易输出
每一笔比特币交易创造输出,输出都会被比特币账簿记录下来。
除特例之外,几乎所有的输出都能创造一定数量的可用于支付的比特币,也就是 UTXO。这些 UTXO 被整个网络识别,并且所有者可在未来的交易中使用它们。给某人发送比特币实际上是创造新的UTXO,注册到那个人的地址,并且能被他用于新的支付。
UTXO 被每一个全节点比特币客户端在一个储存于内存中的数据库所追踪, 该数据库也被称为“UTXO 集”或者“UTXO 池”。新的交易从 UTXO 集中消耗(支付)一个或多个输出。
交易输出包含两部分:
▷ 一定量的比特币,被命名为“聪”,是最小的比特币单位;
一个锁定脚本,也被当作是“障碍”,提出支付输出所必须被满足的条件以“锁住”这笔总额。
支付条件( 障碍)
交易输出把用聪表示的一定数量的比特币,和特定的定义了支付输出所必须被满足的条件的障碍,或者叫锁定脚本,关联到了一起。在大多数情况下,锁定脚本会把输出锁在一个特定的比特币地址上, 从而把一定数量的比特币的所有权转移到新的所有者上。
5.4.2 交易输入
简单地说,交易输入是指向 UTXO 的指针。它们指向特定的 UTXO,并被交易哈希和在区块链中记录 UTXO 的序列号作为参考。若想支付 UTXO,一个交易的输入也需要包含一个解锁脚本,用来满足 UTXO 的支付条件。解锁脚本通常是一个签名,用来证明对于在锁定脚本中的比特币地址拥有所有权。
5.4.3 交易费
大多数交易包含交易费,这是为了在网络安全方面给比特币矿工一种补偿。
交易费可当作是为了包含(挖矿)一笔交易到下一个区块中的一种鼓励,也可当作是对于欺诈交易和任何种类的系统滥用, 在每一笔交易上通过征收一笔小成本的税而造成的一种妨碍。交易费被挖出这个区块的矿工得到,并且记录在这个交易的区块链中。
交易费基于交易的尺寸,用千字节来计算,而不是比特币的价值。总的来说,交易费基于市场所设置,生效于比特币网络中。矿工依据许多不同的标准,按重要性对交易进行排序,这包括费用,并且甚至可能在某种特定情况下免费处理交易。交易费影响处理优先级,这意味着有足够费用的交易会更可能地被包含在下一个挖出的区块中; 与此同时, 交易费不足或者没有交易费的交易可能会被推迟,基于尽力而为的原则在几个区块之后被处理,甚至可能根本不被处理。交易费不是强制的,而且没有交易费的交易也许最终会被处理,但是,包含交易费将提高处理优先级。
随着时间的过去,交易费的计算方式和交易费在交易优先级上的影响一直在发展。起初,交易费是网络中的一个固定常数。渐渐地,交易费的结构被放宽了,以便被市场基于网络容量和交易量而强制影响。 目前最小交易费被固定在每千字节 0.0001 比特币,或者说是每千字节万分之一比特币,最近一次改变是从千分之一比特币减少到这个数值的。大多数交易少于一千字节,但是那些包含多个输入和输出的交易尺寸可能更大。在未来的比特币协议修订版中,钱包应用预计会使用统计学分析,基于最近的几笔交易的平均费用,来计算最恰当的费用并附在交易上。
5.4.4 把交易费加到交易中
交易的数据结构没有交易费的字段。相反地,交易费通过所有输入的总和,以及所有输出的总和之间的差来表示。从所有输入中扣掉所有输出之后的多余的量会被矿工收集走。
交易费被作为输入减输出的余量:
交易费 = 求和(所有输入) - 求和(所有输出)
5.5 交易链条和孤立交易
正如我们之前所看到的那样,交易形成一条链,这条链的形式是一笔交易消耗了先前的交易(父交易)的输出,并为随后的交易(子交易)创造了输出。
5.6 比特币交易脚本和脚本语言
比特币客户端通过执行一个用类 Forth 脚本语言编写的脚本验证比特币交易。锁定脚本被写入 UTXO,同时它往往包含一个用同种脚本语言编写的签名。当一笔比特币交易被验证时, 每一个输入值中的解锁脚本被与其对应的锁定脚本同时(互不干扰地)执行,从而查看这笔交易是否满足使用条件。
5.6.1 脚本创建( 锁定与解锁)
比特币的交易验证引擎依赖于两类脚本来验证比特币交易:一个锁定脚本和一个解锁脚本。
锁定脚本是一个放在一个输出值上的“障碍”,同时它明确了今后花费这笔输出的条件。由于锁定脚本往往含有一个公钥(即比特币地址),在历史上它曾被称作一个脚本公钥代码。由于认识到这种脚本技术存在着更为宽泛的可能性,在本书中,我们将它称为一个“锁定脚本”。在大多数比特币应用源代码中,脚本公钥代码便是我们所说的锁定脚本。
解锁脚本是一个“解决”或满足被锁定脚本在一个输出上设定的花费条件的脚本,同时它将允许输出被消费。解锁脚本是每一笔比特币交易输出的一部分,而且往往含有一个被用户的比特币钱包(通过用户的私钥)生成的数字签名。由于解锁脚本常常包含一个数字签名,因此它曾被称作 ScriptSig。在大多数比特币应用的源代码中,ScriptSig 便是我们所说的解锁脚本。考虑到更宽泛的锁定脚本要求,在本书中,我们将它称为“解锁脚本”。但并非所有解锁脚本都一定会包含签名。
每一个比特币客户端会通过同时执行锁定和解锁脚本来验证一笔交易。对于比特币交易中的每一个输入,验证软件会先检索输入所指向的 UTXO。这个UTXO 包含一个定义了花费条件的锁定脚本。接下来,验证软件会读取试图花费这个 UTXO 的输入中所包含的解锁脚本,并执行这两个脚本。
5.6.2 脚本语言
比特币交易脚本语言,也成为脚本,是一种基于逆波兰表示法的基于堆栈的执行语言。如果这让您听起来似乎在胡言乱语,很有可能是您没学习过 1960 年的编程语言的缘故。脚本是一种非常简单的语言,这种语言被设计为能在有限的硬件上执行,这些硬件类似简单的嵌入式设备,如手持计算器。它仅需最少的处理即可,而且不能做许多现代编程语言可以做的事情。当涉及可编程的钱时,这是它的一个基于深思熟虑的安全特性。
比特币脚本语言被称为基于堆栈语言,因为它使用的数据结构被称为堆栈。堆栈是一个非常简单的数据结构,它可以被理解成为一堆卡片。一个堆栈允许两类操作:推送和弹出。推送是在堆栈顶部增加一个项目,弹出则是从堆栈顶部移除一个项目。
脚本语言通过从左至右地处理每个项目的方式执行脚本。数字(常数)被推送至堆栈,操作符向堆栈推送(或移除)一个或多个参数,对它们进行处理,甚至可能会向堆栈推送一个结果。
5.6.3 图灵非完备性
5.6.4 非主权验证
比特币交易脚本语言是无国家主权的,没有国家能凌驾于脚本之上,也没有国家会在脚本被执行后对其进行保存。 所以需要执行脚本的所有信息都已包含在脚本中。可以预见的是,一个脚本能在任何系统上以相同的方式执行。如果您的系统对一个脚本进行验证, 可以确信的是每一个比特币网络中的其他系统也将对其进行验证,这意味着一个有效的交易对每个人而言都是有效的,而且每一个人都明白这一点。这种对于结果的可预见性是比特币系统的一项重要良性特征。
5.7 标准交易
在比特币最初几年的发展过程中,开发者对可以经由客户端进行操作的脚本类型设置了一些限制。这些限制被编译为一个 Standard()函数,该函数定义了五种类型的标准交易。 这些限制都是临时性的,当您阅读本书时或许已经更新。
5.7.1 P2PKH( Pay-to-Public-Key-Hash)
比特币网络上的大多数交易都是 P2PKH 交易,此类交易都含有一个锁定脚本,该脚本由公钥哈希实现阻止输出功能,公钥哈希即为广为人知的比特币地址。由 P2PKH 脚本锁定的输出可以通过键入公钥和由相应私钥创设的数字签名得以解锁。
5.7.2 P2PK( Pay-to-Public-Key)
与 P2PKH 相比,P2PK 模式更为简单。与 P2PKH 模式含有公钥哈希的模式不同,在 P2PK 脚本模式中,公钥本身已经存储在锁定脚本中,而且代码长度也更短。P2PKH 是由 Satoshi 创建的,主要目的一方面为使比特币地址更简短,另一方面也使之更方便使用。P2PK 目前在 Coinbase 交易中最为常见,Coinbase 交易由老的采矿软件产生,目前还没更新至 P2PKH。
5.7.3 多重签名
多重签名脚本设置了这样一个条件,假如记录在脚本中的公钥个数为 N,则至少需提供其中的 M 个公钥才可以解锁。这也被称为 M-N 组合,其中,N 是记录在脚本中的公钥总个数,M 是使得多重签名生效的公钥数阀值(最少数目) 。
5.7.4 数据输出( OP_RETURN 操作符)
比特币的分发和时间戳账户机制(也即区块链),其潜在运用将大大超越支付领域。许多开发者试图充分发挥交易脚本语言的安全性和可恢复性优势,将其运用于电子公证服务、证券认证和智能协议等领域。比特币脚本语言的早期运用主要包括在区块链上创造出交易输出。例如,为文件记录电子指纹,则任何人都可以通过该机制在特定的日期建立关于文档存在性的证明。
5.7.5 P2SH( Pay-to-Script-Hash)
P2SH 在 2012 年被作为一种新型、强大、且能大大简化复杂交易脚本的交易类型而引入。
5.7.5.1 P2SH 地址
P2SH 的另一重要特征是它能将脚本哈希编译为一个地址(其定义请见BIP0013)。P2SH 地址是基于 Base58 编码的一个含有 20 个字节哈希的脚本,就像比特币地址是基于 Base58 编码的一个含有 20 个字节的公钥。由于 P2SH地址采用 5 作为前缀,这导致基于 Base58 编码的地址以“3”开头。
5.7.5.2 P2SH 的优点
与直接使用复杂脚本以锁定输出的方式相比,P2SH 具有以下特点:
▷ 在交易输出中,复杂脚本由简短电子指纹取代,使得交易代码变短。
▷ 脚本能被编译为地址,支付指令的发出者和支付者的比特币钱包不需要复杂工序就可以执行 P2SH。
▷ P2SH 将构建脚本的重担转移至接收方,而非发送方。
▷ P2SH 将长脚本数据存储的负担从输出方(存储于 UTXO 集,影响内存)转移至输入方(仅存储于区块链)。
▷ P2SH 将长脚本数据存储的重担从当前(支付时)转移至未来(花费时)。
▷ P2SH 将长脚本的交易费成本从发送方转移至接收方,接收方在使用该笔资金时必须含有赎回脚本。
5.7.5.3 赎回脚本和标准确认
第 6 章 比特币网络
6.1 P2P 网络架构
比特币采用了基于国际互联网(Internet)的 P2P(peer-to-peer)网络架构。P2P 是指位于同一网络中的每台计算机都彼此对等,各个节点共同提供网络服务,不存在任何“特殊”节点。每个网络节点以“扁平(flat)”的拓扑结构相互连通。在 P2P 网络中不存在任何服务端(server)、中央化的服务、以及层级结构。P2P 网络的节点之间交互运作、协同处理:每个节点在对外提供服务的同时也使用网络中其他节点所提供的服务。P2P 网络也因此具有可靠性、去中心化,以及开放性。早期的国际互联网就是 P2P 网络架构的一个典型用例:IP网络中的各个节点完全平等。当今的互联网架构具有分层架构,但是 IP 协议仍然保留了扁平拓扑的结构。在比特币之外,规模最大也最成功的 P2P 技术应用是在文件分享领域: Napster 是该领域的先锋, BitTorrent 是其架构的最新演变。比特币所采用的 P2P 网络架构不仅仅是选择拓扑结构这样简单。比特币被设计为一种点对点的数字现金系统,它的网络架构既是这种核心特性的反映,也是该特性的基石。去中心化控制是设计时的核心原则,它只能通过维持一种扁平化、去中心化的 P2P 共识网络来实现。
“比特币网络”是按照比特币 P2P 协议运行的一系列节点的集合。除了比特币 P2P 协议之外,比特币网络中也包含其他协议。例如 Stratum 协议就被应用于挖矿、以及轻量级或移动端比特币钱包之中。
6.2 节点类型及分工
尽管比特币 P2P 网络中的各个节点相互对等,但是根据所提供的功能不同,各节点可能具有不同的分工。每个比特币节点都是路由、区块链数据库、挖矿、钱包服务的功能集合。一个全节点(full node)包括如图 6-1 所示的四个功能:
图 6-1 一个包含四个完整功能的比特币网络节点:钱包、矿工、完整区块链、网络路由
节点
每个节点都参与全网络的路由功能,同时也可能包含其他功能。每个节点都参与验证并传播交易及区块信息,发现并维持与对等节点的连接。在图 6-1 所示的全节点用例中,名为“网络路由节点”的橙色圆圈即表示该路由功能。
一些节点保有一份完整的、最新的区块链拷贝,这样的节点被称为“全节点”。全节点能够独立自主地校验所有交易,而不需借由任何外部参照。另外还有一些节点只保留了区块链的一部分,它们通过一种名为“简易支付验证(SPV)”的方式来完成交易验证。这样的节点被称为“SPV 节点”,又叫“轻量级节点”。在如上图所示的全节点用例中, 名为完整区块链的蓝色圆圈即表示了全节点区块链数据库功能。在图 6-3 中,SPV 节点没有此蓝色圆圈,以示它们没有区块链的完整拷贝。
挖矿节点通过运行在特殊硬件设备上的工作量证明(proof-of-work)算法,以相互竞争的方式创建新的区块。一些挖矿节点同时也是全节点,保有区块链的完整拷贝;还有一些参与矿池挖矿的节点是轻量级节点,它们必须依赖矿池服务器维护的全节点进行工作。在全节点用例中,挖矿功能如图中名为“矿工”的黑色圆圈所示。
用户钱包也可以作为全节点的一部分,这在桌面比特币客户端中比较常见。当前,越来越多的用户钱包都是 SPV 节点,尤其是运行于诸如智能手机等资源受限设备上的比特币钱包应用;而这正变得越来越普遍。在图 6-1 中,名为“钱包”的绿色圆圈代表钱包功能。
在比特币 P2P 协议中,除了这些主要的节点类型之外,还有一些服务器及节点也在运行着其他协议,例如特殊矿池挖矿协议、轻量级客户端访问协议等。图 6-2 描述了扩展比特币网络中最为常见的节点类型。
图 6-2 扩展比特币网络的不同节点类型
6.3 扩展比特币网络
运行比特币 P2P 协议的比特币主网络由大约 7000-10000 个运行着不同版本比特币核心客户端(Bitcoin Core)的监听节点、以及几百个运行着各类比特币 P2P 协议的应用(例如 BitcoinJ、Libbitcoin、btcd 等)的节点组成。比特币 P2P 网络中的一小部分节点也是挖矿节点,它们竞争挖矿、验证交易、并创建新的区块。许多连接到比特币网络的大型公司运行着基于 Bitcoin 核心客户端的全节点客户端,它们具有区块链的完整拷贝及网络节点,但不具备挖矿及钱包功能。这些节点是网络中的边缘路由器(edge routers),通过它们可以搭建
其他服务,例如交易所、钱包、区块浏览器、商家支付处理(merchant payment processing)等。
图 6-3 具有多种节点类型、网关及协议的扩展比特币网络
6.4 网络发现
当新的网络节点启动后,为了能够参与协同运作,它必须发现网络中的其他比特币节点。新的网络节点必须发现至少一个网络中存在的节点并建立连接。由于比特币网络的拓扑结构并不基于节点间的地理位置,因此各个节点之间的地理信息完全无关。在新节点连接时,可以随机选择网络中存在的比特币节点与之相连。
6.5 全节点
全节点是指维持包含全部交易信息的完整区块链的节点。更加准确地说,这样的节点应当被称为完整区块链节点。在比特币发展的早期,所有节点都是全节点;当前的比特币核心客户端也是完整区块链节点。但在过去的两年中出现了许多新型客户端,它们不需要维持完整的区块链,而是作为轻量级客户端运行。在下面的章节里我们会对这些轻量级客户端进行详细介绍。
完整区块链节点保有完整的、最新的包含全部交易信息的比特币区块链拷贝,这样的节点可以独立地进行建立并校验区块链,从第一区块(创世区块)一直建立到网络中最新的区块。完整区块链节点可以独立自主地校验任何交易信息,而不需要借助任何其他节点或其他信息来源。完整区块节点通过比特币网络获取包含交易信息的新区块更新, 在验证无误后将此更新合并至本地的区块链拷贝之中。
运行完整区块链节点可以给您一种纯粹的比特币体验:不需借助或信任其他系统即可独立地对所有交易信息进行验证。辨别您是否在运行全节点是十分容易的:只需要查看您的永久性存储设备(如硬盘)是否有超过 20GB 的空间被用来存储完整区块链即可。如果您需要很大的磁盘空间、并且同步比特币网络耗时 2至 3 天,那么您使用的正是全节点。这就是摆脱中心化管理、获得完全的独立自由所要付出的代价。
6.6 交换“ 库存清单”
一个全节点连接到对等节点之后,第一件要做的事情就是构建完整的区块链。如果该节点是一个全新节点,那么它就不包含任何区块链信息,它只知道一个区块——静态植入在客户端软件中的创世区块。新节点需要下载从 0 号区块(创世区块)开始的数十万区块的全部内容,才能跟网络同步、并重建全区块链。同步区块链的过程从发送 version 消息开始,这是因为该消息中含有的BestHeight 字段标示了一个节点当前的区块链高度(区块数量)。节点可以从它的对等节点中得到版本消息,了解双方各自有多少区块,从而可以与其自身区块链所拥有的区块数量进行比较。对等节点们会交换一个 getblocks 消息,其中包含他们本地区块链的顶端区块哈希值。 如果某个对等节点识别出它接收到的哈希值并不属于顶端区块,而是属于一个非顶端区块的旧区块,那么它就能推断出:其自身的本地区块链比其他对等节点的区块链更长。
6.7 简易支付验证 ( SPV) 节点
并非所有的节点都有能力储存完整的区块链。许多比特币客户端被设计成运行在空间和功率受限的设备上,如智能电话、平板电脑、嵌入式系统等。对于这样的设备,通过简化的支付验证(SPV)的方式可以使它们在不必存储完整区块链的情况下进行工作。这种类型的客端被称为 SPV 客户端或轻量级客户端。随
着比特币的使用热潮,SPV 节点逐渐变成比特币节点(尤其是比特币钱包)所采用的最常见的形式。
SPV 节点只需下载区块头,而不用下载包含在每个区块中的交易信息。由此产生的不含交易信息的区块链,大小只有完整区块链的 1/1000。SPV 节点不能构建所有可用于消费的 UTXO 的全貌,这是由于它们并不知道网络上所有交易的完整信息。SPV 节点验证交易时所使用的方法略有不同,这个方法需依赖对等节点“按需”提供区块链相关部分的局部视图。
简易支付验证是通过参考交易在区块链中的深度,而不是高度,来验证它们。
一个拥有完整区块链的节点会构造一条验证链, 这条链是由沿着区块链按时间倒序一直追溯到创世区块的数千区块及交易组成。而一个 SPV 节点会验证所有区块的链(但不是所有的交易),并且把区块链和有关交易链接起来。
在绝大多数的实际情况中,具有良好连接的 SPV 节点是足够安全的,它在资源需求、实用性和安全性之间维持恰当的平衡。当然,如果要保证万无一失的安全性,最可靠的方法还是运行完整区块链的节点。
完整的区块链节点是通过检查整个链中在它之下的数千个区块来保证这个UTXO 没有被支付,从而验证交易。而 SPV 节点是通过检查在其上面的区块将它压在下面的深度来验证交易。
6.8 Bloom 过滤器
Bloom 过滤器是一个允许用户描述特定的关键词组合而不必精确表述的基于概率的过滤方法。它能让用户在有效搜索关键词的同时保护他们的隐私。在SPV 节点里,这一方法被用来向对等节点发送交易信息查询请求,同时交易地址不会被暴露。
6.9 Bloom 过滤器和存货更新
Bloom 过滤器被用来过滤 SPV 节点从对等节点里收到的交易信息。SPV 会建立一个只能和 SPV 节点钱包里的地址匹配的过滤器。随后,SPV 节点会向对等节点发送一条包含需在该连接中使用的过滤器的 filterload 消息。当过滤器建好之后,对等节点将每个交易的输出值代入过滤器中验证。那些正匹配的交易会被传送回 SPV 节点。
6.10 交易池
比特币网络中几乎每个节点都会维护一份未确认交易的临时列表,被称为内存池或交易池。节点们利用这个池来追踪记录那些被网络所知晓、但还未被区块链所包含的交易。例如,保存用户钱包的节点会利用这个交易池来记录那些网络已经接收但还未被确认的、属于该用户钱包的预支付信息。
随着交易被接收和验证,它们被添加到交易池并通知到相邻节点处,从而传播到网络中。
6.11 警告消息
警告消息并不经常使用,但在大多数节点上都有此功能。警告消息是比特币的“紧急广播系统”,比特币核心开发人员可以借此功能给所有比特币节点发送紧急文本消息。 这一功能是为了让核心开发团队将比特币网络的严重问题通知所有的比特币用户,例如一个需要用户采取措施的的严重 bug。警告系统迄今为止只被用过几次,最严重的一次是在 2013 年,一个关键的数据库缺陷导致比特币区块链中出现了一个多区块分叉。
第 7 章 区块链
7.1 简介
区块链是由包含交易信息的区块从后向前有序链接起来的数据结构。它可以被存储为 flat file(一种包含没有相对关系记录的文件),或是存储在一个简单数据库中。比特币核心客户端使用 Google 的 LevelDB 数据库存储区块链元数据。区块被从后向前有序地链接在这个链条里,每个区块都指向前一个区块。区块链经常被视为一个垂直的栈,第一个区块作为栈底的首区块,随后每个区块都被放置在其他区块之上。用栈来形象化表示区块依次堆叠这一概念后,我们便可以使用一些术语,例如:“高度”来表示区块与首区块之间的距离;以及“顶部”或“顶端”来表示最新添加的区块。
对每个区块头进行 SHA256 加密哈希, 可生成一个哈希值。 通过这个哈希值,可以识别出区块链中的对应区块。同时,每一个区块都可以通过其区块头的“父区块哈希值”字段引用前一区块(父区块)。也就是说,每个区块头都包含它的父区块哈希值。 这样把每个区块链接到各自父区块的哈希值序列就创建了一条一直可以追溯到第一个区块(创世区块)的链条。
7.2 区块结构
区块是一种被包含在公开账簿(区块链)里的聚合了交易信息的容器数据结构。它由一个包含元数据的区块头和紧跟其后的构成区块主体的一长串交易组成。区块头是 80 字节,而平均每个交易至少是 250 字节,而且平均每个区块至少包含超过 500 个交易。因此,一个包含所有交易的完整区块比区块头的 1000倍还要大。
区块头由三组区块元数据组成。首先是一组引用父区块哈希值的数据,这组元数据用于将该区块与区块链中前一区块相连接。第二组元数据,即难度、时间戳和 nonce,与挖矿竞争相关,详见第 8 章。第三组元数据是 merkle 树根(一种用来有效地总结区块中所有交易的数据结构)。表 7-2 描述了区块头的数据结构。
7.4 区块标识符: 区块头哈希值和区块高度
区块主标识符是它的加密哈希值, 一个通过 SHA256 算法对区块头进行二次哈希计算而得到的数字指纹。产生的 32 字节哈希值被称为区块哈希值,但是更准确的名称是:区块头哈希值,因为只有区块头被用于计算。
例如:000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f 是第一个比特币区块的区块哈希值。区块哈希值可以唯一、明确地标识一个区块, 并且任何节点通过简单地对区块头进行哈希计算都可以独立地获取该区块哈希值。
一个区块的区块哈希值总是能唯一地识别出一个特定区块。一个区块也总是有特定的区块高度。但是,一个特定的区块高度并不一定总是能唯一地识别出一个特定区块。更确切地说,两个或者更多数量的区块也许会为了区块中的一个位置而竞争。
7.5 创世区块
区块链里的第一个区块创建于 2009 年,被称为创世区块。它是区块链里面所有区块的共同祖先,这意味着你从任一区块,循链向后回溯,最终都将到达创世区块。
因为创世区块被编入到比特币客户端软件里,所以每一个节点都始于至少包含一个区块的区块链,这能确保创世区块不会被改变。每一个节点都“知道”创世区块的哈希值、结构、被创建的时间和里面的一个交易。因此,每个节点都把该区块作为区块链的首区块,从而构建了一个安全的、可信的区块链的根。在 chainparams.cpp 里可以看到创世区块被编入到比特币核心客户端里。
7.6 区块的连接
比特币的完整节点保存了区块链从创世区块起的一个本地副本。随着新的区块的产生,该区块链的本地副本会不断地更新用于扩展这个链条。当一个节点从网络接收传入的区块时,它会验证这些区块,然后链接到现有的区块链上。为建立一个连接,一个节点将检查传入的区块头并寻找该区块的“父区块哈希值”。
图 7-1 区块通过引用父区块的区块头哈希值的方式,以链条的形式进行相连
7.7 Merkle 树
区块链中的每个区块都包含了产生于该区块的所有交易,且以 Merkle 树表示。
Merkle 树是一种哈希二叉树,它是一种用作快速归纳和校验大规模数据完整性的数据结构。这种二叉树包含加密哈希值。术语“树”在计算机学科中常被用来描述一种具有分支的数据结构,但是树常常被倒置显示,“根”在图的上部同时“叶子”在图的下部,你会在后续章节中看到相应的例子。
在比特币网络中,Merkle 树被用来归纳一个区块中的所有交易,同时生成整个交易集合的数字指纹,且提供了一种校验区块是否存在某交易的高效途径。生成一棵完整的 Merkle 树需要递归地对哈希节点对进行哈希,并将新生成的哈希节点插入到 Merkle 树中,直到只剩一个哈希节点,该节点就是 Merkle 树的根。在比特币的 Merkle 树中两次使用到了 SHA256 算法,因此其加密哈希算法也被称为 double-SHA256。
7.8 Merkle 树和简单支付验证( SPV)
Merkle 树被 SPV 节点广泛使用。SPV 节点不保存所有交易也不会下载整个区块,仅仅保存区块头。它们使用认证路径或者 Merkle 路径来验证交易存在于区块中,而不必下载区块中所有交易。