北大肖臻《区块链技术与应用》学习笔记
区块链学习笔记这是关于北京大学肖臻老师的《区块链技术与应用》课程的学习笔记。
区块链学习笔记\huge{区块链学习笔记}区块链学习笔记
这是关于北京大学肖臻老师的《区块链技术与应用》课程的学习笔记。
BTC
BTC的数据结构
Hash Pointers:既保存结构体的对应地址位置(指针),又保存结构体对应映射的hash值(hash)。
❗区块链:本质就是一个一个区块组成的链表。
Block chain is a linked list using hash pointers.
后区块的hash pointer存放的是前区块的地址以及hash值。
对于一个区块的hash是连同这个块中所有的内容\red{连同这个块中所有的内容}连同这个块中所有的内容来取hash值的。
Tamper-evident Log:因为区块链中后区块存放着指向前一个区块的指针,如果其中的一个区块发生了变化,那么后续的区块指针都会变化,最终导致最后一个区块的hash pointer发生变化,从而可以侦测数据的变化以及变化的位置。
Merkel tree(默克尔树):相对于binary tree来讲,使用了哈希指针来代替了普通的指针\red{使用了哈希指针来代替了普通的指针}使用了哈希指针来代替了普通的指针。

树顶的块拥有根哈希值(对于根节点取hash得到的值)
对于Merkel tree树上任何一个节点的修改,都能通过根hash值的改变来检索节点修改的位置。
Block Header:存放hash值,但是不保存交易的具体信息。
Block Body:保存交易的具体信息。
❗头不保存交易信息,但是体保存具体的交易信息。
Merkel proof:
对于区块来讲,整个区块链的形态是链表形态\red{整个区块链的形态是链表形态}整个区块链的形态是链表形态。每个区块中有一个Merkel Root,用于指向这个区块中存放各个交易的默克尔树,也就是说区块中的交易是以二叉树的形式组织的\red{区块中的交易是以二叉树的形式组织的}区块中的交易是以二叉树的形式组织的。
⭕如何判断一个交易是否发生在一个默克尔树中?
树中最低层的叶子节点表示一个交易\red{交易}交易。双亲节点中存储孩子节点的hash值组合,然后逐级向上寻找节点,最后找到根节点,然后比较接收的Merkel proof中存储的信息与最终找到的信息是否一致,如果一致就说明这个交易就是发生在这个区块中。
Collision resistance
proof of membership:O(logn)复杂度
proof of non-membership:O(n)复杂度
sorted Merkel tree:排序方便查询节点。
小细节:
对于普通的指针,上述结构是成立的,但是对于哈希指针就不成立,因为hash指针中的hash要根据指向的块的信息来确定,使用hash pointer构建上述结构出现循环依赖。
BTC的协议
数字货币与纸质货币最大的区别:唯一性\red{唯一性}唯一性
Double Spending Attack:双花攻击,如何保证在数字货币易复制的前提下,保证每个货币的唯一性?
数字货币要解决的中心问题:(去中心化\red{去中心化}去中心化)
①. 数字货币的发行问题
②. 如何验证交易的正确性(防范双花攻击)
中心化系统→去中心化职能分担区块链中心化系统\xrightarrow[]{\red{去中心化职能分担}}区块链中心化系统去中心化职能分担区块链
小型区块链结构示意图:
❗私钥签名,公钥验证\red{私钥签名,公钥验证}私钥签名,公钥验证
输入部分:A的公钥与币的来源
输出部分:收款人公钥的hash
币的来源:证明交易的合法性与防范双花攻击。
所以对于BTC的交易,必须证明交易货币的合法来源地址。
❗BTC的交易流程
①. A向B转账(交易发起)
A需要知道B的地址(B的公钥哈希),然后A用自己的私钥对于这个交易进行签名,证明交易的确是由A发起,并且交易内容没有被篡改。
②. 节点验证交易
所有节点需要知道A的公钥,使用A的公钥来验证之前签名的交易是否有效,是不是真的是由A发起的。
③. 接收方接收资金
B(接收方)的地址本质是公钥的哈希,解锁的时候B会提供自己的公钥和签名(证明地址是自己的),然后节点验证B的公钥哈希是否与交易中标名的接收方地址相匹配。
❗区块链中的交易是不需要加密的\red{区块链中的交易是不需要加密的}区块链中的交易是不需要加密的
首先区块链设计的时候就是要公开交易,其次对于每一桩交易,都会有双方提供私钥签名,确保交易双方不可伪造交易、不可以篡改交易。
Block Header
一般包含区块链比较宏观的信息
Version:协议版本信息
Hash of Previous Block Header:前一个区块的hash值,这个hash值是由前一个区块所有的内容确定的。
Merkel root hash:保存这个区块对应的保存交易的默克尔树的根hash值。用于快速验证交易是否存在于区块中、保证数据无法篡改、优化数据的存储等…
Target:解决问题时答案所需要落入的区间阈值(后续挖矿用)
Nonce:出块时的随机数
Block Body
Transaction List:交易列表
Full Node:全节点,保存着区块链中所有的信息,用于验证交易的合法性、执行共识机制。
为什么需要全节点?
①. 维护去中心化
多数的全节点分散在世界各地,防止少数用户的恶意操作。
②. 抵抗51%攻击\red{抵抗51\%攻击}抵抗51%攻击
即使是攻击者能够控制多数的算力,全节点也有权拒绝恶意节点的交易服务。
③. 隐私保护
轻节点查询交易数据的时候可能会暴露自己的地址,但是全节点可以进行自行验证,无需向其他节点发送信息。
Light Node:轻节点,仅保存block header等少量的数据,不下载完整的区块链信息,无法独立交易交易的合法性,需要依赖于全节点,轻量化、资源占有量极低。能够快速同步信息。
Distributed Consensus 分布式共识
Distributed Hash Table:分布式哈希表
❗什么是共识?
共识是指在某个群体或者是系统中,成员通过协商、讨论某种机制达成一致意见或者是共同认可的状态\red{成员通过协商、讨论某种机制达成一致意见或者是共同认可的状态}成员通过协商、讨论某种机制达成一致意见或者是共同认可的状态。
🔥BTC中需要解决的核心问题是:
在无中心权威\red{无中心权威}无中心权威的情况下,所有节点如何对于交易顺序与账本状态达成一致\red{一致}一致?
FLP impossibility result:如果整个异步系统没有通信速率的上限,那么即使系统中仅有一个成员处于fault状态,那么整个系统中也不能存在共识。
CAP Theorem:下面的三个性质在一个分布式系统中最多只能满足两个条件,不能同时满足三个。
C:Consistency 一致性
A:Availability 可用性
P:Partition Tolerance 分区一致性
Paxos:分布式系统中如果系统到达了共识,那么这个共识必然是唯一的(但是该协议可能会导致整个系统无法达成共识)。
Consensus in BitCoin 比特币中的共识协议
(假设多数成员是好意的)
基于投票\blue{投票}投票的解决方案:关键是投票人员的投票权\red{投票权}投票权。
Sybil attack:使用性能强大的计算机来注册大量用户,从而操作系统中的投票结果。
区块链中记账权\red{记账权}记账权的分配:
记账权分配:记账权的分配本质是通过共识机制决定的一个数学过程。
以下为PoW机制(proof of work工作量证明)的核心规则。
H(BlockHeader)<=targetH(Block Header) <= targetH(BlockHeader)<=target
保证块头信息的hash处于目标阈值内,就视为能够分配记账权。
此处的记账,实际是系统中的用户进行记账,例如矿工、验证者(以太坊)。
🔥记账权的技术\blue{技术}技术本质
Target(目标值):简单来说就是挖出的nonce符合条件的阈值范围,越小说明挖矿难度越高。由全网的算力进行动态调整,目的是控制出块的速度。
哈希竞争:本质是寻找一个随机数(Nonce),使得区块头的哈希值落在目标范围中(哈希碰撞)
记账权的分配会直接影响整个区块链的抗攻击能力(51%攻击),也会影响整个系统的去中心化程度。
🔥记账权分配流程(非常重要)\red{🔥记账权分配流程(非常重要)}🔥记账权分配流程(非常重要)
- 交易收集与验证:收集未确认的交易到内存池,并且验证交易的合法性。
- 构建候选区块:矿工从内存池中选择交易,组装新的区块。
- 计算区块的哈希(挖矿竞争)
①. 不断调整Nonce,计算块头的哈希(❗注意这个验证调整过程只能是反复修改值代入尝试,没有其他的捷径)
②. 找到了符合条件的Nonce之后,向着全体广播 - 全网验证与共识:其他节点收到新区块后,验证区块是否符合条件与区块上交易的合法性。若验证通过,则将该区块加入到本地链上,然后继续挖矿。
- 记账权确认:最长合法链原则。挖出合法区块的矿工获得出块奖励和区块内所有交易的手续费总和。
- 挖矿难度调整:通过调整target,调整出块时间(BTC的出块时间一般在10分钟左右)。Target越小出块难度越大。
⭕最长合法链(Longest Valid Chain)
最长合法链:区块链中的核心规则,用于在分布式网络中确定唯一被认可的主链,确保所有节点对于账本状态达成一致,是BTC、ETH等区块链系统的底层共识机制\red{底层共识机制}底层共识机制。
最长链规则的作用
①.让所有的节点自动收敛到同一条链,避免永久性分裂。
②. 通过工作量证明(PoW)或者是权益证明(PoS)确保攻击者难以篡改历史记录。
❗BTC的最长合法链防御机制
①. 最长链规则:节点默认选择累计工作量最大的合法链作为主链接。
②. 确认数保护:BTC交易之后6\blue{6}6个区块确认后视视为不可逆,所以攻击者如果想要回滚操作,至少需要快速生成7\blue{7}7个区块(基本不可能)。
③. 节点广播验证:诚实节点会拒绝非法的区块,使得攻击者对于合法链接的攻击没有办法被全网接受。
比特币中新增的区块应当连接至最长合法链之后。
上述图中的新增分支是一种分叉攻击(forking attack),试图回滚已经发生了的交易。
分叉攻击本质:
构造一条更长的竞争链,撤销已经确认的交易(双花攻击)\red{构造一条更长的竞争链,撤销已经确认的交易(双花攻击)}构造一条更长的竞争链,撤销已经确认的交易(双花攻击)
攻击者在PoW机制之下需要掌握51%51\%51%以上的算力才能够实现。
当一个区块节点后接节点发生分叉的时候,就会出现如下的情况:
这种情况会保持一段时间,直到下一个区块进行链接的时候:
假设下一个区块连接到了上方的区块,此时上方的链就变成了当前的最长合法链,下方分叉处单独的区块自然就是非法的了。
孤块(Orphan Block):不在最长链上的块。
区块合法性的核心条件
一个区块是否合法,不在于它本身的内容,而在于它当前是不是被纳入了最长的合法链中。纳入了就是合法的区块,没有纳入就是孤块。
❗孤块处理方式
孤块最终状态既不是“作废”,也不是立刻“回滚”。
孤块中的交易处于静默状态,但是仍然存在于全网的内存池中,如果未来的某时这些孤块被矿工重新纳入到最长合法链中,通过确认之后,这些交易就又生效了。
❗交易的生命周期
- 初次广播:用户发起交易,全网的节点接收这个交易并且把交易存储到内存池中。
- 首次打包:矿工将交易打包到区块中。
- 分叉发生:如果发生分叉的话,孤块会被抛弃。
- 交易重新进入内存池:某时刻孤块所在的链成为了最新的最长合法链,那么孤块中的交易重新返回内存池(活动状态),如果交易是合法的,那么就会重新快速打包到新的区块中。
🔥例外
如果孤块中的交易与主链中某笔交易冲突(例如双花攻击),那么孤块中的交易会被永久作废、永久无效化\red{永久作废、永久无效化}永久作废、永久无效化。
Block Reward 出块奖励
区块奖励:矿工获得新BTC的唯一方式\red{获得新BTC的唯一方式}获得新BTC的唯一方式,也是BTC货币发行的核心机制。区块奖励的设计直接影响BTC的通胀率和稀缺性。
区块奖励组成
- Coinbase奖励:每个区块会生成全新\red{全新}全新的BTC,这是BTC总量增加的唯一方式。
- transaction fees:区块内包含的交易需要支付手续费,这部分费用也归挖出该区块的矿工所有。
关键点:
总量恒定:BTC最大的供应量就是2100万枚,无法增发。
通缩模型:每过四年新币产出的速度就会减半,最终新币的产出会趋近于0。
🔥据估计,大约2140年以后,矿工的收入就只能完全依赖于交易的手续费了,不会在产生新币了。
⭕Halving区块奖励减半机制
50BTC→25BTC→12.5BTC50BTC\xrightarrow[]{}25BTC\xrightarrow[]{}12.5BTC50BTC25BTC12.5BTC
随着时间的推移,挖掘一个区块获得的比特币数量,开始减少,但是单位比特币所相当的价值逐渐飞跃。减半机制确保BTC的稀缺性,遏制通货膨胀。
此图中下方的块就已经是无效块了,那么他其中所保存的BTC也就无效了,因为BTC交易的时候会查询的是区块链中最长合法链中BTC数据(上面一条链),如上面所言,只是无效了不是作废了,只有恶意攻击的区块上的交易才会作废。
❗❗比特币的共识机制本质是算力投票。
BTC的核心共识机制是通过算力竞争决定记账权,确保去中心化账本的一致性。
🔥算力即投票权,最长合法链即共识结果\red{🔥算力即投票权,最长合法链即共识结果}🔥算力即投票权,最长合法链即共识结果
比特币中要取得的共识是去中心化账本中的数据,但是只有系统中具有记账权的区块才能够获得数据,所以大家需要获得记账权力。记账权力的分配就是通过:
H(blockheader)<=targetH(block header) <= targetH(blockheader)<=target
解决这个问题,使得结果在阈值内来获得的。
但是上述这个问题根据puzzle friendly特性,必然是需要通过大量数据验证(没有捷径)来进行操作的,所以从根上面来讲计算速度越高,获得记账权的概率就越大。这就是比特币共识机制是算力主导的本质。
Puzzle—Friendly特性与算力主导
Puzzle−Friendly\red{Puzzle-Friendly}Puzzle−Friendly:
**不可预测:**对于Nonce的选取,只能是暴力测试。
**难度可调:**调整target就是在调整难度
算力即权力
没有算力就无法参加记账,算力越强,话语权就越大。\blue{没有算力就无法参加记账,算力越强,话语权就越大。}没有算力就无法参加记账,算力越强,话语权就越大。
比特币争夺记账权的过程就是挖矿(mining)。
争夺记账权的节点成为矿工(miner)。
挖矿(Mining)的本质
通过算力竞争获取记账权的过程。
BTC的基本实现
transaction-based ledger:基于交易驱动的账本模型。
UTXO交易模型\red{UTXO交易模型}UTXO交易模型
UTXO:Unspent Transaction Output 未花费交易输出。
比特币账户不记录账户的余额,而是通过链上交易的输入输出追踪资金的流向。
规则
- 每笔交易的输入必须来自之前交易的UTXO。
- 每笔交易的输出成为新的UTXO。
- 交易的有效条件:

