区块链技术与应用 - P04 - BTC共识协议

Posted by raftale on September 1, 2024

构建去中心化的货币系统

我们假设央行要发行数字货币,很直观的是参考现金的发行形式,现金的特征是:

  1. 防伪标记: 难以伪造,不可篡改
  2. 唯一性:无法复制

如果要实现数字货币的防伪标记,那么基于公私钥体系就能很容易的实现,发行100元需要通过央行的私钥进行签名,公钥是公开的,任何人都可以验证它的权威性。公私钥保证了不可篡改,但没有解决货币的唯一性,毕竟代码本身就是文件,是可以无限复制的。

如果数字货币可以无限复制,就容易产生双花攻击,即被央行发行的一个货币被多次花费。

防止双花攻击的一个中心化的解决方法是: 给每个发行的货币增加一个唯一标识码,再记录该货币在谁手上。每一次交易都需要央行确认。这个方法可以叫做记账法。

中心化记账法的问题是:任何交易都要通过央行确认合法性,但中心化系统会面临一些问题,可能有:

  1. 央行控制者滥发货币;
  2. 央行的数据库容易被攻击篡改;
  3. 交易确认造成的高负载;
  4. 单点故障;

如果要构建一个去中心化的货币系统,那么急需解决两个问题:

  1. 谁有权利发行货币?
  2. 如何验证交易的有效性: 也是如何防止双花?

比特币的每个交易都包含了输入、输出和「签名」。

  1. 输入部分包含了 币的来源和转账方的公钥哈希。
  2. 输出部分包含了 收款人的公钥哈希。
  3. 签名:私钥对交易的签名

一个转账的例子:

               ┌───────────┐    ┌──────────────┐     ┌─────────────┐              
               │           │    │              │     │             │              
 ┌─────────────┼────┐     ┌┼────▼──────┐     ┌─┼─────▼──────┐    ┌─┼────────────┐ 
 │ create coin │    │     │A┌──►B(5)   │     │ B┌───►C(2)   │    │ C────►E(7)   │ 
 │             ▼    │     │ │          │     │  │           │    │ │            │ 
 │       ─────►A(10)│◄────┤ │          │◄────┤  │           │◄───┤ │            │ 
 │                  │     │ └──►C(5)   │     │  └───►D(3)   │    │ │            │ 
 │                  │     │ signed by A│     │  signed by B │    │ │signed by C │ 
 └──────────────────┘     └─────▲──────┘     └──────────────┘    └─┼────────────┘ 
                                │                                  │              
                                │                                  │              
                                └──────────────────────────────────┘              
                                                                                            
                                                                                  

输入部分说明币的来源很重要,因为它可以解决双花问题:如果在最后,B 又转给F账户(公钥的转换)5个coin,但实际上B已经在第二个交易中花费完了,再次转账就无法成功。

A 转给B的交易中,输入部分包含了A的公钥哈希,它被用来验证签名,但公钥哈希和交易的签名是可以伪造的,所以A的公钥哈希必须要与币的来源中的收款方的公钥哈希匹配。

这里产生了一个疑问,如果有人恶意的去匹配A的公钥哈希和签名,那不就可以匹配上了吗?

我的猜测:签名是无法伪造的,因为A是用私钥对整体交易进行了加密,也就是如果你想变动交易中的信息,签名就对不上;如果是全部复制一模一样的交易,但上面说到这种区块链设计又避免了双花攻击,所以全部复制也就没有了意义。

实际系统的扩展

实际系统中每个区块包含了很多交易,区块又分成了block header和block body,签名只是针对于block header,header中的merkle root hash指向block body,block body中的交易组织成了merkle tree,保证了交易不可篡改的特性。

  ┌───────┐◄───┬───────┐◄────┬───────┐   
  │header │    │header │     │header │   
  └───┬───┘    └───┬───┘     └───┬───┘   
      ▼            ▼             ▼       
  ┌───────┐    ┌───────┐     ┌───────┐   
  │ body  │    │ body  │     │ body  │   
  │       │    │       │     │       │   
  │       │    │       │     │       │   
  └───────┘    └───────┘     └───────┘   

区块具体包含:

  1. block header:
    1. version
    2. hash of previous block header
    3. merkle root hash: 保证了body中的交易是无法篡改的
    4. target: H(block header) <= target
    5. nonce
  2. blocker body:存储了交易列表,这些交易又组织成了merkle tree。header中持有的merkle root hash保证了交易不可篡改的形状

  3. full node: full validating node
  4. light node: only including block header

交易是如何写入区块链中的

39分开始

这节的主要问题是:谁来决定哪些交易按照什么顺序被写入区块链中?

分布式共识

区块链是一个分布式的账本,账本的内容要取得分布式的共识。

distributed consensus

分布式共识的一个简单例子就是分布式哈希表。

分布式系统中有很多不可能结论(Impossibility result):

  1. FLP impossibility result:在一个异步(asynchronous)系统里,即使只有一个成员有问题(faulty),也不可能取得共识。
  2. CAP theorem:Consitency, Availability, Partition tolerance. 三者只能取其二。

按照DDIA中的说法,P是必然存在的,出现P时只能选择CP或者AP

  1. Paxos:能够保证Consitency,但是某些情况下有可能小概率的一直没有办法达成共识。

比特币共识

如何设计比特币的共识协议,来防止系统中存在恶意的节点攻击。

简单的设计思路:直接投票。

直接投票的问题有:

  1. 节点投票非法的候选区块
  2. 节点不投票:行政不作为
  3. 效率问题:网络延迟,每轮投票等多久

但更大的问题是:任何基于投票的方案都要确定谁有投票权(membership)。

联盟链中基于投票的方案是可行的,因为不存在恶意的节点。

直接投票在公链中的缺点是:由于比特币中账户的生成是可以无限的,恶意的节点可以产生无限的账户,当产生账户超过总数的一半,投票本身就是恶意攻击,这也被称为女巫攻击(Sybil attack)。

比特币中利用了一个很巧妙的机制来解决这个问题,基于计算力投票(工作量证明)而不是账户数目投票来防止女巫攻击。每个节点都可以在本地构造一个候选区块,把他认为合法的交易放到区块中,然后尝试各种nonce值,只要满足H(block header) <= target ,就获得了记账权,也就是获得了向比特币区块链中中写入下一个区块的权利,其他节点收到这个区块之后验证区块内容的合法性。

Longest Valid Chain

另一个问题来了,通过合法性验证的区块就一定会被接受吗?

看下面这个例子:

 ┌──────┐◄──┬──────┐◄───┬──────┐◄───┬──────┐ 
 │C->A  │   │      │◄-┐ │ A->B │    │      │ 
 └──────┘   └──────┘  │ └──────┘    └──────┘ 
                      │                       
                      └──┬──────┐             
                         │A->A' │             
                         └──────┘             

A 转B 之后,A又转给它自己,相当于把A->B给回滚了。

内容合法的区块不一定在最长合法链上(Longest Valid Chain),这种也被称为forking attack。

比特币协议中规定:接受的区块应该是在最长合法链上。

临时性的分叉的非最长链被称为orphan block,会被丢弃掉。

                                                  ┌───────┐◄──┬───────┐ 
                                              ┌───┤       │   │       │ 
 ┌──────┐◄──┬──────┐ ◄───┬──────┐◄───┬──────┐ │   └───────┘   └───────┘ 
 │C->A  │   │      │ ◄┐  │ A->B │    │      │◄┘                         
 └──────┘   └──────┘  │  └──────┘    └──────┘◄┐   ┌───────┐             
                      │                       └───┼       │             
                      │                           └───────┘             
                      └──┬──────┐                 orphan block          
                         │A->A' │                                       
                         └──────┘                                       

为什么节点要去争夺记账权呢?

获得记账权的节点可以获得铸币的奖励(block reward),coinbase transaction是比特币中发行新的比特币的唯一方法,coinbase transaction不用指定币的来源。

最开始每一个发布的区块可以产生50BTC,每过21万个区块(大概4年) 出块就需要减半。

视频1小时21分

课后问题:

  • 比特币的共识机制要取得的共识是什么?只有获得记账权的节点才能写入区块。
  • 如何防范女巫攻击?
    • 每秒钟能够试多少个nonce的数目,称为hash rate,hash rate决定了出块的概率。
    • 争夺记账权的过程:mining
    • 争夺记账权的节点被称为矿工miner