【转载+整理】区块链学习笔记-北大肖臻老师课后笔记(01-13)——BTC篇

学习视频来自:北京大学计算机系肖臻区块链学习视频
还有一些参考了一些博客的记录。

其他博客1

01 简介

1.1 教材

教材和参考资料如下:

  • BitCoin and CryptoCurrency Technologies A comprehensive introduction (2016)
  • 以太坊白皮书、黄皮书、源代码
  • Solidity 文档

1.2 主要内容

比特币:

  1. 密码学基础
  2. 比特币的数据结构
  3. 共识协议和系统实现
  4. 挖矿算法和难度调整
  5. 比特币脚本
  6. 软分叉和硬分叉
  7. 匿名和隐私保护

以太坊:

  1. 概述:基于账户的分布式账户
  2. 数据结构:状态树、交易树、收据树
  3. GHOST协议 挖矿:memory-hard mining puzzle 挖矿难度调整 权益证明 casper the Friend Finality Gadget(FFG)
  4. 智能合约

02 BTC密码学原理

2.1 哈希

加密货币特性:crypto-currency 本身并不加密,转账地址是公开。主要使用了哈希函数,哈希函数特性:Cryptographic hash function ,collision resistance,抗碰撞性。

x=y 那么 Hash(x)=Hash(y);而且 Hash(x)≠Hash(y),那么x≠y

人为制造哈希collision没有好的方法,只能采用穷举法破解,brute-force。d在比特币系统中,采用SHA-256算法。输出空间为2^256。

哈希函数的作用:生成消息摘要digest。在实际生活中,以网盘上传文件为例,文件上传前计算文件的Hash值,下载保存文件后,再次计算文件的Hash值,如果2个Hash值不一致,文件就是被篡改了。如果2个Hash值一致,那么保存在云盘上的文件是没有被篡改过的。(云厂商为什么要篡改文件,云厂商本身的原因造成文件损坏,用户没有察觉这个问题,通过校验Hash值的方式可以发现)。

哈希函数作用二:信息隐藏。举例为,我要预测股票,将股票预测文本的摘要hash公布出去,但是股票预测这段文本M没有公布。当股票结果被证实了(经过一段时间),我再将股票预测文本M公布,所有人都可以用Hash算法验证M摘要信息hash2,如果hash2=hash,那么可以证明我之前公布文本M。

信息隐藏必须满足条件,输入的样本空间必须大。否则,恶意攻击者会穷举输入,找到产生摘要的原文。例如,股票的个数比较少,那么可以添加随机数,计算H(X || nonce)并公布,公布原文的时候要一并公布随机数nonce。可能有人会怀疑,我通过修改X和nonce,伪造了摘要信息,但是哈希函数的抗碰撞性,伪造出这个摘要值是非常困难的。
2.2 工作量证明

在比特币中要求,合法的区块必须满足:

H(block header)≤target

在区块头(block header)中有一个域nonce,穷举计算nonce,计算block header哈希值小于target,确定一个合法区块。

区块链的工作原理,记账节点(矿工)收集网络上广播的交易(tx),维护一个交易集合,将若干笔交易打包,计算交易列表hash,放在block header中,穷举nonce域,使H(block header)≤target。

由于Hash函数的puzzle friendly特性,只能使用穷举算法。挖矿的主要工作就是通过穷举计算,找到符合条件的区块头。矿工找到符合条件块头,就获得了记账权,获得出块奖励和交易费,矿工要把这个区块信息发布到网络上,以便其他矿工能够收到这个区块信息。
在这里插入图片描述
2.3 账户信息

在比特币中,用户可以自己创建一个公私钥对,公钥就作为用户的账户信息。公私钥体系又称为非对称密码体系,一对密码分为(public key,private key),私钥保密,公钥公开。利用公私钥实现信息的保密通信和数字签名。

Alice想要给Bob发送信息,Alice在公开场景下获取了Bob的公钥,Bob的私钥自己保密。那么Alice用Bob的公钥加密信息发送给Bob,Bob接收到信息后,用Bob自己私钥解密。加密后的密文可以在不安全的信道上传输,没有Bob的私钥,无法解密密文。

数字签名可以用来实现信息的真实性和抗抵赖性。Alice要向Bob提供一版word版报价单,Bob要求Alice提供报价单的真实性证明,Alice可以采用Hash算法计算文件的摘要,并用Alice自己的私钥对摘要加密,加密后的结果就是数字签名,Alice把原始word文档和数字签名一起发给Bob。Bob收到word文件时,可以计算word摘要,并用Alice的公钥解密数字签名,如果收到的word文档摘要和摘要数字签名解密后的结果一致,证明了报价单在传递过程中没有被篡改,也证明了确实是Alice认可的文档。

在BTC中,用户可以任意生成公私钥,将公钥公布作为自己的账号地址,私钥作为账户所属权证明。实现转账时,发起向某个公钥地址转账的交易(tx),那么这个公钥对应的账号就获得了这笔交易的金额。

在2.2节可以看到比特币的区块中记录的都是一笔一笔交易(tx),而发起交易的节点并不是直接将交易写到区块链上,而是发布到网络上,让矿工节点接收。矿工节点通过挖矿获得记账权,发布打包交易的区块。

这里有一个问题,如果是用户自己产生公私钥,而私钥能够代表一个人身份,如果产生的公私钥重复,怎么办?比特币采用的公钥算法,公钥空间很大,这样即使用户自己产生公私钥,发生碰撞的概率也很小。同样是这个原因,通过穷举公私钥对比特币账户进行攻击,也是不能实现的。但是,用户在生成公私钥时,应采用优质的随机源。如果随机源用的不好,一次签名也可以泄露私钥。
扩充:
1.比特币加密算法一共有两类:非对称加密算法(椭圆曲线加密算法)和哈希算法(SHA256,RIMPED160算法)。
公钥和私钥(encyption key)由椭圆曲线加密算法生成,私钥可推出公钥而反之不能。
【重点】:

有了私钥,你就可以对文本签名。别人拿了你的公钥就可以根据签名认证你是否拥有私钥。这就是证明你拥有存款的办法。

为了安全起见,公钥应该隐藏起来。所以对公钥进行哈希加密,生成公钥哈希值然后计算哈希值的比特币地址:

**

  • 公钥哈希值=RIMPED160(SHA256(公钥))

**

**

  • 比特币地址=1+Base58(0+公钥哈希值+校验码)

**

**

  • 校验码=前四字节(SHA256(SHA256(0+公钥哈希值)))

**
SHA-256算法

单向Hash函数是密码学和信息安全领域中的一个非常重要的基本算法,它是把任意长的消息转化为较短的、固定长度的消息摘要的算法。

2.SHA-256算法的安全性分析

Hash函数的安全性很大程度上取决于抗强碰撞的能力,即攻击者找出两个涓息M和M’(M≠M’),使得H(M)=HM’。因此,评价一个Hash函数的安全性,就是看攻击者在现有的条件下,是否能找到该函数的一对碰撞。目前已有的对Hash函数攻击的方法包括生日攻击、彩虹表攻击、差分攻击等。

3.生日攻击

生日攻击是一种可用于攻击任何类型Hash函数的攻击方法。从攻击原理上看,它没有利用Hash函数的结构和任何代数弱性质,只依赖于Hash值的长度。因此,抵御生日攻击最有效的方法是Hash值必须有足够的长度。

生日攻击步骤:

发送方用私钥对256位的Hash值加密,并将加密结果附于消息之后一并提交给接收者,攻击者可按如下步骤实施攻击:

1)攻击者生成出消息M的2128种不同的消息变形,每一种消息变形都与原消息M具有相同的含义,同时攻击者再伪造一个假冒的消息M’,并对假冒的消息生成出2128个不同消息,其目的是试图用假冒的消息替代真实消息。

2)比较上述两个集合,找出具有相同Hash值的一对消息Mi和M’j,依照生日悖论原理,攻击者找到碰撞的概率大于0.5。如果没找到,则重新伪造一个消息,并生成2128个变形,直至找到碰撞为止。

3)攻击者将消息Mi(与伪造消息M’j有相同Hash值)提交给A请求签名,后将该签名连同伪造消息M’j一起发送给接收者

4.差分攻击

差分攻击是目前破译迭代Hash函数最有效的手法之一,其基本方法是利用明文的输入差值对输出差值的影响,运用差分的高概率的继承或者消除来产生最终的相同输出。一个Hash函数的安全性高低最终要看能否找到函数的整体碰撞,由于SHA-256算法具有迭代型结构,根据迭代算法的雪崩效应,随着轮数的增加,相应的整体碰撞复杂度会急剧上升,这就使得找到整体碰撞变得非常困难,直至目前现有的攻击还无法找到SHA-256的一个整体碰撞。因此,SHA-256算法被认为是目前最安全的Hash函数之一。

5.签名与验证
可以参考这篇文章比特币交易中的签名与验证

03BTC数据结构

