学习视频来自:北京大学计算机系肖臻区块链学习视频
还有一些参考了一些博客的记录。
前面两三节在听视频的时候没有及时做笔记 摘自于
其他博客
1.1 教材
教材和参考资料如下:
1.2 主要内容
比特币:
以太坊:
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)由椭圆曲线加密算法生成,私钥可推出公钥而反之不能。
【重点】:
有了私钥,你就可以对文本签名。别人拿了你的公钥就可以根据签名认证你是否拥有私钥。这就是证明你拥有存款的办法。
为了安全起见,公钥应该隐藏起来。所以对公钥进行哈希加密,生成公钥哈希值然后计算哈希值的比特币地址:
**
**
**
**
**
**
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.签名与验证
可以参考这篇文章比特币交易中的签名与验证
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,因为比特币种不需要不存在证明)
【笔记】实际中,我们只要保证是无环状的结构都可以用哈希指针。但如果是有环的就不可以了。比如 循环单链表就不可以用哈希指针。因为会造成循环依赖。
因为哈希指针后一个指针哈希值需要前一个来确认。但如果是带环的话,则会导致每一个都确认不了 从而导致循环依赖。
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去中心化的数字货币
采用去中心化的数字货币,我们首先就面临着两个问题。
避免双花攻击的方法:每一笔交易都要指明花费来源于哪笔交易。下面是比特币系统中交易的例子,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), 它指出对于一个分布式计算系统来说,不可能同时满足以下三点:
CAP理论的核心是:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求,最多只能同时较好的满足两个。
因此,根据 CAP 原理将 NoSQL 数据库分成了满足 CA 原则、满足 CP 原则和满足 AP 原则三 大类:
节点自己生成一笔筹币交易,并且与其他所有即将打包的交易通过Merkle树算法生成Merkle根哈希。
区块头将被作为计算出工作量证明输出的一个输入参数,因此第一步计算出来的Merkle根哈希和区块头的其他组成部分组装成区块头
计算出工作量证明的输出
下面我们直接通过公式和一些伪代码去理解工作量证明的输出:
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万八千多了。
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系统遵守两个规则: