数字货币和纸质货币的区别是可以复制,若可以复制,那意味着可以将同一货币花费两次,这叫做双花攻击 double spending attack.
在此给一个中心化的解决方案:和纸币一样,对货币添加唯一的编号(且不可篡改),每次支付时向货币发行单位查询真伪。这是一个典型的第三方中心化方案,现实中,我们通过支付宝、微信、信用卡等支付方式交易,必然会依赖第三方,由于他们具有较高的可信度,并且有政府背书,可以采用这种方案。但很多场景下,并不存在一个值得信赖的第三方机构,基于此,以去中心化思想为核心的比特币系统便吸引了人们的注意。
去中心化的货币系统需要解决两个问题:
- 数字货币的发行
- 怎么验证交易的有效性,并防止double spending attack
答案:
- 比特币系统中由挖矿来决定货币发行权和发行量
- 交易的有效性依赖于区块链的数据结构,该数据结构由系统中全体用户共同维护。比特币系统中每笔交易都包含输入和输出两部风,输入部分要说明币的来源,输出部分要给出收款人的地址 (公钥的哈希)。
- 说明币的来源:证明币不是凭空捏造的,同时防范double spending
- 注意比特币系统中没有查询某个人地址的功能,所以某人要接受比特币支付,一般需要自己公开自己的地址或公钥(非必要)
- 发生一笔交易A→B时,A需要知道B的地址,此外B需要知道A的公钥,这代表A的身份,其实所有节点都需要知道A的公钥,因为需要验证签名从而证明交易的合法性。
- 签名是用私钥签名,公钥验证 (别和加密混淆,加密是用接收人的公钥加密,他拿到密文后用自己的私钥解密)
比特币区块信息
- block header
- version(版本协议)
- hash of previous block header(指向前一个区块的哈希指针)
- Merkle root hash( merkle tree 根哈希值)
- target(挖矿难度目标阈值)
- nonce(随机数)
- block body
- transaction list(交易列表)
挖矿求解问题:Hash( blcok header ) ≤ target
hash of previous block header 只计算前一个区块的block header 的哈希( 有merkle root hash保证block body 中的内容不会被篡改 )
在BTC-数据结构篇中提到的轻节点只存储区块的block header信息,一般来说,轻节点只是利用区块链做一些查询,但并不参与区块链系统的维护和构造(因为没法独立验证交易的合法性,而且也没法验证一个交易是否是double spending)
分布式共识 distributed consensus
- 区块链的内容是如何写到区块链里面的?
- 每个节点,每个账户都可以发布交易,交易广播给所有节点,而其中有些交易是合法的有些是非法的,谁来决定将哪些交易打包写入下一个区块,每个人独立构建区块链显然是不可行的,账本的内容需要取得分布式的共识 distributed consensus,保证区块链内容在不同节点上的一致性
关于分布式系统有很多不可能结论( impossiblility result ),在此引入:
- FLP不可能结论:在一个异步的( asynchronous )系统里(网络传输延迟没有上限就叫异步系统),即使只有一个成员是有问题的(faulty),也不可能取得共识。
- CAP Theorem:CAP指分布式系统中三个我们想要的性质,Consistency 系统状态一致性、Availability 别人都可以用、Partition tolerance 容错性,任何一个分布式系统中,以上三个性质最多满足两个
- 分布式共识一个著名的协议是Paxos, 它可以保证Consistency(若达成共识必然一致),但在某些情况下,可能会一直无法达成共识,这种可能性比较小但是客观存在。
【这里附上一个Paxos协议详解:https://my.oschina.net/u/150175/blog/2992187】
比特币中的共识协议 consensus in Bitcoin
比特币中的共识要解决的问题是,有些节点可能是有恶意的,我们假设系统中大多数节点是诚实的,那么如何取得共识协议?
一个简单的想法是投票:
- 某个节点将交易打包成区块发布给其他节点,其他节点检查该候选区块,若检查正确则投赞成票,若赞成票超过票数半数,则达成共识加入区块链。
- 问题-1:若有恶意节点不断打包不合法区块,全部节点一直花时间在投票上,导致一直无法达成共识,可能使系统瘫痪
- 问题-2:由于没有强迫投票的手段,可能有某些节点不投票(行政无作为(╬▔皿▔)凸)
- 问题-3:网络延迟事先未知,投票需要等多久无法确定,导致效率上出现问题
- 还有一个最基本的问题:membership,也就是哪些人拥有投票权的问题。若是联盟链,对加入成员有要求,那么基于此投票是可行的。但是比特币系统中,任何账户都可以投票,而且创建账户极其简单,只需本地产生公私钥对即可。而且只有账户发生转账交易时,比特币系统才能知道该账户的存在。
- 这样,攻击者可以用计算机专门生成大量公私钥对,也就是创建账户,当数量超过系统中账户总数的一半时,就可以获得支配地位,这种攻击称为 女巫攻击 sybil attack.因此投票方法不可取。
比特币系统用了很巧妙的方案解决共识的问题,不是按账户数目投票,而是按计算力投票(算力可以用每秒能试多少个nonce数值表示)
- 每个节点都可以在本地组装出一个候选区块,把它认为合法的交易放在里面,然后开始尝试各种nonce值(大小为4 byte),直到hash( block header )≤target,这个过程就是挖矿( mining ),这些节点被称为矿工( miner )
- 当某个节点找到了符合要求的nonce,它就获得了记账权,从而发布区块。其他节点收到区块后,要验证其合法性。
- 所谓记账权,就是往比特币账本里写入下一个区块的权利
若两个节点同时获得记账权,即差不多同一时间找到了符合要求的nonce,他们都可以将其打包的区块发布,这时区块链会出现分叉。此时两条都是最长合法链(即其中的区块都是通过验证的合法的),那么该接受哪一条呢?
- 在比特币协议中,在缺省(默认的意思)条件下,每个节点接受它最早收到的那个,由于节点在网络中的位置不同,有的节点会先收到那个相对迟一些发布的区块,但还是接受它。
- 其他节点收到区块验证合法通过后,若沿着这个区块往下继续扩展,就算是认可了这个发布的区块。
- 等长的分叉是临时性的,哪一个链抢先一步生成了新的区块,哪一条就是最长合法链,比特币系统中,只承认最长合法链。因此另一个分叉中的区块就被作废,被扔掉的区块被称为 orphan block.
- 出现分叉时,两个新区块有可能会各自拉拢,互相竞争算力以让自己打包的区块写入区块链中,不过有的时候也是看运气的( ̄▽ ̄)"
由此可见,依赖算力进行竞争,有效避免了 女巫攻击
-
分叉攻击 forking attack
由以上的介绍我们想到,如果A转账给B,然后A又把这笔钱转给自己,出现分叉情况,一个区块中有A→B的交易,另一个区块中有A→A的交易,由于是分叉的,其他节点不会将其认为double spending,然后等B方确认收款后,A想办法让A→A所在分叉成为最长合法链,这样就把付出去的钱回滚回来,从而获取非法利益,这就是分叉攻击。
- 比特币系统中,这种攻击很难发生,因为回滚的前提是B确认了收款,在他确认的这段时间里,很可能分叉情况就已经结束了,若A→A的分叉胜出,那么B就没有收到钱,这样攻击就不成立了,如果A→B的分叉胜出,那么绝大多数矿工就认可了A→B的那一条链,此时攻击者A想要回滚交易,需要自己打包区块,使其比最长合法链还要长。
- 理论上说,攻击者需要达到整个系统中51%的算力,才能发动这种攻击。
比特币激励机制
获取记账权有什么好处呢?
- 首先获得记账权的节点本身有一定的权力可以决定哪些交易写到下一区块中。但这不应该被设定为竞争记账权的动力,要知道挖矿是有算力和电力的成本的,节点为什么要去做呢?这就要说到 铸币交易
铸币交易 coinbase transaction
- 比特币协议中规定 获得记账权的节点在发布的区块里可以有一个特殊的交易:铸币交易,也就是凭空产生比特币,矿工获得这笔 出块奖励
- 之前有提到比特币中货币的发行问题,铸币交易为比特币系统中发现新的比特币的唯一方法,这个交易不用指出币的来源。
比特币系统规定,自创世区块开始,每发布一个区块可以产生50BTC(这是比特币的符号),每隔21万个区块,出块奖励减半。
比特币系统设计的平均出块时间是10分钟,挖矿难度会根据全网算力情况进行调整。
可见比特币的总量的确定的,21万x50+21万x25+······=2100万 BTC
-
21万个区块大概要挖多长时间呢?大约是四年。所以基本上出块奖励每四年就会减半。
-
因此出现分叉时一个区块胜出后,另一个作废区块中的出块奖励是没用的,其他诚实节点是不会承认的
交易费 transaction fee
还有一个问题,会不会有些心机节点只想发布区块而不想打包交易,也就是只想挖矿不好好记账?
- 嘿嘿,中本聪在设计该系统时,还引入了交易费,也就是打包区块不仅仅有挖矿奖励,还有打包的手续费,打包交易越多手续费就越多嘛
- 交易费一般很少,有一些简单的交易没有交易费
本系列文章为个人学习笔记,文章的所有内容均不构成任何投资比特币或其他数字货币的意见和建议,也不赞成个人炒作任何数字货币!