1. 特殊的单链表
这个单链表就特殊在它是反过来,而且是hash指针作为记录当前最近的区块。反过来的意思是指指向是反向的,如下图:
在这里插入图片描述
解析一下上面的图,第一个是创始区块,第三个块假如命名为H3(m3) ,H3(m3)= H2(m2+H(m2)),同理,第二个块相应命名为H2(m2) ,H2(m2)= H1(m1+H(m1)),hash指针记录的是当前最新的结点的Hash值。
2. 比特币结构图
下图为比特币结构图:
在这里插入图片描述
比特币的结构分为区块头和区块体,其中区块头细分为:

  • 父区块头哈希值:前一区块的哈希值,使用SHA256(SHA256(父区块头))计算。占32字节

  • 版本:区块版本号,表示本区块遵守的验证规则 。占4字节

  • 时间戳:该区块产生的近似时间,精确到秒的UNIX时间戳,必须严格大于前11个区块时间的中值,同时全节点也会拒绝那些超出自己2个小时时间戳的区块。占4字节

  • 难度:该区块工作量证明算法的难度目标,已经使用特定算法编码。占4字节

  • 随机数(Nonce):为了找到满足难度目标所设定的随机数,为了解决32位随机数在算力飞升的情况下不够用的问题,规定时间戳和coinbase交易信息均可更改,以此扩展nonce的位数。占4字节

  • Merkle根:该区块中交易的Merkle树根的哈希值,同样采用SHA256(SHA256())计算。占32字节

区块头总共占了80字节。

3.比特币的Merkle树
在这里插入图片描述
最底层的叶子结点是有信息的区块,每一个区块各取一个hash值,兄弟结点的hash值组成一个父结点,两个父结点再组成爷结点,爷结点再……最后得到的hash值作为根哈希值。
【注:】轻结点就是保存根H(m)的值,而全结点就是指保存所有区块的结点。轻节点的数目不多,,大部分还是全节点。举个例子:BTC的钱包就是轻结点只保存根哈希。
【笔记】:

Merkle树特点记住root hash的值,则可以保护整个树 ,保证每个节点不被修改

4.Merkle树的作用
1.Merkle的作用之一提供Merkle proof
前面我们提过轻结点即保存根H(m)的值,全结点是指保存所有区块的结点。那么我们如何向轻节点证明某个交易是写入区块链的则需要用到Merkle proof。

在这里插入图片描述
首先算出黄色代证明tx的哈希值也就是绿色的。再和右边红色的哈希值也就是全结点提供的哈希值拼接起来可以算出上一层绿色的哈希值,同理 以此类推可以得出Merkle 的根哈希值,再将该值与block header的哈希值对比一下即可证明黄色代证明tx是否在该Merkle tree里。
【总结】从下往上 每一次检查都是正确的也即是正确的。需要注意的是 我们只能检查半边也就是绿色的哈希值 ,和红色拼接最后得到根哈希值。我们改变任意一个都会导致最后根哈希值与block header里存放的哈希值不一样从而达到纠错。
如果上述文字还不是很理解,可以看下面图片方式讲解交易过程如下:
在这里插入图片描述
红色的date block可以生成最靠近的红色H(m),最靠近蓝色H(m)是向全结点请求的结果,两个hash结果得到橙色H(m)最后结合向全结点请求的绿色H(m)最后就得到了一个H(m),再和根哈希值比较,假如相等就是指已经添加到链上。

从而我们可以证明proof of membership.时间复杂度为O(log(n))
【课堂提问】
我们是否可以证明proof of non-membership?

答:可以。比较高效的方法是对叶节点的哈希值进行排序。我们把我们要查找的哈希值算出来
然后看他在哪两个叶子节点之间。我们需要提供的proof是看把那新节点和这两个节点之间进行一次计算,不断往上 最后与根哈希值比对 如果改变了
则proof of non-membership。这种排好序的方法叫做sorted merkle tree。(比特币中没有用到sorted
merkle tree,因为比特币种不需要不存在证明)

【笔记】实际中,我们只要保证是无环状的结构都可以用哈希指针。但如果是有环的就不可以了。比如 循环单链表就不可以用哈希指针。因为会造成循环依赖。
在这里插入图片描述
因为哈希指针后一个指针哈希值需要前一个来确认。但如果是带环的话,则会导致每一个都确认不了 从而导致循环依赖。

04.BTC协议

4.1.数字货币与双花攻击(double spending attack)
央行可以发行一种和纸币对应的数字货币,数字货币中包含面额、编号和央行数字签名。如下图所示:
如果采用
在这里插入图片描述
当Alice向Bob花费100元时,可以将手中的100元数字货币转交给Bob。但是,这种数字货币会有一个严重问题,Alice可以复制这个数字货币,并在下一次支付时候,再次使用。这个就是双花问题double spending attack。
我们可以考虑 引入编号 来避免这个问题。
比如 017对应 Alice。Alice向Bob支付100元后。017对应的拥有者就修改为Bob。如果Alice想复制一份这个数字货币100元进行第二次支付给jack。jack只需要向央行核实017对应的拥有者 发现不是Alice这笔交易就无法执行 从而避免了双花攻击。
但是这个方案也有一个严重的弊端 每一笔交易都必须去和央行核实 虽然正确性是能解决的。但是这是一个很中心化的方法 极为不便。
4.2去中心化的数字货币
采用去中心化的数字货币,我们首先就面临着两个问题。

  1. 谁来发现,货币什么时候该发现,发行多少?
  2. 怎么验证交易的有效性,怎么避免双花攻击?
    第一个问题的解决方法:
    货币的发行是根据比特币协议产生,由获得记账权的矿工取得的。当矿工挖矿的时候,交易列表中记录一笔“铸币”交易,由矿工获得当前区块的出块奖励。在时间线上,可能与我们的认知顺序不一样,你可能会认为矿工首先获得了记账权,再获得出块奖励,但实际情况是在出块之前,矿工就会将自己获得出块奖励的交易记录打包到区块中,再进行挖矿,当挖矿成功并得到确认之后自然得到出块奖励。
    第二个问题的解决方法:

避免双花攻击的方法:每一笔交易都要指明花费来源于哪笔交易。下面是比特币系统中交易的例子,A通过挖矿获得10BTC,在下面A将这10BTC转给B 5BTC,转给C 5BTC。
在这里插入图片描述
比特币系统中每一笔交易都包含了输入和输出两部分。输入部分要包含币的来源,输出部分要给出收款人的公钥的哈希
每一个币的来源都可以追溯。也就避免了双花攻击,不合法的交易则不会被写入区块链中。
4.3比特币的交易
一个典型的比特币交易如下图,连续4个区块,每个区块记录只记录了一笔交易。

在第一个区块中,A账户通过记账获得10BTC的记账奖励;第二个区块记录,A花掉了10BTC,转给B 5BTC,转给C 5BTC,A的10BTC来源是第一个区块;第三个区块记录B花掉5BTC,转给C 2BTC,转给D 3BTC,来源是第二个区块记录交易;第三个区块记录C转给E 7BTC,来源与第二个区块C获得的5 BTC和第三个区块中C获得的2 BTC。

以上例子中,每个区块只记录了一笔交易,而真实的比特币系统中会记录多笔(几千)笔交易。
在这里插入图片描述
每笔交易,都需要转账者签名,收款方就是对应的公钥地址。A转给B 5BTC,指明币的来源是上一笔铸币交易,通常A要说明自己的公钥,并在这笔交易上附上自己的数字签名。(如果A宣传的公钥故意报错误的是否有安全漏洞?答:没有。因为每一笔交易可以追溯到前一个哈希值 如果修改了 匹配不上)

这笔交易在比特币网上扩散,矿工节点要验证交易的合法性,用A的公钥验证交易的数字签名,同时验证A的公钥和交易来源交易的收币用户是同一个用户。

一笔转账交易的地址,通常用用户公钥的hash值,这样不会直接显示用户的公钥,有更好的匿名性。
4.4对称加密和非对称加密
1.对称密码编码技术,它的特点是文件加密和解密使用相同的密钥加密

也就是密钥也可以用作解密密钥,这种方法在密码学中叫做对称加密算法,对称加密算法使用起来简单快捷,密钥较短,且破译困难,除了数据加密标准(DES),另一个对称密钥加密系统是国际数据加密算法(IDEA),它比DES的加密性好,而且对计算机功能要求也没有那么高

对称加密算法在电子商务交易过程中存在几个问题:

1、要求提供一条安全的渠道使通讯双方在首次通讯时协商一个共同的密钥。直接的面对面协商可能是不现实而且难于实施的,所以双方可能需要借助于邮件和电话等其它相对不够安全的手段来进行协商;

2、密钥的数目难于管理。因为对于每一个合作者都需要使用不同的密钥,很难适应开放社会中大量的信息交流;

2.非对称加密 BTC采用的加密方法
非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)

公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。
例如:
非对称加密:A给B发送一条信息,用B的公钥加密 。公钥是公开透明的,这时加密后只有B自己有私钥解开。B解开后查看完信息回复给A用的是A的公钥加密,A再用自己的私钥解开。
4.5.分布式系统相关理论
4.5.1 FLP不可能性(FLP impossibility result)
FLP impossibility是一个定理,它证明了在分布式情景下,无论任何算法,即使是只有一个进程挂掉,对于其他非失败进程,都存在着无法达成一致的可能。

