精通比特币(下)

第七章 区块链

由于区块头里面包含“父区块哈希值”字段,所以当前区块的哈希值因此也受到该字段的影响。如果父区块的身份标识发生变化,子区块的身份标识也会跟着变化。当父区块有任何改动时,父区块的哈希值也发生变化。父区块的哈希值发生改变将迫使子区块的“父区块哈希值”字段发生改变,从而又将导致子区块的哈希值发生改变。而子区块的哈希值发生改变又将迫使孙区块的“父区块哈希值”字段发生改变,又因此改变了孙区块哈希值,等等以此类推。一旦一个区块有很多代以后,这种瀑布效应将保证该区块不会被改变,除非强制重新计算该区块所有后续的区块。正是因为这样的重新计算需要耗费巨大的计算量,所以一个长区块链的存在可以让区块链的历史不可改变,这也是比特币安全性的一个关键特征。

[注] 除非强制重新计算该区块所有后续的区块:是指更改一个区块的内容之后,该区块后面的所有区块。由于这条“新”链不是最长的链,所以其他的矿工不会进行计算,只能更改区块的矿工自己计算,而这个计算又要赶超最长的链(要不然,就不会被认可是真正的链,也就使得之前区块的改动没有意义),这个难度显然是很大的。

区块是一种被包含在公开账簿(区块链)里的聚合了交易信息的容器数据结构。它由一个包含元数据的区块头和紧跟其后的构成区块主体的一长串交易组成。区块头是80字节,而平均每个交易至少是250字节,而且平均每个区块至少包含超过500个交易。因此,一个包含所有交易的完整区块比区块头的1000倍还要大。

[注] 平均每个交易至少是250字节?第五章交易里面,我们知道,交易的结构是4个字节的版本信息+1到9个字节的输入数量+一个或多个的交易输入+1到9个字节的输出数量+一个或多个的交易输出+4个字节的时钟时间。即至少10个字节+输入+输出。

交易输出的结构是:8个字节的总量+1到9个字节的锁定脚本尺寸+锁定脚本。即至少9个字节+锁定脚本。

交易输入的结构是:32个字节的UTXO的哈希指针+4个字节的输出索引+1到9个字节的解锁脚本尺寸+解锁脚本+4个字节的序列号。即至少41个字节+解锁脚本。

锁定脚本和解锁脚本的大小又是多少?这样可以计算出交易最小的字节数。

250*500/80=1562.5

区块头由三组区块元数据组成。首先是一组引用父区块哈希值的数据,这组元数据用于将该区块与区块链中前一区块相连接。第二组元数据,即难度、时间戳和nonce,与挖矿竞争相关。第三组元数据是merkle树根(一种用来有效地总结区块中所有交易的数据结构)。

[问题] 这里的父区块哈希是指父区块的哈希还是父区块头的哈希?

[解答] 从后文的区块标识符可以看出,这里的父区块哈希应该是父区块头的哈希。由于区块头中有merkle树的根,这个数据与交易有关,如果交易变化,则这个数据变化,从而导致区块投变化,进一步区块哈希也变化。

区块哈希值实际上并不包含在区块的数据结构里,区块的哈希值可能会作为区块元数据的一部分被存储在一个独立的数据库表中,以便于索引和更快地从磁盘检索区块。

[注] 不是在下一个区块的区块头中有父区块哈希吗?则可以获取这个区块头的哈希值。这里为什么说是不包含在区块的数据结构里呢?还是说,节点获取这个区块之后需要自己计算,从而进行验证。而不能直接取下一个区块的区块头里面的父区块哈希?并且将这个区块哈希值进行保存在本地的数据库中。区块哈希和区块高度都可以表示一个区块

在chainparams.cpp里可以看到创世区块被编入到比特币核心客户端里。

[注] 因此创世区块是程序默认的写在程序中,只要运行程序,则对应的区块链的起点(创世区块)是一样的,再从网络上同步区块链,则可以获得相同的区块数据:链的起点和链的本身的内容是相同的。

一个节点能够通过生成一条仅有4个32字节哈希值长度(总128字节)的Merkle路径,来证明区块中存在一笔交易K。该路径有4个哈希值(在图7-5中由蓝色标注)HL、HIJ、HMNOP和HABCDEFGH。由这4个哈希值产生的认证路径,再通过计算另外四对哈希值HKL、HIJKL、HIJKLMNOP和Merkle树根(在图中由虚线标注),任何节点都能证明HK(在图中由绿色标注)包含在Merkle根中。

[问题] 计算已经知道了HL、HIJ等,为什么不用HK与之比较?是因为这笔交易不知道是哪一笔每个进行比较吗?还是说如果要比较其中的一个交易,之前要保存HA到HK这16个数据,而现在只需要这4个数据?

