1️⃣ 参考
- 北京大学肖臻老师《区块链技术与应用》
6️⃣ 网络篇
设计原则:简单、鲁棒 simple and robust but not efficient
,尽力而为best off
接收到新交易/区块,随机转给邻近节点验证并记录
比特币系统的工作过程:
用户将交易发布到比特币网络上 ➡️ 节点收到交易后打包到区块中 ➡️ 将区块发布到比特币网络上。
- 工作原理
- 比特币工作在应用层(
application layer: Bitcoin block chain
),其底层是一个网络层(network layer: P2P overlay network
) - 比特币的P2P网络是非常简单的,所有节点都是对等的。不像其他网络存在超级节点(
super node
) - 要加入P2P网络,至少需要知道一个种子节点,然后你和种子节点联系,它会告诉你它所知道的网络中的其他节点,节点之间的通信采用TCP协议,便于穿透防火墙。当节点要离开时不用做任何操作,不用通知其他节点,只需自行退出即可,其他节点在一定时间后没有收到该节点的消息,便会将其删掉。
- 比特币工作在应用层(
- 比特币网络设计原则:简单,鲁棒(最坏情况下能达到最优状况,即健壮性),而不是高效。
- 每个节点维护一个邻居节点的集合,消息传播在网络中采取flooding的方式。节点第一次收到某个消息时,它会把此消息传播给所有邻居节点并标记已经收到过此消息,下次再收到此消息便不会发送出去。
- 邻居节点的选取随机,未考虑网络底层的的拓扑结构。一个在加州的节点,它选取的邻居节点可能是在阿根廷的,这样的设计的好处是增强鲁棒性,但牺牲了网络效率。
比特币系统中,每个节点要维护一个等待上链的交易的集合。第一次听到某个交易,若是合法交易,则将其加入交易集合并转发给邻居节点,以后再收到此交易就不再转发(避免无限传播),假设网络中存在两个有冲突的合法交易,比如说A→B, A→C(花费的是同一笔钱),那么一个节点先收到哪一笔交易,就将哪一笔交易写入交易集合,当收到与其交易集合中冲突的交易时,它就不会接收。
- 此外,当一个区块发布后,每个节点会更新交易集合,删去已经写入区块链的交易,倘若交易集合中包含A→B的交易,而A→C的交易被写入区块链中,那节点也要把A→B的交易删除,因为此交易就变成了非法交易(
double spending
) - 新发布区块在网络上的传播方式与新发布交易的传播方式类似,每个节点除了要检查区块的内容合法性之外,还要检查它是否位于最长合法链上。
- 比特币协议对区块的大小由1M的限制,比特币网络采用的传播方式是非常耗费带宽的,带宽是瓶颈。1M大小的区块,可能需要几十秒才能传输到网络绝大部分节点,所以这个限制其实不算小。
- 区块越大,网络上传播时延越长;区块越小,可包含的交易数目越少
- 注意,比特币网络传播属于 尽力而为(
Best effort
),一个交易发布到比特币网络,不一定所有节点都能收到,也未必收到交易的顺序都一致。有的节点也不一定按比特币协议的要求进行转发(比如不合法交易)
7️⃣ 挖矿难度调整篇
之前有提到比特币系统中,区块链的出块时间保持在平均10min。可见随系统算力的变化,挖矿的难度需要相应调整。
① 挖矿难度调整的原因
挖矿的本质就是不断调整(尝试)nonce
,使block header
的哈希值小于等于目标阈值。 即 H ( b l o c k h e a d e r ) ≤ t a r g e t H(block header) \leq target H(blockheader)≤target(目标阈值),目标阈值越小,挖矿难度越大。调整挖矿的难度就是调整目标空间在整个输出空间中所占的比例。
比特币用的哈希算法是SHA-256,产生的哈希值是256位的,所以整个输出空间为2^256,调整目标空间所占比例,通俗的说,就是要求哈希值前面要有多少个0.
挖矿难度和目标阈值成反比, d i f f i c u l t y = d i f f i c u l t y _ 1 _ t a r g e t t a r g e t difficulty = \frac{difficulty\_1\_target}{target} difficulty=targetdifficulty_1_target,其中difficulty_1_target
为挖矿难度为1时的target
,即最小挖矿难度,是个非常大的数。
-
如果不调整挖矿难度,会有什么问题 ❔
答:系统总算力越来越强,挖矿难度不变的话,出块时间会越来越短。 -
出块时间越来越短,会有什么问题 ❔
- 出块时间变短,交易可以更快被写入区块链,提高了系统效率。
- 上一节中说到区块在比特币网络上传播时间比较慢,可能需要几十秒才能使全网大部分节点收到,这时若出块时间很快,比如不到一秒就出一个区块,别的区块没有收到之前还是会延原来区块链继续扩展。这样出现分叉会成为常态,不仅会出现二分叉,可能会出现很多的分叉。分叉过多对系统达成共识是没有好处的,而且造成算力分散,使攻击者发动分叉攻击的成本大大降低(不用掌握51%的算力就有较大几率发动攻击)
-
10分钟的出块时间是最优的吗 ❔
- 显然不是的,目前好像没有文章专门研究出块时间并取得较为理想的结果的,但可以确定的是,出块时间需要维持在一个常数范围内。
- 以太坊系统中出块时间就降低到了15s,(在此稍作介绍,后续文章会介绍以太坊),时间大幅降低后,由以上分析得系统的安全性得不到保证,所以以太坊就要设计新的共识协议
Ghost
,在该协议中,被丢弃的orphan block
就不能简单废除掉了,而是也要给他们一些奖励,叫uncle reward
.以太坊中也要调整挖矿难度,使出块时间保持在15s.
② 如何调整挖矿难度
比特币协议中规定,每2016个区块就要调整目标阈值,按10min的平均出块时间来计算,大概是14天(两周)调整一次目标阈值。
-
调整公式: t a r g e t = t a r g e t × a c t u a l t i m e e x p e c t e d t i m e target = \frac{target \times actual time}{expected time} target=expectedtimetarget×actualtime
actual time
指产生2016个区块实际花费的时间expected time
指产生2016个区块应该花费的时间,即 2016 × 10 m i n 2016\times10min 2016×10min- 实际上,上调和下调都有四倍的限制,假如实际时间超过了8个星期,计算公式也只能按8个星期算,少于0.5个星期也一样。(避免大的波动)
-
如何让所有矿工同时调整目标阈值呢 ❔
- 计算target的算法是写在比特币系统的代码里,每挖到2016个区块会自动进行调整。
-
如果有恶意节点故意不调整,会怎么样 ❔
- 不调整目标阈值的节点发布的区块,诚实节点是不会认可的。
block header
中有一个nBits
的域,nBits
是target
的一个编码版本,block header
中没有直接存储target
,因为target
为256位,直接存需要32个字节,nBits
为32位,只占4个字节,可以认为它是一种压缩编码。- 其他节点收到恶意节点未调整目标阈值的区块时,在独立验证区块合法性的时候会对
nBits
域进行检查,不合法的话就不会被认可。