Michael.W深度剖析Bitcoin系统第3期——比特币的UTXO模型
-
- 1 比特币的账户模式
- 2 coinbase交易中数据域的秘密
- 3 挖矿“对于每个参与者都是平等的么?
- 4 比特币发行总量
1 比特币的账户模式
比特币采用的是基于交易的账本模式,
transaction-based ledger
。账本中并不像传统银行的中心数据库那样,记录着所有开户人的资产信息。如果你想知道某个比特币地址上的所有资产量,只能通过计算与该账户有关的所有交易而得出。
此时,我要引入UTXO(
Unspent Transaction Output
)模型 ,即所有未被花销的交易输出集合。一个地址下的所有UTXO的金额之和可以认为是当前地址中有多少可消费的比特币余额。
UTXO中的每个元素要给出产生这个输出的交易哈希值以及它是这笔交易中的第几个输出。依靠这以上两个信息就可以在比特币区块链中精确定位到该UTXO。
为什么会出现UTXO集合这种设计呢?个人觉得中本聪的本意是用来防止交易中产生**”双花“现象**。简单地说,你要花销的比特币如果不在UTXO集合中,就说明你发起的交易是无效的,是伪造的,是不堪的!
既然每个人在发起一笔交易时都需要查询UTXO集合,那么所有的全节点都要在本地内存中维护UTXO这样的一个数据结构的大集合,以便快速校验出"双花"交易。
每笔交易都会消耗一笔UTXO,同时也会产生新的一笔UTXO。形象地说,A给B成功转了5BTC,那么以前属于A的UTXO就变成无效,同时生成属于B的有效UTXO。
迄今为止,比特币的全账本已经超过200个G,但当前网络内的所有UTXO加在一起大概在2个G左右徘徊(只要有交易,UTXO就会变化)。这对于一个维护全网UTXO的服务器内存来说,还是绰绰有余的的。
一笔交易可以有多个输入或多个输出。同时支持1对1、1对多、多对1、多对多,像极了现在的爱情。
一笔交易的输入与输出的差额将会成为矿工的手续费。这是为了激励矿工来为所有人来打包交易而设计的,即比特币系统中的第二种激励机制。
除了基于交易的账本模式外,区块链世界中还有一种基于账户的账本模式,
account-based ledger
。后来诞生的以太坊的就是基于这种模式设计。
以太坊系统要显式地记录每个用户账户中共有多少资产,跟银行的中心服务器有异曲同工之妙。
由于比特币是基于交易的账本模式,所以每一笔比特币交易都需要把钱的来源和有效性说明白。因为比特币中完全没有账户的概念,没人知道你的账户还有多少钱可以使用。以太坊则不然,并不用这样显式地说明每一笔钱的来源和走向。
2 coinbase交易中数据域的秘密
这是最近一个区块的属性:
可以看到所有符合难度要求的区块头哈希值转成16进制后,前面都是一大长串的0。这与比特币的挖矿机制有关,后面我会写篇文章细说。
来看一下比特币源码中的区块头属性:
注意一下
nonce
这个成员属性。它是个32位无符号整形变量,所以它的最大值也就是2^32-1。
按照现在比特币网络内的挖矿难度来算,很有可能遍历0~2^32-1之间所有的整数也找不到满足条件的nonce值。
如果遍历了所有可能的nonce值也无法满足H(block header)<=target条件,那么我们还能更改比特币区块头中的哪些属性的?
答案是:改
merkle root
!你一定很奇怪,merkle root用来校验交易是否被篡改,这怎么还可以随便改呢?
每个区块都会包含有一个coinbase交易(区块体中的第一笔交易),矿工通过这个交易获取出块奖励。coinbase交易中有个coinbase数据域。这里面是矿工的地盘,他想写什么就可以写什么,因为所有交易的验证工作都不涉及这个区域!
上面是中本聪在比特币的创世区块的coinbase域中写下的话。大家注意,如果我改变coinbase数据域中的内容,那么coinbase交易的哈希值就会改变,接着会直接影响到merkle tree的根哈希值,最后可以导致改变整个区块头的哈希值。
所以比特币矿机挖矿的真正逻辑是包含两层循环。外层循环调整coinbase数据域的前八个字节,内层循环调整区块头中的nonce值。这样输出空间扩大了2^64倍,根本不存在找不到合适的nonce值的情况了。
来看刚刚产生的一笔比特币交易记录:
1个输入,2个输出。输入为0.0091298BTC,输出为0.0075293BTC,手续费0.0016005BTC。
下面是这笔交易的解锁脚本和锁定脚本:
比特币中验证交易的合法性就是把每笔交易的Input Scripts和Output Script拼装到一起后执行。
注意,不是将本交易中的输入和输出脚本配对,而是将本交易的输入的脚本和该输入在前面那个提供币的来源的交易的输出脚本拼装到一起。一定要注意!注意!再注意!
如果输入脚本和输出脚本拼接在一起能够顺利执行不报错,那么这个交易就是合法的。
比特币的挖矿难度值每2016个区块调整一次,时间大约为2周(每个区块出块时间大约在10分钟左右)。这种挖矿难度自调整模式也是为了稳定出块时间而设计的。
3 挖矿“对于每个参与者都是平等的么?
每次”挖矿“就是一个伯努利试验(
Bernoulli trial
)。
生活中最典型的伯努利试验的例子就是抛硬币。理想情况下,抛硬币的胜负概率均为50%,但对于”挖矿“来说,挖不到占很大概率,挖到占很小概率。
而连续挖矿就可以认为是一个伯努利过程(
Bernoulli process
),是无记忆性的。
形象地理解就是前面的试验对后面的试验没有任何影响。这就好像:假如你抛硬币扔了5把都是反面,那么是不是你第6次抛出正面的概率就要比反面更高呢?答案是否定的。因为每一次试验都是独立事件。
如果当”挖矿“次数足够多的时候,这个伯努利过程就可以近似看成一个泊松过程(
Poisson process
)。
假如整个比特币网络中各节点”挖矿“已经挖了十分钟还没有出矿,那么从现在开始还需要多久能挖出矿呢?直觉上给我们的感觉是那应该是快了,但是数学告诉我们距离下次挖出矿的时间还是大约十分钟!
比特币系统中某一个矿工能挖到下一个区块所需的时间可以认为是取决于他的算力占整个比特币系统算力的百分比。比如:一个矿工它的算力是整个比特币网络所里的千分之一,那么他平均挖到下一个区块的时间间隔为10*1000=10000分钟。
如果一种加密数字货币的POW模型算法不具备无记忆性(
progress free
),会出现一个什么问题?
就是算力强的矿工会有不成比例的优势。
举个栗子:如果矿工A的算力是矿工B的十倍,那么矿工A挖到矿的概率也应该是矿工B的十倍这才叫公平(pow模型满足progress free)。但是如果不满足这个性质,那么矿工A挖到矿的概率就要远远超过矿工B的十倍了。因为前面不成功的操作越多回到导致后面成功的概率增大。
所以不要觉得比特币挖矿这种progress free属性很无情,这恰恰是保证挖矿公平的根本。
4 比特币发行总量
比特币协议规定:出块奖励每21万块后减半(最开始出块奖励为50BTC),这样比特币总量就构成了一个几何序列:
21*50+21*25+21*12.5+….
=21*50*(1+1/2+1/4+1/8+….)
=21*50*(1/(1-1/2))
=2100(万)
大家要注意:挖矿的过程是没有任何实质意义的,但是挖矿的行为对于维护比特币系统的安全是至关重要的 。
在一个没有
membership
控制的分布式系统中,挖矿提供了一种凭借算力投票的有效手段。只要大部分算力掌握在诚实节点手里,那么这个系统的安全就可以得到保障。
那是不是随着比特币出块奖励越来越少,矿工挖矿的动力就降低了呢?
从比特币价格走势图上看,非也非也。虽然奖励少了,但是比特币单价提高了。
那么,假如有朝一日比特币的出块奖励变成0,还有人挖矿么?答案是肯定的,因为还有手续费可以作为盈利手段。
ps:
本人热爱图灵,热爱中本聪,热爱V神,热爱一切被梨花照过的姑娘。
以下是我个人的公众号,如果有技术问题可以关注我的公众号来跟我交流。
同时我也会在这个公众号上每周更新我的原创文章,喜欢的小伙伴或者老伙计可以支持一下!
如果需要转发,麻烦注明作者。十分感谢!
公众号名称:后现代泼痞浪漫主义奠基人