TotalInputs>=TotalOutputsTotalInputs >= Total OutputsTotalInputs>=TotalOutputs
两者中间的差额是矿工的的交易费
Transaction Fee 交易手续费
**作用:**激励矿工,高手续费的交易优先打包,防止网络资源滥用。
交易的手续费越高,确认的速度就越快。
**极端情况:**随着时间推移,BTC的价值不断递减,有可能出现一笔交易的手续费大于交易金额。
挖矿过程的概率分析
Bernoulli trial:a random experiment with binary outcome 单次随机的(等概率)并且仅有两种结果的实验。
Bernoulli process:a sequence of independent Bernoulli trials 一组无关联的伯努利实验组合。
Memoryless:无记忆性,每次实验都是独立的,当次实验结果不会影响下次实验的结果。
如果实验的次数比较多(n大),并且实验成功的概率比较小(p小),那么伯努利实验可以通过泊松实验(Poisson process)来进行近似。
上图中数轴代表的是概率密度,横轴代表出块时间,类似指数分布。
每次出块的概率都是相同的,与之前的实验没有任何的关系。(progress free:这个性质保证了挖矿的公平性)挖矿的时候就只是存在单次算力的差距,而不存在出块概率的差距。
geometric series BTC的数量
21万×50+21万×25+21万×12.5+...=21万∗(1+12+14....)(几何级数)=2100万21万\times50 + 21万\times25 + 21万\times12.5 + ... = 21万\ast(1 + \frac{1}{2}+\frac{1}{4}....)(几何级数) = 2100万21万×50+21万×25+21万×12.5+...=21万∗(1+21+41....)(几何级数)=2100万
对的,整个系统中BTC的数量是确定的,包括已经挖出和未被挖出的,总量就是2100万\blue{2100万}2100万。
Bitcon is secured by mining.
挖矿的背后就是算力的比拼,只要系统中多数的节点正常运行争夺记账权,那么整个系统的安全性就不会发生重大问题(共识机制),所以单说挖矿只是纯粹的算力,但是对于BTC系统来讲挖矿能够保证系统的安全性。
恶意节点掌握记账权的情况
分叉攻击
通俗来讲就是通过回滚已经上链的交易,使得BTC网络认为这个交易没有发生,从而既获得商品,又拿到比特币。

此时两个链都是登场的合法链
M→AM→AM→A是M向着A进行转账,M→M‘M→M‘M→M‘是M向着自己进行转账,设定一个背景,当M从A购买东西的时候,M向A转账,A将物品交易给M,整个过程写入到了M→AM→AM→A,并且加入到链中,表示当前的交易已经进行了记录。
但是如果M向着自己发起转账,并且算力够强的情况下额外增加节点,将下面强行变成当前系统中的最长合法链,那么后续读取记录的时候M→AM→AM→A此纪录相当于没发生,M既获得了物品,又通过回滚的方式获得了货币。
攻击成功条件
5151%51算力:攻击者必须控制全网多数的算力
快速生成区块:能够快速改变最长合法链。
交易冲突:
即回滚的时候必须是自己转账给自己\red{即回滚的时候必须是自己转账给自己}即回滚的时候必须是自己转账给自己。
防御措施
通俗一点来讲就是多等几个confirmation,使得上面的链一定是最长合法链的时候才会视为当前的交易是完成的不可篡改的交易。
上图中等待了后续六个节点才看作M→AM→AM→A这个交易的完成,这样再次发生分叉攻击变换最长合法链的时候就变得非常的困难。
irrevocable ledger:不可篡改性\red{不可篡改性}不可篡改性
区块链是一个不可篡改的分布式账本,此处的不可篡改是在概率方面进行说明的,新加入的节点相对来说是比较容易篡改的,但是旧节点相对于新节点来说,篡改难度是指数倍数的增加,所以是“不可篡改”的。
zero confirmation:零确认交易。表面是区块链无需后续多个confirmation,实际上交易中已经保证了后续有了等待的时间。
selfish mining(挖出而不发)
在具有强大算力的支撑之下,如果已经挖出了几个块,但是不将这些块进行上链,等待好的时机的时候将所有的块都上链,这样也能操作最长合法链的判定。
当其他用户挖取上方的块时,如果有用户已经挖取了多个块,并且发出,那么不但上方的用户做了半天的无用功(进度全部作废),下方的用户能够一次性获取多个块的奖励(selfish)。
BTC网络工作原理
application layer:BitCoin Block chain 应用层
network layer:P2P Overlay Network P2P覆盖网络
比特币的P2P网络,是一种全分布式对等网络,无中心服务器所有的节点都是平权的\red{所有的节点都是平权的}所有的节点都是平权的,必须有一个种子节点(seed node),可以寻找到其他的节点,并且各个节点之间的通信是通过TCP来通信的,有利于穿透防火墙。
比特币网络的设计原则
❗simple,robust,but not efficient
比特币网络最注重的是简易与安全,效率情况可以往后放放。
节点类型
- 全节点Full Node:存储完整的区块链数据,能够独立验证所有的交易与区块。

- 轻节点SPV:仅存放区块头,验证交易的时候依赖于全节点,轻量化、资源损耗低。

- 矿工节点(Miner):是全节点的一部分,拥有参与挖矿竞争的职能。
节点通信
每个节点维护一个邻居节点的集合,使用floading的方式来进行集合之间的交流。
floading:节点需要转发信息的时候就会向着所有的邻居节点进行数据转发,等到信息转发到了目的地的时候,记录路径信息,下次转发的时候就无需再次全部转发信息了。
挖矿难度
H(BlockHeader)<=targetH(BlockHeader) <=targetH(BlockHeader)<=target
调整挖矿难度就是调整target\red{调整挖矿难度就是调整target}调整挖矿难度就是调整target。
比特币所用的哈希算法是SHA-256,产生的结果有22562^{256}2256,既256位01序列。
difficulty=difficulty_1_targettargetdifficulty = \frac{difficulty\_1\_target}{target}difficulty=targetdifficulty_1_target
difficulty_1_target:是指难度为1的时候对应的目标阈值。
从上述公式可以知道挖矿的困难程度与目标阈值是成反比,目标阈值越大,最后算得的hash结果就约有可能落在阈值区间中,自然挖矿难度就是越小。
❓为什么要调整difficulty?
全网的算力增加会显著增加挖矿的速度,如果挖矿的难度保持不变,那么整个系统中区块增加的速度就会非常的块,此时如果有用户的算力显著高于其他用户的话,那么他就可以添加大量节点来操纵最长合法链的选取(51%attack51\%attack51%attack)。同时恶意用户也可以通过自己增加区块来分散其他人的算力,这样之后操作最长合法链选取的时候甚至都不需要51%51\%51%的占比了(恶性循环)。
所以出块速度不是越快越好。
以太坊的出块速度大概是15s左右,是BTC的40倍,需要新的共识协议来解决上述高速出块所带来的问题(ghost)
系统大约每2016\blue{2016}2016个块就要调整一次难度,大约是两星期。
tartget=target×actualTimeexpectedTimetartget = target ×\frac{actualTime}{expectedTime}tartget=target×expectedTimeactualTime
actualTimeactualTimeactualTime:最近2016个区块出现的实际时间
expectedTimeexpectedTimeexpectedTime:期望的2016个区块出现的时间
💻难度的动态调整:
如果实际时间增大,那么说明难度过高需要降低难度,此时比值大于1,会增大target从而降低难度。实际时间减少的时候情况会相反。
⭕决定沿着哪条链挖下去?
最长合法链
⭕当出现等长的分叉的时候,选择哪一个分叉呢?
选择最先被监听到的分叉块
⚪挖矿的安全性保证
①. 密码学原理的保证:只要其他用户没有你的私钥,就没有办法伪造你的签名,从而无法操作你的个人数据。
哈希函数的不可逆性。
②. 共识机制的保证:多数用户是正常用户,能够保证整个系统是稳定的。
挖矿操作
CPU:通用计算
GPU:通用并行计算
ASIC:专门用来挖矿的芯片,并且不同的芯片可能只适配一种加密货币的挖取(会随着时间的推移而淘汰)。
mining puzzle:挖矿问题
merge mining:其他加密货币的挖取方式使用与BTC一样的puzzle来吸引用户挖取的情况。
alternative mining puzzle:抗芯片化,让通用的计算机也能够挖矿,而不是仅仅使用了专门芯片的计算机。
矿池
算力更加集中,个人收益提高
pool manager:矿主,监听网上的交易,并把交易进行组织打包(完成全节点的智能)
miner:矿工,只能进行算数运算(挖矿)
矿主负责将任务分配给各位矿工,矿工接收到任务之后进行计算,计算完成之后将结果返回给矿主,出现出块奖励之后,矿工和矿主根据相应的比率进行收益。根据不同矿工的工作量来进行收益分红。
每个矿工进行挖掘的时候,将不合法的区块(无效)提交给矿主,矿主对于每个矿工都单独记录其提交的不合法区块当作工作量,之后出现出块奖励的时候,奖励分红就按照工作量的高低进行分红。
潜在危害
同时矿池将算力集中,并且由于矿主可以向大量矿工发布任务,于是矿主就能调动大量的算力来发动51%51\%51%攻击,通过操纵最长合法链的选择来消除其他用户的交易(分叉 + 多块链接 强行改变最长合法链)
矿池存在有利有弊\red{矿池存在有利有弊}矿池存在有利有弊
BTC脚本语言信息(待重听)

locktime:用来交易的交易时间(n个区块之后才进行交易)


B→CB→CB→C vin中的vout表明的是B向C交易中货币的来源是A→BA→BA→B处获得的(指针)。
脚本执行的时候是先进行后面的输入脚本,然后进行前面的输出脚本。如果新交易有多个输入输出脚本,所有的输入与输出脚本都一一对应,所有的匹配都成功了,这才算是验证了新交易的合法性。
P2PK (Pay to Public Key)
输出脚本中直接给出收款人的公钥。
P2PKH(Pay to Public Key Hash)
输出脚本中给出的是收款人的hash。
P2SH(Pay to Script Hash)
输出脚本中给出的是收款人一个脚本的hash
BTC的分叉(fork)
state fork:对区块链当前意见分歧的分叉
forking attack:分叉攻击(deliberate fork)
protocol fork:协议分歧,分布式系统中很难做到所有子系统的版本同时迭代,可能会有不同子系统之间协议版本号不兼容的问题。
硬分叉(hard fork)
对比特币协议进行更改,旧节点版本更新不及时,会产生意见分叉。
block size limit:块大小限制
大约的区块系统每秒处理的交易量(很小)
当系统的版本更新之后new nodes 4M→1M4M→1M4M→1M,块的大小发生变化之后,旧的没有更新的节点就会发生硬分叉。
新的挖出的大的节点块链接到上方,旧的挖出的小的节点块连接到下方。并且之后的新块都会连接到上方,旧的节点都会连接到下方(两种节点都会判断自己认为的最长合法链从而一直分叉下去),这种分叉是永久的。出现了两条平行运行的链,有两种加密货币。
使用chain ID,来区分分离出来的两条链,使得两条链的交易完全独立,消去了原来从一个节点分离出来产生的耦合性。
软分叉(soft fork)
对于现有的比特币协议进行条件的增加或者是更改,导致已有的区块的交易从合法状态变为不合法状态。
❗对于去中心化系统数据的更改,是非常困难的,因为很难做到系统中所有成员的数据都同步更改,所以数据更改时可能会出现软分叉或者是硬分叉。
block size limit:1M→0.5M1M→0.5M1M→0.5M

⭕分叉前,链一直延申,分叉后旧的节点(大)在下方,新的节点在上方。之后新节点挖取的时候不承认旧的节点,于是链开始向上延申,但是旧的节点承认新的节点,于是挖出的旧块也会向上延申。之后再次分叉的时候又会发生同样的情况。这种分叉会导致最长合法链始终在新块的链上,从而使得挖出的旧块大部分是无效的。但是软分叉始终会保持一条最长合法链,不会像硬分叉那样进行永久的分叉。
coinbase:作为extra nonce,将coin base的前八个字节添加到nonce域当中,延长搜索的空间。
P2SH:Pay to Script Hash 支付的时候支付给一个赎回脚本(redeem Script)的hash。
课堂精华问题回答
①. 在区块链中进行转账交易的时候,如果被转账方没有在线的话,会发生什么?
答:什么都不会发生,交易的时候只会把交易的结果上链记录,与被转账方在线情况无关。
②. BTC转账的时候,有没有可能转给一个地址从来都没有见到过的用户?
答:当然可能,因为BTC账户创建的时候,不会广播,只会在本地产生第一个公私钥对,只有当这个新账户进行交易的时候,其他账户才会察觉这个新账户的存在。
③. 账户私钥丢失了怎么办?
答:私钥丢失后,账户的钱就变成“死钱”了,因为在去中心化的系统中,很难为一个用户恢复私钥。所谓的交易所(银行)其实是中心化的机构,在用户创建账户的时候会收集并保存用户的身份信息,当然交易所也可以保存用户的私钥,等到你忘记了你的私钥,可以凭借着身份验证从机构中拿出给你保存好的私钥(本质上私钥没有丢失,只是有人给你保存)。
❗虚拟货币的交易所目前没有监管机构,不能说十分的安全。
④. 账户的私钥泄露怎么办?
答:迅速将账户上的货币转到一个安全的账户上。
⑤. 转账时地址写错了怎么办?
答:没有任何办法,BTC不支持取消进行了的交易。
⑥. 如何知晓挖矿时一个有效结果是由哪位矿工得出的?
答:coinbase tx中保存了收款地址的信息,如果需要更改收款地址的话,连同交易的Merkel tree的根hash也会改变,这笔交易就作废了(牵一发动全身)。根本不存在挖矿时偷答案的情况。
BTC的匿名性 Bitcoin and anonymity
pseudoymity:BTC更多的是一种化名匿名性。
unnamed lake:未名湖(😀)
以太坊
以太坊与BTC的差别概述
以太坊的出块时间大幅度减少,为了匹配极短的出块时间,以太坊使用了基于ghost协议的共识机制。
BTC的mining puzzle是单独的算力比拼,会导致设备的专业化,违背了去中心化的初心。
以太坊更多的是对于memory hard存储空间的要求,推崇ASIC resistance。
BTC使用的是proof of work工作量证明,但是以太坊使用的是proof of stake 权益性证明,类似股票机制。
smart contract
BitCoin:decentralized currency
Ethereum:decentralized contract 智能合约
BTC最小计量单位:Satoshi 一聪
ETH最小计量单位:Wei 一伟
货币是由政府发行的,货币的价值是由政府的公信力所保证的。现实合约的有效性通过司法进行权益保证。智能合约是将合同翻译为代码,将代码上链,利用区块链的不可篡改性保证智能合约的履行有效性。
去中心化货币优势:跨国转账等…
智能合约优势:在跨国合作中不同的司法管辖权会带来合约履行的困难,但是智能合约可以使用代码程序强制同一各种操作,很大程度减少了合同参与方的违约情况。
以太坊账户模型
BTC是基于交易的账本,系统中不会显式记录账户的资产,只能通过交易信息字段进行推算,使用体验不是很好。
A向B转了10个BTC,B向C转3个BTC之前必须知道B中BTC来源于之前哪个交易,合法才能进行转账。并且转账的时候,B的10个BTC必须全部转出去,转给其他账户也好,转给B的另一个个人账户也好,总之不能留下。因为BTC系统的维护不是基于显式的账户模式。
❗但是以太坊是基于账户的模型进行资产保管。(account-based ledger)
以太坊背景下,A向B转账无需知道A中ETH的来源,并且以太坊类似现实中的银行账户,有余额的概念,所以不必将所有的ETH都转移。
以太坊系统天然能够抵抗双花攻击,每次交易后只需要对于特定的接收人与发送人进行账户资产修改即可。
replay attack
A→B(10ETH)A→B(10ETH)A→B(10ETH)
重放攻击:正常交易中A向B转账后,广播交易的结果,区块链中节点接收到后更新账户信息。但是如果B再次广播了交易的结果,那么交易信息又会更新,A的账户转账了两次。
解决方法:记录账户的交易次数
**nonce:**账户的交易次数,此字段作为交易信息交换中的一部分,并且nonce被私有签名保护。nonce随着交易进行自动增加。
externally owned account:外部账户,本地产生一个公钥私钥序对,只要掌握了私钥就掌握了这个账户。
组成:balance,nonce
smart contract account:合约账户,一个合约可以调取另外一个合约。
组成:nonce,code,storage
但但是所有交易的发起必须由外部账户进行,合约账户只能是交易发起之后,传递信息进行调用,不能够发起交易。
以太坊创始人:Vitalik
以太坊的状态树
需要完成的功能:账户地址到账户状态的一个映射。
要证明账户的余额,就把整个账户的信息组成一个Merkel tree,只要Merkel proof没有改变,说明账户的信息是安全的。
将hash表中的内容组织成一个Merkel tree,也可以查询信息有没有被修改。但是新增加区块的时候会改变hash表中的内容了,于是之前的Merkel tree就作废了,这种方法的更新代价太大。
如果放弃了hash,直接使用Merkel tree组织所有的信息,这个方法如何?
也不是很好,Merkel tree本身没有很高效的查找与更新算法,效率不行。并且要不要对于不同Merkel tree进行排序?要证明一个交易在Merkel tree上很简单,但是如果要证明一个交易不在Merkel tree就会非常困难。而且如果树中叶子节点所包含的值不按照同一的标准进行排序的话,生成的Merkel tree不是唯一的,后续会产生很大的麻烦。
sorted Merkel tree
trie:字典树
branching factor
Trie的特征:
优点\red{优点}优点
①.trie的查找效率取决于查找信息的长度。
②. BTC与以太坊的地址不通用,但是大体结构与hash计算的方法是一致的。
③. Trie的数据结构决定了,不同的数据信息必定最后存储在不同的叶子节点,查询时不会发生碰撞。
④. 对于给定的信息,无论按照什么顺序输入,最后构成的Trie必然是一致的。
⑤. 更新局部性:对于信息的部分更新,是否会影响到其他的信息。Tire的更新局部性非常好,访问更新一个信息不会影响到其他的信息。
缺点\blue{缺点}缺点
常规的Trie对于存储空间有很大的浪费。
Patricia Tree:路径压缩Trie,可以大幅度减少存储空间的浪费。
压缩空间之后的Trie,树高明显变低,查询存储效率都会增加。

这是正常的Trie,因为三个单词之间字母分布比较杂乱,导致最后形成的Trie基本退化成了线性了,效率很低。
但是路径压缩之后的Trie:
效率变得非常的高,所以说路径压缩非常适合键值稀疏的数据存储情况。
以太坊地址大小:21602^{160}2160
增加地址的安全性,防止查询信息时候的碰撞。
MPT:Merkel Patricia Tree
modified MPT

MPT不但要保存现有的状态,并且需要保留MPT历史信息,便于状态的回滚。
在以太坊高速出块的现状下,系统中的区块分叉是非常常见的,这是就需要对于一些分叉后无效的交易进行roll back回滚。
块头的数据结构字段:
交易树和收据树
**交易树:**每次交易提出之后,都会将很多交易组成一个交易树,便于组织管理。
**收据树:**通俗来讲就是保存的是交易的结果。收据树的存在可以方便后序智能合约的实行。
交易树和收据树仅仅保存的是当前进行的交易的信息,但是状态树保存的是交易的当前状态和历史状态(全局)。当新交易发布的时候,修改的信息会组织成一个新的状态树,没有修改的信息就一致沿用之前的状态树存储即可。
每个区块的交易树和收据树都是独立的。
布隆过滤器
bloom filter:快速查找一个信息是否在一个集合中。
简图:
将一个集合中的所有元素取hash值后进行映射,映射到的位置设定为1。最后保存的01序列就是相对于原信息集合的一个摘要。
查询信息的时候,将待查询的信息取hash,然后在摘要中查询,如果地址处的值为0,说明该信息一定不在原集合中。但是如果地址处的值为1,说明该信息可能在集合中。
false positive(假阳性):hash碰撞之后地址的在探测导致一些信息没有存放在取hash之后应该存放的地方,此时其他的信息如果也取hash恰好是当前的地址,就会产生误报的情况。
布隆过滤器只会有false positive,不会有false negative。
删除操作:很遗憾这就是简单的布隆过滤器的局限性,简单布隆过滤器是无法删除元素的。
实例:如何查询一个交易是否在区块中。首先查询保存整个区块的布隆过滤器,看有没有符合的交易类型,如果有的话,那么进入到这个区块中,查询区块下的收据树与交易树的布隆过滤器(false positive)。这可能查不出来结果,但是已经层层筛查出了一些符合条件的节点,此时向全节点所索要更多的匹配信息,在比对就可以了。
以太坊的运行过程可以看作是一个交易驱动的状态机(transaction-driven state machine),状态转移必须是确定的,必须是从一个确定的状态转移到另一个确定的状态,这样才能保证所有交易的正常运行。
以太坊与BTC相同,创建账户的时候不会广播,只有当有对于这个账户的交易的时候才会“察觉”出这个账户的存在。
区块创建函数
Ghost协议
BTC与ETH都是运行在应用层的共识协议,底层就是一个P2P的传输。
BTC:
只有最长合法链上的数据才会被记录成为有效的数据,BTC的出块速度很慢,所以其实这种结构是没有什么大问题的。但是ETH的出块速度非常的快,如果还是采用上述的结构的话,那么对于一个挖出的块,很大的概率是要被废除的,这对于矿工(尤其是个体的矿工)非常的不友好。
试想以下的场景:
上下区块都是个人挖出来的,中间是拥有大量算力的矿池挖出来的。那么如果上下区块想要成为最长合法链,只能寄希望于其他的矿工能够在这链上进行挖掘(因为个人的算力比较小),但是对于新的矿工挖矿来说,没有理由不在算力更强的矿池中进行挖掘。这最后导致的结果就是,当出现分叉的时候,矿池所在的分支成为最长合法链的概率显著增加(mining centralization 挖掘集中)。
centralization bias:愈是算力大的矿池获得的效益是不成比例的增加的。
Ghost协议核心思想
原始协议:对于挖到了无效块的矿工(仅两位)提供相应的安慰,虽然挖出来的区块不是最长合法链上的区块,但是你仍然能够获得大部分的出块奖励。
uncle block:挖出的不是有效的区块。
原始协议的问题:
①. 叔父区块能够获得奖励的前提是新区块加入时发现了叔父区块,并且合并,才可以提供给叔父区块奖励。但是如果新的区块没能发现叔父区块呢?那么叔父区块就不能获得奖励i了,白挖了。
②. 原始协议规定只能包含两个叔父区块,太少了。
③. 出于商业利益,可以故意不接纳叔父区块,来对个人进行排挤。
协议调整优化
产生了叔父区块之后不仅仅只能够是同辈节点包含了,只要是新来的区块都能够包含叔父区块节点。
uncle block:与当前区块在七代以内都有共同的主线。合法的“叔父”只有六个辈分,并且六个辈分根据出块的时间,奖励依次递减。
BTC中的奖励:
block reward:出块奖励,又叫做静态奖励。
tx fee:完成交易的时候获得的奖励,又叫做动态奖励。
ETH中的奖励:
block reward:同样的出块奖励。
gas fee:履行系统中智能合约获得的奖励。
以太坊中没有定期减少货币数量的机制,不会人为制造稀缺性。
发布智能合约的发布者需要支付gas fee,履行相应智能合约的履行者就会获得这部分gas fee。
合并叔父区块的时候是不可以执行叔父区块中包含的交易的。因为叔父中包含的交易可能是于主链中的交易冲突。系统中对于区块的检查,只是检查一个区块是否是叔父区块,但是对有区块中的交易是不做检查的。
合并问题
为什么不能将下链中所有的区块都当作叔父区块进行合并,然后分别发放奖励?
因为这样就会让分叉攻击的效益提升非常明显。
如果分叉攻击成功,那么就可以操作最长合法链。如果分叉攻击不成功,那就合并区块获得奖励,这对于攻击者来说是一种非常好的福利。
❗所以ETH鼓励的是出块之后只有分叉的一个区块能够被成为叔父区块,合并后给予部分出块奖励,后续的分叉长链就都作废了。鼓励出现分叉之后就及时合并。
ETH的挖矿算法
Block chain is secured by mining
bug bounty:悬赏来找软件的漏洞
bounty hunter:赏金猎人
BTC的挖矿算法安全性非常好。
one cpu,one vote
ASIC resistance
memory hard mining puzzle
LiteCoin莱特币
LiteCoin:莱特币
Scrypt:莱特币的puzzlepuzzlepuzzle,是hard memory型puzzle,对于内存的要求很高。
开始的时候给定一个seedseedseed,通过某种运算获得第一个初始值,填到第一个位置上。之后对于后续的模块中值,每个值都是前一个模块中值取哈希。当解决puzzle是,首先取出一个位置的值,然后根据相应的算法获得下一个要取值的地址,之后以此类推。因为要实现上述的操作,必然需要存放整个表,不然计算的难度会大幅度上升,这就是为什么这个问题是hard memory类型的。
好处:对于矿工是hard memory问题。
坏处\red{坏处}坏处:对于轻节点也是hard memory 问题。
puzzle设计标准:difficult to solve,but easy to verify
莱特币的出块速度是比特币的四倍。
ETH以太坊