我所理解的验证区块中存在交易K,应该是将交易K的哈希与HL哈希得到HKL,再用HKL和HIJ哈希得到HIJKL再与HMNOP哈希,一步一步得到merkle的根,再与区块头中的根进行比较。这样是验证一个交易K。那么要验证其他的交易存储的路径也会不同。所以,要获得全路径(所有的交易从A到P都可以验证),那么需要存储8+4+2+1=15个哈希值,仅比节点的哈希少一个。

[解答] 那么应该从场景考虑,而不是上面理论的推导。场景如下段的描述:轻量级的钱包会搜索与自己钱包的地址有关的交易,由于不能泄露自己的信息,所以需要bloom过滤器,而过滤器过滤得到的数据有一些不是该地址和的交易。则需要使用该交易与该区块头和Merkle路径来进行验证。这里只要节点提供给轻量级钱包区块头和Merkle就可以进行验证,而不用提供该区块中的所有的交易或所有的交易的哈希值。

它将以Merkleblock消息的形式发送该区块。Merkleblock消息包含区块头和一条连接目标交易与Merkle根的Merkle路径。SPV节点能够使用该路径找到与该交易相关的区块,进而验证对应区块中该交易的有无。SPV节点同时也使用区块头去关联区块和区块链中的区域区块。这两种关联,交易与区块、区块和区块链,证明交易存在于区块链。简而言之,SPV节点会收到少于1KB的有关区块头和Merkle路径的数据,其数据量比一个完整的区块(目前大约有1MB)少了一千倍有余。

[注] 由于获得的是交易以及该交易对应的Merkle的路径,所以不需要所有的路径或所有的交易。所以,能够达到节省下载数据量的效果。

第8章 挖矿与共识

矿工通过创造一个新区块得到的比特币数量大约每四年(或准确说是每210,000个块)减少一半。

[知识点] 每210,000个块挖矿收益较小一半。

尽管挖矿带来的奖励是一种激励,但它最主要的目的并不是奖励本身或者新币的产生。如果只把挖矿看作生产新币的过程,那你是把手段(激励措施)当成了目的。挖矿是一种将结算所去中心化的过程,每个结算所对处理的交易进行验证和结算。挖矿保护了比特币系统的安全,并且实现了在没有中心机构的情况下,也能使整个比特币网络达成共识。它可以调节矿工行为和网络安全,同时又完成了比特币的货币发行。

[注] 挖矿兼具如下几个作用:充当清算中心、发行新币、激励。而作为依靠计算复杂难题(牺牲算力和电费)清算中心是最主要的,而与之而来的激励(新币的获得)则作为激励,就像BT提供下载方,如果仅仅是激情或理想一个网络并不能够提供很高的速度。而引入这个激励,作为以利益优先的理性人能够更长久的坚持下来。

在经过1,344万个区块之后,所有的共2,099,999,997,690,000聪比特币将全部发行完毕。换句话说,到2140年左右,会存在接近2,100万比特币。

[注] 即挖矿的奖励降低到最小单位:1聪之后,无法再进行分割,从而挖矿的新币奖励消失之后的结果。

每一个节点在校验每一笔交易时,都需要对照一个长长的标准列表:

其中一项为:对于每一个输入,如果引用的输出交易是一个coinbase输出,该输入必须至少获得COINBASE_MATURITY (100)个确认。

注:区块中的第一笔交易是笔特殊交易,称为创币交易或者coinbase交易。

[注] 即挖矿的新币收益作为一个特殊的交易:并不是其他人的币输出的。这也解释了挖矿的新币收益的存在形式:是一种特殊的交易。然后,这种交易要进行消费,则需要更严格的确认:100个确认约17个小时,而一般的交易只需要6次确认。

UTXO的“块龄”是自该UTXO被记录到区块链为止所经历过的区块数,即这个UTXO在区块链中的深度。

比特币交易中没有过期、超时的概念,一笔交易现在有效,那么它就永远有效。然而,如果一笔交易只在全网广播了一次,那么它只会保存在一个挖矿节点的内存中。因为内存池是以未持久化的方式保存在挖矿节点存储器中的,所以一旦这个节点重新启动,内存池中的数据就会被完全擦除。而且,即便一笔有效交易被传播到了全网,如果它长时间未处理,它将从挖矿节点的内存池中消失。如果交易本应该在一段时间内被处理而实际没有,那么钱包软件应该重新发送交易或重新支付更高的矿工费。

[注] 这个解答了会不会出现交易(转账)失败的情况。从上面的描述看,是存在这个可能的:尤其是当网络比较拥堵,需要较大的矿工费,而你的交易又提供很少的交易费的时候。毕竟交易费用是节点评估优先级的一个因素。

创币交易,与常规交易不同,创币交易没有输入,不消耗UTXO。它只包含一个被称作coinbase的输入,仅仅用来创建新的比特币。

[注] 产生的输出叫UTXO吗?还是单独的另外的结构:coinbase输出

“普通“交易输入的结构 与 生成交易输入的结构 的对比

“普通“交易输入的结构

生成交易输入的结构

[注] 在创币交易中,“交易哈希”字段32个字节全部填充0,“交易输出索引”字段全部填充0xFF(十进制的255),这两个字段的值表示不引用UTXO。“解锁脚本”由coinbase数据代替,数据可以由矿工自定义。

创币交易不包含“解锁脚本“(又称作 scriptSig)字段,这个字段被coinbase数据替代,长度最小2字节,最大100字节。除了开始的几个字节外,矿工可以任意使用coinbase的其他部分,随意填充任何数据。

以创世块为例,中本聪在coinbase中填入了这样的数据“The Times 03/Jan/ 2009 Chancellor on brink of second bailout for banks“(泰晤士报 2009年1月3日 财政大臣将再次对银行施以援手),表示对日期的证明。

[注] 因此创世区块中不是使用之前提到的“数据输出(OP_RETURN操作符)”来写入的,而是通过这里的“锁定脚本”来写入的。

区块头完成全部的字段填充后,挖矿就可以开始进行了。挖矿的目标是找到一个使区块头哈希值小于难度目标的nonce。挖矿节点通常需要尝试数十亿甚至数万亿个不同的nonce取值,直到找到一个满足条件的nonce值。

[注] 因此这里的挖矿的难度是一连串的0,找到小于难度目标的值,就获得了记账权。由于每个要计算的区块头中包含前一个区块的区块哈希,前一个区块的区块哈希又与前一个区块的Merkle树根有关,因此与前一个区块的交易有关。因此,当一个新的区块(不是自己挖到的)出现时,就需要重新进行计算该难题。而不能提前埋伏。

矿工用一些交易构建一个候选区块。接下来,这个矿工计算这个区块头信息的哈希值,看其是否小于当前目标值。如果这个哈希值不小于目标值,矿工就会修改这个nonce(通常将之加1)然后再试一次。按当前比特币系统的难度,矿工得试10^15次(10的15次方)才能找到一个合适的nonce使区块头信息哈希值足够小。

[注] 即使用遍历的方式进行计算。

比特币将区块间隔设计为10分钟,是在更快速的交易确认和更低的分叉概率间作出的妥协。更短的区块产生间隔会让交易清算更快地完成,也会导致更加频繁地区块链分叉。与之相对地,更长的间隔会减少分叉数量,却会导致更长的清算时间。

[注] POW验证机制的限制。当然后续仍然有很多其他的山寨币使用了不同于10分钟的出块间隔。

2012年以来,比特币挖矿发展出一个解决区块头基本结构限制的方案。在比特币的早期,矿工可以通过遍历随机数(Nonce)获得符合要求的hash来挖出一个块。难度增长后,矿工经常在尝试了40亿个值后仍然没有出块。然而,这很容易通过读取块的时间戳并计算经过的时间来解决。因为时间戳是区块头的一部分,它的变化可以让矿工用不同的随机值再次遍历。当挖矿硬件的速度达到了4GH/秒,这种方法变得越来越困难,因为随机数的取值在一秒内就被用尽了。当出现ASIC矿机并很快达到了TH/秒的hash速率后,挖矿软件为了找到有效的块,需要更多的空间来储存nonce值。可以把时间戳延后一点,但将来如果把它移动得太远,会导致区块变为无效。区块头需要一个新的“差异性”的信息来源。解决方案是使用coinbase交易作为额外的随机值来源,因为coinbase脚本可以储存2-100字节的数据,矿工们开始使用这个空间作为额外随机值的来源,允许他们去探索一个大得多的区块头值范围来找到有效的块。

[注] 难度增加,导致一些数据的遍历不足以找到对应的难度目标的数值。从而开始动用其他的数据结构来提供遍历的可能性。

第9章 竞争币、竞争块链和应用程序

[注] 目前由于以太坊的发币功能,从而使得数字货币的种类达到了几千种。而真正有技术创新的很少。

第10章 比特币安全

相比之下,比特币这样的去中心化系统则将责任和控制权都移交给了用户。由于网络的安全性是基于工作量证明而非访问控制,比特币网络可以对所有人开放,也无需对比特币流量进行加密。

[注] 即用户来负责保存私钥,丢失私钥则丧失了该笔资产的控制权。也无法像传统的中心化金融机构那样可以通过其他的信息来找回。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180819G0CK0100?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券