双花攻击
数字货币容易产生双花攻击 double spending attack
“双花”,即一笔钱被花了两次或者两次以上,也叫“双重支付”。
中心化解决double spending:给货币制定编号,维护一个大数据库,用来记录某编号的货币在谁手里。
去中心化要解决的两个问题:
1.谁发行?在比特币中是由挖矿来解决。
2.验证交易的有效性,防止double spending attack。那么如何验证交易有效性?
与中心化类似,需要维护一个数据结构,记录某币是否被消费,被谁消费过。只是这个数据结构由所有用户共同维护,而不是中心化机构维护,这个数据结构就是区块链。
区块链系统
比特币系统中每个交易都包含输入和输出两部分,输入部分要说明币的来源以及付款人的公钥,输出部分要给出收款人的公钥的哈希。
转账交易要说明币的来源,即花掉的币从哪来的:1.防止币是凭空捏造的 2.防止double spending.
转账交易(A-->B)需要的信息:A的签名,B的地址。
A需要知道B的地址,比特币中收款地址是通过公钥推算出来的,地址相当于银行账号,而公钥是可以公开的,不需要保密。
B需要知道A的公钥,大家都需要知道,代表A的身份,用来验签。
A--->B交易中A的公钥要与币的来源中A的公钥的哈希对得上。如果此时有B’伪造一对公私钥,冒充A给B转账,虽然B'的公钥能够验签成功,但是该公钥与币的来源中公钥的哈希值对不上,所以无法伪造交易。
图中一个简化假设是每一个区块只有一个交易,实际系统中每个区块可以包含很多笔交易,这些交易组织成merkle tree。每个区块分成块头 Block header和块身 Block body两部分。
Block header保存区块的宏观信息 | Block body保存交易列表 |
--version比特币哪个版本的协议 | --transaction list |
--hash of previous block header指向前一区块的指针 | |
--Merkle root hash整个merkle tree的根哈希值 | |
--target挖矿的难度目标阈值的编码nBits | |
--nonce随机数 | |
--timestamp时间戳 |
注意:前一个区块的哈希,算的只是区块的block header,不包含block body。header中的root hash就已经能保证了body中所包含的交易列表是没有办法被篡改的。类似下图:
另一个简化假设是每一个节点都会验证所有交易的合法性。但是实际中,系统中的节点分为全节点 full node和轻节点 light node。其中,全节点保存所有信息,验证每一个交易,所以全节点也叫作fully validating node。但是轻节点只保存header,没法独立验证交易合法性以及某交易是否double spending。系统中大部分是light node,full node不是很多。
分布式共识
上面说的是区块链中所包含的内容,那么这些内容如何被写到区块链中?每个节点都可以发布交易,交易广播给所有节点,有些交易合法而有些交易非法。那么谁来决定哪些交易应该被写到下一个区块中?按照什么样的顺序写?
账本的内容,要取得分布式的共识 distributed consensus。分布式共识一个简单例子就是分布式哈希表 distributed hash table。其中要取得共识的内容是key-value pair.
分布式理论
1.不可能结论 FLP impossibility result.
在一个异步系统 asynchronous中(网络传输延迟无上限),即使只有一个成员有问题 faulty,也不可能取得共识。
2.CAP Theorem.
Consisence 一致性/ Avalilability 可用性/ Partition tolerance 分区容错性。最多满足两个,不可能都满足。
分布式共识中的一个协议:Paxos协议,保证了一致性
Consensus in BitCoin 比特币中的共识协议:
该协议要解决的是,有些节点是恶意的,假设系统中大多数节点是好的,有恶意的是少数。
---投票
问题:
1.节点本身有恶意的,不断地提出非法候选区块,大家不停地进行投票,造成时间浪费在投票上
2.各别节点不投票,行政不作为
3.效率问题。网络延迟,投票等待时间
4.membership问题。确定谁有投票权,不是谁都可以加入,比如联盟链协议 hyperledger facric,只有大公司可以加入,这种情况下基于投票是可行的。但是比特币系统中创建账户很容易,不需要外部批准。恶意节点可以不停地产生账号,占据控制权,操纵投票结果,这就是女巫攻击 sybil attack。所以简单,直接的投票在比特币中不可行。
比特币中投票不是按照账户数目,而是按照算力投票。每个节点都可以在本地组装一个候选区块,把认为合法交易放在区块中,然后开始尝试各种nonce值,即H(block header) <= target, header中有一个随机数nonce,组装好区块后就开始试随机数nonce(4 bytes).如果某个节点找到符合要求的nonce,就会获得记账权,即往比特币去中心化的账本里写入下一个区块的权利。只有找到nonce,获得记账权,才有权发布下一区块,其他节点收到区块,验证合法性,比如验证header中的内容是否正确,验证body中每个交易是否都是合法,有合法的签名,以前也没有被消费过。
但是,也不是说一个区块只要经过检查,header和body中的交易列表都符合要求,就一定会被接受。如图:
出现分叉的情况:
如图,A-->A'的区块中包含的交易都是合法的,但是插在了区块链中间(根据hash of previous block header判断区块位置),比如A先把钱转给了B,又把钱转给了自己A',这个交易是合法的,不属于double spending(验证double spending是从当前区块到币的来源之间,中间的区块是否有花过这些币)。A-->A'是想把A-->B的交易回滚掉,把钱再转给自己,虽然交易合法,但是不在最长合法链 longest valid chain中,上面的链才是最长合法链。所以在比特币中,接收的区块应该是在最长合法链中。A-->A'例子其实是分叉攻击 forking attack,通过往区块链中间位置插入区块,来回滚某个已经发生过的交易。
正常情况下也会出现分叉,比如两个节点同时获得记账权,这时候会出现两个等长的分叉,如图后半部分的分叉,此时这两个都属于最长合法链。如果出现系统中两个节点同时发布区块,这种等长的,临时性的区块会维持一段时间,直到某一个分叉最后胜出(被扩展),另一个被丢弃,叫做orphan block。
通过竞争,争夺记账权的好处:
1.获得记账权的节点本身有一定的权利,可以决定哪些交易被写进下一个区块,但不是主要动力,凡是合法交易都应可以被写入区块中。
2.出块奖励 block reward。获得记账权的节点,在发布的区块里,可以有一个特殊交易,即铸币交易 coinbase transaction。在这个交易中可以发布一定数量的比特币,这就是开始提到的去中心化要解决的第一个问题:谁来发行比特币。coinbase transaction是比特币系统中产生新的比特币的唯一方法,造币数量50BTC-->25BTC-->12.5BTC,每21万个区块(4年)出块奖励都要减半。orphan block中的出块奖励无效。
比特币系统中要取得什么共识?去中心化的账本要取得共识。谁又能决定账本的内容呢?只有获得记账权的节点才能写东西。怎么获得记账权呢?就是解pow(挖矿)。按照算力记票,算力可以用每秒能试多少nonce数值表示。那怎样防范女巫攻击呢?按算力记票,即使创建再多的账户,也无法使算力增强。
比特币中争夺记账权的过程也叫挖矿 mining。把比特币比作数字黄金 digital gold,矿工 miner就是争夺记账权的节点,而区块就是通过挖矿挖出来的。