FLP是Fischer, Lynch,Patterson三位作者名字组合的简写,表明这定理是由它们三位发明的。
4.5.2 CAP定理(CAP theorem)
在计算机科学中, CAP定理(CAP theorem), 又被称作 布鲁尔定理(Brewer’s theorem), 它指出对于一个分布式计算系统来说,不可能同时满足以下三点:

  1. 一致性(Consistency) (所有节点在同一时间具有相同的数据)
  2. 可用性(Availability) (保证每个请求不管成功或者失败都有响应)
  3. 分隔容忍(Partition tolerance) (系统中任意信息的丢失或失败不会影响系统的继续运作)

CAP理论的核心是:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求,最多只能同时较好的满足两个。

因此,根据 CAP 原理将 NoSQL 数据库分成了满足 CA 原则、满足 CP 原则和满足 AP 原则三 大类:

  1. CA - 单点集群,满足一致性,可用性的系统,通常在可扩展性上不太强大。
  2. CP - 满足一致性,分区容忍性的系统,通常性能不是特别高。
  3. AP - 满足可用性,分区容忍性的系统,通常可能对一致性要求低一些。
    4.5.3 Paxos协议
    Paxos 可以分为两种:
  4. Single-Decree Paxos:决策单个 Value
  5. Multi-Paxos:连续决策多个 Value,并且保证每个节点上的顺序完全一致,多 Paxos 往往是同事运行多个单 Paxos
    协议共同执行的结果。
    分布式理论这里没有深入去了解paxos协议详细可以看看paxos协议文章
    4.6.比特币中的共识协议(consensus in BitCoin)
    4.6.1比特币中的共识机制—POW(Proof of Work)工作量证明
    在比特币网路中,每个账户都可以发布交易,每个节点独立打包交易,最终对账本内容取得分布式共识(distributed consensus)。
    在比特币中,分布式共识是通过投票机制达成共识,采用比拼算力的方法,实现投票权。投入的算力越多,获取记账权概率越大。
    在联盟链hyperledger fabric,合法的用户才能投票。
    POW共识机制

优点:
1,完全去中心化
2,节点自由进出,容易实现。
3,破坏系统花费的成本巨大
缺点:
1,区块的确认时间难以缩短,并且交易的确认时间需要10-16分钟,不能满足实时性需求
2,新的区块链必须找到一种不同的散列算法,否则就会面临比特币的算力攻击 3,浪费能源;

4.6.2pow工作量证明流程
在这里插入图片描述
流程主要分为3步:

  1. 生成Merkle根哈希

节点自己生成一笔筹币交易,并且与其他所有即将打包的交易通过Merkle树算法生成Merkle根哈希。

  1. 组装区块头

区块头将被作为计算出工作量证明输出的一个输入参数,因此第一步计算出来的Merkle根哈希和区块头的其他组成部分组装成区块头

  1. 计算出工作量证明的输出

       下面我们直接通过公式和一些伪代码去理解工作量证明的输出:
    
       i. 工作量证明的输出=SHA256(SHA256(区块头))
    
       ii. if(工作量证明的输出<目标值),证明工作量完成
    
       iii.if(工作量证明的输出>=目标值),变更随机数,递归i的逻辑,继续与目标值比对。
    

4.7 出块奖励

在比特币系统中,通过挖矿获得区块记账权的矿工获得比特币奖励。在初始阶段,每个区块获得50 BTC,约定每隔21万个区块,奖励数减半。

210000∗10 / 365∗24∗60≈4

每个区块的出块时间约为10分钟,21万个区块约占用4年时间。2009年,BTC初始时出块奖励是50BTC,2013年时变为25BTC,2017年是12.5BTC。离我们最近出块奖励变化时间是2021年,BTC出块奖励降为6.25BTC。2020年8月14日,比特币的价格约为81,437.05 人民币,那么出块奖励折合成人民币就是50万八千多了。

05.BTC实现

5.1UTXO(Unspent Transaction Output)
“中本聪”采用了一种追踪比特币的流水账记录法——UTXO。本质上,就是只记录交易本身,而不记录交易的结果。从金融系统设计角度来说,这种方式有点“交易清算分离”的意思。区块链系统只处理所有的交易,而需要清算、查看余额等信息,由区块链节点自行处理。

在比特币中,采用transcation-base ledger,即基于交易的记账本。通常大家更容易理解account-base ledger基于账户的记账本。由于采用基于交易的记账本,因此在比特币系统中很难确定一个账户下拥有多少比特币。

比特币系统中,全节点负责维护UTXO数据结构,保存没有花费的交易。全节点将UTXO存储内容中,并用来验证收到的交易的正确性,当交易的输入是保存在UTXO中的未花费交易,那么交易来源的合法性是正确的。有些交易长期保存在UTXO中,一些由于丢失私钥,那么这些比特币再也无法交易。还有一些,例如中本聪早期挖矿所得,他本人也不用来交易,也会长期存储在UTXO系统中。
讲一个故事来理解一下UTXO:淘金者 Tom 挖到了一块黄金,重量是100克,于是首先记录了一条挖矿记录,有100克黄金进入了 Tom 的口袋。然后 Tom 把这块黄金送给了 Alice,于是系统记录了一条交易——有100克黄金从 Tom 的口袋转移到了 Alice 的口袋。后来 Alice 又把黄金切成了两半,卖给了 Bob 和 Charlie,于是系统又记录了一条交易——有100克黄金从 Alice 口袋里转出,分别转给了 Bob 50克和 Charlie 50克。上面的记录看上去就是像下面这个表格:

在这里插入图片描述
用程序员最熟悉的树结构来描述:
在这里插入图片描述
每一个根节点都是一个CoinBase(挖矿交易),也就是每一枚比特币的最初来源。继而随着交易的变动,这棵树不断的生长,每个叶子节点就是一个UTXO——Unspent Transaction Output——未花费过的交易输出。严格来说,比特币系统并不是一个树结构,而是一个单向图。伴随着交易的复杂程度,中间树枝会有不断的交错,但是不妨碍我们利用树结构来理解它。
在这里插入图片描述
比特币的UTXO系统遵守两个规则:

  1. 除了 CoinBase(挖矿交易)之外,所有的资金来源都必须来自前面某一个或者几个交易的UTXO;
  2. 任何一笔交易的输入总量必须等于输出总量,等式两边必须配平。(在比特币系统中,一般输出小于输入,差额则是转账手续费,归矿工所有。)
    【注:】
    比特币是基于transaction-based ledger
    以太坊是基于accoubnbt-based ledger
    5.2.Block Example讲解

在这里插入图片描述
我们可以在比特币网站上打开一个区块查看区块详细信息。比如我们打开这个第529709的区块可以看到这些信息。
从上往下 从左往右
左边:

第一行代表的是该区块打包的交易数量 是686次
第二行是该区块包含的所有交易总额 第四行是这686次交易的总交易费是0.124BTC
最下面一个是出块奖励 12.5BTC(这是大头)
第五行是区块的高度也可以理解为区块的序号 第六行是时间戳也即是产生的时间 第七行是币的来源
第八行是挖矿难度 每隔2016个区块就会调整一次难度 保证挖矿时间在10分钟左右 第十四行Nonce
是挖矿时尝试的随机数。这里的Nonce值是最后符合挖矿要求的
右边: Hash是指当前区块的哈希值 Previous Block前一个区块块头的哈希。

【注意】 计算哈希值的时候都只算block header的哈希值,而不会计算
block body的哈希值。

我们可以看到这两个值的共同点 前面都是一连串的0,这并不是偶然的,所谓的挖矿就是不断的调整随机数nonce
,使得整个block header的哈希值小于等于给定的目标阈值,目标阈值表示成十六进制 前面就有一长串的0.所以凡事符合难度要求
的区块前面算出来都有一长串的0.
最下面一行保存的是Merkle Root的哈希值,作用03的时候我们讲过就不再赘述。
5.3 Bernulli trail
提到挖矿是一个无记忆性的过程Memoryless,符合Bernulli trail。
挖矿的工程如果不是Prograss free,那么算力强的矿工会取得不成比例的优势。

这块的理解,以抛硬币为例也是一个bernulli trail,memory less的过程,我想要一个正面的结果,和我前面几次抛硬币获得反面的结果都没有关系。在比特币挖矿过程中,我计算一个nonce,再计算下一个nonce时是否能满足条件都是不可知的。

这个Bernulli process过程,和穷举密钥攻击的过程相识,但不一样。穷举密钥,在密钥空间中存在这样的密钥,计算一个结果就排除一个结果。但是挖矿过程,就好像抛一个2^256个面的骰子,
只有2^target个面是符合条件的。
5.4 Selfish mining

恶意节点挖到节点后,先不发布,并沿着自己挖到的区块继续挖矿,等有其他节点发布了,发布2个连续的区块。目的是浪费其他矿工的算力。

但是这种selfish mining是有风险的,不发布区块,就得不到区块奖励,连续领先挖出2个区块的概率是很低的。

通常,正常的节点收到其他节点发布的区块,都会停下自己的挖矿工作,沿着发布区块往后继续挖矿。因为挖矿是pregress free,继续挖矿和沿着新区块挖矿意义一样。
5.5 挖矿的意义
挖矿本身没有意义,但是挖矿是比特币安全的保障。Bitcoin is secured by mining。在分叉攻击的例子中,恶意节点发布一个包含回滚交易的区块,网络上的节点有可能按照恶意路径继续挖矿,造成交易信息失败。
在这里插入图片描述
上图中,M首先转A若干BTC,同时发布一个区块,包含一个M转给M‘的区块,如果下面M转给M’的交易生效,根据UTXO的记录上面区块记录的M转给A的交易就不会生效。也就造成了所谓的双花攻击,防止分叉交易的方法,等待该链上多产生几个区块,又叫多等待几个确认。此处恶意节点想要回滚交易,就不是争夺一个区块的记账权,而是连续几个区块的记账权,难度很大。在攻击时,攻击者要沿着自己构造的区块往下生产,而网络上的其他矿工默认沿最长合法链挖矿挖矿,会保持正常的交易继续进行。

通过这个分叉攻击的例子,说明了挖矿是区块链安全的保障。在实际中,交易要等6个确认,才算被认为是生效。也就避免了这个问题

在这个过程中,当M转给A时我们称为 one confirmation.以此类推 一直到第六个区块 six confirmation.才算认定M转给A生效 不可篡改。等待时间平均1h。

06 BTC网络

6.1 网络结构
新的交易要发布到比特币网络上,矿工将交易打包成的区块也要发布到比特币网络上。节点之间采用flooding泛洪广播,网络层采用p2p网络,应用层采用区块链协议。

  1. 应用层:Bitcoin Blockchain
  2. 网络层:P2P Overlay Network
    在这里插入图片描述
    比特币网络中的P2P网络是很简单的,所有结点之间都是对等的,没有超级结点。要加入这个网络,至少要有一个种子结点(seed node),和种子结点联系,它会告知它所知道的网络中的其它结点(有点像构造路由表的过程)。结点之间通过TCP来通信,有利于穿透防火墙。要离开网络也不必通知其它结点,只需要直接退出应用程序,其它结点一直没有听到你的消息,过一段时间就会将你删除掉。

比特币网络的设计原则是简单、鲁棒,而非高效。每个结点维护一个邻居结点的集合,消息在网络中采用flooding方式传播,结点第一次听到某个消息,会将它传播给所有邻居结点,同时记录一下自己已经收到过这个消息了。

邻居结点的选取是随机的,没有考虑底层的拓扑结构。比如美国的一个结点可能和中国的一个结点是邻居结点。这样设计的好处是增强鲁棒性(强健,防风险),牺牲了效率。
6.2新发布的交易的传播
比特币网络中,每个结点要维护一个等待上链的交易的集合,这个集合中的交易都是要写入区块链的合法的交易,结点第一次收到这个交易的时候就会把它写入这个集合,并转发给所有邻居。

如果有两个有冲突的交易,几乎同时发布到网络上,每个结点根据其位置的不同,可能先收到的交易是不同的,那么另一个交易对于这个结点而言就是非法的了,不会被收纳到集合中。
在这里插入图片描述
以左边的集合为例,它先听到A->B的交易,将其写入到了自己的交易集合中。接下来它收到了一个新发布的区块,其中包含A->B这个交易,说明这个交易已经被写入区块链了,所以就要在自己的交易集合中将其删除掉。
6.3 Risk condition
如果这个结点收到的新发布的区块中的交易是被自己丢弃掉的A->C的这个交易呢?这时也要将集合中的A->B删除掉,因为检查可以发现此时集合中的A->B这个交易是非法交易,因为它和新发布的区块中的A->C这个交易冲突了。

也就是说要看接收A->B交易的结点先获得记账权,还是接收A->C交易的结点先获得记账权。
6.4 Best effort
一个交易发布到比特币网络上,未必所有结点都能收到(有的结点不一定按照比特币协议的要求来转发,可能合法的不转发,不合法的又转发了),而且不同结点收到交易的顺序也很可能是不一样的(网络传输中的延迟可能很大)。这是一个去中心化的系统中要面临的实际问题,只能尽力而为。
6.5新发布的区块的传播
和新发布的交易的传播方式是类似的,不过每个结点除了要检查区块的内容是不是合法的,还要检查区块是不是在最长合法链上。
越大的区块在网络上传播越慢,比特币协议要求区块大小不能超过1M,因为比特币网络的效率比较低,一个1M大小的区块可能要几十秒才能传播给比特币网络上的大多数结点。

07 BTC挖矿难度

7.1 挖矿难度
比特币中设定合法的区块,区块头的哈希值必须小于等于target。采用的哈希算法是SHA-256,计算哈希的结果是256位,将结果看成一个整数,与target转化成256位整数比较。挖矿的过程就是找到nonce,计算block header的哈希满足上面的条件。公式描述了target和挖矿难度之间的关系,target越小难度越大。

难度是对挖矿困难程度的度量,即指:计算符合给定目标的一个HASH值的困难程度。比特币网络有一个全局的区块难度,有效的区域必须有一个HASH值,该HASH值必须小于给定的目标HASH。矿池也会有一个自定义的共享难度用来设定产生股份的最低难度限制。
难度每过2016块改变一次,计算公式:difficulty = difficulty_1_target / current_target。目标(target)是一个256位长的数值。

有许多不同测量难度的方法,得到的difficulty_1_target可能不同。传统地,它表示一个HASH值,前32位为0,后续部分为1(称之为:矿池难度或pdiff),比特币协议把目标HASH表示成一个固定精度的自定义浮点类型,因而,比特币客户端用该值来估计难度(称之为:bdiff)。
7.2难度调整公式

newdiff=diff*(2016*10*60)/R

newdiff:      新的难度调整值
diff:          上次难度调整结果
(2016*10*60):  每10分钟产生一个区块,两周时间产生区块数=2016,
R:             本次难度调整的2016个出快实际用时

难度=创世块hash/当前难度hash

中本聪的源码src/chainparams.cpp文件220行代码的创世块里写死了第一个区块的难度hash为:0x1d00ffff。

genesis = CreateGenesisBlock(1296688602, 414098458, 0x1d00ffff, 1, 50 * COIN);

这个数的理解是,0x1d表示难度数据的数值有多少个字节。0x1d十进制是29。表示0x00ffff后边补上0后一共是29个字节的长度。所以创世块难度hash就是:
0x00000000FFFF0000000000000000000000000000000000000000000000000000
每次难度调整时都会有新的难度调整Bits值。比如当前的难度Bits值就是:386990361,这是十进制,转成十六进制就是0x17110119。用转换创世hash的方法转换后为:
0x0000000000000000001101190000000000000000000000000000000000000000
7.3 出块时间
为保证比特币的出块时间在10分钟左右,比特币系统会根据前一段时间的出块时间调整target值。每隔2016个区块,采用下面的公式对target调整。expect_time就是14天,如果actual_time大于14天,target变大,降低难度;actual_time小于14天,target变小,难度增大。难度调整还有一个限制,调整幅度不能超过4倍和1/4。(比如出块时间如果大于八周了,我们也只按照八周来算,主要是为了避免系统出现意外情况 时间特别大,出块时间小于半周按照半周来算。)比特币系统中,如果区块时间设置的更短,例如5分钟,那么比特币系统中会更容易出现分叉,如图所示。系统中出现多分叉时,相当于系统中合法节点算力被分散,那么系统更容易被分叉攻击。10分钟是比特币设计者中本聪设定的。
在这里插入图片描述
规定每2016个区块调整一次难度(以太坊每个区块都可能会调整难度,比特币每2016个调整一次是中本聪规定的),产生一个块的时间理论上是10分钟。一天24小时,一小时60分钟
所以expect time=14天
其中 expect time=2016*10(分钟)/(24*60)=14天
actual time是最近产生2016个区块实际发生的时间
课堂问题
【⚠️】如何让所有矿工同时调整目标阈值target的值呢?
答:计算target的方法是写在比特币系统的代码里的,每挖到2016个区块。难度就会自动调整。
【⚠️】写入计算target的代码是开源的,如果存在恶意节点故意不调整难度,如何处理?
答:如果恶意节点不调整难度,后面会有诚实节点会进行合法性检查,如果发现nBits不对,最后通不过合法性检查不会被承认。
如图可以看到target设置确实让挖矿时间在10分钟上下波动。
在这里插入图片描述

08.BTC挖矿

首先对前面课程内容进行一个简单的回顾
8.1 全节点与轻节点
1.全节点:

  • 一直在线

  • 在本地硬盘上维护完整的区块链信息

  • 在内存里维护UTXO集合,以便快速检验交易的正确性

  • 监听比特币网络上的交易信息,验证每个交易的合法性

  • 决定哪些交易会被打包在区块里

  • 监听别的矿工挖出来的区块,验证其合法性

  • 挖矿并且可以决定挖矿的方向:最长链方向,如果出现等长的分叉时,选择最先监听到的那一条分叉
    2.轻节点

  • 不是一直在线

  • 不用保存全部整个区块链,只要保存每个区块的块头

  • 不用保存全部交易,只保存与自己相关的交易

  • 无法检验大多数交易的合法性,只能检验与自己相关的那些交易的合法性

  • 无法检测网上发布的区块的正确性

  • 可以验证挖矿的难度(即检测你发布的区块是否符合难度要求)

  • 只能检测哪个是最长链,不知道哪个是最长合法链
    【注意⚠️】如果不需要进行挖矿,只需要进行转账 只需要运行一个轻节点就可以,没必要运行全节点。
    课堂问题:比特币是如何保证安全性的?
    答:比特币的安全性是从两方面进行保证的。一方面是密码学上的保证 ,另一方面是共识机制。
    密码学上的保证体现在:非对称加密算法,别人没有你的私钥没有办法伪造你的签名,也就不能够转走你账户上的钱。(这个前提是大部分矿工是好的矿工不接受非法的交易)
    8.2挖矿
    比特币系统中有全节点和轻节点,全节点是挖矿,即争夺记账权、打包区块。挖矿的过程就是穷举nonce,使区块头哈希值小于等于target。

挖矿的过程是无记忆性的memoryless,又称progress free。之前的章节解释过这一个过程,比如抛硬币,我想要抛一个正面向上的硬币,和已经抛过的过程无关系。

每尝试一个nonce,都是在一定概率下满足挖矿条件,和之前尝试了多少次nonce没关系。这种memoryless的特性,使得挖矿成功的概率等于节点占总算力的比例。
8.3挖矿方法
比特币的mining puzzle是哈希算法,流行的运算工具有CPU、GPU、ASIC等。

CPU擅长逻辑控制,串行的运算。和通用类型数据运算,GPU擅长的是大规模并发计算,这也正是密码破解等所需要的。所以第二代开始采用GPU。不过GPU还是有不少浪费,比如用于计算浮点数这些部件,这些用于深度学习计算梯度很重要,但是对于比特币而言并无作用,挖矿只涉及整数运算。
**ASIC芯片是用于供专门应用的集成电路(ASIC,Application Specific Integrated Circuit)芯片技术,在集成电路界被认为是一种为专门目的而设计的集成电路。**但是ASIC制作成本高、周期长,设计一款挖矿通常需要一年时间,投入巨大。而矿机的淘汰速度也很快,过一段时间就有更好的矿机问世,比老款矿机速度更快,老款矿机就会因电费的原因被淘汰。
8.4 矿池挖矿
矿池可以将分散的算力集中起来,一个矿池可以管理很多个矿工,矿池负责打包区块,矿工负责接收矿池的任务进行hash运算。

矿池中的矿工按贡献率分配挖矿奖励,矿工的贡献也是采用工作量证明的方式。实际,矿池要求矿工提交一个较比特币puzzle难度低的结果,比如比特币puzzle要求包含70个0,而矿池要求puzzle是60个0。

矿工每提交一个这样的结果,被认为比较了一个share。这些share中可能包含了符合比特币要求的结果,矿池就可以获得收益。而绝大部分的share是没有意义的,仅仅作为矿工的工作量证明。

从概率上分析,加入矿池的矿工的收入期望并没有增加,获得的收益任然是矿工占全部节点算力的比例。但是,通过加入矿池,矿工收入的稳定性提高了。一些矿池为了吸引矿工加入,会为矿工提供额外的奖励,这也导致了超大型矿池的出现。

出现超大型矿池可能占全部节点算力的51%,这种情况在区块链历史上是出现过的。大型矿池可以利用51%算力,进行分叉攻击。而获取51%攻击想要盗取其他人账户中的比特币是办不到的。
在这里插入图片描述
课堂问题1:矿池中是否有恶意的矿工,当矿工挖到了符合比特币puzzle的结果,但是不将这个结果发送给矿池,而是自己偷偷的把这个区块发出去,得到出块奖励,当发到share就发给矿池计入奖励?
答:这是不可能的,每个矿工的任务是由矿组来分配的。矿组负责组装好一个区块,然后交给矿工进行一次又一次nonce的尝试。矿工如果挖到一个区块,不提交给矿池自己发表出去,是得不到奖励的。里面的收款地址是矿组的,他取不出钱的。
课堂问题2:有没有可能,存在恶意节点挖到share给矿池,但如果挖到一个有效的区块不将这个结果发送给矿池,矿池就不会得到出块奖励。矿池之间是竞争关系,可能将自己的节点加入对手的矿池,搞一些破坏,分散对手的算力。
各国矿池比例图:
在这里插入图片描述
如果有一个矿池 包含了百分之51的节点,也不一定是百分之51,相当大的算力就有可能
那么他可以发动分叉攻击以及Boycott
1.分叉攻击:
在这里插入图片描述
如图,比如A将一笔交易给了B,经过了6个区块确认生效后。A发动分岔攻击,再生成一个链比原来的更长(拥有足够高的算力是有可能达到的)然后A转给B这笔交易就无效了 会造成交易回滚。这样B就造成了经济损失。

2.Boycott:
即对任意用户进行“封杀”,比如对A进行封杀,A进行的所有的交易都不让上链,比如上图,只要A进行一次交易 就进行一次分岔。和分岔攻击不同的是,boycott不需要等6个区块确认,只要A进行上链就发动分岔 越早越好。

【总结:】大型矿池的出现有一定的好处:给矿工减轻了负担,矿工仅需要计算哈希值即可。其他部分有矿组负责,收入分配也更加稳定了,原来相当于有很小的概率能够得到一大笔钱,有矿池后有很大概率得到一小部分钱。
也有一定的坏处:比如会发动上述的两种恶意攻击行为,这些行为会使得用户对比特币丧失信心,所以太大型的矿池会被抵制,也不应当出现。

在这里插入图片描述

如果大家对比特币的信心丧失了,比特币的价值也将不复存在了。GHash这个矿池曾经一度拥有全球百分之51的算力,当时曝光出来后引起不小恐慌,为了避免大家对比特币丧失信心。GHash主动大幅度降低了自己的算力

在这里插入图片描述

09 BTC比特币脚本

9.1交易结构
比特币每一笔交易结构如下图所示:
在这里插入图片描述
locktime:是用来表明生效的时间的,绝大多数情况下都是0,如果非0的话一般要过一段时间才生效。
其中vin被称作输入脚本,vout被称为输出脚本。交易是否合法,首先要检查比特币的来源,输入脚本中要包含交易中比特币来源的证明,要素是签名。输出脚本中要包含接收方的地址。比特币系统中,不会校验输出脚本的合法性。

比特币被称作可编程的加密货币,交易过程中需要执行输入输出脚本。在比特币系统,全部币都来至挖矿,即铸币交易。在铸币交易中,没有输入脚本,输出脚本指明了矿工的地址。可以直接用公钥地址作目的地址,也可以用矿工公钥地址hash作为目的地址。
在这里插入图片描述

  1. 矿工挖矿成功,获得记账权,得到铸币奖励并写入区块链。
  2. 当其他节点收到广播的新区块,就会修改本地的UTXO,增加一条PK1账户转入25BTC的记录。
  3. 当PK1要花掉这个25BTC时,要构造一条交易,在交易中指明交易id(txid),并指明将钱转给PK2,并对交易用PK2对应的私钥签名。
  4. 当其他节点收到这个交易的时候,会校验是否与待上链交易冲突。
  5. 全节点还要验证UTXO中存在txid交易,再用PK1公钥验证签名,验签通过说明是PK1发起的交易,最终证明交易合法。
    9.2 输入脚本和输出脚本

比特币系统中,可以看做以交易tx驱动UTXO账本记录。通常一笔交易要在UTXO中花费掉记录,并生成新的记录。

UTXO中添加记录,被称为将比特币锁定在账本上,与锁定对应,要花掉比特币的行为称作解锁。一笔交易通常解锁、锁定过程。下图中,A转给B 5BTC和C 5BTC,A花费铸币交易称作解锁,在UTXO中产生B(5) C(5)称作锁定。
在这里插入图片描述
输入脚本的目的就是提供解锁证明,与之对应锁定脚本可以将比特币锁定在一下4种类型:

  1. 锁定在公钥中。即支付对象是接收者的公钥,pay to public key (P2PK)
  2. 锁定在公钥哈希中。即支付对象是接收者的公钥哈希,可以隐藏接收者的公钥信息,pay to public key hash(P2PKH)
  3. 锁定在锁定在多重账户中。支付对象以多个接受者为整体。
  4. 锁定在一段脚本中。Pay to Script Hash(P2SH)
    9.3 脚本实例

9.3.1 P2PK型交易

f418交易产生2个结果,ea44交易花掉了10BTC,交易信息如图(注f418和ea44是txid的前4位,交易txid也是交易的hash)。2笔交易的地址如下:

地址1
地址2
在这里插入图片描述
一、f418输出脚本:

查看交易信息,重点关注输出outputs,输出脚本Pkscript如下:

04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c
OP_CHECKSIG

其中:

04:操作符 OP_PUSHDATA
ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c:公钥64位,公钥由2个32字节数组成,这里转换为16进制表示是64位。
OP_CHECKSIG:操作符
点击HEX按钮,显示16进制信息。这段HEX中,开头4104、结尾ac都是操作符,这一段HEX字符就是输出脚本,就是锁定脚本。

4104ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84cac

二、ea44脚本输入:

通过1Q2T(UXTO)指明了来源,引用Pkscript信息。Sigscript是签名信息。

P2PK(Pay to Public Key)的执行脚本以堆栈方式执行,

input script:
PUSHDATA(Sig)
output script:
PUSHDATA(PubKey)
CHECKSIG

执行过程如下,最终结果为TRUE证明校验通过。

9.3.2 P2PKH型交易

P2PKH(pay to public key hash)是在交易中,指明收货地址的hash值。用Hash值代替公钥,可以隐藏公钥信息,而且Hash值的长度比公钥的长度短,数据量小。执行脚本如下:

input script:
PUSHDATA(Sig)
PUSHDATA(PubKey)
output script:
DUP
HASH160
PUSHDATA(PubKeyHash)
EQUALVERIFY
CHECKSIG

实际例子
例子1

例子2

在921a交易中给出了公钥和交易签名,解锁c0cb脚本的输出交易。

9.3.3 P2SH型交易

P2SH(pay to script hash)是指交易的地址是一段代码的hash值,与之与对应解锁交易必须给出这段交易的原文script,而且运行script必须得到正确的结果。

input script:
…
PUSHDATA(Sig)
…
PUSHDATA(serialized redeemScript)
output script:
HASH160
PUSHDATA(redeemScriptHash)
EQUAL

input script要给出一些签名(数目不定)及一段序列化的redeemScript。验证时分两步:第一步验证这段序列化的redeemScript是否与output script中的哈希值匹配。第二步反序列化并执行redeemScript ,配合前边的签名是否可以执行通过。

实际例子

例子1

例子2

脚本执行

此例中,redeemscript解析如下:


52 #2
21027ca87e1aa2595ec7771afee8fdc6efdbc301b8370c4386731b4bd82247dc74a3
#pk1
21022cc9874ba092095dda47a4e4edb1781c43c35b3ec0429ac005df37b9d6eec94b
#pk2
21035739f07de25c205525d81b126ed87bc30377e688705072d186e4f5c88908ce3a
#pk3
53 #3
ae #checkMultisig

10BTC分叉

课堂前言:

这节课介绍了比特币系统中硬分叉(hard fork)和软分叉(soft fork)的概念:
软分叉是只要系统中拥有50%以上算力的节点更新了软件,就不会出现永久性的分叉;
硬分叉是必须系统中全部节点都更新软件,才不会出现永久性的分叉。 这节课结合区块大小调整、P2SH等具体的实例讲解了各种分叉形成的原因和特征。

10.1 分叉概念
分叉指的是,原来的系统中为一条链,但分成了两条链。分叉形成的原因可能有多种,例如:

1.挖矿时两个节点差不多同时挖出矿,都会发布区块(对比特币系统当前状态产生分歧导致的分叉——state fork);分叉攻击,同样也会导致分叉(forking attack,人为故意造成);也称为deliberate fork。

2.比特币协议改变,在分布式系统中不能保证所有节点同时升级软件,假设存在少数节点未升级,导致出现分叉(protocal fork);

根据对比特币协议修改的不同,可以将分叉分为硬分叉软分叉
10.2 硬分叉与软分叉
1.硬分叉:如果区块链软件的共识规则被改变,并且这种规则改变无法向前兼容,旧节点无法认可新节点产生的区块,即为硬分叉。

硬分叉:,硬分叉其实是把比特币这条链直接分成了两条完全不同的链,一条是旧链,一条是新链,旧链即是不愿意让比特币分叉的社区成员所坚持的原有的链,新链即是社区成员希望在现有区块链上进行技术优化改进所生成的链,这两条链此后将不再有交集,完全按各自的道路发展。
【例子】打个比方,没分叉前的比特币就好比是安卓系统,因为有些人不满于安卓系统的功能而又开发出了苹果系统,苹果系统这时就相当于是硬分叉后的结果,分叉后,安卓系统和苹果系统形成了两个完全不同的系统,人们也根据各自的喜好开始用着不用的系统。

例子:
在BTC系统中,区块大小最大为1MB,可以包含的交易最大数量为4000笔左右。而一个区块产生大概需要10min左右,也就是说,整个比特币系统,平均每10分钟最多只能处理4000笔交易(平均每秒7笔交易),相比目前银行等金融机构每秒数十万数百万的交易量来说,根本不在一个数量级上,严重影响吞吐率和交易处理(即上链)时间(因为交易太多,无法写入只能等待下一个区块)。所以,有人便认为可以增大区块大小,使得一个区块中可以包含的交易数量增多,在此,我们假设将区块大小从1MB增大至4MB。

假设系统中大多数节点更新了软件,少数节点仍然遵从1MB限制的协议(注意,这里大多数和少数是按照算力来区分的,和账户数量无关)。即:新节点认为区块大小最大4MB,旧节点认为区块大小最大1MB,且新节点占据大多数。
在这里插入图片描述
从图中可看出,新节点(更新了比特币协议版本的节点)和旧节点(即没有更新比特币协议版本的节点)产生的区块分成了2条线路,但因为新节点的区块大小要求最大是4MB(假设),因此新区块构成的分支上除了可以接收新区块,同样也可以接收旧节点产生的旧区块。反之,旧区块构成的分支认为区块大小最大是1MB,那些新区块最大是4MB,对于旧区块构成的分支而言新区块是非法的区块,因此只能选择上面的分支接入,下面的分支只能接入旧区块。只要旧节点没有更新比特币协议版本,那么这两个分叉就会永久存在,这就是“硬分叉(hard fork)”。

1.BTC社区中有些人很保守,不愿意加大区块大小 2.区块大小并非越大越好,在网络篇中提到,比特币网络传输为"尽力而为",区块加大会造成传输变慢等问题。 3.单纯增加区块大小,对交易数量的增加远不能达到数量级的提升。

出现hard fork后,便变成了两条平行的链,也就造成了社区分裂。社区中有一部分人,会认为下面的链才是”正统“(根正苗红),各个链上的货币独立

实际上,这个事情真正出现过。后续会介绍以太坊,以太坊历史上的一件大事就是硬分叉事件。以太坊称为ETH,但目前看到的ETH已经不是最初的ETH了,以太坊在历史上发生过硬分叉,另一个链称为ETC。实际上,ETC才是以太坊设计原本的协议,而ETH是黑客攻击ETH上一个智能合约THE
DAO后进行回滚的协议链(将黑客攻击偷取的以太币采用硬分叉方式回滚回到另一智能合约,然后退还给真正拥有者)。
但是这次硬分叉的后果,由于有人不愿意这么做,造成了以太坊社区的分裂。实际上,虽然ETC不如ETH又名,但实际它也是目前一种主流货币。
分叉之初,由于两个链分叉造成了互相影响,产生了很多麻烦。比如:在ETH链上有一笔转账B->C,有人便在ETC链上回放,将ETC链上的货币页转给了C(C收到两笔钱)。后来,对两条链各添加了一个chainID,将两个链区分开,才使得这两条链真正分开。

2.软分叉:如果区块链的共识规则改变后,这种改变是向前兼容的,旧节点可以兼容新节点产生的区块,即为软分叉。

软分叉通常刚开始并不会产生两条区块链,因为新规则下产生的块会被旧节点接受,旧节点只是无法识别新规则的真实意义。所以新旧节点仍然处于同一条区块链上,对整个系统的影响也就较小。

例如:

有人想将区块大小调大,也就会有人思考调小的好处。在这里,我们假设将区块大小从1MB减小至0.5MB(实际中,1MB已经足够小,不会调小了).

需要注意的是,区块链中区块大小调整并非简单修改一个参数,调改大小便很有可能会引发分叉,由于参数修改方式不同,有可能会是硬分叉,也有可能是软分叉。

假设系统中大多数节点更新了软件,少数节点仍然遵从1MB限制的协议(注意,这里大多数和少数是按照算力来区分的,和账户数量无关)。即:新节点认为区块大小最大0.5MB,旧节点认为区块大小最大1MB,且新节点占据大多数。
在这里插入图片描述

我们假设对节点中块的内容做了调整,使得产生出来的新区块比原来的旧区块要小。新区块只会认同新区块,也就是说如果产生的是旧区块不管是上面还是下面的分支都可以接入,但要是产生的是新区块,那么它只会从新区块处接入,久而久之新区块构成的分支将成为最长合法链,而旧区块分支将被舍弃,这就是“软分叉(soft fork)”。

需要注意的是,旧节点如果不升级软件,挖出的区块可能就白挖了(大于0.5MB),但对于系统来说,不会存在永久性分叉。
系统中可能出现软分叉的情况及其实例:

1.给某些目前协议中未规定的域赋予新的含义或规则。
最经典的就是,铸币交易中CoinBase域。在CoinBase域中写入任何内容都可以,没有任何规定。之前,在介绍挖矿时,提到挖矿本质是调整block header中的nonce,但其本身只有4个字节,搜索空间太小。所以实际使用中,将CoinBase域前8个字节作为另一个extra nonce,此时搜索空间从原本2^32 增长到2^96,对于目前挖矿难度来说已经足够。
但CoinBase中并不是只有8个字节,还剩下很多空间。有人便提出将其作为UTXO(当前还没花掉的交易结合)集合的根哈希值。目前UTXO是全节点自己在本地为了方便查询自行维护的,但UTXO内容并未写入区块链(Merkle proof用于验证某个交易是否在区块中,Merkle proof的交易信息是写入区块链的。)
由于UTXO存在本地,如果查询某账户余额,轻节点便需要询问全节点,全节点根据UTXO中信息可以计算得到账户余额,但如何确保全节点给的数据可信?由于直接修改block header会造成硬分叉,有人便提出了以上的方案(该域刚好无人用)。
可以看到,旧节点认可新节点的区块,但新节点对于旧节点CoinBase域检查时候,发行并没有这个UTXO的根哈希值,不会认可其发布的区块,所以这是软分叉。

2.P2SH:Pay to Script Hash
P2SH是多重签名的一种应用形式。在P2SH的交易中,多了一个Redeem Script的概念,称为赎回脚本。当向P2SH脚本的地址转账时,锁定脚本中填写的不是公钥地址的列表,而是Redeem Script的hash值,这样锁定脚本变的非常短。只有在P2SH向外转账时的解锁脚本才会很长。这样就避免了多重签交易中锁定脚本过长导致交易费也骤增的问题。
上一篇中提到过,最初比特币版本中没有该功能,后来通过软分叉方法加入了进去。

【⚠️】总结:
要区分好软分叉和硬分叉

硬分叉:如果区块链软件的共识规则被改变,并且这种规则改变无法向前兼容,旧节点无法认可新节点产生的区块
特点:必须系统中所有节点更新软件,系统才不会产生永久性分叉
软分叉:这种改变是向前兼容的,旧节点可以兼容新节点产生的区块
特点软分叉要求至少有半数以上算力的节点必须更新软件,才不会出现分叉,即使出现分叉了也是临时性分叉,软分叉不会出现永久性分叉

11.BTC问答

本讲以课堂提问的方式帮助大家更好地理解前面学过的知识,解答了很多令同学们感到困惑的问题,例如转账交易的时候,如果接收者不在线怎么办?如果你帐户的私钥丢失了怎么办?如果转账的时候写错了地址怎么办?

1. 转账交易时候,如果接收者不在线(没有连在比特币网络上)怎么办?
答:转账交易只需要在区块链上记录,将某账户比特币转到另一账户,而接收方是否在线并无影响。
2. 如果账户私钥丢失怎么办?
答:没有办法。因为比特币是去中心化货币,没有第三方中心机构可以重置密码,所以账户上的钱也就变成了死钱。

通过加密货币交易所(中心化机构),一般需要提供身份证明,如果忘记私钥可以找交易所申请追回私钥。但目前这类货币的交易所,尚且处于缺少监管的状态,并不一定具有可信力。而且,其本身仅起到“中介”作用,与该提问的回答“私钥丢失无法追回里面的比特币”并不冲突。
在历史上,有很多次交易所被黑客攻击偷走大量加密货币的事情,其中最著名的为Mt.
GOX(中文译为:门头沟)事件。该交易所曾经为全球最大比特币交易所,交易量占到全球比特币交易量的70%左右,设于日本。后来由于被攻击丢失大量比特币,导致交易所破产,其CEO被判刑入狱。
此外,也有交易所监守自盗,工作人员卷款跑路(有点类似 rm -rf */ 删库跑路系列)。

3. 假设某全节点收到某个转账交易,会不会有可能转账交易中收款人地址该全节点从未听过?
答:可能,因为比特币账户只需要本地产生即可。只有该账户第一次收到钱时,其他节点才能知道该节点的存在。
4. 私钥泄露怎么办?
尽快将剩余BTC转到其他安全账户上,没有第三方中心机构重置密码或冻结账户,只能自己对自己负责。
BTC系统中账户便是公私钥对,密码就是私钥,无法更改。
5.转账写错地址怎么办?
答:没有办法,只能自认倒霉,无法取消已经发布的交易。如果转入不存在地址,则该部分比答:特币便成为了死钱。当然,比特币系统中UTXO会永久保存该交易,记录该并不存在的地址。因此,对全节点来说,这是不友好的。
6.之前在BTC脚本中介绍了OP_RETURN指令,我们提到,这种方法为普通用户提供了一个向比特币网络中写入想要一直保存的内容。但OP_RETURN执行结果是无条件返回错误,而交易返回错误,区块又怎么会包含它?区块链又如何会接收这个区块?
答:

思想1:特殊机制,该脚本即使返回错误,仍然写入区块链。(实际并不是)
思想2:即使返回失败,仍然写入区块链,只是具体处理时候不计算其即可。(恶意节点大量抛出失败交易,攻击区块链怎么办?上一篇中提到,每秒平均只能处理7笔交易。

OP_RETURN实际写在当前交易的输出脚本中,而验证交易合法性时,使用的当前交易的输入脚本和前一个交易(币来源的交易)的输出脚本进行验证。也就是说,验证当前交易合法性时,并不会执行该语句。只有在有人想花这笔钱时候,才会执行该语句。

7.BTC系统挖矿,会不会有矿工“偷”答案?例如:某个矿工发现其他矿工发布了nonce,收到后验证该区块合法,将该nonce作为自己找到的nonce发布出去。
答:实际上这是不可能的。发布的区块中包含铸币交易,其收款人地址为挖到矿的矿工地址,如果要偷答案,需要修改该收款地址,而地址改变,铸币交易内容也发生改变,从而引发Merkle Tree根哈希值改变。从而导致原本的nonce作废。也就是说,不可能会“偷”答案。
8.交易费是交易者为了自己交易可以上链而给出的“小费”,那么如何得知哪个矿工可以挖到矿?
答:事先无需知道谁会挖到矿,交易中总输入和总输出差额就是交易费。哪个矿工挖到矿,在打包交易时,可以将这些交易费收集起来作为自己获得的交易费。

12.BTC匿名性

12.1Bitcoin and anonymity
一般来说,匿名性多与隐私保护相关。但实际上,比特币中的匿名并非真正的匿名,而是假的匿名。实际上,比特币与纸币相比,纸币的匿名性更好,因为其并没有对个人信息的标记。也正是因为其匿名性,很多非法交易采用现金交易。但现金存在保管、运输等各个方面的不便。
12.2BTC系统中什么情况会破坏其匿名性?
1.用户可以生成多个地址账户,但这些地址账户可以被关联起来
表面上看,每次交易可以更换公私钥对,从而每次都是新的账户,具有很强的匿名性。但实际上,这些账户在一定情况下,是可以被关联起来的。
例如:
在这里插入图片描述

在图中可以看到该交易有2个输入和两个输出,所以addr1和addr2很可能是同一个人所持有的账户,因为该人同时拥有这两个私钥的地址。
而在输出中,很有可能有一个地址是属于找零钱的地址,即花掉之后剩余的钱。在某些情况下,也是可以分析出来的。

在这里插入图片描述

如上图,针对该交易,账户上面数字表示BTC,可以指导addr4很明显是找零钱的地址,而非addr3(支付6个比特币,单个账户不够用,所以用两个账户)。

2.地址账户与个人在真实社会中的身份也可能会产生关联。
任何使得BTC和实体世界中关联的操作都有可能泄露用户真实身份,其中最明显的就是资金的转入转出。要得到BTC,如果用钱买,就会与实体世界进行交互。想要将BTC转为现实中的货币,也同样需要与实体世界交互。

在很多国家,都有防洗钱法。如何防范不法分子采用BTC进行洗钱呢?其实很简单,只需要盯住资金转入转出链即可。对于大额资金转入BTC或将大量BTC转为现实货币,很难逃避司法金融机构的监管。

3.BTC支付时候
例如某些商家接受用BTC进行支付,例如可以用BTC购买咖啡、蛋糕等。(这种场景信用卡已经解决的很好了,用BTC交易延迟高,交易费贵,并非一个好的idea)
在进行支付时候,便和个人账户建立了联系,从而会泄露掉个人信息。
也就是说,BTC并不是具有很好的匿名信。实际中,很多人保持有较好的匿名性。保持最好的便是其开发者中本聪,其参与BTC时间最长,全世界都想知道他是谁。但实际上,中本聪的比特币并非有花出去,这也使得我们难以发现他具体是谁。

总而言之:互联网并非法外之地。

12.3 如何提高比特币的匿名性
匿名的本质是不想要暴露身份。而对于普通人来说,BTC的现有机制已经足够保持个人隐私了。但如果涉及违法,行政机关想要获得真实身份,其实很容易。
那么可以采取哪些方法尽可能提高匿名性?

从应用层看,可以将各个不同用户的BTC混合在一起,使得追查变得混乱(Coin
mixing);从网络层看,可以采用多路径转发的方法,数据不直接发送出去,而是经过很多跳(洋葱路由的基本思想)。

12.4零知识证明

零知识证明:一方(证明者)向另一方(验证者)证明某一个陈述是正确的,但不需要透露除该陈述是正确的之外的任何信息。
例如:A想要向B证明某一账户属于A,这说明A知道该账户的私钥。但不可能通过A公布私钥的方法来证明,该账户确实属于A。因此,A可以产生一个账户签名,B通过公钥对签名进行验证。(实际上该证明是否属于零知识证明存在争议,因为泄露了用私钥产生的签名)

同态隐藏——零知识证明的数学基础
在这里插入图片描述
零知识证明的数学基础便是同态隐藏。上图为同态隐藏的三个性质。

第一个性质,说明如果有E(X)=E(y),则必然有x=y。(无碰撞) 第二个性质,说明加密函数不可逆。知道加密值,无法反推出密码值。
第三个性质,最为重要,称为同态运算。说明对加密后的函数值进行某些代数运算,等价于对输入直接进行代数运算再加密。

例子:
在这里插入图片描述

其中证明者为Alice,验证者为Bob。最简单的证明版本如下:
1.Alice将E(x)、E(y)发给Bob。(性质2,不可逆)
2.Bob通过收到的E(x)、E(y)计算得到E(X+Y)。(性质3,同态加法)
3.Bob进行验证E(x+y)和E(7)是否相等。若相等则验证通过,否则验证失败。(性质1,无碰撞)
缺陷:Bob可以暴力获取x与y的值。
12.5盲签
盲签名是一种特殊的数字签名技术。盲签名因签名的人看不到所签署文件的具体内容而闻名,它有两个显著的特点:一是签名者对消息的内容是不可见的 ;二是签名被公开后,签名者不能追踪签名。

为什么要这么做呢?
例如电子交易中,我们的交易信息依赖于银行等第三方机构。第三方机构需要防范双花攻击等,就需要对电子货币进行签名。而签名的过程中,必然会导致其了解到交易内容。如果想要银行等第三方机构负责相应工作,但不知道交易具体内容,就可以采用盲签的方法

例如A向B转账。
在这里插入图片描述
既然了解到BTC提供了较好匿名性,但其无法完全消除关联性,那么如果想要这样一种货币怎么办?这就涉及了零币和零钞。

12.6零币和零钞——专门为匿名性设计的货币

在这里插入图片描述
零币在花费的时候,只需要用零知识证明来证明所花掉的币是系统中存在的某一个合法的币,但不用透露具体花掉的是系统中哪一个币。这样就破坏了关联性。
当然,这类货币并非主流加密货币,因为其为了设计匿名性,付出了一定代价,而且,需要强匿名性的用户并不多。

从数学上看,零币和零钞是安全的。但其并不是百分之百的匿名,其并未解决与系统外部实体发生交互时对匿名性的破坏。

13 BTC思考

这节课是比特币学习的最后一节课。这节课内容包括:哈希指针与通常所说的内存指针有什么区别?由“区块恋”引发的对私钥分割带来的安全性问题的讨论。比特币为什么能绕过分布式共识的那些不可能结论?比特币中人为造成的稀缺性适合做为货币吗?量子计算对区块链系统安全性的冲击等。

13.1 哈希指针
BTC系统中很多地方使用到了哈希指针。指针保存的本地内存地址,只有在本地计算机上才具有意义,如果发送给其他计算机就没有意义了。那么在区块发布时候,哈希指针如何通过网络进行传播?

所谓哈希指针,只是系统中一种形象化的方法。实际应用时候,只有哈希而没有指针。回顾之前提过的Block header数据结构。
在这里插入图片描述

因此可见,在block header中只有hash值,没有指针。那么如何查找到前一个区块的内容?
全节点一般将区块存储于一个key-value数据库中,key为哈希,value为区块内容。常用的key-value数据库为levelDB,只要掌握到最后一个区块的哈希值即可通过levelDB查找哈希值key对应的value即可把最后一个区块的内容取出来。 区块的块头里又有指向前一个区块的哈希值再去查找key-value,一步步往前 即可查询到整个区块的所有信息。
有些节点只保存区块链部分信息,如果需要用到前面的区块,可以问其他节点要。哈希指针性质保证了整个区块链内容是不可篡改的。

13.2 区块“恋”

有情侣一起买BTC,将私钥从中截断,每人保留其中一部分。如果未来两人依旧感情很好,就可以将钱取出;如果分手,这部分钱就会永久锁死,谁也无法取出,通过区块链的不可篡改性作为两人的爱情见证。这样做有什么问题?
如此下来,N个人怎么办?

如果按照这种方法,将私钥分为N份。但这样会有一系列问题。一. 如果N个人中任意一个人忘记私钥,则无法将钱取出。二.截断私钥长度,会降低安全性,因为私钥长度会直接影响破解难度(2^256 远远大于2的128次方),之间难度差距远远不止一倍。【可见,对于多个人账户,应该使用多重签名,而非截断私钥的方法。】三.如果分手,该钱变成死钱,一直保存在UTXO集合中,对矿工不友好。
13.3分布式共识
之前有提及,理论上来说,分布式系统不可能达成共识。

为什么比特币系统能够绕过分布式共识中的那些不可能理论?

严格来说,BTC并没有取得真正意义下的共识,BTC系统取得的共识随时可能被推翻,例如分叉攻击导致系统回滚。
因此按照分布式共识要求,共识一旦达成后就不应该再更改了。从这个意义上来说,比特币并没有绕过分布式系统下不可能的结论,因为他没有达到真正意义下的共识
此外,理论和实际存在差异。不可能结论针对特定模型,实际中对模型稍微修改或添加线下方法即可将不可能变为可能。

知识改变命运,这句话本身没有错,但是对知识的一知半解可能让你的命运变得更差,搞科研是很有意义的,但是不要给学术界的思维限制头脑,不要为程序员的思维限制想象力。

13.4BTC的稀缺性
为什么要挖矿?因为有收益,且收益大于开销。早期BTC难度低且出块奖励高,从而吸引矿工。
之前有提到,BTC总量固定,有人认为其是一个精妙的设计。但实际上,总量固定的东西并不适合作为货币,这也就决定了BTC并不能在未来完全颠覆现有货币体系。以太坊中便没有BTC中出块奖励定期减半的做法,此外,某些新型货币会自带通货膨胀的功能。

有人提到过黄金总量是固定的在很长一段时间有充当过货币的职责,但是黄金并不适合作为通用货币,严格地说黄金的量并不是定死的,每年都有新的金矿被挖出来,但是每年黄金挖出来的速度远远满足不了社会财富的增长速度。如果我们用黄金作为货币,那么黄金会越来越值钱。

对个人来说,通货膨胀并非好事,因为钱不值钱了。但人类每年创造的价值,如果用总量固定的东西作为货币,则其只会越来越值钱,而这会导致拥有者不断看着其升值,其他没有的人无论如何奋斗都赶不上(房市也是如此,炒房使一部分人靠房租便可大赚特赚,个人奋斗却很难买房。这也是我国目前存在的较大的问题,社会财富的分配不公,最终引发各种社会矛盾,需要政府解决)

13.5 量子计算
首先我们需要明白量子计算的概念

1.量子计算:一种遵循量子力学规律调控量子信息单元进行计算的新型计算模式。对照于传统的通用计算机,其理论模型是通用图灵机;通用的量子计算机,其理论模型是用量子力学规律重新诠释的通用图灵机。从可计算的问题来看,量子计算机只能解决传统计算机所能解决的问题,但是从计算的效率上,由于量子力学叠加性的存在,某些已知的量子算法在处理问题时速度要快于传统的通用计算机。

量子计算机:基于量子力学基本原理的计算机,和常规计算机的区别主要在于其基本信息单元不是比特而是量子比特。之前我们用0和1表示两个状态,而量子计算机的两个状态用0和1的相应量子叠加态来表示,单个量子CPU具有强大的并行处理数据的能力,其运算能力随CPU的个数指数增加

这就可能会造成一个问题:

有人提出:BTC这种建立在密码学上的加密货币,在量子计算出来后会不会变得不安全。

这个想法其实不必担心
一. 量子计算距离使用仍然有很长距离(人工智能也是,目前仍然处于弱人工智能阶段。其实很多技术都是如此,炒的情况很严重,但距离实用很远。但是不炒便不会有资本流入进行研究,这也是一个非常相悖的地方)。
二. 量子计算若真正使用到破坏现有加密算法,对传统金融业的破坏仍然是最大的。加密货币目前占有的市值只有很小一部分。
三. 实际中使用的并非公钥,而是可以用公钥哈希。而哈希函数一般都是不可逆的,所以即使量子计算也无法反推私钥。
BTC中用的SHA-256,无论输入多大,最终结果都为256位,必然会导致信息丢失,无法反推原本数据。

加密和取哈希是不一样的:加密可逆、哈希不可逆;加密不损失信息、哈希破坏信息

至此BTC内容已学完

猜你喜欢

转载自blog.csdn.net/qq_41569591/article/details/107932841