区块链学习笔记4——BTC实现
Posted PolarDay.
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了区块链学习笔记4——BTC实现相关的知识,希望对你有一定的参考价值。
区块链学习笔记4——BTC实现
学习视频:北京大学肖臻老师《区块链技术与应用》
笔记参考:北京大学肖臻老师《区块链技术与应用》公开课系列笔记——目录导航页
UTXO
区块链是一个去中心化的账本,比特币采用了基于交易的账本模式 。然而,系统中并没有记录账户所包含的比特币数,需要通过交易记录进行推算。在比特币系统中,全节点需要维护一个名为 UTXO(Unspent Transaction Output 还没有被花掉的交易输出) 的数据结构。
A转给B五个BTC,转给C三个BTC,B将5个BTC花掉,则该交易记录不保存在UTXO中,C没有花掉,则该交易记录保存在UTXO中
UTXO中的每个元素包括产生这个输出的交易的哈希值以及它在这个交易里是第几个输出就可以定位到这个输出
作用
检测交易是否合法,要花的币必须在UTXO中,便于快速检测double spending
每个交易会消耗输出,也会产生新的输出
如图,A转给B五个BTC,之后B将其转给D,则UTXO中会删掉A->B这一交易记录,同时会添加B->D这一交易记录。
如果一个人的比特币一直都不花,那他就会永久的保存在utxo中。
Transaction fee
交易可以有多个输入也可以有多个输出,但输入之和要等于输出之和(total inputs = total outputs)。
有一些交易的total inputs会略大于total outputs,这个差额就是transaction fee,给了获得记账权的结点。
之前有提到过会不会存在节点只想发布区块获得出块奖励而不想打包交易?
因此,BTC系统设计了Tranction fee(交易费),对于获得记账权节点来说,除了出块奖励之外,还可以得到打包交易的交易费。但目前来说,交易费远远小于出块奖励。等到未来出块奖励变少,可能区块链的维护便主要依赖于交易费了。
平均每隔十分钟产生一个新区块,每21万个区块,出块奖励减半,大约每隔四年出块奖励就会减半。
基于账户的模式
比特币是基于交易的模式,与之对应,还有一种基于账户的模式(如:以太坊)。基于账户的模式要求,系统中显示记录账户余额。也就是说,可以直接查询当前账户余额是多少货币。可以看到,比特币这种模式,隐私性较好,但其也付出一定代价。在进行交易时,因为没有账户这一概念,无法知道账户剩余多少BTC,所以必须说明币的来源(防止双花攻击)。而基于账户的模式,则天然地避免了这种缺陷,转账交易就是对一个(多个)账户余额的数字减和另一个(多个)账户余额的数字加
铸币交易(coinbase交易)
区块头中的nonce是一个32位无符号整数,在挖矿时候是通过不断调整nonce进行的,但可以看到,nonce的取值最多为232种。但并非将这些nonce全部遍历一遍,就一定能找到符合要求的nonce。由于近年来,挖矿人员越来越多,挖矿难度已经调整的比较大了,而2^32这一搜索空间太小,所以仅调整nonce很大可能找不到正确的结果。
那么,还能修改哪些值呢?
从上图可以看出,只有Merkle Tree的根哈希值可以进行修改,对根哈希值的修改主要是通过修改coinbase实现的。
每个发布区块者可以得到出块奖励,也就是可以在区块中发布一个 铸币交易(coinbase交易) ,这也是BTC系统中产生新比特币的唯一方式。下为一个铸币交易的内容:
可以看到,有一个CoinBase域,其中可以写入任何内容,在这里写什么都没有影响。所以可以在这里添加一些任意信息,便可以实现无法篡改(也无法删除)。(例如:提前写入股票预测结果的哈希值)
所以,只要我们改变了写入内容,便可以改变Merkle Tree 的根哈希值。
下图为一个小型的区块链,假定左下角交易为coinbase交易,可以看到,该交易发生改变会逐级向上传递,最终导致Merkle Tree根哈希值发生改变。
在实际的挖矿中,包括两层循环,外层循环调整coinbase域(可以规定只将其中前x个字节作为另一个nonce),算出block header中根哈希值后,内层循环再调整nonce。
普通转账交易
如果将输入脚本和输出脚本拼接起来可以顺利执行不出现错误,则说明交易合法。
挖矿过程的概率分析
挖矿本质上是不断尝试各种nonce,来求解这样一个puzzle。每次尝试nonce,可以视为一次伯努利试验。最典型的伯努利试验就是投掷硬币,正面和反面朝上概率为p和1-p。在挖矿过程中,一次伯努利试验,成功的概率极小,失败的概率极大。挖矿便是多次进行伯努利试验,且每次随机。这些伯努利试验便构成了a sequence of independent Bernoulli trials(一系列独立的伯努利试验)。根据概率论相关知识知道,伯努利试验本身具有无记忆性。也就是说,无论之前做多少大量试验,对后续继续试验没有任何影响 对于挖矿来说,便是多次伯努利试验尝试nonce,最终找到一个符合要求的nonce。在这种情况下,可以采用泊松分布进行近似,由此通过概率论可以推断出,系统出块时间服从指数分布。(需要注意的是,出块时间指的是整个系统出块时间,并非挖矿的个人)
指数分布本身也具有无记忆性。也就是说,对整个系统而言,已经过去10min,仍然没有人挖到区块,那么平均仍然还需要等10min(很不符合人的直觉)。也就是说,将来要挖多久和已经挖多久无关。
比特币总数计算:
Geometric series
21万×50+21万×25+21万×12.5+…
=21万×50×(1+1/2+1/4+…)
=21万×50×1/(1-1/2)
=2100万 -> 比特币总数
BitCoin is secured by mining
1.可否将其他账户上比特币转给自己?
答案:
不能。因为转账交易需要签名,恶意节点无法伪造他人签名。
如果恶意结点强行把一个非法的交易加到区块链中,其他的诚实结点检测到这个区块含有非法交易就不会接到这个区块链之后,并且另外形成一条最长合法链,这样恶意结点所添加的区块不在最长合法链上,恶意节点不仅无法偷币,而且无法获得出块奖励。
2.可否将已经话过的币再花一遍?
如下图1,若M已经将钱转给B,现在想再转给自己,假设其获得记账权,若按照图1方式,很明显为一个非法区块,不会被其他节点承认。
所以,M只能选择图2方式,将M转账给B的记录回滚掉。这样就有了两条等长合法链,取决于哪一个会胜出。
如果在M->B这个交易之后还延续有几个区块,如下图所示,则大多数诚实节点不会承认下面的链。所以,便变成了恶意节点挖下面的链,其他节点挖上面的链的算力比拼。由于区块链中大多数节点为善意节点,则最终上面链会胜出,而恶意节点的链会不被认可,从而导致投入成本白费。
一种简单防范防范便是多等几个确认区块。比特币协议中,缺省需要等6个确认区块,此时才认为该记录是不可篡改的。平均出块时间10min,六个确认区块便需要1小时。
Selfish mining
如图所示,假使挖到2号时候先不发布,则其他人仍然需要挖1号区块,若其算力足够强,能保证别人挖出1之后可以挖出3.可以此时将2和3一起发布,从而将1区块所在链最长合法链挤掉(减少了别人和自己竞争挖3号区块)。
但这样存在风险,如果别人已经挖出1,自己还没挖出3,则需要尽快发布2和别人竞争最长合法链地位。
以上是关于区块链学习笔记4——BTC实现的主要内容,如果未能解决你的问题,请参考以下文章