1️⃣ 参考
- 北京大学肖臻老师《区块链技术与应用》
- 部分图片来源
- https://www.blockchain.com/explorer/charts
- https://www.statista.com/statistics/647523/worldwide-bitcoin-blockchain-size
1️⃣0️⃣分叉
① 分叉分类
- 分叉:在去中心化的系统,改变一个参数,就可能导致分叉。硬分叉和软分叉取决于这个参数是怎么改的。
State Fork
由于对比特币区块链当前的状态有意见分歧而导致的分叉(无意)- 比如挖矿的时候,两个节点差不多同一个时候挖到了矿,就会出现一个临时性的分叉
Forking Attack
分叉攻击,它也属于 state fork,也是属于对比特币这个区块链当前的状态产生的意见分歧,只不过这个意见分歧是故意造成的,人为造成的,所以我们又叫它Deliberate Fork
。
Protocol Fork
协议分叉- 比特币的协议发生了改变,要修改比特币系统需要软件升级。在一个去中心化的系统里,升级软件的时候没有办法保证所有的节点同时都升级软件,少数节点因为种种原因可能没有升级,有可能是还没来得及升级,也可能是不同意对这个协议的修改。
- 根据对协议修改的内容的不同,我们又可以进一步分成硬分叉(
hard fork
)和软分叉(sotf fork
)
② Hard Fork
-
硬分叉出现情况(新节点认可,最终会有两条链)
如果对比特币协议增加一些新的特性,扩展一些新的功能,这些时候那些没有升级软件的这些旧的节点,它是不认可这些新特性的,认为这些特性是非法的,这就属于对比特币协议内容产生了意见分歧,所以会导致分叉。 -
例子
比特币中的区块大小限制 (block size limit
)。比特币系统规定每个区块最多是 1M 字节,有些人认为 1M 的限制太小了,影响了吞吐量(throughput
),也增加了交易的延迟。
可以计算一下:
1M = 1 百万字节,
一个交易大概认为是 250字节,
一个区块大概是 4000 个交易(1 百万 / 250=4000),
平均 10 分钟出现一个区块,大概每秒钟产生 7 笔交易[4000/(60×10)=7tx/sec],
这个吞吐量是非常低的。
假设:有人发布一个软件更新,把block size limit
从 1M 增加到 4M。且大多数节点更新这个软件,把block size limit
更新到 4M,少数节点没有更新。新节点认为区块大小限制是 4M,旧节点认为是 1M。
这里的大多数节点和少数节点不是按照账户数目来算的,而是按照算力(即系统中拥有大多数哈希算力的节点都更新了软件)。
- 为什么会产生分岔呢?
- 新节点认为上下两条链都是合法的
- 旧节点认为上面的链无论多长都是非法的,它们只会沿着下面的链挖
- 所以,分叉是永久性的,只要旧节点不更新软件,分叉就不会消失,所以才叫它硬结点。
比特币社区当中有些人是比较保守的,提高block size limit
有些人就是不同意。而且区块的大小也不是越大越好,比特币底层系统是个P2P overlay network
,它的传播主要采用flooding
的方式,所以对带宽的消耗是很大的,带宽是瓶颈。
-
那么旧节点挖出的小的区块还有没有出块奖励呢?
下面链的出块奖励在下面链里是认的。而分叉之前的币按道理应该是上下两条链都认可,所以会拆成两部分。 -
举例:以太坊分叉后交易回放问题
-
回放交易是指攻击者利用历史交易数据,在另一条区块链上伪造交易记录,从而牟取不当利益的行为。在以太坊分叉的场景中,由于两条链拥有相同的历史交易记录,攻击者可以截取主链上的交易数据,并在分叉链上重新打包这些交易,使其看起来像是发生在分叉链上。如果攻击者能够成功欺骗矿工确认这些回放交易,那么攻击者就能够从交易中获利
- 假设用户 B 在主链上向 C 支付了一笔钱,用于购物。之后,B 又在分叉链上发起回放交易,试图将这笔钱重新转回自己账户。如果 B 在分叉链上发起的回放交易被确认之前,主链上的支付交易也尚未被确认,那么 B 就有可能成功回放交易,并从 C 处获得双倍收益。
- 为了解决这个问题,以太坊在硬分叉后引入了
chain ID
的概念。每个链都拥有自己的chain ID
,交易记录中会包含相应的chain ID
信息。
-
补充
在以太坊历史上,最著名的硬分叉事件是 2016 年的 The DAO 事件。该事件导致以太坊分裂为以太坊(ETH)和以太坊经典(ETC)两条链。除了 chain ID 之外,以太坊还采用了其他一些措施来防止交易回放,例如 replay protection fork(RPF)。
③ Soft Fork:
-
软分叉出现情况?(新节点不认可,所以最终只会有一条链)
如果对比特币协议加一些限制,加入限制之后原来合法的交易或区块在新的协议当中有变的不合法,这就引起软分叉。 -
举例
- 假设新节点(多数)把区块大小改为 0.5M,旧节点(少数)依然以 1M 为准
- 此时区块链开始分叉,新节点挖出小区块,这种区块旧节点是认的。而旧节点挖出的大区块新节点是不认的。这样下去,旧节点看到上面链更长,而且是合法的之后,就会转去挖上面链。(这里把区块大小变小只是为了解释软分叉这个概念,实际中是不会这么做的。)
-
所以为什么称这种分叉是软分叉?
因为这种分叉是临时性的。所以旧节点如果不更新软件,它们挖的区块可能就白挖了😩。旧节点转向上面链挖的话,问题可能又会出现(如上图,它们可能又挖出了大区块)。而新节点不认这个,新节点会继续沿着大区块前面一个小区块挖,导致旧节点又白挖了
-
实际中可能出现软分叉的情况
- 给某些目前协议中没有规定的域增加一些新的含义,赋予它们一些新的规则,典型的例子就是
coinbase
域。前面讲过每一个发布的区块里可以有一个铸币交易 (coinbase transaction
),coinbase transaction
里有一个域叫coinbase
域,这个域用来干什么是没人规定也没人检查
- 给某些目前协议中没有规定的域增加一些新的含义,赋予它们一些新的规则,典型的例子就是
-
回顾
coinbase
用途-
前面讲过
coinbase
域的一个用途:可以把它作为extra nonce
。挖矿的时候要不断调整block header
里的nonce
,但block header
里的nonce
只有四个字节,最多只有 2 32 2^{32} 232 可能性,所以实际中可以把coinbase
前八个字节用来做extra nonce
。两个合在一起就成了 2 96 2^{96} 296 ,对于目前的挖矿难度,这个域已经是足够了。但coinbase
域不止是八个字节,后面还有很多,剩下的字节有人就提议做UTXO
(Unspent Transaction Output
)集合的根哈希值。 -
目前这个集合只是每个全节点自己在内存中维护,主要是为了快速查找、判断该交易是不是属于
double spending
,但这个集合的内容并没有写到区块链里,这跟前面讲到的merkle proof
是不太一样的。
-
-
merkle proof
能证明什么?- 证明某个交易是不是在给定的区块里。
- 比如一个轻节点,没有维护整个区块的内容,只知道
block header
。- 轻节点向全节点提问:“该交易是不是在这个区块里?”。
- 全节点返回一个
merkle proof
作为证明 - 轻节点就可以验证是否属实。
- 但如果是另外一种情况,想要证明某个账户上有多少钱,这个目前在比特币系统中是证不出来的。
- 全节点可以计算,方法如下:想要知道 A 账户有多少钱,就看一下
A
在UTXO
里对应的输出总共收到多少个币,就是该账户上有多少钱。
- 全节点可以计算,方法如下:想要知道 A 账户有多少钱,就看一下
对于全节点是可以算出来的,但如果是区块链钱包、有的手机上的 APP,它不可能在手机上维护一个完整的区块链,它实际上是个轻节点,它想要知道账户的余额需要询问全节点。全节点返回一个结果,怎么知道这个结果是不是对的?现在是证不出来的。如果你自己不维护一个 UTXO 集合,就没法用 merkle proof 证出来。
有人提议把UTXO
集合的内容组织成merkle tree
,算出一个根哈希值来,写入coinbase
域里的某个位置。coinbase
域的内容本身也会算哈希,算到block header
里的根哈希值,这样就可以用 merkle proof
证出来了。
假设有人发布一个软件更新,规定coinbase
域要按照这个要求来填写,大多数节点都升级了软件,少数节点没有更新,这属于软分叉(旧节点不在乎coinbase
写了什么,所以旧认可新,但新不认旧)
- 比特币历史上比较著名的软分叉的例子是
pay to script hash
。- 对于旧节点来说,它不知道
P2SH
的特性,只会做第一阶段的验证,即验证redeem script
是否正确。 - 新节点才会做第二阶段的验证,所以旧节点认为合法的交易新节点可能认为是非法的 (如果第二阶段的验证通不过的话)。而新节点认为合法的交易旧节点肯定认为是合法的,因为旧节点只验证第一阶段。(下图是P2SH两阶段验证,具体可看这里)
- 对于旧节点来说,它不知道
④ 总结
- soft fork 特点
- 只要系统中拥有半数以上算力的节点更新了软件,那么系统就不会出现永久性的分叉,只可能有一些临时性的分叉。
- hard fork 特点
- 必须是所有的节点都要更新软件,系统才不会出现永久性的分叉,如果有小部分节点不愿意更新,那么系统就会分成两条链。
1️⃣1️⃣课程回顾
① 问答
问题 1
- 转账交易时如果接收者不在线怎么办?
这个时候不需要接收者在线,转账交易只是在区块链上记录一下,把一个人账户上的比特币转移到他人的账户上,他人是否当时连接在比特币网络上是没有影响的。
问题 2
- 假设某个全节点收到了一个转账交易,有没有可能转账交易中接收者的收款地址是这个节点以前从来没有听说过的?
这是可能的。比特币账户在创建的时候是不需要通知其他人的,在本地产生一个公私钥对就可以了。只有在产生收款地址以后第一次收到钱时,其他节点才知道这个账户的存在。
问题 3
- 如果账户的私钥丢失了,该怎么办?
私钥丢失之后是没有办法的。该账户上的钱就变成了死钱,永远取不出来了。在去中心化的系统里,是没有人可以给你重置密码的。
在中心化的(比特币)交易所中账户密码丢失了,是可以跟交易所联系的,通过身份验证之后重置密码。有一些在线钱包也提供保管私钥的功能,但比特币或加密货币的交易所处于一种缺乏监管的状态,这个跟股票交易所是很不一样的。
历史上曾发生很多次加密货币的交易所被黑客攻击的情况。最著名的是日本的 Mt.Gox 的事件,它曾经是全世界最大的一个比特币交易所,交易量占到了全球比特币交易量的 70%,后来被黑客攻击,丢失了大量的比特币。后来交易所破产了,其 CEO 被判刑。各种加密货币交易所出现问题的情况发生了很多次,也有内部监管不当,管理人员卷钱跑路也时常发生。相比之下,一些冷钱包和硬钱包是比较安全的。
问题 4
- 如果私钥泄露了怎么办?
- 比如你发现自己账户上出现一些可疑的交易,这个时候该怎么办?
这时应该尽快把自己账上的钱转到另外一个安全的账户上
- 比特币账户所谓的密码是什么?
- 就是它的私钥。公私钥对生成之后是没有办法改的。可以生成一个新的账户,但是原来账户上的私钥是改不了的。
同样,也无法阻止别人在这个账户上转账的交易把账户上的钱转走。
问题 5
- 如果转账的时候写错了地址怎么办?
这是没有办法的。
问题6
- 那转到不存在的地址呢?
- 什么是不存在的地址?
-
正常的地址是公钥取哈希得到的。
-
但有些地址其实不是公钥的哈希得来的,比如第一节课的
digital commitment
的例子。你想把某项内容的哈希值发布到区块链上,证明你曾在某个时间知道某个事情。
-
在前面讲比特币脚本的时候,有人把(
digital commitment
)哈希值放到return
的后面,因为OP_RETURN
后写什么都是没有人管的。但有人会把他要保存的那个哈希值(就是OP_RETURN后写的内容)生成一个地址,作为收款人的地址,它其实是个假的地址,比特币系统并不知道这个地址的真假,别人也看不出来。所以这样转账的钱就变成了死钱。
-
这种做法一般牺牲一点比特币,比如转很少一点钱,换取往这个区块链里写入这个哈希值的机会。这个做法是不提倡的,因为这样的话转账交易的输出会永久的保存在UTXO
里面,这样对全节点是不友好的。
问题7
proof of burn
、OP_RETURN
这些实际当中是怎么操作的?- 当一个全节点收到一个转账交易的时候,它首先要检查一下,这个交易的合法性,只有合法的交易才会被写入区块链里。而
OP_RETURN
这个语句是无条件的返回错误,既然如此,它怎么可能通过验证,怎么可能被写到区块链里呢?
- 首先要理解
OP_RETURN
是写在哪里的?
OP_RETURN
是写在当前交易的输出脚本中的,在验证的时候不会用到,因为验证只需要上一次的输出和这一次的输入
所以,验证当前交易合法性的时候,不会执行这个语句。即当前交易的输出脚本在验证交易合法性的时候,是不会被执行的。只有有人想花这笔钱,后面再有一个交易,要花这个交易的输出的时候才会执行这个交易的输出脚本。
问题8
- 挖矿时会不会有的矿工偷答案?
- 怎么知道是哪个矿工先找到这个
nonce
?
不会,因为每个矿工挖到的nonce
是和他自己的收款地址绑定在一起的。。
发布的区块里有coinbase transaction
,里面有一个收款人地址,是挖到矿的矿工的地址。假如 A 挖到了矿,里面就是 A 的收款地址。如果要偷答案的话,就要把 A 的地址换成自己的地址,而地址如果一变化,coinbase transaction
的内容就发生了改变。会导致merkle tree
的根哈希值变化(因为这个交易和区块中所包含的其他交易是合在一起构成了merkle tree
,任何一个地方发生改变,根哈希值就会变)
而nonce
是在块头里面,根哈希值也是在块头里面,block header
的内容发生了变化之后,原来找到的nonce
就作废了。所以不可能偷答案。
问题9
- 怎么判断交易费该给哪个矿工?
- 即事先怎么知道哪个矿工会挖到矿?
给谁不需要事先知道,哪个矿工挖到矿了,就可以把这个区块里所包含的交易差额收集起来,作为他自己的交易费。
- 交易费(
transaction fees
)是怎么算的?total inputs - total outputs = transaction fees
。
② 统计数据(2024)
②① Blockchain Size
上图显示的是比特币区块链的大小的变化情况(单位
GB
,来源),可以看到区块链是越来越大的。这也不奇怪,区块链只能往里面添东西,所以区块链只会越来越长。目前的size
对于硬盘的容量来说,还是完全没有问题的,区块链大部分内容还是可以保存在硬盘上的。
②② Number of Unspent Transaction Outputs
上图是
UTXO
集合的大小变化。该集合总的趋势是不断变大的,有一些波动,主要原因就是比特币交易增多后UTXO
的集合会跟着一起变大。当然还有另一些方面是历史原因造成的,有一些账户私钥丢失了,所以这些账户对应的输出在UTXO
里就要永久的保存下去,时间长了也会累计增多。(图片来源)
②③ Hashrate Distribution
上图是比特币矿池挖矿的情况。可以看出,挖矿集中化的趋势也非常严重,几个大的矿池占了系统中很大一部分。(图片来源)
②④ market price
②⑤ Market Capitalization
这里的市值是绝对的市值,不是说在加密货币整体中占的百分比。
②⑥ Exchange Trade Volume
上图是比特币的交易量。可以看出17-18和20-21交易量增加的很明显,而且波动非常大,这个交易量是按照美元价格算出的,所以这些波动当中有一些是比特币本身的价格波动造成的。
②⑦ Confirmed Transactions Per Day
②⑧ Average Transactions Per Block
如上图是每个区块的交易数量,趋势跟前面的图很接近,因为难度调整算法要把出块时间稳定在 10 分钟,这样的话每天能产生多少个区块就是差不多的。交易数目的变化主要是因为每个区块里所包含的交易数目发生了变化。每个区块最多包含交易的上限差不多是 4000 个,图中的情况是远远没有达到这个上限。很多人说 1M 太小了,但真实的区块链上很多区块是没有装满的。(现在是基本装满了)