存在一个16MMM的数据集,这个数据集可以生成一个1G1G1G大小的dataset。轻节点只需存储16MMM数据集,矿工存储全部的dataset即可。
数据生成:
Cache中的数据生成与莱特币中的puzzle数据生成大同小异,都是设定一个seed然后经过运算,将结果放在第一个位置。然后整个表按照当前块的值是前一个块的值取hash来填充。
数据集的构建:
(数据集这个数组长度比cache的长度大的多的多)
使用伪随机数确定一个位置,计算值获得下一个位置的地址,以此类推计算256次。将结果值值填充到数据集中第一个数据。后面的数据都是这个方法生成。
Puzzle:使用随机数找到数据集中的一个运算,然后计算找到下一个位置。读取的时候要读取当前位置的元素,也要读取下一个位置的元素(一次读两个),循环64次,一共读出来128个数,然后计算hash值看是否在给定阈值中。
ethash
proof of work → proof of stake
挖矿的算法设计要尽可能让通用的设备也能够参与进来,挖矿的人数越多,决策就越民主,整个系统的稳定性就越好。但是与之而来就是关于系统安全性的问题,因为挖矿的通用性导致很多主机可以被组织起来临时用来挖矿发动攻击。
ETH—难度调整算法
区块难度D(H)



**难度炸弹:**方便实行ETH从工作量证明到权益证明的转换。


权益证明 Proof of Stake
virtual mining:虚拟货币发行的之前会预留一些货币用来分配给开发人员或者是用于出售兑换初始资金。
权益证明共识机制会让用户根据持有货币的数量进行投票。
AltCoin infanticide:将某种虚拟货币扼杀在摇篮中。
❗**权益证明共识机制下,维护系统安全性的所需资源是闭环的。**因为权益证明类似持股投票机制,是按照用户持有币的数量进行的。如果有人想要恶意操纵币价,那就必须将外部资源(现实金钱…)抓换成内部资源(对应虚拟货币),才能够进行下一步操作。但是对于虚拟货币开发者来说,大量收购虚拟货币不一定是一件坏事。
混合共识机制 Proof of Deposit
工作量证明 & 权益证明
出块奖励基于工作量进行发放(工作量证明),但是每次挖矿的难度会随着持币数量上升而下降(权益证明)。
nothing at stake
在权益证明机制之下,可以向着区块链的两端进行投币下注,实际上两端只会有一段成为最长合法链的那一端,但不是最长合法链的那一端投入的币的有效性也完全不受影响。
Casper the Friendly Finality gadget(FFG)
**Validator:**验证者,用户吃成为验证者需要投入资金。验证者的工作是推动整个系统达成共识,投票决定哪条链是最长合法链,按照资金数量多少来进行投票。
two-phase commit:
实际系统中不在区分prepare message和commit message,并且将epoch由100减少到50。当前的epoch对于前一个epoch是commit message,对于后一个epoch是prepare message。
验证者促进系统达成共识会有相应的奖励,如果验证者不作为会扣除一定量的保证经,如果验证者本身怀有恶意,则会扣除全部的保证金。扣除的保证金直接销毁了(以太币总数量下降)。当然其他人也可以监督验证者的行为,进行检举揭发。
相对于工作量证明,权益证明的发展还不是很成熟,没有经过长时间的检验。
DPOS:delegated Proof of Stake 委托权益证明
挖矿是一种将电力资源转换为货币的手段,可以有效化解过剩产能。
智能合约
以太坊的精髓
智能合约的大致代码结构:
solidity:面向对象语言、强类型语言
外部账户如何调用智能合约?
A向B发送请求时,如果B是普通账户,那么这就是一个普通的转账交易。如果B是合约账户,那么A向B的请求本质是A调用B的智能合约。

特别地,一个交易只有外部账户才能够发起,普通的合约账户无法发起。
直接调用方法的错误处理:函数抛出异常,程序停止运行。
使用address类型的call()函数错误处理:函数的返回值为false,但是对于程序本身还是能够运行的。

代理调用:不需要切换到被调用者合约的环境,在当前的环境下运行即可。


GasLimit:这个交易愿意支付的最大汽油费。汽油费支付的时候首先是按照最大汽油费进行支付的,交易完成之后计算实际所需的汽油费,然后退布差值。如果实际所需的汽油费更多的话,则会引起交易的回滚。根据不同的交易计算的复杂度和保存变量的状态的程度,所需的汽油费也会不同。
错误处理
以太坊中的交易具有原子性,只要执行一定是整体执行完毕,一旦中间发生了错误,就会对于整个交易状态进行回滚。
汽油费不足造成的回滚也是一种错误处理,汽油费支付不足的时候,会将整个交易进行回滚,但是提前预支付的汽油费是不退还的,防止有恶意的节点一直发布大量高汽油费花费的交易来浪费系统的算力。
solidity中没有try-catch自定义异常的结果。

❗❗❗智能合约执行过程中,任何对于数据结构的修改都是在本地的数据结构的修改。只有合约执行完毕之后,区块向外发布了,这些数据结构的改变才会被其他块承认,变成共识
假设某个全节点要打包一些信息到区块中,这些信息中包含智能合约的调用,那么这个全节点是先执行智能合约在挖矿,还是先挖矿在执行智能合约?
答:先执行后挖矿,因为必须先执行完所有的交易(包括智能合约的交易),后续才能更新交易树、状态树、收据树的hash值,这三个根hash值确定之后才能确定出Block header的值,最后才能尝试各种nonce进行挖矿。
三个树的字段
汽油费只能给获得记账权,发布区块的矿工。
⭕发生错误的交易有必要发布到区块链上吗?
**发布到区块链上面的交易不一定都是成功执行的。**并且发生错误的交易也要发布到区块链上面,这样才能扣汽油费。
以太坊中智能合约没有办法产生真正意义上的伪随机数,因为如果使用了真正的随机数,每个节点运行结果都不一样,无法产生共识。
智能合约的执行必须是确定性的,这就导致了智能合约程序不能通过系统调用来得到一些系统的环境信息,因为每个智能合约履行的环境不同。所以一个智能合约必须使用一些字段来记录这些系统环境信息。

更多推荐




所有评论(0)