-
央行发行数字货币(私钥签名后发行货币,公钥验证确实是央行发行的货币后完成交易)的挑战:
1. 货币是一种文件,文件内容不能伪造,但可以复制——花两次攻击 double spending attack
2. 中心化方案:央行给每一个数字货币编号,则需要维护一个数字货币归属的数据库,每一次交易都需要央行的确认。 -
去中心化货币要解决两个问题:
1. 数字货币的发行 —— 比特币的发行是由挖矿决定的
2. 怎么验证交易的有效性,防止double spending attack —— 由用户共同维护区块链的数据结构 -
区块链:
比特币的发行者A拥有铸币权(Create coin)。假如A发行10个比特币, A(10)分别给B和C各五个,即B(5)C(5), 该交易需要有A的签名,证明经A同意(Signed by A)。同时,还要说明花掉的10个比特币的来源。有的交易部分比较复杂,如C的货币来源是第二第三个方框,要标识清楚。
![](https://img-blog.csdnimg.cn/bbfc2ebf1b93496ea74623244475d9bf.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAQ2hlMnJ5,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
比特币系统中每个交易都包含输入和输出两部分。 输入部分要说明币的来源,输出部分要给出收款人公钥的哈希,相当于地址。
上图就构成了一个小型的区块链,有两种哈希指针:
1. 第一种哈希指针是连接在各个区块之间的,把它们串起来构成一个链表。
2. 第二种哈希指针,是指向前面某个交易的指针,用来指明账户币的来源。证明币不是凭空捏造的是有记录的,防范double spending。
-
交易合法性验证:
问题:第二个方框的交易,所有节点都要知道A的公钥,区块链上每个节点都要独立验证该交易中A的签名。
解决:输入币的来源和A的公钥,且币来源的交易输出的A的公钥哈希值,要与交易时A提供的公钥哈希相等。 -
比特币脚本(BitCoin Script):
在比特币系统当中,前面这些验证过程,是通过执行脚本来实现的。每个交易的输入是一段脚本,包括给出公钥的过程,公钥也是在输入的脚本里指定的。每个交易的输出也是一段脚本,验证其的合法性,就需要把当前交易的输入脚本跟前面交易(提供币来源的交易)的输出脚本拼在一起,然后看看能不能顺利执行,如果能执行说明是合法的。 -
区块:
实际上每个区块(对应图中的每个方框)可以有很多交易,这些交易就组成Merkle Tree。每个区块分为块头和块身。
![](https://img-blog.csdnimg.cn/5ab5580f7ef843f59fc60cc0d4f6eed7.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAQ2hlMnJ5,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
Block header包含:
区块的宏观信息,如:比特币的版本(version)的协议;
区块链当中指向前一个区块的哈希指针(hash of previous block header);
整颗Merkle tree 的根哈希值(Merkle root hash); —— 保证body中的交易信息未被篡改
是挖矿的难度目标预值(target); —— H(Block header)≤target
随机数nonce。
注意:前一个区块的哈希值只算前一个区块的块头。
![](https://img-blog.csdnimg.cn/ef1f1ea9a8f54655a0b7eb5df6e74582.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAQ2hlMnJ5,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
Block body包含: 交易列表(transaction list)。
系统中的节点分全节点(full node)和轻节点(light node),全节点是保存区块链所有的信息的,验证每一个交易,所以全节点又叫fully validating node。轻节点只保存lock header的信息,一般来说轻节点没法独立验证交易的合法性。系统中大多数节点是轻节点,但其没有参与区块链的构造和维护。
-
交易如何写到区块链里面?—— 账本的内容是要取得分布式的共识(distributed consensus)。
-
分布式共识:
分布式的哈希表(distributed hash table);
分布式系统的不可能结论(impossibility result),如FLP、CAP Theorem;
分布式共识一个著名协议Paxos,该协议能够保证一致性; -
比特币中的共识协议(Consensus in BitCoin):投票方案 —— 投票确定哪个区块写入主链
- 问题:应该确定哪些区块拥有投票权membership。
某些系统的membership有严格的要求,例如联盟链Hyper Ledger Fabric,这种情况下基于投票的方案是可行的。但是,比特币系统创建账户是容易的,一个人产生的公私钥对只有在转账时,其他账户才能知道,所以攻击者可以不停的创建账户(不断生成公私钥对)。当攻击者创建超过账户总数一半的账户数目时,攻击者就拥有了对账本的控制权。这种称为女巫攻击(sybil attack),因此这种投票方法不可取。因此,对于比特币来说,简单的直接投票不可行。
- 解决:不是按照账户数目投票,按照计算力来投票。
每个节点都可以在本地组装出一个候选区块,把它认为合法的交易放在候选区块里。然后该节点开始尝试各种nonce随机值(占4 byte),使其能满足不等式 H(block header)≤target 的要求。如果某个节点找到了符合要求的nonce,它就获得了记账权。 由于hash函数具有puzzle friendly的性质,因此,计算力代表了投票的权重。 -
记账权
所谓的记账权,就是往比特币账本里写入下一个区块的权利。只有找到这个nonce,获得记账权的节点才有权利发布下一个区块。其他节点在收到这个区块之后,要验证该区块的合法性。 -
验证区块合法性
block header 的内容检查:检查block header中nBits的域设置是否符合比特币协议中规定的难度要求,不等式是否成立等。
block body 的交易列表检查,验证每个交易是否都合法:1、要有合法的签名; 2、比特币之前没有被花
如果有一项不符合要求,这个区块就不能被接受。如果所有条件都符合,也不一定接受,见下图。
![](https://img-blog.csdnimg.cn/1c7ddab3bebb48229e5f89a6197392e5.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAQ2hlMnJ5,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
虽然红色区块是合法的,但是它不在最长合法链(longest valid chain)上,故不接受该区块,这种称为分叉攻击(forking attack)。所有接收的区块应该是扩展最长合法链。
区块链在正常情况下也可能出现分岔 —— 两个节点同时获得记账权:
每个节点在本地自己组装一个它认为合适的区块,然后去尝试各种nonce,如果两个节点在差不多同一时间找到了符合要求的nonce,就都可以把区块发布,这时会出现两个等长的分岔,这两条都是最长合法链。
比特币协议中用到了implicit consign,即如果沿着某个区块继续往后扩展,该区块认为是合法的。等长的临时性的分岔会维持一段时间,直到一个分岔胜出成为最长合法链。 也就是哪一个链抢先一步生成了新的区块,哪一条就是最长合法链。orphan block中的交易会回滚,其得到的比特币是没有作用的。
-
获得记账权的好处(奖励机制)
1. 区块奖励(block reward):比特币协议中规定获得记账权的节点在发布的区块里可以有一个特殊的交易——铸币交易,在这个交易里可以发布一定数量的比特币。Coinbase transaction是比特币系统中发行新币的唯一方法,此后的交易都是比特币的转移,而这个交易不用指出币的来源。出块奖励:比特币刚上线,每个发布的区块可以产生50BTC,21万个区块以后,出块奖励减半成25BTC。再过21万个区块,减半为12.5BTC。
2. transaction fee 交易费:所有交易输入金额之和要等于输出金额之和。即total inputs=total outputs。某些交易的total inputs略微大于total outputs。例如,输入1比特币,输出0.99比特币,另外0.01比特币作为交易费给获得记账权发布区块的节点。 -
总结:
去中心化的账本需要取得所有节点的共识。只有获得记账权的节点才能写账本。记账权通过pow(挖矿)获得。比特币争夺记账权的过程叫作挖矿(mining),比特币被称为数字黄金(digital gold),争夺记账权的节点被称为矿工(miner)。