区块链|肖臻《区块链技术与应用》公开课之比特币篇
比特币中的密码学原理
一. 哈希
x -> H(x)
哈希函数两个性质:
1. collision resistance:确保不同的 x 计算出的 H(x) 必然不相同
2. hiding:确保无法使用 H(x) 倒推出 x
nonce:在输入空间不是足够大的情况下,为了防止被暴力破解,用 Hash(x) 倒推出 x,所以在 x 后拼接了 nonce,即:x -> H(x||nonce)
比特币的哈希函数(SHA-256)除此之外还有第三个性质:
3. puzzle friendly:H(black header) ≤ target,其中 black header 中不仅包含了交易哈希,还包含了 nonce。挖矿没有捷径,只有通过大量的计算,才能找到符合要求的 nonce,这就是工作量证明
二. 签名
公私钥对(public key, private key):来自于非对称加密体系
对称加密体系:使用同一把密钥进行加密和解密,它的前提是需要有一个安全的渠道能够把密钥传输给对方
非对称加密体系:使用一对公私钥进行加密和解密,发起方要将信息传达给接收方,那么发起方使用接收方的公钥加密信息,接收方拿到加密后的信息使用自己的私钥进行解密。其中公钥是可以公开给所有人的,但是私钥只能保存在自己的本地
比特币的非对称加密:
在发布交易时,使用自己的私钥对该笔交易进行签名,发布后,其他人可用发布人的公钥进行验证,验证该笔交易是否真的由该发布人发布
前提:生成公私钥的时候有一个好的随机源,并且在签名的时候也要有好的随机源,如果在签名的时候没有好的随机源,可能会导致私钥的泄露
比特币的数据结构
一、哈希指针
每一个区块中都有一个指向前一个区块的指针,而这个哈希指针是由前一个区块所有内容(包含前一个区块的哈希指针)计算哈希得到的。因此,一旦有一个区块的内容发生改变,该区块后面所有区块的哈希值都要跟着改。
二、Merkle tree(默克尔树)
最下面的一层是数据块,上部节点均为哈希指针,最上方的称为根哈希值,根哈希值将存储于 block header(区块头)中
全节点:不仅记录了 block header,还记录了 block body(块身)
轻节点:只记录 block header
Q:轻节点如何知道某一笔交易是否上链?
A:轻节点向某个全节点发起请求,请求全节点提供该笔待证明交易的 Merkle proof,全节点收到请求后,将图中红色的哈希值交给轻节点,轻节点即可在本地计算出所有图中绿色的哈希值(自下往上计算)
Q:如何知道某一笔交易不在某一区块内?(即不存在证明,BTC中不存在该证明)
A:全节点将所有的交易按照哈希从小到大排列,找到该笔交易相邻的两笔交易(假设为 a 和 b,a < 待证明交易哈希 < b),计算这两笔交易对应向上直至根哈希的所有哈希值是否正确,若正确则代表待证明的交易不存在该区块内
比特币的共识协议
一个比特币转账订单需要包含以下内容:
1. 转账金额
2. 转账金额来源
3. 收款人地址:由公钥哈希计算得到,且可以逆推得到公钥哈希
4. 转账人公钥:所有参与验证的节点都需要知道转账人的公钥,为了验证该笔订单的确是由转账人签字的。而且该公钥必须和该笔金额来源的转账交易中输出的公钥哈希相对应,以此证明公钥的正确性
block header 包含以下内容:
1. version:比特币版本
2. hash of previous block header:指向前一个区块的指针
3. merkle root hash:根哈希值
4. time:挖到该区块的时间
5. nBits:target(目标阈值)的编码值
6. nonce:随机数
block body 包含 transaction list(交易列表)
full node(全节点):保存 block header 和 block body
light node(轻节点):只保存 block header,一般情况下没有办法独立验证交易的合法性。系统中大部分都是 light node,没有参与区块链的构造和维护
比特币系统的实现
UTXO:指某个钱包地址所有没有被花掉的交易的输出。每个全节点都需要在内存中维护这个数据结构,以便快速检测双花
交易费/矿工费:节点将用户的交易打包至区块中,用户奖励一定量的 BTC 给节点。交易费是为了避免节点只打包自己的交易,而不打包其他用户的交易。另外,比特币每 10 分钟出一个区块,每 21 万个区块,block reward(挖矿奖励)减半一次,大约 4 年减半一次,随着 block reward 的减少,交易费慢慢会变成矿工们的主要收入来源
· 挖矿这种行为从表面上看没有什么实际意义,但是挖矿的过程对于维护比特币系统的安全性是至关重要的
· 比特币区块的大小是有限制的,每个区块最大为 1 MB
比特币网络
application layer(应用层):运行比特币协议
network layer(底层):运行 P2P 覆盖网络
不存在 super node(超级节点)或 master node(主节点)
· 若你想加入比特币网络,必须得知道至少一个节点(称之为种子节点),然后和种子节点建立联系,种子节点会告知你比特币网络中所有的节点
· 节点之间是通过 TCP 来通信的
· 每个节点维护一个邻居节点的集合,邻居节点的选取是随机性的,没有考虑底层的拓扑结构
· 消息在网络中传播采取 floading 的方式,节点第一次收到消息时,会将消息传播给它的所有邻居节点,并记录它已收到过该消息,当下次再收到该消息时,就不会再进行传播
比特币的挖矿难度调整
· 通过调整 black header 中的 nonce 值,使得满足公式:H(black header) ≤ target
· 挖矿难度与 target 成反比,target 越小,挖矿难度越大
· 比特币采用的哈希算法是 SHA-256,产生的哈希值是 256 位,可能的取值有 2^256 个
· 每 2016 个区块(两周)调整一次 target,调整公式:target = target * ( actual time / expected time ),即:产生 2016 个区块实际时间与两周进行对比
· 挖矿难度调整的上下限最大为原来的 4 倍或 1/4
Q:出块速度越快越好吗?
A:不是,因为如果出块速度过快,将导致大量的分叉出现,此时可信算力就被分散了,而不可信算力可以借此机会将自己的区块发展成为最长的区块链条,无需拥有51%以上的算力
Q:如何让所有矿工的同时调整 target?
A:比特币代码中已经包含该规则,每挖 2016 个区块代码会自动调整 target
比特币挖矿
一、全节点和轻节点
全节点:
1. 一直在线
2. 在本地硬盘上维护完整的区块链信息
3. 在内存里维护 UTXO 集合,以便快速检验交易的正确性
4. 监听比特币网络上的交易信息,验证每个交易的合法性
5. 决定哪些交易会被打包到区块里
6. 监听别的矿工挖出来的区块,验证其合法性
7. 挖矿:决定沿着哪条链挖下去?当出现等长的分叉的时候,选择哪一个分叉?
轻节点:
1. 不是一直在线
2. 不用保存整个区块链,只要保证每个区块的块头(大小和整个区块差了 1000 倍)
3. 不用保存全部交易,只保存与自己相关的交易
4. 无法检验大多数交易的合法性,只能检验与自己相关的那些交易的合法性
5. 无法检验网上发布的区块的正确性
6. 可以检验挖矿的难度
7. 只能检测哪个是最长链,不知道哪个是最长合法链(因为没有办法检测链上的交易是否合法)
综上,如果只是需要转账,不需要挖矿,只需要运行一个轻节点即可
二、挖矿设备
CPU -> GPU -> ASIC 芯片
由通用向专用演变
三、矿池
矿池的架构:一个全节点驱动很多的矿机,由一个 pool manager(矿主)和众多的 miner(矿工)组成
矿池的收益分配:pool manager 通过收取部分的区块奖励或者手续费获得收益。miner 依旧利用工作量证明分配收益,pool manager 会降低挖矿难度,例如:原来需要计算所得的哈希值前 70 位为 0,现在只需要计算所得的前 60 为 0 即可。这些挖出来却不合法的区块被称为 almost valid block,miner 把这些区块提交给 pool manager,pool manager 会记录这些区块,做为各个 miner 的工作量证明,直到有 miner 挖到合法的区块获得区块奖励后,再按照之前个 miner 提交的 almost valid block 的数量分配奖励
比特币分叉
硬分叉与软分叉
hard fork:协议发生变化,无法向前兼容(即旧节点不认可新节点产生的区块,但新节点认可就节点产生的区块),且大部分节点(这个大部分指的是算力,而不是节点数量)升级到新节点,此时将会导致硬分叉的出现。例如:原来 BTC 规定一个区块大小上限为 1MB,但是新的 BTC 协议将区块大小上限修改为 4 MB,此时旧节点将无法沿着新节点的区块继续往后挖,它们只能沿着最后一块大小为 1MB 的区块往后挖。即便新节点区块所在的链上出现了小于 1MB 的区块,旧节点也不会沿着个该区块挖,因为该链上存在不符合旧协议的区块,旧节点认定该链为非法链
soft fork:协议发生变化,但向前兼容(即旧节点认可新节点产生的区块,但新节点不认可旧节点产生的区块),且大部分节点升级到新节点,导致出现软分叉。例如:原来 BTC 规定一个区块大小上限为 1MB,但是新的 BTC 协议将区块大小上限修改为 0.5 MB,因为新节点算力较强,所以旧节点会沿着新节点挖出的区块继续挖,但是新节点不认可旧节点挖出的区块,会沿着该链最后一块大小为 0.5MB 的区块往后挖,这就导致了旧节点挖出的区块一直会被认定为非法区块,倒逼旧节点更新协议
比特币的匿名性
其实比特币的匿名性并没有那么好,有以下两种情况会破坏比特币的匿名性:
1. 不同地址账户可以通过交易被关联起来
2. 在现实生活中使用比特币,可以将地址账户和人相关联
零知识证明:指一方(证明者)向另一方(验证者)证明一个陈述是正确的,而无需透露除该陈述是正确的外的任何信息。
同态隐藏:
· 如果 x,y 不同,那么它们的加密函数值 E(x) 和 E(y) 也不相同
· 给定 E(x) 的值,很难反推出 x 的值
· 给定 E(x) 和 E(y) 的值,可以很容易的计算出某些关于 x,y的加密函数值
- 同态加法:通过 E(x) 和 E(y) 计算出 E(x+y) 的值
- 同态乘法:通过 E(x) 和 E(y) 计算出 E(xy) 的值
- 扩展到多项式
盲签方法
· 用户 A 提供 SerialNum,银行在不知道 SerialNum 的情况下返回签名 Token,减少 A 的存款
· 用户 A 把 SerialNum 和 Token 交给 B 完成交易
· 用户 B 拿 SerialNum 和 Token 给银行验证,银行验证通过,增加 B 的存款
· 银行无法把 A 和 B 联系起来
· 中心化