北京大学肖臻老师区块链课程笔记

1.1BTC-密码学基础:哈希、签名

image-20250110112804874

image-20250110113039222

1、比特币中的密码学原理

比特币(Bitcoin)

crypto-currency加密货币

但其实加密货币是不加密的,区块链所有的交易内容都是公开的,包括账户的地址,转账的金额。

比特币中主要用到了密码学中的两个功能:哈希、签名

密码学中用的哈希函数:cryptographic hash function

一、哈希

性质:

1、collision resistance

(哈希碰撞:两个不同输入算出的哈希值相等)/collision free ,但是碰撞是客观存在的,这个resistance是说没有办法人为制造哈希碰撞(ps:这个性质,理论上证明不了。实践经验)

两个输入x和y,如果x != y,H(x)= H(y),这就叫哈希碰撞

不同的输入可能会被映射到哈希表中的同一个位置,一般来说哈希碰撞是不可避免的,因为输入空间远远大于输出空间

例如:256位的哈希值,输出函数的空间:所有哈希值的取值:2^256,但输入空间可以无限大->任意多种输入的可能性

戈农原理:必然两个输入被映射到同一个输出的情况

要求x和y,遍历所有取值可能,brute-force

m->H(m),message digest用来检测对这个message的篡改

比如:有人改message的内容,他的哈希值就会变化。

这个性质说的是你找不到m‘,求H(m’)跟原来的哈希值恰好相等

--》不可能篡改内容又不被检测出来

例:很大的文件,想把他存放到某个云存储服务上,将来用到的时候再把它下载回来,你怎么知道你下载的版本跟当初上传的版本是一样的呢,这就用到hash function collision resistance这个性质,在上传文件之前,算一个哈希值出来,这个哈希值存在本地,将来下载之后,再算一个哈希值,跟原来的比较,一样:上传的文件没有被篡改,下载的还是原来那个版本

2、hiding

哈希函数的计算过程是单向的,不可逆的,

给x算出H(x),但是给H(x)没办法反推x,

这个哈希值没有泄露有关输入x的任何信息,

hiding成立前提:输入空间足够大,使蛮力求解的方法不可行

输入分布比较均匀,各种取值的可能性都是差不多的

比如如果输入空间比较大,但是绝大多数情况下取值集中在少数几个值,也是比较容易被破解

两个性质结合在一起,实现digital commitment

digital equivalent of a sealed envelope

比如:一个人预测股票会涨停,验证预测准不准确的方法如,这个人提前一天在电视台上公布预测结果:我预测明天某某股票会涨停,第二天收盘后,看这个股票是否真的涨停,

问题:如果预测结果提前公布了,可能会影响股市,比如这个人很有名气(股神),本来大家认为这只股票不会涨停的,她公开预测,大家买,结果把他变成了涨停(或者反方向的情况也可能发生(砸盘))

--》预测结果不能提前公开

H(x || nonce)

nonce:选取的一个随机数保证

除了密码学中要求的两个性质外,比特币中用到的哈希函数还要求第三个性质,

3、puzzle friendly

(挖矿的过程没有捷径,只能靠不停地尝试大量的nonce才能找到符合要求的解,所以这个过程才可以用来作为工作量证明:proof of work。你挖到矿了,找到符合要求的nonce了,一定是因为你做了大量的工作,没有捷径。但是一旦有人找到这个nonce,别人要验证是否符合要求,是很容易的。(难找易验)挖矿很难,验证很容易-》

(difficult to solve, but easy to verify))

哈希值的计算,事先是不可预测的

你想求在某范围内的哈希值,只能一个一个输入,

image-20250110121358483

挖矿实际上就是找一个nonce(跟区块的块头里的其他信息合在一起作为输入,取出一个哈希来,哈希值要小于等于某个指定的目标阈值

image-20250110121610029

区块链,一个一个区块组成的链表,每一个区块有块头,块头有很多个阈,其中有一个阈是我们可以设置的随机数nonce

挖矿的过程:不停地尝试各种随机数,使得整个block header取哈希后,落在指定的范围之内(target)

image-20250110122020639

比特币中用的哈希函数SHA-256

secure hash algorithm

二、签名

比特币系统中的账户管理

日常生活要开账户:带证件去银行办理开户手续

(中心化系统的账户管理方式)

比特币:去中心化,没有银行之类的机构。

怎么开户?每个用户自己决定开户,不需要任何人批准,开户的过程:创立一个公钥和私钥的对。在本地创立一个公私钥对,就是一个账户

image-20250110122845695

公私钥这个概念,来源于非对称的加密体系,asymmetric encryption algorithm

最早的加密体系是对称的,最早叫做symmetric encryption algorithm

两个人通信,通讯的网络有可能被窃听,于是两个人事先商量好一个密钥(encryption key),我把这个信息加密之后发给你,你收到之后用这个密钥解密,因为加密和解密用同一个密钥,所以叫做对称的加密体系,前提是假设有某种安全的渠道能够把这个密钥分发给通讯的双方,因为密钥不能以明文的形式在网络上传输,(假设网络本身不安全),对称加密体系的弱点:密钥的分发不是很方便

加密用公钥,解密用私钥。

比如要把一个信息传给你,我用你的公钥给这个信息加密,你收到之后,用你的私钥解密得到原来的信息,(加密和解密用的是同一个人的公钥和私钥,都是接收方的公钥和私钥。

好处:解决了对称加密体系中密钥分发不方便的问题(加密的公钥不用保密,私钥要保密,但是私钥只要保存在本地就行,不需传给对方。给你通讯的人不需要知道你的私钥。你要回复他,相同的做法,你变成发出方,他变成接受方)

(用他的锁,只有他有钥匙能打开)

比特币是加密货币,但其实是不加密的,信息是公开的。

公私钥是用来实现签名功能的

比如我要发10个比特币给你,我把这个交易发布到区块链上,别人怎么知道这个交易是由我发起的呢

(会不会有人冒名顶替,把我账户的钱转走了(公钥=银行账户,私钥=账户密码))

需要我在发布这个交易的时候,用我自己的私钥对这个交易签名,其他人收到交易后,用我的公钥验证这个签名的正确性。

(签名用发出方的私钥,验证签名用发出方的公钥(都是同一个人的))

如果两人生成的公私钥对恰好相同怎么办?

比如有人要偷比特币,可以大量产生公私钥,对比我产生的公钥跟区块链上已有的某个公钥是否相同,一样:用对应的私钥把账上钱偷走。理论上可以,但实际上很难,2^256的公私钥,产生相同的公私钥的可能性很小,

比地球爆炸的概率还小,到目前为止,还没有这种方法攻击成功的先例

假设生成公私钥的过程有一个好的随机源

a sood source of randomness

如果选取的随机源不好,前面的分析就不成立了(比如有可能两个人的公私钥对一样),

比特币中用的签名算法,不光是生成公私钥的时候要有好的随机源,之后每一次签名的时候也要有好的随机源,只要有一次随机源选取不好,就有可能泄露私钥-》全完了

比特币系统,一般先对一个message取一个哈希,然后再对这个哈希值签名

1.2BTC-数据结构

1、区块链

区块链表和普通链表的区别:

1、用哈希指针代替普通指针

image-20250111131855283

最前面的区块是系统中产生的第一个区块-->创世纪块

最后的区块是最近产生的区块

image-20250111132226759

这种数据结构的好处?我只需要记住最后这个哈希值H()就可以检测出对区块链中任何部位的修改(无论哪个部分改动,最后都会导致保存的哈希值变化)-->多米诺骨牌效应

取哈希:把整个区块的内容合在一起取哈希。图中粉色全部(包括哈希值H())

image-20250111132401178

image-20250111132321988

比如我修改粉色部分,会导致后面的哈希值变化,再导致后后面的哈希值变化,最终影响到最后一个H(),所以要检测是否被篡改,只需要将最后一个H()保留在系统中,他变了,就说明前面有人变了

怎么知道别人给的区块是否正确?(哈希指针的性质)

只保存后面的区块,前面不保存,用到了再问别人要。

算他的哈希值,跟保存的哈希值对比一下就知道了

image-20250111133040212

2、Merkle tree

与binary tree的区别:

1、用哈希指针代替普通的指针

image-20250111133427814

一个数据块,他的哈希值存在上面那个节点,旁边的数据块也存在上面这个节点旁边

image-20250111133534693

两个哈希值拼在一起,再取哈希,存在上层节点

最上面的哈希值H()叫root hash

image-20250111133646079

只要记住根哈希值,就能检测出对树中任何部位的修改(整棵树都得到了保护)

image-20250111133921217

底下每一个数据块实际上是一个交易transaction

image-20250111134023445

每个区块分为两部分:块头和块身

block header

block body

在block header里有root hash

包含的所有交易组成的Merkle tree的根哈希值存在这个区块的block header里面,但是block header里没有交易的具体内容,只有一个根哈希值,block body里有交易列表

Merkle tree的作用:提供Merkle proof

比特币节点是比特币网络的支柱。它们确保和验证交易,并将它们广播给其他节点。主要有三种类型的节点:全节点、轻节点和挖矿节点。full nodes、miner nodes、light nodes

比特币中的节点分为两类:全节点、轻节点

全节点:保存整个区块的内容(block header、block body)交易的具体信息

轻节点:(如手机中的比特币钱包的应用)只保存一个block header。(轻量级节点)

问题:如果需要向一个轻节点证明某个交易是写入到区块链

比如:你向我买一些东西,需要转给我一笔钱。你跟我说你转给我的交易已经写到区块链里了,支付已经完成了。我是轻节点(比如只能在手机上查,怎么知道这个交易已经被写到区块链里了???

找到这个交易所在的位置,从这个交易往上一直到根节点的路径,这条路径就是Merkle proof

image-20250111192439435

image-20250111192502620

怎么知道黄色交易是否包含在Merkle tree里?

轻节点没有交易列表,没有这棵Merkle tree的具体内容,只有一个根哈希值(因为根哈希值是保存在block header里的)这个轻节点有block header。

轻节点向某个全节点发出请求,请求能够证明黄色交易包含在Merkle tree里的Merkle proof,收到请求之后,只要把图中标为红色的这三个哈希值发送给这个轻节点就行,有了这些红色哈希值,轻节点可以在本地算出图中标为绿色的三个哈希值

image-20250111232725712

首先算出黄色部分的哈希值,然后跟右边这个红色哈希值拼接起来,算出上一层节点的绿色哈希值,再跟左边这个红色哈希值拼接起来,再算出上一层节点的绿色哈希值,然后再跟右边这个红色哈希值拼接起来,算出整棵树的根哈希值,轻节点把这个哈希值跟block header里的根哈希值比较,就能知道黄色交易是否包含在Merkle tree里

image-20250111232837951

image-20250111232921268

全节点在Merkle proof里提供的这几个哈希值,就是从黄色交易所在的叶节点的位置到根节点的路径上用到的所有哈希值。

轻节点收到merkle proof之后,只要从下往上验证这些哈希值是否正确即可

只能查自己所在路径的那支,旁边的哈希值是查不了的(红色值算不出来,只能全节点给出)。

那旁边的哈希值你查不到不就给篡改哈希值制造一定的自由度了吗?

能不能两个哈希值(绿色和红色交易)都改了,这样上一层哈希值不就不变了吗?

-->人为制造哈希碰撞

实际中不可行,collision resistance这个性质

image-20250112004013870

Merkle proof可以证明Merkle tree包含了某个交易,所以这个证明也叫proof of membership/proof of inclusion

我是轻节点,你发给我一个Merkle proof,验证的复杂度是多少?时间、空间?

对地下这一层有n个交易,复杂度是对数级别,O(log(n)),较高效

能不能证明不包含某个交易?proof of non-membership?复杂度O(n)

最简单的证明方法(暴力遍历):把整棵树传给轻节点,验证树的构造都是对的,每一层用到的哈希值都正确,说明这些树里只有这些叶节点,没有别的,找的交易不在这里面,就证明了。。。

答案是没有更高效的方法,但是对叶节点的排列顺序要求,对交易的内容取哈希,按照哈希值从小到大排序,我要查的那个交易,算出一个哈希,看他在哪里。比如说在图中黄色部分中间(箭头指向),提供的proof包含这两个节点往上的路径到根节点,最后算出root hash都正确。

(除了左边那个交易,右边也得算进去)说明这两个节点在原来的Merkle tree里是相邻的节点,我要找的交易如果存在,应该在这两个之间,但是他没有出现,所以不存在。复杂度O(log(n)),但是要排序。

image-20250112005652797

image-20250112005444375

排好序的叫sort Merkle tree。

但是比特币里不需要排序,因为不需要证明不存在

区块链和Merkle tree都是用哈希指针(hash pointers)来构造。

那哈希指针还能用在哪里?只要这个数据结构是无环的都可以用哈希指针代替普通指针

例如:循环链表。如果用哈希链表的话,第一个hash pointer要依赖第二个hash pointer,所以得把第二个区块内容定下来,才能定第一个区块内容,第二个区块依赖第三个区块内容,而第三个区块依赖第一个区块内容。最后所有区块都未定-->循环依赖

image-20250112010313063

1.3BTC共识协议

double spending attack

引导

image-20250112140616416

CB(center bank)发行100元和50元,发行的数字货币都有CB的私钥签名,CB的公钥大家都知道,

我收到数字货币可验证真伪,买东西的时候,把数字货币发给你,你验证确实是CB发行的。这就完成了支付的过程。但是这个方案有很大的问题。

应用:密码学中公私钥体系、非对称加密算法,但是没有用到区块链。

(假设CB的私钥不会泄露,因为如果CB都会泄露,那普通人的就更会了,那比特币就没用了)

如果CB无限制发行货币-->通货膨胀。例如美联储量化宽松,影响市场的金融秩序。

更大的问题:这是一个文件,文件的内容不可伪造,但是文件可以复制,买一个东西给一个文件,与纸质货币不一样,给了就没了

数字货币和纸质货币的区别:double spending attack花两次攻击/双花攻击

改动:(还是CB发行数字货币)每个数字货币上有一个编号。央行要维护一个大的数据库(表),上面记录每个编号的数字货币在谁手里

image-20250112141637178

记录内容:以前在我这,现在给你了,在张三手里,张三支付是合法的。例如下图,现在在xz手里,改动后,现在在zjc手里,

image-20250112141850103

image-20250112141839238

央行核实后,人不对,这个数字货币已经花出去了-->double spending attack

缺点:太麻烦了,且是中心化方案(货币发行是央行控制、交易需要央行确认才能证明合法)

比特币中,谁来发行货币?挖矿。如何防范double spending attack?与上述类似,也是需要维护一个数据结构来检测是否发生交易。区别在于这个结构由所有用户共同维护,这个数据结构就是区块链

交易分为输入和输出

输入部分要说明币的来源和A的公钥;输出部分要给出收款人的公钥的哈希

铸币交易coinbase tx

image-20250112144837127

image-20250112144928045

两种哈希指针

1、连接各个区块(串起来)构成一个链表

2、指向前面某个交易,为了说明币的来源(记录,防伪和DSA)

image-20250112145455181

最后一个区块显示,B给F五个币,这里的B指向来源(A-》B),别的节点收到这个交易后,从这个区块往B的来源回溯,查到B-》C那里发现不对,,A-》B的钱已经被花出去了,说明最后这个交易(B-》E)不合法,就不会把他接受到区块链里

image-20250112145411026

image-20250112145554438

A-》B这个交易需要什么信息?

A的签名、B的地址。

在比特币系统中,收款的地址是通过公钥推算出来的,如B的地址,通过B的公钥取哈希得到

银行本身没有提供查询的功能(指定某个人,可以查到他的账户),都是你要告诉我(接收方告诉发起方),比特币系统类似,也没有提供查询功能。

A需要知道B的地址,B需要A的信息吗?必须知道A的公钥。(我得知道钱从哪来的)

思考,如何证明这个交易已经写进去?先要证明交易要写到区块链之前,需要符合什么条件?A有无足够的币的来源,指向铸币的交易,币的来源是A要证明的,与B无关。

每个节点必须知道A的公钥。因为私钥签名公钥验证(更重要的原因),每个节点都得独立验证(有可能有恶意节点),不能依靠别人,我收到这个交易,验证是否合法。假设A转给

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值