数字货币vs纸质货币
数字货币和纸质货币区别是数字货币可以复制,即一钱多花。叫作双花攻击 即double spending attack。在中心化的系统中,央行可以维护一个数据库,记录每一份发行的数字货币是由谁持有的;当有一份交易请求时,验证付款人是不是还持有这份货币。这个方法是可行的,前提是每份交易都要向央行请求验证。
即,我手里把一个100的数字货币给了B,B首先确认这个货币还在我手上,并没有给别人,要确认这一点就只有向央行请求。同时,我们交易完成之后,还需要请求央行,把货币的持有人改为B。
对于去中心化的货币,它要解决两个问题:
- 数字货币的发行
- 怎么验证交易的有效性,防止double spending attack。
比特币给出的答案是:
- 发行靠挖矿决定
- 交易的有效性靠区块链的数据结构保证
交易的有效性
先来看第二个问题。假设A拥有铸币权(create coin), 发行10个比特币(coin base transaction)。注意,这个交易中,要包含A的公钥。实际上,所有交易都要包含收款者的公钥的哈希值。我们之后会明白为什么。
现在,A分别给B和C各五个比特币:A(10) → B(5)C(5)。 该交易需要有A的签名(A用私钥签名,大家可以用A的公钥验证)。同时还要说明花掉的10个比特币从哪来的(第二个方框中的钱是从第一个框内铸币交易中来的),所以交易要包含指向币的来源的哈希指针。

上图构成了一个小型的区块链,这里有两种哈希指针,一种哈希指针是连接在各个区块之间的,把它们串起来构成一个链表,前面学的就是这种哈希指针。在图中还有第二种哈希指针,是指向前面某个交易的指针,用来指明币的来源,防范double spending。
(该图对交易系统进行了简化,实际上每个区块(对应图中的每个方框)可以有很多交易,这些交易就组成Merkle tree)
比特币系统中每个交易都包含输入和输出两部分。!!!输入部分包含币的来源(哈希指针)以及付款者的公钥,输出部分要给出收款人公钥的哈希值!!!有的交易比较复杂,如C的货币来源是第二第三个交易,在第四个方框中C转账给E的交易中,要包含指向第二、第三交易的哈希指针。
现在来看第二个方框里A向B的转账,该交易需要A的签名和B的地址。比特币系统里收款的地址是通过公钥推算出来的。比如B的地址就是B的公钥取哈希然后经过一些转换得到的。
A如何知道B的地址?比特币系统中没有查询对方地址的功能,必须通过其他渠道。比如某个电商网站,接受比特币支付,就可以公开它的地址或公钥。
A需要知道B的地址,B需要知道A的什么信息吗?B其实也要知道A的公钥,这代表A的身份。不仅是B,所有节点都需要知道A的公钥,用来验证A的签名。注意:签名是用私钥签名公钥验证。加密是用接收人的公钥加密私钥解密。
那如何才能知道A的公钥?前面提到,A付款给B、C的交易中,要包含A的公钥信息。这样会不会存在安全漏洞呢?假如B的同伙F要伪造这次交易,声称F的公钥为A的公钥,发布在交易中,然后用F的私钥为这次交易签名。这样签名验证肯定能通过。这时,就要靠交易输出部分给出的收款人公钥的哈希值了。F想要伪造的第二个交易,包含了指向第一个交易的哈希指针,用来说明币的来源。而第一个交易的输出部分,包含着A的公钥的哈希值。大家在验证交易时,不仅要验证签名,还要验证本次交易声称的付款人公钥,经过哈希运算后,是不是和得到币的交易中输出部分公钥哈希值保持一致。
区块的内容
(上面的分析对交易系统进行了简化,实际上每个区块(对应图中的每个方框)包含很多交易,这些交易会组成Merkle tree)
每个区块分为块头和块身。 块身里面有详细的交易列表(transaction list),即Merkle tree。块头包含的是区块的宏观信息:
- 用的是比特币哪个版本(version)的协议
- 区块链当中指向前一个区块块头的指针(hash of previous block header),即对前一个块头的所有部分取哈希值
- 整棵Merkle tree 的根哈希值(Merkle root hash)
- 挖矿的难度目标阈值(target)
- 另一个是随机数nonce, 目标是H(x || nonce) < target
前面还有一个内容讲的时候简化了:并不是每个节点都需要验证所有的交易。实际上系统中的节点分全节点(full node)和轻节点(light node)。全节点保存区块链所有的信息,验证每一个交易,所以全节点又叫fully validating node。轻节点只保存block header的信息,一般来说轻节点没法独立验证交易的合法性,详情见第二节。系统中大多数节点是轻节点,这节课内容主要针对全节点,因为轻节点没有参与区块链的构造和维护,只是利用了区块链的信息和结构做一些查询。
比特币中的共识协议(consensus in BitCoin)
区块链里的内容是如何写到区块链里面的呢?每个节点,每个账户都可以发布交易,交易是广播给所有节点的。有些交易是合法的,有些是非法的。谁来决定哪些交易应该被写入下一个区块中呢?按照什么顺序写呢?每个节点自己决定可以吗?如果每个人在本地维护一个区块链,那区块链的统一性得不到保证,而账本的内容是要取得分布式的共识(distributed consensus)。
比特币中共识要解决的一个问题是,有些节点可能是有恶意的。我们假设系统中大多数节点是好的,那么该如何取得共识协议?
第一种方案是投票,首先应该确定哪些区块有投票权,有些membership是有严格要求的,这种情况下基于投票的方案是可行的。但比特币系统创建账户是很容易的,甚至一个人产生了公私钥对,别人都无法得知,只有转账时别人才知道。所以有些人可以不停的创建账户,当超过账户总数的一半时就有了控制权,这种称为女巫攻击(sybil attack)。因此投票方法不可取。
比特币账户巧妙的解决了这个问题,不是按照账户数目投票,而是按照算力来投票。每个节点都可以在本地组装出一个候选区块,把它认为合法的交易放在里面,然后开始尝试各种nonce值(占4 byte),看哪一个能满足puzzle H(block header)≤target的要求。如果某个节点找到了符合要求的nonce,它就获得了记账权。
所谓的记账权,就是往比特币账本里写入下一个区块的权利。只有找到这个nonce,获得记账权的节点才有权利发布下一个区块。其他节点收到这个区块之后,要验证这个区块的合法性:比如括号里block header的内容填的对不对;block header里面有一个域,叫nBits域,实际上它是目标阈值的一个编码,检查一下nBits域设置的是不是符合比特币协议中规定的难度要求;该不等式是否成立。假设都符合要求,然后检查block body 里面的交易列表,验证一下每个交易都是合法的:1. 要有合法的签名;2. 以前没有被花过(详见上一小节)。如果有一项不符合要求,这个区块就是不能被接受的。
最长合法链
假如生成了一个新区块,怎么知道新区块插在了哪里呢?答案是根据新区块块头中的hash of previous block header。
下面思考这样一个问题。如果一个新的区块不是接在最新的区块后面,而是接在之前的区块之后呢?此时区块链出现了分叉。假设区块内容是合法的(块头puzzle正确,块身内的交易也合法),那么如何避免这种分叉呢?答案是最长合法链(longest valid chain)。比特币协议中规定,一个新的区块只有接在最长的合法链上,才会被大家承认。比特币协议中用到了implicit consign,如果沿着某个区块往下继续扩展,就算认可了这个区块。而根据最长合法链协议,大家都会顺着最长的合法链计算下一个区块,不承认分叉上的区块,它是无效的。
我们还记得,记账权的取得,靠的是算力。这就涉及到了51%算力攻击。如果我拥有全世界一半以上的算力,我就可以对抗剩下的所有人,因为我的打包速度比他们加起来都要快。我可以在我新打包的区块后面继续计算,直到超过最长合法链,这样我所在的链条就成为了最长合法链。
临时性分叉
区块链在正常情况下也可能出现分叉:两个节点几乎同时获得记账权,发布了区块。这种情况下,出现了两个等长的分叉。这两条都是最长合法链,那该接受那条呢?比特币协议当中,在默认情况下,每个节点接受它最早收到的那个区块。所以不同节点根据在网络上的位置不同,有的节点先接收到新生成的其中一个区块,那就接受这个区块;有些节点先接收到另一个区块,那就接受另一个区块。
等长的临时性的分叉会维持一段时间,直到一个分叉胜出。也就是哪一个链抢先一步生成了新的区块,哪一条就是最长合法链。另一个作废的就叫orphan block。当一个区块胜出后,另一个作废的区块得到的比特币是没有作用的,其他人不会承认。所以即使成功解开puzzle,也不一定能最终获得比特币。如下图,两个区块都是合法的,他们就会在这里僵持住,直到有一方胜出。


竞争记账权
那么大家为什么要竞争记账权呢?解开puzzle需要很高的算力,硬件和电费是一笔不小的支出。竞争记账权的好处在于,首先获得记账权的节点本身有一定的权力,可以决定哪些交易写到下一个区块里。更重要的一点在于区块奖励(block reward)。
比特币协议中规定获得记账权的节点在发布的区块里可以有一个特殊的交易:铸币交易。在这个交易里,打包这个区块的人获得一定数量的比特币。这里要回到前面的问题1,谁来决定货币的发行?答案是,打包区块是比特币系统中发行新的比特币的唯一方法。那么能造多少币呢?比特币刚上线的时候,每一个发布的区块可以产生50BTC (BTC=比特币)。协议中规定,21万个区块以后,初块奖励就要减半,就变成了25BTC。再过21万个区块,又要减半。21万个区块大概要挖多长时间呢?比特币系统设计的平均出块时间是10分钟,大约4年出块奖励就会减半。按照这个协议,比特币的总量不会超过2100万。
比特币争夺记账权的过程叫作挖矿(mining),比特币被称为数字黄金(digital gold),争夺记账权的节点被称为矿工(miner)。
- Post link: https://www.godhearing.cn/qu-kuai-lian-gong-kai-ke-bi-ji-3-bi-te-bi-xie-yi/
- Copyright Notice: All articles in this blog are licensed under unless otherwise stated.